我有一个bash shell脚本,我通常会将其输入shell,并定义了许多环境变量,这些变量是不导出的。我不想:
我想将相同的shell脚本源于makefile的环境,以便我可以访问这些变量。这可能吗?我怎样才能做到这一点?理想情况下,我会在makefile中执行:
source setup-env.sh
makefile没有source
命令,但也许等同于什么?我可以使用任何特殊的黑客来模拟相同的效果吗?
答案 0 :(得分:6)
根据additional question in the comment,这是一种有效地将整个环境标记为已导出的方法:
for var in $(compgen -v); do export $var; done
根据{{3}}, compgen -v
只输出所有变量名称。然后我们简单地遍历此列表并export
每个列表。
归功于bash manual, section 8.7 Programmable Completion Builtins - compgen
对我而言是新的。
我可以通过两种方式将其整合到您的制作工作流程中:
只需编写一个shell脚本来源您的setup-env.sh,导出所有变量,然后调用make
本身。类似的东西:
#!/bin/bash
./source setup-env.sh
for var in $(compgen -v); do export $var; done
make $@
可能您不想要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
此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'
$
我们检查GNU Make内置变量MAKELEVEL以查看我们所处的递归级别。如果级别为0,那么我们递归调用所有目标的make,但首先源./setup-env.sh并导出所有变量。如果递归级别是其他任何东西,我们只是做普通的makefile,但是你看到你需要的变量现在可用了。这由Makefile顶部的$(info )
行突出显示,该行显示递归级别和myvar的值(或不是)。
我们必须使用bash -c
,因为compgen
严格来说是内置的bash,并且在Posix模式下不可用 - 即默认情况下make调用shell为sh -c
。 / p>
第一个$
食谱中的all:
需要非常谨慎地转义。 $$
使$
无法通过make进行展开,而\$$
使$
无法通过隐式sh
有很多文献认为"递归制作被认为是有害的"。例如。 https://stackoverflow.com/a/16337687/2113226