在Makefile中设置环境变量是否可行 - 以便在之后使用

19

我正在尝试在Makefile中设置环境变量,以便在make运行后,在同一shell中运行的另一个程序中可以使用该变量。

更新:根据经过评论确认,这是不可能的。

步骤:

  1. 运行make test并设置环境变量:export TEST_ENV_ONE=OneString
  2. 运行另一个程序,该程序可以读取TEST_ENV_ONE

尝试过以下方法:

无效:

test:
    export TEST_ENV_ONE=OneString
    $(shell export TEST_ENV_TWO=TwoString)

之后这是空的:

echo $TEST_ENV_ONE
echo $TEST_ENV_TWO
2个回答

22

你在上面使用的export TEST_ENV_ONE=OneString是在一个独立的shell中运行的。随后的命令会运行在其他shell实例中,因此它们不会继承环境变量TEST_ENV_ONE


你可以在makefile中使用顶层(即不在目标配方中的)export指令

export env_var := MyEnvVariable

.PHONY: all
all:
    echo env_var: $$env_var

这样,变量env_var会被导出到将执行配方的shell中。

如果您使用上述makefile运行make

$ make
echo env_var: $env_var
env_var: MyEnvVariable

从输出中可以看出,运行echo env_var: $env_var的Shell在其环境变量中有变量env_var


谢谢,你说得对。正如你所写的“...有变量...”,我的问题是我需要让env_var在另一个程序中可用 - 仍然在同一个shell /终端/ bash中,就像make一样。 - Chris G.
你的意思是它必须在执行“make”的终端中可用吗? - JFMR
是的,如果可能的话 - Chris G.
2
make 运行在该 shell 的子进程中,因此在该子进程中创建环境变量不会影响父进程的环境。 - JFMR
1
我建议您创建一个全新的问题,以更高层次的方式解释您的问题。这对我来说看起来像是一个XY问题。 - JFMR
@ChrisG。有办法实现你想要的功能。请看我的回答。 - Renaud Pacalet

11

如果您希望将环境变量从make子进程导出到调用make的父进程(即shell),则会遇到一些困难,因为正如ネロク所解释的那样,您无法直接将环境变量从子进程导出到其父进程。但是,如果您愿意像这样调用make:

eval "$(make -s)"

如果您想要实现这个功能,只需要在您的配方中使用export VARIABLE1=VALUE1; export VARIABLE2=VALUE2; ...命令即可。请注意:您还需要确保make在标准输入上不会输出其他内容。但是您可以使用标准错误输出代替。例如:

$ cat Makefile
export TEST_ENV_ONE := OneString

all:
    printf 'make variable TEST_ENV_ONE = %s\n' "$(TEST_ENV_ONE)" 1>&2
    printf 'in-recipe shell variable TEST_ENV_ONE = %s\n' "$$TEST_ENV_ONE" 1>&2
    printf 'export TEST_ENV_ONE="%s"\n' '$(TEST_ENV_ONE)'

$ unset TEST_ENV_ONE
$ printenv TEST_ENV_ONE
$ eval "$(make -s)"
make variable TEST_ENV_ONE = OneString
in-recipe shell variable TEST_ENV_ONE = OneString
$ printenv TEST_ENV_ONE
OneString

请注意,make 更多或更少地将环境变量视为 make 变量。来自 GNU make 手册:

在 make 中的变量可以来自运行 make 的环境。当 make 启动时, 它看到的每个环境变量都会转换为一个具有相同名称和值的 make 变量。 但是,在 makefile 中明确赋值或使用命令参数会覆盖环境变量。 (如果指定了“-e”标志,则环境中的值会覆盖 makefile 中的分配。 请参阅选项概述。但这不是推荐的做法。)

因此,除非您的变量的值是由 make 自身进行复杂计算得出的结果, 否则获得相同结果的更自然方法是在父 shell 中定义环境变量, 并在 Makefile 中直接使用它:

$ cat Makefile
all:
    printf 'make variable TEST_ENV_ONE = %s\n' "$(TEST_ENV_ONE)"
    printf 'in-recipe shell variable TEST_ENV_ONE = %s\n' "$$TEST_ENV_ONE"

$ export TEST_ENV_ONE=OneString
$ make -s
make variable TEST_ENV_ONE = OneString
in-recipe shell variable TEST_ENV_ONE = OneString
$ printenv TEST_ENV_ONE
OneString

1
eval "$(make)",带引号的话会减少出错的可能性。eval 不是特殊语法 -- 它的参数和其他任何东西一样都会受到单词拆分和通配符扩展的影响。 - Charles Duffy

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