Curly Brace Wildcards是否可以在GNU Make 4(甚至POSIX Make)中使用?

时间:2018-12-06 07:51:32

标签: unix makefile posix gnu-make

我发现GNU Make 4.1和3.81之间的行为有所不同,想知道我的代码是否不符合POSIX规范,而后者更严格地执行了4,或者是否还有其他问题。

我将失败案例提炼到该Makefile

.POSIX:

all: test-b

test-a:
    cat a.txt b.txt c.txt >results.txt

test-b:
    cat {a,b,c}.txt >results.txt

假设这些文件是使用cat {a,b,c}.txt创建的,则目标test-a始终有效,而test-b可以在Make 3.81上运行,但在4.1上失败。

3.81的输出:

$ make --version
GNU Make 3.81
Copyright (C) 2006  Free Software Foundation, Inc.
This is free software; see the source for copying conditions.
There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A
PARTICULAR PURPOSE.

This program built for i386-apple-darwin11.3.0
$ make
cat {a,b,c}.txt >results.txt
$ echo $?
0

4.1的输出:

$ make --version
GNU Make 4.1
Built for x86_64-pc-linux-gnu
Copyright (C) 1988-2014 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
$ make
cat {a,b,c}.txt >results.txt
cat: {a,b,c}.txt: No such file or directory
Makefile:9: recipe for target 'test-b' failed
make: *** [test-b] Error 1
$ echo $?
2

cat命令实际上在3.81中失败了,只是没有指出它,因为GNU的更高版本提到了在调用目标命令时将-e标志传递给shell。使它更符合POSIX,但我看不到该命令可能失败的原因。

我假定通配符仅由外壳程序处理,所以我看不到通过make target命令调用外壳程序应该有什么不同。

这些行为正确吗?如果类似的通配符在Makefile中不起作用,我可以假定其他哪些通配符起作用?

即使从文件中删除了test-b

.POSIX:在4.1中仍然失败。

1 个答案:

答案 0 :(得分:2)

食谱被发送到外壳。它们不是由make解释的。因此,您的问题是,shell是否支持花括号扩展?

这取决于使用哪个shell。 POSIX标准sh不支持它们。它们由bash(和许多其他shell)支持。

Make始终调用/bin/sh,无论您个人使用什么shell,除非您将make SHELL变量专门设置为其他变量。在某些系统上,/bin/sh是到/bin/bash的符号链接,因此它们是同一对象(bash在以/bin/sh调用时以“ POSIX仿真”模式运行,但大多数bash功能仍然可用) 。其他系统使用不同的shell,例如破折号/bin/sh,它们没有额外的bash功能。

因此,您可以(a)没有可移植的makefile并假设/bin/sh/bin/bash相同,(b)在makefile中设置SHELL := /bin/bash强制其使用始终使用bash(但在未安装bash的系统上失败),或(c)编写makefile配方以仅使用POSIX sh功能,因此无论/bin/sh使用哪个shell,它都可以工作。