web-dev-qa-db-ja.com

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

私はしばしば Bash 構文が非常に役立つと思います。 diff <(sort file1) <(sort file2)のようなプロセス置換。

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

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

GNU Make 3.80では、Shellの代わりにbashを使用してコマンドを実行するため、これはエラーになります。

187
Frank

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のどこにでも行けますが、ターゲットの直前にある必要はありません。

341
derobert

bashを直接呼び出すには、-cフラグを使用します。

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

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

15
Chris Lutz

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

bash -c "ls -al"

の代わりに:

ls -al
4
paxdiablo

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

4
Menno Smits

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

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

2
Bill G