我有一种非常舒适的方式来通过几行bash命令编译我的项目。但现在我需要通过makefile编译它。考虑到每个命令都在自己的shell中运行,我的问题是在makefile中运行多行bash命令的最佳方式是什么,相互依赖? 例如,像这样:
for i in `find`
do
all="$all $i"
done
gcc $all
此外,有人可以解释为什么即使单行命令bash -c 'a=3; echo $a > file'
在终端中工作正常,但在makefile情况下创建空文件?
答案 0 :(得分:103)
您可以使用反斜杠进行续行。但请注意,shell接收整个命令连接成一行,因此您还需要使用分号终止某些行:
foo:
for i in `find`; \
do \
all="$$all $$i"; \
done; \
gcc $$all
但是如果您只想获取find
调用返回的整个列表并将其传递给gcc
,您实际上不一定需要多行命令:
foo:
gcc `find`
或者,使用更常规的$(command)
方法(注意$
转义):
foo:
gcc $$(find)
答案 1 :(得分:69)
如问题所示,每个子命令都在自己的shell中运行。这使得编写非平凡的shell脚本有点混乱 - 但它有可能!解决方案是将您的脚本合并到make将考虑单个子命令(单行)。 / p>
$
$$
的使用
;
\
set -e
开头,以匹配make的配置,以便在子命令失败时中止()
或{}
以强调多行序列的内聚性 - 这不是典型的makefile命令序列这是一个受OP启发的例子:
mytarget:
{ \
set -e ;\
msg="header:" ;\
for i in $$(seq 1 3) ; do msg="$$msg pre_$${i}_post" ; done ;\
msg="$$msg :footer" ;\
echo msg=$$msg ;\
}
答案 2 :(得分:2)
当然,编写Makefile的正确方法是实际记录哪些目标取决于哪些来源。在简单的情况下,建议的解决方案将使foo
依赖于自身,但当然,make
足够聪明,可以放弃循环依赖。但是如果你将一个临时文件添加到你的目录中,它将“神奇地”成为依赖链的一部分。最好是一劳永逸地创建一个明确的依赖列表,可能是通过脚本。
GNU make知道如何运行gcc
从一组.c
和.h
文件中生成可执行文件,所以你真正需要的就是
foo: $(wildcard *.h) $(wildcard *.c)
答案 3 :(得分:1)
只是调用命令有什么问题?
foo:
echo line1
echo line2
....
对于第二个问题,您需要使用$
来代替$$
,bash -c '... echo $$a ...'
。
编辑:您的示例可以重写为单行脚本,如下所示:
gcc $(for i in `find`; do echo $i; done)
答案 4 :(得分:1)
ONESHELL指令允许编写要在同一shell调用中执行的多个行配方。
echo t(1)
尽管有一个缺点:特殊前缀字符(“ @”,“-”和“ +”)的解释不同。
https://www.gnu.org/software/make/manual/html_node/One-Shell.html