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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-09 23:04:40  来源:igfitidea点击:

How do I use shell variables in Makefile actions?

bashmakefile

提问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.o

default: 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:%.c
touch $@

# 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:%.c
touch $@

# 虚拟源代码生成
%.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