【问题标题】:How to set child process' environment variable in Makefile如何在 Makefile 中设置子进程的环境变量
【发布时间】:2014-07-13 15:10:48
【问题描述】:

我想更改这个 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

不幸的是第二个不起作用(节点进程仍然使用默认的NODE_ENV运行。

我错过了什么?

【问题讨论】:

  • 您的Unfortunately 评论源于环境变量与Makefile 变量之间的误解。证明已设置环境变量的最佳方法是在make 将调用的另一个程序中查询此环境变量。只做echo $(BLAH) 只是评估Makefile 在Makefile 中的键/值机制。在python中可以print(os.getenv("MURDOC"))真正查询环境变量。

标签: shell makefile environment-variables target


【解决方案1】:

我会重写原始目标测试,注意所需的变量是在与要启动的应用程序相同的子进程中定义的:

test:
    ( NODE_ENV=test mocha --harmony --reporter spec test )

【讨论】:

    【解决方案2】:

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

    test: NODE_ENV = test
    

    到这里:

    test: export NODE_ENV = test
    

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

    【讨论】:

    • 我有 GNU make 3.81,all: <\n\t>export PROJ_ROOT=$(CURDIR)<\n\t>echo $(PROJ_ROOT)<\n> 为第一行输出正确的扩展,但只有echo 为第二行输出。运行 make 后未设置 PROJ_ROOT= 周围的空格为导出提供“错误的变量名”。将第一行作为您的示例中的先决条件给出“命令在第一个目标之前开始”
    • @Gauthier 当然是的。那不是我写的。您在all: 之后添加了一个 ,这不在我的示例中。我的示例旨在按原样使用:它定义了一个特定于目标的变量,NOT 将命令添加到配方中。此外,您不能同时在目标上使用配方和目标特定变量:您必须编写目标两次。请参阅问题中的第二个示例,如果这不能帮助解释它,请提出一个新问题:cmets 中没有足够的空间或格式。
    • 多个变量呢?
    • 没关系,但您已将其添加到目标头部。仅仅在目标上下文中列出它们是行不通的?因为它不适合我
    • 在 GNU make 3.77 中添加了特定于目标的变量。它们可以从 GNU make 3.81 开始导出。见git.savannah.gnu.org/cgit/make.git/tree/NEWS
    【解决方案3】:

    作为MadScientist pointed out,您可以导出单个变量:

    export MY_VAR = foo  # Available for all targets
    

    或导出特定目标的变量 (target-specific variables):

    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

    【讨论】:

    • 奇怪的是,我之前确实对其进行了测试,结果表明它有效..(现在不知道为什么..)我可以回去删除我猜的评论..
    • @AnthonyC 之所以有效,是因为有两个MY_VARs:一个是makefile变量,以${MY_VAR}访问,另一个是bash导出变量,以$$MY_VAR访问
    • 有用。但是找不到只导出一组变量的方法。
    • 注意如果变量已经存在于你的makefile中并且你只是想将它导出到另一个命令中,你可以使用export var ?=语法而不用分配一个新值
    【解决方案4】:

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

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

    【讨论】:

    • 请编辑您的答案以包含一些解释。仅代码的答案对教育未来的 SO 读者几乎没有作用。您的答案因质量低劣而在审核队列中。
    • ThorSummoner,这个解决方案不如上面的方法灵活。例如,一个人可能希望有一个用于调用命令的规则,然后是几个其他规则,这些规则通过设置环境变量来修改该行为。考虑: test: cmd perf: export PERF="yes" perf: test 如果 'cmd' 很复杂(通常很复杂),那么这种方法更容易维护。您在 cmd 规则中设置环境变量的方法使这变得更加困难。
    猜你喜欢
    • 2016-06-27
    • 2015-02-01
    • 2013-10-28
    • 1970-01-01
    • 2016-04-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多