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

时间:2009-02-26 05:56:16

标签: bash shell makefile

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

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

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

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

6 个答案:

答案 0 :(得分:328)

从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的顶部,你应该好好去。

BTW:您也可以为一个目标执行此操作,至少对于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中的任何位置,它不必紧接在目标之前。

答案 1 :(得分:14)

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

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

当然,你可能无法重定向到变量$ @,但是当我尝试这样做时,我得到-bash: $@: ambiguous redirect作为错误消息,所以你可能想要在你得到之前调查一下对此(虽然我使用bash 3.2.something,所以也许你的工作方式不同)。

答案 2 :(得分:4)

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

bash -c "ls -al"

而不是:

ls -al

答案 3 :(得分:4)

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

答案 4 :(得分:2)

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

如果您运行sudo dpkg-reconfigure dash并回答“否”&#39;在提示符下,您的系统不会将dash用作默认shell。然后它将指向bash(至少在Ubuntu中)。请注意,使用dash作为系统shell会更有效率。

答案 5 :(得分:0)

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

your-target: $(eval SHELL:=/bin/bash)
    @echo "here shell is $$0"