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)