bash 如何在 Makefile 操作中使用 shell 变量?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/13774784/
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
How do I use shell variables in Makefile actions?
提问by hekevintran
I have the following in a Makefile for the purpose of recreating my database including destroying it if necessary. It does not work.
我在 Makefile 中有以下内容,目的是重新创建我的数据库,包括在必要时销毁它。这是行不通的。
.PHONY: rebuilddb
exists=$(psql postgres --tuples-only --no-align --command "SELECT 1 FROM pg_database WHERE datname='the_db'")
if [ $(exists) -eq 1 ]; then
dropdb the_db
fi
createdb -E UTF8 the_db
Running it results in an error:
运行它会导致错误:
$ make rebuilddb
exists=
if [ -eq 1 ]; then
/bin/sh: -c: line 1: syntax error: unexpected end of file
make: *** [rebuilddb_postgres] Error 2
Why is this wrong? It looks like valid Bash as far as I can tell? Are there special considerations I must make when doing this in a Makefile?
为什么这是错误的?据我所知,它看起来像有效的 Bash?在 Makefile 中执行此操作时是否需要特别注意?
UPDATE:
更新:
Using the answer I arrived at a working version:
使用答案我得到了一个工作版本:
.PHONY: rebuilddb
exists=$$(psql postgres --tuples-only --no-align --command "SELECT 1 FROM pg_database WHERE datname='the_db'"); \
if [ "$$exists" == "1" ]; then \
dropdb the_db; \
fi;
createdb -E UTF8 the_db
回答by William Pursell
There are at least two considerations. $()
references a Make variable. You must escape the $
to do command substitution. Also, the shell commands must be all on one line. Try:
至少有两个考虑。 $()
引用 Make 变量。您必须转义$
以执行命令替换。此外,shell 命令必须全部在一行上。尝试:
exists=$$(psql postgres --tuples-only --no-align --command "SELECT 1 FROM \
pg_database WHERE datname='the_db'"); \
if [ "$$exists" -eq 1 ]; then \
dropdb the_db; \
fi; \
createdb -E UTF8 the_db
On the other hand, it seems like it would be simpler to just always try to drop the database, and allow failure:
另一方面,似乎总是尝试删除数据库并允许失败似乎更简单:
rebuilddb:
-dropdb the_db # Leading - instructs make to not abort on error
createdb -E UTF8 the_db
回答by Clemens1509
For completness the usage in $(eval $(call ...)
为了完整起见,在 $(eval $(call ...)
The usage in dynamic generation rules you have to escape the shell variables with $$$$.
动态生成规则中的用法您必须使用 $$$$ 对 shell 变量进行转义。
Here is an example which has been tested with "GNU Make 4.2.1":
这是一个已经用“GNU Make 4.2.1”测试过的例子:
MY_LIBS=a b c
a_objs=a1.o a2.o
b_objs=b1.o b2.o b3.o
c_objs=c1.o c2.o c3.o c4.odefault: libs
# function lib_rule(name, objs)
define lib_rule
lib$(1).a: $(2)exit 1 | tee make.log ; test $$$${PIPESTATUS[0]} -eq 0
endef# generate rules
$(foreach L,$(MY_LIBS),$(eval $(call lib_rule,$(L),$($(L)_objs))))# call generated rules
libs: $(patsubst %,lib%.a,$(MY_LIBS))# dummy object generation
%.o:%.ctouch $@
# dummy source generation
%.c:touch $@
clean::
rm -f *.c *.o lib*.a make.log
MY_LIBS=abc
a_objs=a1.o a2.o
b_objs=b1.o b2.o b3.o
c_objs=c1.o c2.o c3.o c4.o默认:库
# 函数 lib_rule(name, objs)
定义 lib_rule
lib$(1).a: $(2)exit 1 | 三通 make.log ; 测试$$$${PIPESTATUS[0]} -eq 0
endef# 生成规则
$(foreach L,$(MY_LIBS),$(eval $(call lib_rule,$(L),$($(L)_objs))))# 调用生成的规则
库: $(patsubst %,lib%.a,$(MY_LIBS))# 虚拟对象生成
%.o:%.ctouch $@
# 虚拟源代码生成
%.c:touch $@
清洁::
rm -f *.c *.o lib*.a make.log
The output: 'make -Rr'
输出:'make -Rr'
exit 1 | tee make.log ; test ${PIPESTATUS[0]} -eq 0
make: *** [Makefile:18: liba.a] Error 1
出口 1 | 三通 make.log ; 测试${PIPESTATUS[0]} -eq 0
make: *** [Makefile:18: liba.a] 错误 1
Result of last command in pipe is truefrom tee. You can see bash variable PIPESTATUS[0]has the value falsefrom exit 1
来自tee 的管道中最后一个命令的结果为真。您可以看到 bash 变量PIPESTATUS[0]从exit 1开始的值为false
Watch the Database: 'make -Rrp'
观察数据库:'make -Rrp'
define lib_rule
lib$(1).a: $(2)exit 1 | tee make.log ; test $$$${PIPESTATUS[0]} -eq 0
endef
定义 lib_rule
lib$(1).a: $(2)exit 1 | 三通 make.log ; 测试$$$${PIPESTATUS[0]} -eq 0
endef
...
...
libc.a: c1.o c2.o c3.o c4.o
exit 1 | tee make.log ; test $${PIPESTATUS[0]} -eq 0
libc.a: c1.o c2.o c3.o c4.o
exit 1 | 三通 make.log ; 测试$${PIPESTATUS[0]} -eq 0