Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>With GNU Make 3.82 it is possible to <strong><code>define</code></strong> <em>canned recipes</em> which – after being made parametric – might be used as templates for the double/triple objects' build specifications. The templates can be then instantiated with Make's unique <code>$(call var,par,...)</code> function and evaluated with the very special <code>$(eval code)</code>, available since version 3.8. This trick allows us to avoid a lot of boilerplate code and enables Makefile to automatically adapt to forthcoming project growth.</p> <p>While having all possible module-building rules available, we are one step away from the goal; this is a quite tricky step however. We need to rebuild each build's <em>prerequisites</em> to explicitly expose each inter-module dependency. It is done by replacing the single module objects with the special cases arising from the ambient neighbourhood (e.g., a superficial <code>mod_red.o mod_green.o</code> is substituted with an explicit <code>mod_red+G.o mod_green+R.o</code>). The substitution is handled by the <code>discover</code> macro anclosing each prerequisite list and driven by the <code>xdepend</code> global variable, which specifies the cross dependencies – in practice, only a few modules will depend on one another.</p> <pre><code># Cross dependency specification (dependent+dependency) xdepend := blue+red red+blue # Test for string equality and set membership equals = $(if $(subst $1,,$2),$(empty),true) exists = $(if $(filter $1,$2),true,$(empty)) # Extract of the first and second member of a dependency token pred = $(firstword $(subst +, ,$1)) succ = $(lastword $(subst +, ,$1)) # Rebuild prerequisites to expose modules' interdependencies discover = $(strip $(foreach mod,$(basename $1),\ $(subst $(space),,$(obj)/$(mod)\ $(foreach dep,$(xdepend),\ $(and\ $(call equals,$(call pred,$(dep)),$(mod)),\ $(call exists,$(call succ,$(dep)),$(basename $1)),\ $(lnk)$(call succ,$(dep))\ )\ ).o)\ )) # Create compilation rules for interdependent module objects define rule $(obj)/$1$(lnk)$2.o: $(src)/$1.c $(inc)/$1.h $(inc)/$2.h | $(obj) $(CC) $(CFLAGS) -include $(inc)/$2.h -c $(src)/$1.c -o $(obj)/$1$(lnk)$2.o endef $(foreach dep,$(xdepend),\ $(eval $(call rule,$(call pred,$(dep)),$(call succ,$(dep))))\ ) </code></pre> <p>Armed with the above definitions, we can now build our project in the following way:</p> <pre><code># Rules for Magenta Build and intermediate objects magenta: $(call discover, magenta.o mod_red.o mod_blue.o) $(CC) $(CFLAGS) $^ -o $@ $(LDFLAGS) $(obj)/%.o: $(src)/%.c $(inc)/%.h | $(obj) $(CC) $(CFLAGS) -c -o $@ $&lt; $(obj): mkdir $(obj) </code></pre> <p>For further clarification and the most recent knowledge – read <a href="http://www.gnu.org/software/make/manual/make.pdf" rel="nofollow">GNU Make Manual</a>.</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload