dan*_*ast 7 bash shell makefile environment-variables
我有一个bash shell脚本,我通常将其源码发送到我的shell中,定义了许多环境变量,这些变量不会被导出.我不想:
我想将相同的shell脚本源到makefile的环境中,以便我可以访问这些变量.这可能吗?我怎样才能做到这一点?理想情况下我会在makefile中执行:
source setup-env.sh
Run Code Online (Sandbox Code Playgroud)
没有sourcemakefile的命令,但可能是等价的东西?我可以使用任何特殊的黑客来模拟相同的效果吗?
根据评论中的其他问题,这里有一种方法可以有效地将整个环境标记为已导出:
for var in $(compgen -v); do export $var; done
Run Code Online (Sandbox Code Playgroud)
compgen -v根据bash手册,第8.7节"可编程完成内置",简单地输出所有变量名称.然后我们简单地遍历这个列表和export每个列表.
感谢/sf/answers/1143638121/ - compgen对我来说是新的.
我可以通过两种方式将其集成到您的make工作流程中:
只需编写一个源脚本来源setup-env.sh的shell脚本,如上所述导出所有变量,然后make自行调用.就像是:
#!/bin/bash
./source setup-env.sh
for var in $(compgen -v); do export $var; done
make $@
Run Code Online (Sandbox Code Playgroud)
可能是您不想要shell脚本包装器,并且想要出于任何原因直接调用make.您可以在一个Makefile中执行此操作,该文件以递归方式调用自身:
$(info MAKELEVEL=$(MAKELEVEL) myvar=$(myvar))
ifeq ($(MAKELEVEL), 0)
all:
bash -c "source ./setup-env.sh; \
for var in \$$(compgen -v); do export \$$var; done; \
$(MAKE) $@"
else
all: myprog
myprog:
echo "Recipe for myprog. myvar=$(myvar)"
endif
Run Code Online (Sandbox Code Playgroud)
此Makefile的输出是:
$ make
MAKELEVEL=0 myvar=
bash -c "source ./setup-env.sh; \
for var in \$(compgen -v); do export \$var; done; \
make all"
MAKELEVEL=1 myvar=Hello World
make[1]: Entering directory `/home/ubuntu/makesource'
echo "Recipe for myprog. myvar=Hello World"
Recipe for myprog. myvar=Hello World
make[1]: Leaving directory `/home/ubuntu/makesource'
$
Run Code Online (Sandbox Code Playgroud)
我们检查GNU Make内置变量MAKELEVEL以查看我们所处的递归级别.如果级别为0,那么我们递归调用所有目标的make,但首先源./setup-env.sh并导出所有变量.如果递归级别是其他任何东西,我们只是做普通的makefile,但是你看到你需要的变量现在可用.这由$(info )Makefile顶部的行突出显示,该行显示了递归级别以及myvar的值(或不是).
我们必须使用bash -c因为compgen严格来说是内置的bash,并且在Posix模式下不可用 - 即sh -c默认情况下make调用shell时.
第$一个all:食谱需要非常小心地逃脱.在$$逃脱$从被make扩大,而\$$逃脱的$从由隐正在扩大sh
有很多文献认为"递归制作被认为是有害的".例如http://aegis.sourceforge.net/auug97.pdf