在makefile中重新定义变量的条件语句?

4

我在我的makefile中有一个变量,我想要将其unset或重新定义,这样目标abc就可以在各自的makefile中使用正确的MY_VARIABLE值(或者根本不使用)。

如果我运行以下命令make foo

export MY_VARIABLE := 'false'
foo: prep_foo dist
prep_foo:
    $(shell export MY_VARIABLE='true')
    echo ${MY_VARIABLE}
dist: a b c
a: 
    make -C a/src
b: 
    make -C b/src
c: 
    make -C c/src

我收到了这个输出:
export MY_VARIABLE='true'
echo 'false'
false
...

如果我使用以下makefile运行make foo
export MY_VARIABLE := 'false'
foo: prep_foo dist
prep_foo:
    $(shell unset MY_VARIABLE)
    echo ${MY_VARIABLE}
dist: a b c
a: 
    make -C a/src
b: 
    make -C b/src
c: 
    make -C c/src

我得到以下输出:
make: unset: No such file or directory
echo 'false'
false
...

当指定目标(比如在本例中的foo)时,我该如何取消设置或重新定义MY_VARIABLE

编辑

以下是我想要避免的情况:

dist: a b c 
foo: a_foo b_foo c_foo
a:
    make -C a/src
...
a_foo
    make -C a_foo/src

我希望在特定的变量中,a目标使用不同的值,以便在该目标的makefile中处理编译时采用不同的方式。
此外,看起来我无法在目标内部使用exportunset变量。例如:
dist: a b c 
foo: a_foo b_foo c_foo
a:
    make -C a/src
...
a_foo:
    export MY_VARIABLE='true'; make -C a/src

如果我尝试这样做,我会在export MY_VARIABLE='true'行上得到类似以下错误的内容(如果我尝试使用unset同样如此):

Makefile:16: *** unterminated variable reference.  Stop.

这有助于澄清我想做什么吗?

编辑2

我尝试了一个目标,它touch一个文件并尝试运行子目标的makefile(该文件检查文件是否存在):

foo: prep_foo
prep_foo:
    touch a/src/.foo
    make -C a/src

当我尝试通过 make foo 运行时,我遇到了以下错误:

Makefile:14: *** commands commence before first target.  Stop.

如果我从`prep_foo`中删除`make`语句,那么我就可以触摸文件而不会收到错误消息,但是我不能触发制作`a`目标,所以这似乎没有帮助。
以下内容会产生相同的“在第一个目标之前开始命令”错误消息:
foo: prep_foo a
prep_foo:
    touch a/src/.foo

有没有使用“touch”将状态传递给子目标的示例?

不同目标中的命令互不影响,甚至无法保证目标的顺序(例如,在您的情况下,“make -j”将尝试同时运行所有目标)。您无法使“a”,“b”或“c”根据您是尝试“make foo”还是只是“make dist”而有所不同。 - Neil
我认为这与我的问题无关。我只想让所有子目标在调用父目标时有条件地使用特定变量的不同值。我并不真正关心子目标在父目标内的评估顺序。这有助于澄清问题吗? - Alex Reynolds
2个回答

1

在Makefile中,目标之间的常见通信方式是通过文件。只需在一个目标中touch一个文件,然后在另一个目标中检查它。这能帮助您解决问题吗?


不,我会编辑我的问题并附上由该方法导致的错误信息。 - Alex Reynolds
@AlexReynolds:我无法复制您的问题。第14行是哪一行? - choroba
为了简洁起见,我的 makefile 与我发布的不同。它相当长。你有时间发布一个使用 touch 的工作示例吗? - Alex Reynolds

0

不要忘记,make 中的每个 shell 执行都在新进程中完成。试图在此类配方中操纵环境变量并没有太多意义——您在任何给定行中修改的环境在该 shell 死亡后就消失了,在执行下一行之前。

您可以像这样完成工作:

a:
    unset MY_VARIABLE; $MAKE -C a/src

或者

a:
    $MAKE MY_VARIABLE=foo -C a/src

我正在寻找一种干净的方法来设置一个目标中的变量,然后将其传递给其他目标。如何在不设置自定义目标的情况下实现这一点(也就是说,如何避免编写处理每种情况的aa_foobb_foo等目标)? - Alex Reynolds
你的建议似乎不起作用。如果我在prep_foo中放置unset MY_VARIABLE; echo ${MY_VARIABLE},当运行make foo时,我仍然会得到旧值的MY_VARIABLE - Alex Reynolds
哦,该死。我知道我应该先进行测试,但看起来似乎很清楚...你能在问题描述中添加关于aa_foo目标的一两句话吗?然后我会删除这个回答。那似乎太有用了,不能丢失 - 虽然我不完全明白为什么您会有两种构建a的不同方式:通过foo和不通过foo。(您能解释一下吗?) - sarnold

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接