bash 将 shell 脚本源到 makefile 中
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/25175546/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Source shell script into makefile
提问by blueFast
I have a bash shell script which I usually source into my shell, with lots of environment variables defined, which are notexported. I do not want to:
我有一个 bash shell 脚本,我通常将其输入到我的 shell 中,其中定义了许多环境变量,但未导出。我不想:
- Export the variables, because this would make the exportable environment too big, and eventually make the whole system slower (it must be exported when running every command from the shell)
- Redefine those variables in the makefile (DRY)
- 导出变量,因为这会使可导出的环境太大,最终使整个系统变慢(从shell运行每个命令时都必须导出)
- 在 makefile (DRY) 中重新定义这些变量
I would like to source the same shell script into the environment of the makefile, so that I can access those variables. Is this possible? How can I do that? Ideally I would do in the makefile:
我想在 makefile 的环境中使用相同的 shell 脚本,以便我可以访问这些变量。这可能吗?我怎样才能做到这一点?理想情况下,我会在 makefile 中执行以下操作:
source setup-env.sh
There is not source
command for makefiles, but maybe something equivalent? Any special hack I can use to simulate the same effect?
没有source
生成文件的命令,但也许是等价的?我可以使用任何特殊的技巧来模拟相同的效果吗?
采纳答案by Digital Trauma
As per the additional question in the comment, here is one way to effectively mark the whole environment as exported:
根据评论中的附加问题,这是一种有效地将整个环境标记为已导出的方法:
for var in $(compgen -v); do export $var; done
compgen -v
simply outputs all variable names, as per the bash manual, section 8.7 Programmable Completion Builtins. Then we simply loop over this list and export
each one.
compgen -v
根据bash 手册的第 8.7 节 Programmable Completion Builtins ,简单地输出所有变量名称。然后我们简单地遍历这个列表和export
每个列表。
Credit to https://stackoverflow.com/a/16337687/2113226- compgen
is new to me.
归功于https://stackoverflow.com/a/16337687/2113226-compgen
对我来说是新的。
There are two ways I can think of to integrate this into your make workflow:
我可以想到两种方法将其集成到您的制作工作流程中:
- Shell script wrapper
- Shell 脚本包装器
Simply write a shell script which sources your setup-env.sh, exports all variables as above, then calls make
itself. Something like:
只需编写一个 shell 脚本来获取您的 setup-env.sh,导出如上的所有变量,然后调用make
自身。就像是:
#!/bin/bash
./source setup-env.sh
for var in $(compgen -v); do export $var; done
make $@
- Recursive make
- 递归制作
It may be that you don't want a shell script wrapper, and want to directly invoke make for whatever reason. You can do this all in one Makefile which calls itself recursively:
可能是您不想要 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
Output for this Makefile is:
这个 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'
$
We check the GNU Make builtin variable MAKELEVEL to see what level of recursion we are at. if the level is 0, then we recursively call make for all targets, but first source ./setup-env.sh and export all variables. If the recursion level is anything else, we just do the normal makefile stuff, but you see that the variables you need are now available. This is highlighted by the $(info )
line at the top of the Makefile, which shows the recursion level, and the value (or not) of myvar.
我们检查 GNU Make 内置变量 MAKELEVEL 以查看我们处于什么级别的递归。如果级别为 0,那么我们递归地为所有目标调用 make,但首先源 ./setup-env.sh 并导出所有变量。如果递归级别是其他任何东西,我们只做正常的 makefile 内容,但是您会看到您需要的变量现在可用。这由$(info )
Makefile 顶部的行突出显示,它显示了递归级别和 myvar 的值(或不是)。
Notes:
笔记:
We have to use
bash -c
becausecompgen
is strictly a bash builtin, and not available in Posix mode - i.e. when make invokes the shell assh -c
by default.The
$
in the firstall:
recipe need to be escaped very carefully. The$$
escapes the$
from being expanded by make, and the\$$
escapes the$
from being expanded by the implicitsh
There is plenty of literature arguing that "Recursive make is considered harmful". E.g. http://aegis.sourceforge.net/auug97.pdf
我们必须使用,
bash -c
因为它compgen
是严格的 bash 内置函数,在 Posix 模式下不可用 - 即sh -c
默认情况下make 调用 shell 时。第
$
一个all:
配方中的 需要非常小心地转义。The$$
转义$
from 被 make 扩展,而 the\$$
转义 the$
from 被隐式扩展sh
有大量文献认为“递归 make 被认为是有害的”。例如http://aegis.sourceforge.net/auug97.pdf