Reputation: 323
Makefile
abc:
TEST=$@ /* TEST=abc */
def:
TEST=$@ /* TEST=def */
xxx:
@echo $(TEST)
If I run make abc xxx
, I
expect output abc
.
If I run make def xxx
, I
expect output def
.
But it doesn't work like that. It seems like make
won't let me define a variable in target. My question is how could I define a variable and its value which depend on which target is built?
Upvotes: 2
Views: 3669
Reputation: 1710
Using GNU Make, you can duplicate the intended result of your Makefile as follows:
echo.%:
@echo $*
or simply:
%:
@echo $*
These would allow you to specify make echo.abc
or make abc
, respectively, and see abc
as output.
That's all well and good, but it sounds like you would be more interested in target-specific variables. If the variable value is dependent on, but not a substring of, the target name, you can do something like this:
%:
@echo $(TEST)
abc: TEST=xyzzy
def: TEST=plugh
This allows you to specify make abc
and see xyzzy
as output.
If you want to go beyond this, so that the behavior of a target changes based on what other targets are specified on the command line, we have two options: either have .PHONY
targets that update a file used by your primary target, or do some processing of the MAKECMDGOALS
variable:
Option 1:
xxx: xxx.temp
@cat xxx.temp
@rm xxx.temp
abc def:
@echo $@ > xxx.temp
.PHONY: xxx abc def
This relies on the fact that the command line goals are processed in order (If you specify several goals, make processes each of them in turn, in the order you name them. -GNU Make Manual, section 9.2), so you must specify make abc xxx
and not make xxx abc
.
Option 2:
ifneq (,$(findstring abc,$(MAKECMDGOALS)))
VAR=abc
else ifneq (,$(findstring def,$(MAKECMDGOALS)))
VAR=def
endif
xxx:
@echo $(VAR)
abc def:
@echo -n > /dev/null
.PHONY: xxx abc def
The @echo -n > /dev/null
suppresses the make: Nothing to be done for 'abc'.
message. This seems much clumsier to me, and I would recommend Option 1 if you can tolerate the temp file.
Upvotes: 5