make,变量取决于目标

use*_*637 2 gnu makefile

生成文件

abc:
TEST=$@ /* TEST=abc */

def:
TEST=$@ /* TEST=def */

xxx:
        @echo $(TEST)
Run Code Online (Sandbox Code Playgroud)

如果我运行make abc xxx,我期望输出abc

如果我运行make def xxx,我期望输出def

但事实并非如此。似乎make不允许我在目标中定义变量。我的问题是如何定义一个变量及其值(取决于构建的目标)?

lai*_*dir 5

使用 GNU Make,您可以复制 Makefile 的预期结果,如下所示:

echo.%:
    @echo $*
Run Code Online (Sandbox Code Playgroud)

或者简单地:

%:
    @echo $*
Run Code Online (Sandbox Code Playgroud)

这些将允许您分别指定make echo.abcmake abc,并将其视为abc输出。

这一切都很好,但听起来您会对特定于目标的变量更感兴趣。如果变量值依赖于目标名称,但不是目标名称的子字符串,则可以执行以下操作:

%:
    @echo $(TEST)

abc: TEST=xyzzy

def: TEST=plugh
Run Code Online (Sandbox Code Playgroud)

这允许您指定make abc并查看xyzzy输出。


如果您想超越这一点,以便目标的行为根据命令行上指定的其他目标而变化,我们有两个选择:要么让.PHONY目标更新主要目标使用的文件,要么进行一些处理变量的MAKECMDGOALS

选项1:

xxx: xxx.temp
    @cat xxx.temp
    @rm xxx.temp

abc def:
    @echo $@ > xxx.temp

.PHONY: xxx abc def
Run Code Online (Sandbox Code Playgroud)

这依赖于命令行目标按顺序处理的事实(如果您指定了多个目标,则 make 按照您命名的顺序依次处理每个目标。 -GNU Make 手册,第 9.2 节),因此您必须指定make abc xxx和不是make xxx abc

选项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
Run Code Online (Sandbox Code Playgroud)

抑制@echo -n > /dev/nullmake: Nothing to be done for 'abc'.消息。这对我来说似乎更笨拙,如果您可以容忍临时文件,我会推荐选项 1。