Reputation: 13
I have a command foo
that accepts a list of parameters. I want to alter the parameters I pass to foo
depending on the target I am building. I have tried appending to target-specific variables, but that doesn't quite do what I want...
So, for example take this Makefile (which doesn't work since foo is built by target1):
all: target1 target2
foo:
echo foo $(foo_args)
target1: foo_args += abc
target1: foo
echo Target1
target2: foo_args += def
target2: foo
echo Target2
.PHONY: foo target1 target2
What happens:
> make all
foo abc
target1
target2
> make target1
foo abc
target1
> make target2
foo def
target2
What I want:
> make all
foo abc def
target1
target2
> make target1
foo abc
target1
> make target2
foo def
target2
Makefile syntax can be specific to GNU make. I'd also like to keep the parallelism so that target1 and target2 can be built in parallel.
Upvotes: 1
Views: 815
Reputation: 704
Scalable variant of John's answer:
define add_target
foo_args_all += $2
foo_args_$(strip $1) := $2
$1: foo; @echo $$@
foo_targets += $1
endef
all:
$(eval $(call add_target, target1, abc))
$(eval $(call add_target, target2, def))
all: $(foo_targets)
foo:; @echo foo $(sort $(foreach g,$(or $(MAKECMDGOALS), all),$(foo_args_$g)))
.PHONY: all $(foo_targets)
Output:
$ make -f sample.gmk
foo abc def
target1
target2
$ make -f sample.gmk all
foo abc def
target1
target2
$ make -f sample.gmk target1
foo abc
target1
$ make -f sample.gmk target2
foo def
target2
$ make -f sample.gmk target2 target1
foo abc def
target2
target1
$ make -f sample.gmk target1 target2
foo abc def
target1
target2
Upvotes: 1
Reputation: 1825
The problem with making target-specific variables is that they are only available in the scope of that target. In particular, if you were building a target with multiple dependencies, you would only go down one dependency at a time, and foo_args
would only reflect the targets on the side of the tree you happen to be invoking foo
from.
Another solution might be to use something like the following at the top of your makefile:
foo_args_target1 := abc
foo_args_target2 := def
foo_args_all := abc def
foo_args := $(sort $(foreach goal,$(MAKECMDGOALS),$(foo_args_$(goal))))
$(info foo_args is $(foo_args))
This has the advantage that foo_args
is available globaly. This still has a scalability issue though -- if you were to create a new target all2 : target1 target2
, then you would have to add a foo_args_all2 := ...
into the makefile (you couldn't automatically detect that all2
was dependent on target1
or target2
, and update foo_args
automatically).
Upvotes: 0
Reputation: 21000
Your example is missing a number of details and there may be a better way of handing things (e.g. why are the targets PHONY
? How does foo
depend on target1
?), a complete example that shows exactly how the files are generated will get you a better answer.
That said, something like the following should work in this case
.PHONY: all foo target1 target2
all: foo_args += abc def
all: target1 target2
target1: foo_args += abc
target1: foo
@echo Target1
target2: foo_args += def
target2: foo
@echo Target2
foo:
@echo foo $(sort $(foo_args))
Upvotes: 0