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

我经常发现Bash语法非常有用,例如像diff <(sort file1) <(sort file2)这样的进程replace。

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

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

在我的GNU Make 3.80中,由于它使用shell而不是bash来执行命令,所以会出现错误。

从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/bash放在你的makefile的顶部,你应该很好。

顺便说一句:你也可以为一个目标做到这一点,至less对于GNU Make来说。 每个目标都可以有自己的variables赋值,如下所示:

 all: ab 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 

有关更多详细信息,请参阅文档中的“特定于目标的variables值”。 该行可以在Makefile中的任何位置,它不一定要在目标之前。

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

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

当然,你可能无法redirect到variables$ @,但是当我试图做到这一点,我得到了-bash: $@: ambiguous redirect作为一个错误消息,所以你可能想要看看之前,你会得到也进入这个(虽然我使用bash 3.2.something,所以也许你的工作方式不同)。

如果可移植性很重要,你可能不想依赖你的Makefile中的特定shell。 并不是所有的环境都有可用的bash。

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

 bash -c "ls -al" 

代替:

 ls -al 

有一种方法可以做到这一点,而不必明确地设置你的SHELLvariables指向bash。 如果你有许多makefile文件,这可能是有用的,因为SHELL没有被后续的makefile所inheritance,或者从环境中获取。 您还需要确保编译您的代码的人以这种方式configuration他们的系统。

如果运行sudo dpkg-reconfigure dash并在提示中回答“no”,系统将不会使用短划线作为默认shell。 然后它会指向bash(至less在Ubuntu中)。 请注意,使用破折号作为您的系统shell是更有效率,虽然。