MakefileターゲットでBash構文を使用するにはどうすればよいですか?


208

Bashの構文は非常に役立つことがよくあります。たとえば、のようなプロセス置換diff <(sort file1) <(sort file2)です。

MakefileでそのようなBashコマンドを使用することは可能ですか?私はこのようなことを考えています:

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

私のGNU Make 3.80 shellではbash、コマンドを実行する代わりにを使用するため、エラーが発生します。


これはまさに私の問題でした。この質問を見つけるのに少なくとも1時間かかりました。今後の読者が見つけられるように、ここにエラーメッセージを残します/bin/sh: -c: line 0: syntax error near unexpected token ( '`
David

回答:


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/bashあなたのメイクファイルの一番上に置くと、あなたは行くのが良いはずです。

ところで、少なくともGNU Makeでは、これを1つのターゲットに対して行うことができます。各ターゲットには、次のように独自の変数を割り当てることができます。

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実際には、しかし、それはアンディを本当に助けたと思います。私はそのような日があったことを知っています...
derobert

3
疑わしい場合は、@ derobertは文字通りSHELL=/bin/bash、Makefileの最初の行(またはコメントの直後)を意味していました。
Yauhen Yakimovich 2013

1
ありがとう@derobertは、stackoverflow.com
Choudhury

2
特定のmakeターゲットに対してのみSHELL変数を変更し、他のターゲットはそのままにしておくことは可能ですか?
2016

18

bash-cフラグを使用して直接呼び出すことができます。

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

もちろん、変数$ @にリダイレクトできない場合がありますが、これを実行しようとする-bash: $@: ambiguous redirectと、エラーメッセージが表示されます。 bash 3.2.somethingを使用しているため、おそらく動作が異なります)。


4

移植性が重要な場合は、Makefileの特定のシェルに依存したくない場合があります。すべての環境でbashを使用できるわけではありません。


4

デフォルトのシェルを使用する代わりに、Makefile内で直接bashを呼び出すことができます。

bash -c "ls -al"

の代わりに:

ls -al

1
make環境変数SHELLの値を無視することに注意してください。
choroba

2

SHELL変数をbashを指すように明示的に設定せずにこれを行う方法があります。SHELLは後続のmakefileに継承されず、環境から取得されないため、これは多くのmakefileがある場合に役立ちます。また、コードをコンパイルする人は誰でも、このようにシステムを構成する必要があります。

実行sudo dpkg-reconfigure dashしてプロンプトに「no」と応答すると、システムはデフォルトのシェルとしてダッシュを使用しません。次に、bashをポイントします(少なくともUbuntuでは)。ただし、システムシェルとしてダッシュを使用する方が少し効率的です。


1
名前shで呼び出されると、bashは互換モード(set -o posix)で実行されます。OPが使用しようとしている機能であるプロセス置換は、このモードでは使用できません。
Charles Duffy 2017年

1

これも機能する1つの方法は、ターゲットの最初の行に次のように配置することです。

your-target: $(eval SHELL:=/bin/bash)
    @echo "here shell is $$0"
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.