在makefile中设置环境变量

12

我有一个像这样的Makefile:

setup:
  setenv var1 "$(var1)"; \
  setenv var2 "$(var2)";

task1: setup
  source task1.csh

task2: setup
  source task2.csh

我使用以下命令调用makefile:

make var1=value1 var2=value2 task1

我希望环境变量var1var2task1.cshtask2.csh中都可见,但是除非我更改Makefile为:

task1:
  setenv var1 "$(var1)"; \
  setenv var2 "$(var2)"; \
  source task1.csh

task2:
  setenv var1 "$(var1)"; \
  setenv var2 "$(var2)"; \
  source task2.csh

为什么第一种方法不起作用,我该如何修复它?


5
我应该指出,你永远不应该使用csh编写makefile。csh在与make一起使用时太容易出错了。实际上,即使在脚本编写中,csh也是一个太容易出错的shell,但这是另一个讨论话题。 - MadScientist
1
@MadScientist:我实际上正在使用tcsh。 仍然不建议吗? - Ari
3
不建议使用Csh及其所有变体,包括tcsh。如果您想要交互式shell,可以使用它们(个人而言,我不使用它们,因为现代的Bourne shell(如bash)具有任何csh/衍生产品的交互功能以及更多,并且在我的交互式shell中编写了许多小型一行脚本,但无论如何)。但是,Csh在使用make时基本上是有缺陷的;请参见http://lists.gnu.org/archive/html/bug-make/2010-12/msg00017.html 获取更多详细信息有关Csh脚本编写的内容,请参见http://www-uxsup.csx.cam.ac.uk/misc/csh.html。 - MadScientist
可能是如何在Makefile中设置环境变量的重复问题。 - Eugen Konkov
1个回答

18

这样做不起作用,因为makefile规则中的每一行都在自己独立的shell实例中运行。

根据GNU make手册:

当执行配方以更新目标时,会为配方的每一行调用新的子shell进行执行,除非.ONESHELL特殊目标正在生效(请参阅使用一个Shell)。 (实际上,make可能会采取不影响结果的快捷方式。)

请注意:这意味着设置shell变量和调用诸如cd等在每个进程本地设置环境的shell命令将不会影响配方中的后续行。如果要使用cd来影响下一条语句,请将两个语句放在单个配方行中。

所以你可以按照你列出的方法操作,或者你可以从make中导出变量,它们已经在子shell的环境中了。

export var1 = value1
export var1 = value2

任务1: 源 task1.csh

任务2: 源 task2.csh

另外,为什么你要引用这些脚本而不是直接运行它们 (./task1.sh)?

(我假设您已经在makefile中设置了SHELL = csh或类似的内容以使其正常工作.)


1
@Ari 如果你的变量已经被赋值,只需使用export var1,而无需进行赋值。 - Louis
@EtanReisner:C shell不支持在命令行上设置环境变量——它不像Bourne衍生的shell。 - Jonathan Leffler
@JonathanLeffler 根据我理解的make手册中提到的部分,当make在其命令行上读取一个变量(作为参数而不是Bourne shell预命令变量)时,它会自动导出该变量。如果makefile中有export,那么这应该适用于csh等shell。 - Etan Reisner
嗯...看起来GNU make确实这样做,而POSIX要求它。很久很久以前(几十年前),当我在编写make的变体时,我没有在我的研究中发现这种行为,这意味着我的研究不完整或者当时不支持设置环境。此外,我假设你是在考虑var=value make …符号而不是make var=value …符号 - 但那是一个错误。 - Jonathan Leffler
1
关于使用 .ONESHELL 指令需要记住的一件事情是 - 它只在 GNU make 3.82+ 中可用。例如,Ubuntu 12.04、CentOS 6.6 都带有 GNU make 3.81。 - tvar0g
显示剩余2条评论

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