On 2024-07-24 04:34, Paul Smith wrote: > On Wed, 2024-07-24 at 18:44 +0900, Masahiro Yamada wrote: >> ifdef GENERATE_B_AS_WELL >> # When this flag is set, we want to generate %.b as well. >> # I know I cannot update MAKECMDGOALS... >> MAKECMDGOALS := $(patsubst %.a, %.b, $(MAKECMDGOALS)) >> endif >> >> >> %.a: >> touch >> >> %.b: %.a >> cp $< $@ > >> Then, I hope the following would happen. >> >> >> $ make x.a >> -> create x.a >> >> >> $ make x.a GENERATE_B_AS_WELL=1 >> -> create x.b as well as x.a > > > Your example output cannot be generated by this makefile, so it's > confusing as to what exactly you want to happen. > > However, doesn't something like this work: > > a_prereq = > ifdef GENERATE_B_AS_WELL > a_prereq = %.b > endif > > %a: $(a_prereq) > touch $@ > > %.b: %.a > cp $< $@
Suppose that, if the flag is set, we would like a certain target to be built regardless of what targets have been requested on the command line. What we can do is: 1. Determine the name of a target that /is/ being built. 2. Make the extra target a prerequisite of that target. For (1) we have two cases: if MAKECMDGOALS is empty, then we have to know what the default target is and use that. Otherwise we can take the $(firstword ...) of MAKECMDGOALS. Something like: ifdef GENERATE_B_AS_WELL ifeq ($(MAKECMDGOALS),) all : btarget else $(firstword $(MAKECMDGOALS)) : btarget endif endif .PHONY: all alpha beta gamma btarget all: alpha beta gamma alpha: @echo $@ target beta: @echo $@ target gamma: @echo $@ target btarget: @echo $@ target Default target without flag: $ make alpha target beta target gamma target alpha and beta targets without flag: $ make alpha alpha target $ make beta beta target default with flag: btarget is made (first) $ make GENERATE_B_AS_WELL=y btarget target alpha target beta target gamma target alpha target with flag: btarget made first, as dependency of alpha. $ make GENERATE_B_AS_WELL=y alpha btarget target alpha target beta target, same: $ make GENERATE_B_AS_WELL=y beta btarget target beta target What is not obvious how to do is to insert the beta target into the tree such that it is built last. For that we would have to make it a top-level goal, like Masahiro ideally wants. Of course we could always have a fragment which is conditionally added to all the necessary targets: define B_BUILD_STEPS # conditionally defined based on flag ... endef B_BUILD_STEPS contain a hand coded check whether B needs to be updated, not relying on make (E.g. using shell [ "$x" -nt "$y" ]. We add $(call B_BUILD_STEPS) into all the top-level targets. alpha: @echo $@ target $(call B_BUILD_STEPS)