如何在Makefile中设置子进程的环境变量


134

我想更改此Makefile:

SHELL := /bin/bash
PATH  := node_modules/.bin:$(PATH)

boot:
    @supervisor         \
      --harmony         \
      --watch etc,lib       \
      --extensions js,json      \
      --no-restart-on error     \
        lib

test:
    NODE_ENV=test mocha         \
      --harmony             \
      --reporter spec       \
        test

clean:
    @rm -rf node_modules

.PHONY: test clean

至:

SHELL := /bin/bash
PATH  := node_modules/.bin:$(PATH)

boot:
    @supervisor         \
      --harmony         \
      --watch etc,lib       \
      --extensions js,json      \
      --no-restart-on error     \
        lib

test: NODE_ENV=test
test:
    mocha                   \
      --harmony             \
      --reporter spec       \
        test

clean:
    @rm -rf node_modules

.PHONY: test clean

不幸的是,第二个命令不起作用(节点进程仍然使用default运行NODE_ENV

我错过了什么?

Answers:


153

默认情况下,make变量不会导出到进程make invokes的环境中。但是,您可以使用make export强制他们这样做。更改:

test: NODE_ENV = test

对此:

test: export NODE_ENV = test

(假设您有足够现代的GNU make> = 3.77)。


3
我有GNU make 3.81,并all: <\n\t>export PROJ_ROOT=$(CURDIR)<\n\t>echo $(PROJ_ROOT)<\n>为第一行输出正确的扩展,但仅对echo第二行输出。PROJ_ROOT运行make后未设置。周围的空格=为导出提供了“错误的变量名”。将第一行作为示例中的前提条件,可以使“命令在第一个目标之前开始”
Gauthier 2014年

8
@Gauthier是的。那不是我写的 您在后面添加了<\ n \ t> all:,但在我的示例中却没有。我的示例旨在以书面形式使用:它定义了特定于目标的变量,而不是在配方中添加命令。同样,您不能同时在目标上使用配方和目标特定的变量:您必须两次写入目标。请参阅问题中的第二个示例,并提出一个新问题,如果这不能帮助解释它:注释中没有足够的空间或格式。
MadScientist 2014年

1
多个变量呢?
霍尔姆斯'18

1
很好,但是您将其添加到了目标的开头。仅在目标上下文中列出它们是行不通的?因为它对我不起作用
霍姆斯(Homs)

2
在GNU make 3.77中添加了特定于目标的变量。从GNU make 3.81开始,它们可以导出。参见git.savannah.gnu.org/cgit/make.git/tree/NEWS
MadScientist

79

正如MadScientist指出的那样,您可以使用以下命令导出单个变量:

export MY_VAR = foo  # Available for all targets

或导出特定目标的变量(特定于目标的变量):

my-target: export MY_VAR_1 = foo
my-target: export MY_VAR_2 = bar
my-target: export MY_VAR_3 = baz

my-target: dependency_1 dependency_2
  echo do something

您还可以指定.EXPORT_ALL_VARIABLES目标(猜对了!)导出所有内容!!:

.EXPORT_ALL_VARIABLES:

MY_VAR_1 = foo
MY_VAR_2 = bar
MY_VAR_3 = baz

test:
  @echo $$MY_VAR_1 $$MY_VAR_2 $$MY_VAR_3

请参阅.EXPORT_ALL_VARIABLES


2
奇怪的是,我之前进行了测试,证明它可以正常工作..(不知道为什么现在..)我可以返回并删除我认为的评论
。– AnthonyC

3
@AnthonyC它之所以有效,是因为有两个MY_VARs:一个是作为makefile变量访问,${MY_VAR}而另一个是bash导出变量,访问为$$MY_VAR
Sergei

有用。但是找不到仅导出一组变量的方法。
埃里克·陈

15

我只需要本地环境变量来调用我的测试命令,下面的示例在bash shell中设置多个环境变量,并在中转义美元符号make

SHELL := /bin/bash

.PHONY: test tests
test tests:
    PATH=./node_modules/.bin/:$$PATH \
    JSCOVERAGE=1 \
    nodeunit tests/

6
请修改您的答案以包含一些解释。纯代码的答案对教育未来的SO读者几乎没有作用。您的回答在质量不高的审核队列中。
mickmackusa

ThorSummoner,此解决方案不如上述方法灵活。例如,可能希望有一个规则来调用命令,然后希望有几个其他规则来通过设置环境变量来修改该行为。考虑:测试:cmd性能:导出PERF =“ yes”性能:测试如果'cmd'很复杂(通常很复杂),则此方法易于维护。您在cmd规则中设置环境变量的方法使此操作更加困难。
基思·汉兰

1

我将重新编写原始目标测试,注意在启动子应用程序中将所需的变量定义在相同的子过程中:

test:
    ( NODE_ENV=test mocha --harmony --reporter spec test )
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.