Rules for the Downstream Target
We now have all the pieces in place for implementing our downstream
target recipe. As mentioned earlier, this technique requires a two-pass
make operation. A new variable PREREQS_BUILT
is used to define which pass is being performed. Initially it will be undefined, which causes the ‘ifneq
‘ test to succeed, and we include the rules to generate the intermediate prereqfile1
file:
ifneq ($(PREREQS_BUILT),1)
$(eval $(call gen_file_if_different,grpA,typeX,prereqfile1,GENPROGRAM))
all : grpA_typeX_FILEGEN
$(MAKE) --no-print-directory -f $(THIS_MAKEFILE) \
PREREQS_BUILT=1 $(MAKECMDGOALS)
else
all : prereqfile1
@echo "Must have generated the dependent file!"
@echo "Executing recipe for $@"
touch $@
endif
During the initial pass, the downstream target (‘all
‘ in this example) lists our function-defined pseudo-target ‘grpA_typeX_FILEGEN
‘ as its prerequisite, instead of prereqfile1
. If prereqfile1
needs to be updated, it will be, by the function-generated rules.
Otherwise it will be left untouched. Then a recursive Make is executed
(the second pass) with PREREQS_BUILT=1
defined. On that second pass, the ‘ifneq
‘ test will fail, causing the ‘else
‘
portion to be used. This portion contains what normally would be the
recipe for the downstream target, had we not introduced the dynamic
generation capability.
Finally, you’ll see that we explicitly name the makefile in the
recursive call during pass one. This is because Make does not pass this
along by default. If your makefile is named anything besides “Makefile
“,
the recursive invocation will fail. The name is not directly
available; instead, we have to extract it using the following statement,
located prior to any include statements in the makefile:
THIS_MAKEFILE := $(lastword $(MAKEFILE_LIST))
In Conclusion
Using Make to build complex systems, as opposed to compiled software programs, is well within reach with a little persistence and cleverness. The rich feature set available with Make allows many higher level functions to be created that enable very flexible use models. In this article, we’ve described a technique to enable a chain of targets to be rebuilt dynamically from any intermediate point, from the command line. We hope you gained some valuable insights here that will accelerate your successful use of Make in challenging build environments. Please contact us with questions or comments. Take a look at our products and services – we can help you create or fine tune your build framework.