2 # Rules for NuttX binaries compilation of C, C++ and assembler
3 # sources using GNU toolchain.
5 # Interface to other rules:
8 # NUTTX_EXPORT - export directory of NuttX build
9 # it should contain subdirectories:
10 # arch build include libs registry startup)
11 # LIB_DIR - directory where compiled libraries are stored
12 # OBJS_DIR - directory where intermediate files (.o, .map, ...) are stored
13 # INCLUDE_DIR - where includes can be found
14 # from config.omk or Makefile.omk
15 # CROSS_COMPILE - target architecture tools prefix
16 # TARGET_ARCH, DEBUG, OPTIMIZE, DEFS - forms CFLAGS
17 # from base: SOURCES_DIR
18 # from Makefile.omk: lib_LOADLIBES
21 # SOURCES - all the source files that needs to be compiled (except for shared library sources)
22 # SOLIB_SOURCES - all the source files that needs to be compiled for a shared library
23 # OBJ_EXT - extension of object files
24 # LIB_EXT - extension of library files
25 # LIB_PREF - prefix for library files
26 # ASM_EXT - extension of assembler sources
29 # COMPILER_DEFS_template - definitions that should be defined before
30 # the following templates can be used. The input variables needs to be
31 # defined before evaluating this template
33 # COMPILE_c_o_template, COMPILE_cc_o_template, COMPILE_S_o_template -
34 # templates that create rules for compilation of sources
36 # PROGRAM_template, LIBRARY_template, SOLIB_template - templates that
37 # create rules for compilation of a program, library and shared
38 # library. The rules can use rules produced by COMPILE_xxx_template.
40 define COMPILER_DEFS_template
46 CC = $(CROSS_COMPILE)gcc
47 CXX = $(CROSS_COMPILE)g++
48 LINK = $(CROSS_COMPILE)ld
49 AR = $(CROSS_COMPILE)ar
50 OBJCOPY = $(CROSS_COMPILE)objcopy
51 NM = $(CROSS_COMPILE)nm
53 CFLAGS += $(TARGET_ARCH) $(DEBUG) $(OPTIMIZE)
55 CFLAGS += -I$(SOURCES_DIR)
56 CFLAGS += -I$(INCLUDE_DIR)
58 LOADLIBES += -L$(LIB_DIR)
59 LOADLIBES += $(lib_LOADLIBES:%=-l%)
62 -include $(OBJS_DIR)/*.d
64 SOURCES2OBJS = .o/.c .o/.cc .o/.cxx .o/.S .o/.s .o/.o
66 SOURCES2OBJSLO = .lo/.c .lo/.cc .lo/.cxx .lo/.S .lo/.s .lo/.lo
69 # $(CC) -o $@ $(LCFLAGS) -c $<
71 c_o_COMPILE = $$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(OMK_CPPFLAGS) \
72 $(CPPFLAGS) $(OMK_CFLAGS) $$(CFLAGS)
74 cc_o_COMPILE = $$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(OMK_CPPFLAGS) \
75 $(CPPFLAGS) $(CXXFLAGS) $(OMK_CFLAGS) $$(CFLAGS)
77 S_o_COMPILE = $$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
78 $(CPPFLAGS) $(OMK_CFLAGS) $$(CFLAGS) $(ASFLAGS)
81 # Check GCC version for user build
82 ifndef CC_MAJOR_VERSION
83 CC_MAJOR_VERSION = $$(shell $$(CC) -dumpversion | $(SED4OMK) -e 's/\([^.]\)\..*/\1/')
85 # Prepare suitable define for dependency building
86 ifeq ($$(CC_MAJOR_VERSION),2)
87 CC_DEPFLAGS = -Wp,-MD,"$$@.d.tmp"
89 CC_DEPFLAGS = -MT $$@ -MD -MP -MF "$$@.d.tmp"
92 endef # COMPILER_DEFS_template
95 # Syntax: $(call COMPILE_c_o_template,<source>,<target>,<additional c-flags>)
96 define COMPILE_c_o_template
97 $(2): $(1) $$(GEN_HEADERS)
98 @$(QUIET_CMD_ECHO) " CC $$@"
99 $(Q) if $$(c_o_COMPILE) $$(CC_DEPFLAGS) $(3) -o $$@ -c $$< ; \
100 then mv -f "$$@.d.tmp" "$$@.d" ; \
101 else rm -f "$$@.d.tmp" ; exit 1; \
106 # Syntax: $(call COMPILE_cc_o_template,<source>,<target>,<additional c-flags>)
107 define COMPILE_cc_o_template
108 $(2): $(1) $$(GEN_HEADERS)
109 @$(QUIET_CMD_ECHO) " CXX $$@"
110 $(Q) if $$(cc_o_COMPILE) $$(CC_DEPFLAGS) $(3) -o $$@ -c $$< ; \
111 then mv -f "$$@.d.tmp" "$$@.d" ; \
112 else rm -f "$$@.d.tmp" ; exit 1; \
116 # Syntax: $(call COMPILE_S_o_template,<source>,<target>,<additional c-flags>)
117 define COMPILE_S_o_template
118 $(2): $(1) $$(GEN_HEADERS)
119 @$(QUIET_CMD_ECHO) " AS $$@"
120 $(Q) if $$(S_o_COMPILE) -D__ASSEMBLY__ $$(CC_DEPFLAGS) $(3) -o $$@ -c $$< ; \
121 then if [ -e "$$@.d.tmp" ] ; then mv -f "$$@.d.tmp" "$$@.d" ; fi ; \
122 else rm -f "$$@.d.tmp" ; exit 1; \
126 # Syntax: $(call PROGRAM_template,<executable-name>,<dir>,<link-variant>)
127 define PROGRAM_template
129 GEN_SOURCES += $$($(1)_GEN_SOURCES)
131 $(foreach x, $(SOURCES2OBJS),
132 $(1)_OBJS += $$(patsubst %$(notdir $(x)),%$(dir $(x)),$$(filter %$(notdir $(x)),\
133 $$($(1)_SOURCES) $$($(1)_GEN_SOURCES)))
135 $(1)_OBJS := $$(sort $$($(1)_OBJS:%/=%))
137 SOURCES += $$($(1)_SOURCES)
139 ifneq ($$($(1)_PROGBUILTIN),)
140 ifneq ($$($(1)_PROGBUILTIN),all)
141 $(1)_PROGBUILTIN_LIST = $$($(1)_PROGBUILTIN)
143 $(1)_PROGBUILTIN_TMP = $$(wildcard $$(USER_COMPILED_DIR_NAME)/registry/*.pbi)
144 $(1)_PROGBUILTIN_LIST = $$($(1)_PROGBUILTIN_TMP:$$(USER_COMPILED_DIR_NAME)/registry/%.pbi=%)
147 $(1)_PROGBUILTIN_PBI=$$($(1)_PROGBUILTIN_LIST:%=$$(USER_COMPILED_DIR_NAME)/registry/%.pbi)
148 $(1)_PROGBUILTIN_ldat=$$($(1)_PROGBUILTIN_LIST:%=$$(USER_COMPILED_DIR_NAME)/registry/%.ldat)
149 $(1)_PROGBUILTIN_PDAT=$$($(1)_PROGBUILTIN_LIST:%=$$(USER_COMPILED_DIR_NAME)/registry/%.pdat) \
150 $$(wildcard $(NUTTXREGISTRY)/*.pdat)
151 $(1)_PROGBUILTIN_BDAT=$$($(1)_PROGBUILTIN_LIST:%=$$(USER_COMPILED_DIR_NAME)/registry/%.bdat) \
152 $$(wildcard $(NUTTXREGISTRY)/*.bdat)
154 ifneq ($$($(1)_PROGBUILTIN_PDAT),)
155 $(1)_BUILTINTABLE = $(OBJS_DIR)/$(1)-builtintab.c
157 $$($(1)_BUILTINTABLE): $$($(1)_PROGBUILTIN_PDAT) $$($(1)_PROGBUILTIN_BDAT)
158 $(Q) cat $$($(1)_PROGBUILTIN_PDAT) >$$@
159 $(Q) echo "#include <nuttx/config.h>" >>$$@
160 $(Q) echo "#include <nuttx/binfmt/builtin.h>" >>$$@
161 $(Q) echo "const struct builtin_s g_builtins[] = {" >>$$@
162 $(Q) cat $$($(1)_PROGBUILTIN_BDAT) >>$$@
163 $(Q) echo "{ NULL, 0, 0, 0 }};" >>$$@
164 $(Q) echo "const int g_builtin_count = sizeof(g_builtins) / sizeof(g_builtins[0]);" >>$$@
166 GEN_SOURCES += $$($(1)_BUILTINTABLE)
171 ifneq ($$(LD_SCRIPT$(3:%=-%)),)
172 $(1)$(3:%=-%)_LD_SCRIPT_FN = $$(LD_SCRIPT$(3:%=-%))
174 $(1)$(3:%=-%)_LD_SCRIPT_FN = $$(LD_SCRIPT)
177 ifeq ($$(dir $$($(1)$(3:%=-%)_LD_SCRIPT_FN)),)
178 $(1)$(3:%=-%)_LD_SCRIPT = $$(LIB_DIR)/$$($(1)$(3:%=-%)_LD_SCRIPT_FN)
180 $(1)$(3:%=-%)_LD_SCRIPT = $$($(1)$(3:%=-%)_LD_SCRIPT_FN)
183 $(1)$(3:%=-%)_LDFLAGS = -Wl,-T,$$($(1)$(3:%=-%)_LD_SCRIPT)
185 $(2)/$(1)$(3:%=-%): $$($(1)_OBJS) $$($(1)_BUILTINTABLE:%.c=%.o) $$($(1)_PROGBUILTIN_ldat) $$($(1)$(3:%=-%)_LD_SCRIPT)
186 @$(QUIET_CMD_ECHO) " LINK $$@"
187 $(Q) if [ -n "$$($(1)_PROGBUILTIN_LIST)" ] ; then echo ; fi
188 $(Q) $$(if $$(filter %.cc,$$($(1)_SOURCES)) , \
189 $$(CXX) $$(CPPFLAGS) $$(OMK_CPPFLAGS) $$(OMK_CXXFLAGS) $$(CXXFLAGS) , \
190 $$(CC) $$(CPPFLAGS) $$(OMK_CPPFLAGS) $$(OMK_CFLAGS) $$(CFLAGS) ) \
191 $$(OMK_LDFLAGS) $$(LDFLAGS) $$($(1)$(3:%=-%)_LDFLAGS) -Wl,-Map,$(1)$(3:%=-%).map \
192 $$($(1)_OBJS) $$($(1)_MOREOBJS) $$($(1)_BUILTINTABLE:%.c=%.o) \
193 $$($(1)_PROGBUILTIN_PBI) $$(LOADLIBES) $$($(1)_LIBS:%=-l%) \
194 $$(shell for i in $$($(1)_PROGBUILTIN_ldat); do cat $$$$i ; done) $$(NUTTXLIBES) \
196 @echo "$(2)/$(1)$(3:%=-%): \\" >$(OBJS_DIR)/$(1)$(3:%=-%).exe.d
197 @$(SED4OMK) -n -e 's|^LOAD \(.*\)$$$$| \1 \&|p' $(OBJS_DIR)/$(1)$(3:%=-%).map|tr '&' '\134' >>$(OBJS_DIR)/$(1)$(3:%=-%).exe.d
198 @echo >>$(OBJS_DIR)/$(1).exe.d
201 # Syntax: $(call ELF_template,<executable-name>,<dir>)
204 $(2)/$(1).elf: $$($(1)_OBJS)
205 @$(QUIET_CMD_ECHO) " ELF $$@"
207 -r -e main -T $(NUTTX_EXPORT)/build/gnu-elf.ld \
209 $$($(1)_OBJS) $$($(1)_MOREOBJS) $$(LOADLIBES) $$($(1)_LIBS:%=-l%) \
211 @echo "$(2)/$(1).elf: \\" >$(OBJS_DIR)/$(1).elf.d
212 @echo " $(NUTTX_EXPORT)/build/gnu-elf.ld \\" >>$(OBJS_DIR)/$(1).elf.d
213 @$(SED4OMK) -n -e 's|^LOAD \(.*\)$$$$| \1 \&|p' $(OBJS_DIR)/$(1).elf.map|tr '&' '\134' >>$(OBJS_DIR)/$(1).elf.d
214 @echo >>$(OBJS_DIR)/$(1).elf.d
217 # Syntax: $(call PROGBUILTIN_template,<executable-name>,<dir>,<registry-dir>)
218 define PROGBUILTIN_template
220 $(1)_PRIORITY ?= SCHED_PRIORITY_DEFAULT
221 $(1)_STACKSIZE ?= 2048
223 $(2)/$(1).pbi: $$($(1)_OBJS)
224 @$(QUIET_CMD_ECHO) " PROGMOD $$@"
226 -r -x --defsym=$(1)_main=main \
228 $$($(1)_OBJS) $$($(1)_MOREOBJS) \
229 -o $(OBJS_DIR)/$(1).pbo
230 $(Q) $(OBJCOPY) --keep-global-symbol=$(1)_main $(OBJS_DIR)/$(1).pbo $$@
231 @echo "$(2)/$(1).pbi: \\" >$(OBJS_DIR)/$(1).pbi.d
232 @$(SED4OMK) -n -e 's|^LOAD \(.*\)$$$$| \1 \&|p' $(OBJS_DIR)/$(1).pbi.map|tr '&' '\134' >>$(OBJS_DIR)/$(1).pbi.d
233 @echo >>$(OBJS_DIR)/$(1).pbi.d
234 @echo "{ \"$1\", $$($(1)_PRIORITY), $$($(1)_STACKSIZE), $(1)_main }," >$(3)/$(1).bdat
235 @echo "int $(1)_main(int argc, char *argv[]);" >$(3)/$(1).pdat
236 @echo "$$(LOADLIBES) $$($(1)_LIBS:%=-l%)" >$(3)/$(1).ldat
240 # Rules for other output formats (can be specified by OUTPUT_FORMATS)
242 @$(QUIET_CMD_ECHO) " OBJCOPY $@"
243 $(Q) $(OBJCOPY) --output-target=binary -S $< $@
246 @$(QUIET_CMD_ECHO) " OBJCOPY $@"
247 $(Q) $(OBJCOPY) --output-target=ihex -S $< $@
250 @$(QUIET_CMD_ECHO) " OBJCOPY $@"
251 $(Q) $(OBJCOPY) --output-target=srec -S $< $@
253 # Syntax: $(call LIBRARY_template,<library-name>)
254 define LIBRARY_template
256 GEN_SOURCES += $$($(1)_GEN_SOURCES)
258 $(foreach x, $(SOURCES2OBJS),
259 $(1)_OBJS += $$(patsubst %$(notdir $(x)),%$(dir $(x)),$$(filter %$(notdir $(x)),\
260 $$($(1)_SOURCES) $$($(1)_GEN_SOURCES)))
262 $(1)_OBJS := $$(sort $$($(1)_OBJS:%/=%))
264 SOURCES += $$($(1)_SOURCES)
266 $(LIB_DIR)/lib$(1).a: $$($(1)_OBJS)
267 @$(QUIET_CMD_ECHO) " AR $$@"
268 $(Q) $(AR) rcs $$@ $$^
272 # Syntax: $(call SOLIB_template,<library-name>)
273 define SOLIB_template
275 SOLIB_GEN_SOURCES += $$($(1)_GEN_SOURCES)
277 $(foreach x, $(SOURCES2OBJSLO),
278 $(1)_OBJSLO += $$(patsubst %$(notdir $(x)),%$(dir $(x)),$$(filter %$(notdir $(x)),\
279 $$($(1)_SOURCES) $$($(1)_GEN_SOURCES)))
281 $(1)_OBJSLO := $$(sort $$($(1)_OBJSLO:%/=%))
283 SOLIB_OBJS += $$($(1)_OBJSLO)
284 SOLIB_SOURCES += $$($(1)_SOURCES)
286 $(LIB_DIR)/lib$(1).so: $$($(1)_OBJSLO)
287 @$(QUIET_CMD_ECHO) " LINK $$@"
288 $(Q) $(LD) --shared --soname=lib$(1).so -o $$@ $$^
291 ifneq ($(bin_PROGRAMS),)
292 library-pass_HOOKS += force_builtin_library_hook
294 .PHONY: force_builtin_library_hook
295 force_builtin_library_hook: