如何在Makefile目标中使用Bash语法?


208

我经常发现Bash语法非常有用,例如像中的流程替换diff <(sort file1) <(sort file2)

是否可以在Makefile中使用这样的Bash命令?我在想这样的事情:

file-differences:
    diff <(sort file1) <(sort file2) > $@

在我的GNU Make 3.80中,这将产生错误,因为它使用shell而不是bash执行命令。


这正是我的问题,我花了至少一个小时才找到这个问题!我在这里留下我的错误消息,以便将来的读者找到它:(/bin/sh: -c: line 0: syntax error near unexpected token '`
-David

Answers:


380

从GNU Make文档中,

5.3.1 Choosing the Shell
------------------------

The program used as the shell is taken from the variable `SHELL'.  If
this variable is not set in your makefile, the program `/bin/sh' is
used as the shell.

因此,将其放在SHELL := /bin/bashmakefile的顶部,您应该一切顺利。

顺便说一句:您也可以为一个目标执行此操作,至少对于GNU Make。每个目标可以有自己的变量分配,如下所示:

all: a b

a:
    @echo "a is $$0"

b: SHELL:=/bin/bash   # HERE: this is setting the shell for b only
b:
    @echo "b is $$0"

打印:

a is /bin/sh
b is /bin/bash

有关更多详细信息,请参见文档中的“特定于目标的变量值”。该行可以在Makefile中的任何地方进行,而不必紧接在目标文件之前。


43
500赏金等待报价man。谈论时间。:P
SiddharthaRT

3
@inLoveWithPython嗯,info实际上,但是,我认为这确实对Andy有帮助。我知道我曾经有过这样的日子……
derobert

3
如有疑问,@ derobert的字面意思是:SHELL=/bin/bash作为Makefile的第一行(或紧跟在注释之后)。
Yauhen Yakimovich


2
是否可以仅针对一个特定的make目标更改SHELL变量,而使其他目标不变?
antred

18

您可以bash直接调用,使用-c标志:

bash -c "diff <(sort file1) <(sort file2) > $@"

当然,您可能无法重定向到变量$ @,但是当我尝试执行此操作时,我收到了-bash: $@: ambiguous redirect一条错误消息,因此您可能想在深入了解它之前先进行研究(尽管我使用bash 3.2.something,所以也许您的工作方式有所不同)。


4

如果可移植性很重要,则您可能不希望依赖Makefile中的特定Shell。并非所有环境都有可用的bash。


4

您可以直接在Makefile中调用bash,而不必使用默认的shell:

bash -c "ls -al"

代替:

ls -al

1
注意,它将make忽略环境变量SHELL的值。
choroba

2

无需显式将SHELL变量设置为指向bash,就可以执行此操作。如果您有许多makefile,这将很有用,因为SHELL不会被后续的makefile继承或从环境中获取。您还需要确保任何编译您的代码的人都以这种方式配置他们的系统。

如果运行sudo dpkg-reconfigure dash并对提示回答“否”,则系统将不使用破折号作为默认外壳。然后它将指向bash(至少在Ubuntu中)。请注意,虽然使用破折号作为系统外壳会更有效。


1
当以名称调用时sh,bash以兼容模式(set -o posix)运行。在此模式下,OP尝试使用的功能(进程替换)不可用。
Charles Duffy

1

一种可行的方法是将其放在目标的第一行:

your-target: $(eval SHELL:=/bin/bash)
    @echo "here shell is $$0"
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.