merged
[henge/webcc.git] / make / lib / rules.mk
1 ################################################################################
2 # Desc: Make functions for creating rules (Make making Make)
3 # Author: ksg
4 # Date: 2016
5 ################################################################################
6 # This file consists of library functions for make-making-make functionality
7 ################################################################################
8
9 # A long function definition to grab deps from the source's compiler and route
10 # errors to /dev/null if the rule generator expresses bogus errors
11 define SRC_LANG_FLAGS_OPT_DEPS =
12 $(filter-out \ %:,$(shell $($2_C) $3 $4 -MG $1 2> /dev/null))
13 endef
14
15 #SRC_LANG_RULE###################################################################
16 # Given a source and a language, generate a rule to make the object. The second
17 # invocation of gcc per file lists only its local includes, and filters out
18 # anything already caught. Anything remaining should be considered to be
19 # available in the current working directory of the source file(i.e. if you
20 # '#include "something.h"' in 'mymodule/horseradish.c', you would expect to
21 # include 'mymodule/something.h'. this check lets that happen), otherwise it is
22 # some kind of user error ######################################################
23 define SRC_LANG_RULE =
24 $(if $($1),,$(eval $1 := t)\
25 $(eval MOD := $(filter $(MODULES),$(firstword $(subst /, ,$(subst $(SRC_DIR),,$(dir $1))))))\
26 $(eval FLG := $(MOD:%=-I$(SRC_DIR)/% ))\
27 $(if $(wildcard $1),
28 $(eval DEPS := $(filter-out \ %:,$(shell $($2_C) $(FLG) -M -MG $1)))\
29 $(eval DDEPS := $(filter $(DRIVER_DIR:$(SRC_DIR)/%=%/%),$(DEPS)))\
30 $(eval MDEPS := $(filter $(MODULES:%=%/%),$(DEPS)))\
31 $(eval DEPS := $(filter-out $(DDEPS) $(MDEPS),$(DEPS)))\
32 $(eval MDEPS := $(MDEPS:%=$(SRC_DIR)/%))\
33 $(eval DDEPS := $(DDEPS:%=$(SRC_DIR)/%))\
34 $(eval LOST := $(filter-out \ %: $(DRIVER_DIR:./%=%)/% $(MODULES:%=$(SRC_DIR:./%=%)/%/%),$(shell $($2_C) $(FLG) -MM -MG $1)))\
35 $(eval MDEPS += $(LOST:%=$(dir $1)%))\
36 $(eval MDEPS := $(shell echo $(MDEPS) | sed -e 's@[a-zA-Z0-9\-\+/]*\.\./include@$(LIBINC_DIR)@g'))\
37 $(eval ALLDEPS := $(DDEPS) $(MDEPS) $(DEPS)),\
38 $(error Cannot generate deps for: $1, file not found))\
39 $(eval SRC_OBJ := $(basename $1).$($2_OBJ))\
40 $(eval MAKE_TARGETS += $(SRC_OBJ))
41 # Assume that lost dependencies are in the folder with the source
42 $(foreach lost,$(LOST),
43 $(eval ALLDEPS := $(subst $(lost), $(dir $1)$(lost),$(ALLDEPS))))
44
45 # Find relative deps in our local LIBINC_DIR, if available. Otherwise they
46 # should be expected in the src directory
47 $(eval RELDEPS := $(filter-out $(SRC_DIR:./%=%)/% ./% /%,$(ALLDEPS)))
48 $(foreach dep,$(RELDEPS),
49 $(eval ALLDEPS := $(subst $(dep),\
50 $(if $(wildcard $(LIBINC_DIR)/$(dep)),$(LIBINC_DIR),$(SRC_DIR))/$(dep),$(ALLDEPS))))
51
52 # Find any deps that aren't built yet, which the compiler has flagged as
53 # missing, but which we know the expected location of libs for this language
54 # should have their includes in 'LIBINC_DIR'
55 $(eval BUILDDEPS := $(filter $($2_LIBS:%=%/%),$(ALLDEPS)))
56 $(eval ALLDEPS := $(filter-out $(BUILDDEPS),$(ALLDEPS)) $(BUILDDEPS:%=$(LIBINC_DIR)/%))
57 # Object for $1
58 $(SRC_OBJ): $(ALLDEPS)
59 $($2_C) $$($2_FLAGS) $(FLG) -c -o $$@ $1
60 $(if $($2_DBG),\
61 $(eval DBG_OBJ := $(dir $1).$($2_DBG)/$(basename $(notdir $1)).$($2_OBJ))\
62 $(if $(findstring $(dir $(DBG_OBJ)),$(MAKE_DIRS)),,\
63 $(eval MAKE_DIRS += $(dir $(DBG_OBJ))))
64 $(eval MAKE_TARGETS += $(DBG_OBJ))
65 # Object for $1 with $($2_DBG) symbols
66 $(DBG_OBJ): $(ALLDEPS) | $(dir $(DBG_OBJ))
67 $($2_C) $$($2_FLAGS) $(FLG) -Og -g$($2_DBG) -c -o $$@ $1
68 ))
69 #/SRC_LANG_RULE#################################################################
70 endef
71
72 #LANG_LIB_DEPLIST###############################################################
73 # Crawl the tree of dependencies for static libraries, terminating at root
74 # dependencies or any dynamic link #############################################
75 define LANG_LIB_DEPLIST =
76 $(if $($2_INIT),,$(call LANG_LIB_INIT,$1,$2))
77 $(foreach dep,$($2_DEPS)
78 endef
79
80
81 define LIB_PARSELINKS =
82 $(
83 $(eval DLIBS := $(patsubst +%,%,$(filter +%,$(LINK_ORDER))))
84 $(eval SLIBS := $(patsubst -%,%,$(filter -%,$(LINK_ORDER))))
85 $(foreach ldobj,$(patsubst +%,%,$(LINK_ORDER:-%=%)),
86 $(if $(or $(filter $(ldobj),$(DLIBS)),$(and $(filter-out $(SLIBS),$(ldobj)), $(filter $(ldobj),$($($2_C)_LDLIBS)))),
87 $(eval DRIVER_LDINFO += -l$(ldobj)),
88 $(if $(filter $(ldobj),$(MODULES)),
89 $(eval DRIVER_LDINFO += $(SRC_DIR)/$(ldobj).$($2_AROBJ))
90 $(eval DRIVER_LDINFO_D += $(SRC_DIR)/.$($2_DBG)/$(ldobj).$($2_AROBJ)),
91 $(if $($(ldobj)_INIT),,$(call LANG_LIB_INIT,$2,$(ldobj),$1))
92 $(foreach dep,$($(ldobj)_DEPS)
93
94 endef
95
96 #SRC_LANG_DRVRULE###############################################################
97 # establish a build and link rule given a source driver and language ###########
98 define SRC_LANG_DRVRULE =
99 $(eval DRIVER_NAME := $(basename $(notdir $1)))
100 $(eval DRIVER_TARG := $(1:$(SRC_DIR)/%.$2=$(ROOT_DIR)/%$($2_OUT)))
101 $(eval DRIVER_TARG_D := $(DRIVER_TARG)-d)
102 $(eval DRIVER_SOB := $(basename $1).$($2_OBJ))
103 $(eval DRIVER_SOB_D := $(DRIVER_SOB:$(dir $(DRIVER_SOB))%=$(dir $(DRIVER_SOB)).$($2_DBG)/%))
104
105 # Generate a rule for the driver object
106 $(eval $(call SRC_LANG_RULE,$1,$2))
107
108 # Modules can be implicitly specified by a driver if its dependencies include
109 # ANY files from any module directory. The 'MDEPS' var is set by SRC_LANG_RULE
110 # and expresses the dependencies required to build the object file only.
111 $(foreach module_dep,$(MDEPS),
112 $(eval DRIVER_MODULES += $(firstword $(subst /, ,$(module_dep))))
113 )
114 $(eval DRIVER_MODULES := $(filter-out $(DRIVER_DIR) . ..,$(sort $(DRIVER_MODULES))))
115
116 # Read associated linking data for the driver. If no link data is available,
117 # all libraries are assumed to be statically linked by the build system. files
118 # prefixed with 'test' will first attempt to find a 'ld' file matching its
119 # basename with the 'test' prefix removed (i.e. ./src/bin/testscanner.c will
120 # first attempt to find ./src/bin/scanner.ld for its ld information. if not
121 # available, it will instead use ./src/bin/testscanner.ld. if still not
122 # available, all libraries will attempt static linking - and if those static
123 # libs are not available, the system will attempt to retrieve the source code
124 # and build the static lib
125 $(eval DRIVER_LDFILE := $(1:%.$2=%.mk))
126 $(if $(filter test%,$(DRIVER_NAME)),
127 $(eval DRV_LD := $(subst $(DRIVER_NAME).$2,$(DRIVER_NAME:test%=%).mk,$1))
128 $(if $(wildcard $(DRV_LD)),
129 $(eval DRIVER_LDFILE := $(DRV_LD))
130 ))
131 $(eval undefine LINK_ORDER)
132 $(eval undefine LINK_ORDER_D)
133 $(eval $(file <$(DRIVER_LDFILE)))
134 $(eval undefine DRIVER_LDINFO)
135 $(eval undefine DRIVER_LDINFO_D)
136 $(eval DRIVER_LDINFO += $(1:%.$2=%.$($2_OBJ)))
137 $(eval DRIVER_LDINFO_D += $(1:$(dir $1)%.$2=$(dir $1).$($2_DBG)/%.$($2_OBJ)))
138 $(eval DLIBS := $(patsubst +%,%,$(filter +%,$(LINK_ORDER))))
139 $(eval SLIBS := $(patsubst -%,%,$(filter -%,$(LINK_ORDER))))
140 $(foreach ldobj,$(patsubst +%,%,$(LINK_ORDER:-%=%)),
141 $(if $(or $(filter $(ldobj),$(DLIBS)),$(and $(filter-out $(SLIBS),$(ldobj)), $(filter $(ldobj),$($($2_C)_LDLIBS)))),
142 $(eval DRIVER_LDINFO += -l$(ldobj)),
143 $(if $(filter $(ldobj),$(MODULES)),
144 $(eval DRIVER_LDINFO += $(SRC_DIR)/$(ldobj).$($2_AROBJ))
145 $(eval DRIVER_LDINFO_D += $(SRC_DIR)/.$($2_DBG)/$(ldobj).$($2_AROBJ)),
146 $(if $($(ldobj)_INIT),,$(call LANG_LIB_INIT,$2,$(ldobj),$1))
147 $(foreach dep,$($(ldobj)_DEPS)
148
149 $(if $(filter -l%,$(ldobj)),
150 $(eval ldlibname := $(ldobj:-l%=%))
151 $(if $(filter $(ldlibname),$($($2_C)_LDLIBS)),
152 $(eval DRIVER_LDINFO += $(ldobj))
153 $(eval DRIVER_LDINFO_D += $(ldobj)),
154 $(info Statically linking '$(ldobj:-l%=lib%)', linker '$($($2_C)_LD)' for compiler '$($2_C)' cannot link this lib.)
155 $(if $($(ldlibname)_INIT),,$(call LANG_LIB_INIT,$2,$(ldlibname),$1))
156 $(foreach deplib,$($(ldlibname)_DEPS) $(ldlibname),
157 $(eval DRIVER_LDINFO += $(LIB_DIR)/$(deplib).$($2_AROBJ))
158 $(eval DRIVER_LDINFO_D += $(LIB_DIR)/.$($2_DBG)/$(deplib).$($2_AROBJ)))
159 ),
160 $(if $(findstring $(ldobj),$(MODULES)),
161 $(eval DRIVER_LDINFO += $(SRC_DIR)/$(ldobj).$($2_AROBJ))
162 $(eval DRIVER_LDINFO_D += $(SRC_DIR)/.$($2_DBG)/$(ldobj).$($2_AROBJ)),
163 $(info Resolving static dependencies for '$(ldobj:%=lib%)'.)
164 $(if $($(ldobj)_INIT),,$(call LANG_LIB_INIT,$2,$(ldobj),$1))
165 $(foreach deplib,$($(ldobj)_DEPS) $(ldobj),
166 $(eval DRIVER_LDINFO += $(LIB_DIR)/$(deplib).$($2_AROBJ))
167 $(eval DRIVER_LDINFO_D += $(LIB_DIR)/.$($2_DBG)/$(deplib).$($2_AROBJ)))
168 ))
169 )
170
171 # Directory setup
172 $(eval MAKE_DIRS += $(dir $(DRIVER_TARG)))
173 $(if $($2_DBG),
174 $(eval MAKE_DIRS += $(dir $(DRIVER_TARG_D))))
175
176 # Add the driver target to this language's targets for cleaning
177 $(eval SCRUB_TARGETS += $(DRIVER_TARG) $(DRIVER_TARG_D))
178 $(DRIVER_TARG): $(filter-out -l%,$(DRIVER_LDINFO)) | $(dir $(DRIVER_TARG))
179 $($2_C) $($2_FLAGS) $(DRIVER_LDINFO) -o $$@
180 # Output a rule for building with debug flags
181 $(eval MAKE_DIRS += $(DRIVER_TARG_DIR).$($2_DBG)/)
182 $(DRIVER_TARG_D): $(filter-out -l%,$(DRIVER_LDINFO_D)) | $(dir $(DRIVER_TARG_D))
183 $($2_C) $($2_FLAGS) $(DRIVER_LDINFO_D) -o $$@
184
185 #/SRC_LANG_DRVRULE###############################################################
186 endef
187
188 #MODULE_ARCRULE##################################################################
189 # generate rule for turning an entire module's collection of binary objects into
190 # a single locally-linked (no external -L libs) object (for simplified linking
191 # modules as static libs).#######################################################
192 define MODULE_ARCRULE =
193 $(eval ARCDEPS := $(filter $(SRC_DIR)/$1/%.$(c_OBJ),$(foreach lang,$(LANGS),$($(lang)_MOD_TRG))))\
194 $(eval MAKE_TARGETS+= $(SRC_DIR)/$1.$(c_AROBJ))\
195
196 $(SRC_DIR)/$1.$(c_AROBJ): $(ARCDEPS)
197 $(c_AR) cr $$@ $$^
198 $(if $(c_DBG),
199 $(eval undefine DBGARCDEPS)
200 $(foreach arcdep,$(ARCDEPS),$(eval DBGARCDEPS += $(dir $(arcdep)).$(c_DBG)/$(notdir $(arcdep))))
201 $(eval MAKE_TARGETS+= .$(c_DBG)/$1.$(c_AROBJ))\
202
203 $(SRC_DIR)/.$(c_DBG)/$1.$(c_AROBJ): $(DBGARCDEPS) | .$(c_DBG)/
204 $(c_AR) cr $$@ $$^
205 )
206 #/MODULE_ARCRULE#################################################################
207 endef
208
209 # LANG_LIB_PARENT_BUILDRULE######################################################
210 # define rules for creating unknown libraries in the local build environment for
211 # either binary or bytecode representation given a library name and, optionally,
212 # a parent lib that included it for error reporting #############################
213 define LANG_LIB_PARENT_BUILDRULE =
214 $(eval CONF_FLAG := --prefix=$(abspath $(LIB_DIR)).trash)
215 $(eval CONF_FLAG += --includedir=$(abspath $(LIBINC_DIR)))
216 # Setup installation rule steps for this lib
217 $(eval
218 BUILDSTEPS := $(if $(AUTOGEN),$(AUTOGEN) && )
219 BUILDSTEPS += $(if $(CONFIGURE),$(CONFIGURE) $(CONF_FLAG) --libdir=$(abspath $(LIB_DIR)) && )
220 $(if $(MKCMD),\
221 BUILDSTEPS += $(MKCMD),
222 $(error $2.mk requires a valid MKCMD definition))
223 $(if $(MKINSTALL),\
224 INSTALLCMD := $(MKINSTALL),\
225 $(error $2.mk requires a valid MKINSTALL definition))
226 CLEANCMD := $(MKCLEAN)
227 )
228 # Construct the download method, or error if there isn't a valid one
229 $(if $(GITADDR),$(eval LIBDL := git clone $(GITADDR) $2),\
230 $(if $(HGADDR),$(eval LIBDL := hg clone $(HGADDR) $2),\
231 $(if $(CVSADDR),\
232 $(eval LIBDL := export CVSROOT=$(CVSADDR))\
233 $(eval LIBDL += && echo '$(CVSPASS)' > ~/.cvspass)\
234 $(eval LIBDL += && cvs $($2_CVSGET))
235 $(eval LIBDL += && $(if $(CVSPASS_BAK),echo $(CVSPASS_BAK) > ~/.cvspass,rm ~/.cvspass)),\
236 $(if $(WEBADDR),$(eval LIBDL := wget -O $(WEBTARG) $(WEBADDR)),\
237 $(eval $(error No way to download $2 needed by $3 for $1 language ))))))
238 # '$2' Download Rule
239 $(LIBDL_DIR)/$2:
240 mkdir -p $$@
241 cd $(LIBDL_DIR) && $(LIBDL) $(if $(WEBINIT),&& $(WEBINIT))
242 # '$2' Make and install rule, and ensure it isn't marked "clean"
243 $(LIB_DIR)/lib$2.$($1_AROBJ): $(LIBDEPS:%=$(LIB_DIR)/lib%.$($1_AROBJ)) | $(LIBDL_DIR)/$2
244 @mkdir -p $(LIB_DIR)
245 cd $(LIBDL_DIR)/$2 && export LD_RUN_PATH=$(LIBLDPATH) && $(BUILDSTEPS)
246 cd $(LIBDL_DIR)/$2 && $(INSTALLCMD)
247 @rm -f $(LIBDL_DIR)/$2.clean
248
249 # '$2' Rule for building under debug mode
250 $(if $($1_DBG),\
251 $(eval LIBDBG_DIR := $(LIB_DIR)/.$($1_DBG))\
252 $(eval $(if $(findstring $(LIBDBG_DIR),$(MAKE_DIRS)),,MAKE_DIRS += $(LIBDBG_DIR)))\
253 $(eval LIBDBG_TARG := $(LIBDBG_DIR)/lib$2.$($1_AROBJ))\
254 $(eval LIBDBG_DEPS := $(LIBDEPS:%=$(LIB_DIR)/.$($1_DBG)/lib%.$($1_AROBJ)))\
255 $(eval DBGBUILDSTEPS := $(if $(AUTOGEN),$(if $(AUTOGENDBG),$(AUTOGENDBG),$(AUTOGEN)) && ))\
256 $(eval DBGBUILDSTEPS += $(if $(CONFIGURE),$(if $(CONFIGUREDBG),$(CONFIGUREDBG),$(CONFIGURE)) $(CONF_FLAG) --libdir=$(abspath $(LIB_DIR))/.$($1_DBG)))\
257 $(eval DBGBUILDSTEPS += $(if $(MKDBGCMD),$(MKDBGCDM),$(MKCMD)))\
258
259 # '$2' Make and install rule for debugging
260 $(LIBDBG_TARG): $(LIBDBG_DEPS) | $(LIBDL_DIR)
261 @mkdir -p $(LIBDBG_DIR)
262 cd $(LIBDL_DIR)/$2 && export LD_RUN_PATH=$(LIBLDPATH:$(LIB_DIR)%=$(LIBDBG_DIR)) && $(DBGBUILDSTEPS)
263 cd $(LIBDL_DIR)/$2 && $(INSTALLCMD)
264 @rm -f $(LIBDL_DIR)/$2.clean
265 )
266
267 # '$2' Clean rule - drop a marker in the directory so we don't bother cleaning
268 # things that are clean... by default there is no real way of tracking this in a
269 # makefile
270 clean_$2:
271 $$(if $$(wildcard $(LIBDL_DIR)/$2),$$(if $$(wildcard $(LIBDL_DIR)/$2.clean),,\
272 cd $(LIBDL_DIR)/$2 && $(CLEANCMD) && touch $(abspath $(LIBDL_DIR))/$2.clean))
273
274 #/LANG_LIB_PARENT_BUILDRULE######################################################
275 endef
276
277
278 #LANG_LIB_INIT###################################################################
279 # For every library in this language, we need to determine how, and if, to link
280 # its data. This could potentially be done recursively as libraries have
281 # dependencies upon each other. We call a recursive macro here to expand out
282 # all the libs for this language, and then flatten the tree by removing
283 # duplicates with shell commands. We can't use make's 'sort' function because
284 # we actually care about the ordering so that interdependent libraries can link
285 # back up the tree ##############################################################
286 define LANG_LIB_INIT =
287 # Initialize per-library data, then import data from an accompanying file that
288 # can overwrite these vars
289 $(eval
290 # Implicit defaults for lib.mk files
291 AUTOGEN := ./autogen.sh
292 AUTOGENDBG := ./autogen.sh --enable-debug
293 CONFIGURE := ./configure
294 MKCMD := make -k
295 MKINSTALL := make -k install
296 MKCLEAN := make clean
297 MKDBGCMD := make -k
298 LINK_ORDER :=
299 LIBLANGS := c cpp go
300 LIBLDPATH := $(if $($($1_C)_LD),$(if $(LD_LIBRARY_PATH),$(LD_LIBRARY_PATH):,/usr/lib:)$(abspath $(LIB_DIR)))
301 # One of these must be defined in the .mk file imported
302 $(foreach var, GITADDR WEBADDR HGADDR CVSADDR,\
303 $(eval undefine $(var)))
304 # Other, optional, variables to clear
305 $(foreach var, WEBTARG WEBINIT CVSGET CVSPASS CONFIGUREDBG,
306 $(eval undefine $(var)))
307 )
308 # If there is a .mk file for this lib, import it. Otherwise, inform user of
309 # error
310 $(if $(wildcard $(CONF_DIR)/$2.mk),$(eval $(file <$(CONF_DIR)/$2.mk)),\
311 $(error Expected $(CONF_DIR)/$2.mk for lib$2))
312
313 # Add dependencies we found (potentially recursively, ignore repeats until later
314 # so we can preserve ordering information for interdependency build ordering)
315 $(eval undefine $2_LDINFO)
316 $(foreach ldobj,$(LINK_ORDER),\
317 $(eval $2_LDINFO +=
318 )
319 $(if $(LINK_ORDER),\
320 $(eval $1_LIBS += $(LIBDEPS))\
321 $(if $3,$(eval $3_DEPS += $(LIBDEPS)))\
322 $(eval $2_DEPS += $(LIBDEPS))\
323 )
324 # languages that can link this library (typically any lang that shares the
325 # object format (ELF by default, but this is compiler-dependent (e.g. emcc uses
326 # llvm bitcode, which is just an intermediary representation of data that can
327 # link to anything else statically, or as an archive)))
328 $(if $(findstring $1,$(LIBLANGS)),,\
329 $(error $2.mk must specifically set LIBLANGS := $1 if it is compatible with $1))
330 # Mark this lib as available for all its other compatible languages. This list
331 # is assumed to be sorted later, so we will ignore repeats for speed
332 $(foreach lang,$(LIBLANGS),\
333 $(if $(findstring $2,$($(lang)_LIBS)),,\
334 $(eval $(lang)_LIBS += $2)))
335 # Generate a build rule for this lib, unless it's already built
336 $(if $(findstring $2,$(BUILTLIBS)),,\
337 $(eval $(call LANG_LIB_PARENT_BUILDRULE,$1,$2,$3))\
338 $(eval BUILTLIBS += $2))
339 # Recurse this function for every libdep encountered
340 $(foreach libdep,$(LIBDEPS),\
341 $(call LANG_LIB_INIT,$1,$(libdep),$2))
342 $(eval $2_DEPS := $(shell echo "$($2_DEPS)" | $(call AWK_REVERSE_SQUASH)))
343 $(eval $2_INIT := t)
344 #/LANG_LIB_INIT#################################################################
345 endef
346
347 # Initialize data for supported lanaguages #####################################
348 define LANG_INIT =
349 $(eval
350 $1_OBJ := $($($1_C)_OBJ)
351 $1_OUT := $($($1_C)_OUT)
352 $1_AROBJ := $($($1_C)_AROBJ)
353 $1_SOURCES := $(shell find $(SRC_DIR) -name "*.$1" -not -name ".*")
354 $1_DBG := $($($1_C)_DBG)
355 $1_AR := $($($1_C)_AR)
356 )
357 # Find save language-specific driver and module sources and targets
358 $(eval $1_DRV_SRC := $(filter $(DRIVER_DIR)/%,$($1_SOURCES)))
359 $(eval $1_DRV_TRG := $(patsubst $(SRC_DIR)/%.$1,$(ROOT_DIR)/%$($1_OUT),$($1_DRV_SRC)))
360 $(eval $1_MOD_SRC := $(filter-out $(DRIVER_DIR)/%,$($1_SOURCES)))
361 $(eval $1_MOD_TRG := $(addsuffix .$($1_OBJ),$(basename $($1_MOD_SRC))))
362 # Add those sources and targets to a language-irreverant var
363 $(eval
364 DRV_SRC += $($1_DRV_SRC)
365 DRV_TRG += $($1_DRV_TRG)
366 MOD_SRC += $($1_MOD_SRC)
367 MOD_TRG += $($1_MOD_TRG)
368 )\
369 # First, initialize language-module, module, and language relative data. Then,
370 # filter out each source file from the module and generate Dependency Rules and
371 # Module Object Rules for each of them.
372 $(foreach module,$(MODULES),
373 # Evaluate the module sources for this language
374 $(eval $(module)_$1_SRC := $(filter $(SRC_DIR)/$(module)/%,$($1_MOD_SRC)))
375 # Evaluate module targets for this language
376 $(eval $(module)_$1_TRG := $($(module)_$1_SRC:%.$1=%.$($1_OBJ)))
377 # Add these language-specific sources and targets to the module's src/targs
378 $(eval
379 $(module)_SRC += $($(module)_$1_SRC)
380 $(module)_TRG += $($(module)_$1_TRG)
381 )
382 # For every source file, create a build rule for it for our language
383 $(foreach src,$(filter $(SRC_DIR)/$(module)/%,$($1_MOD_SRC)),\
384 $(eval $(call SRC_LANG_RULE,$(src),$1))\
385 ))
386 #/LANG_INIT#####################################################################
387 endef
388
389 # Create a phony target and rule for the specified source driver
390 define DRVSRC_DRIVERPHONY =
391 $(eval PH_TARG := $(basename $(notdir $1)))
392 $(eval PH_TARGS += $(PH_TARG))
393 $(eval PH_LANG := $(lastword $(subst ., ,$1)))
394 $(eval RL_TARG := $(basename $(subst $(SRC_DIR),$(ROOT_DIR),$1))$($(PH_LANG)_OUT))
395 .PHONY: $(PH_TARG) $(PH_TARG:%=%-d)
396 $(PH_TARG): $(RL_TARG)
397 @echo Built [$$@] at ./$$<
398 $(PH_TARG:%=%-d): $(RL_TARG:%=%-d)
399 @echo Build [$$@] with debugging information at ./$$<
400 #/SRC_SIMLIST_PHONYRULE ########################################################
401 endef