Makefileでシェルコマンドを使用する方法 質問する

Makefileでシェルコマンドを使用する方法 質問する

結果をls他のコマンド (例: echo、rsync) で使用しようとしています。

all:
    <Building, creating some .tgz files - removed for clarity>
    FILES = $(shell ls)
    echo $(FILES)

しかし、私はこう思います:

make
FILES = Makefile file1.tgz file2.tgz file3.tgz
make: FILES: No such file or directory
make: *** [all] Error 1

echo $$FILES、 、を使ってみましたecho ${FILES}echo $(FILES)、うまくいきませんでした。

ベストアンサー1

と:

FILES = $(shell ls)

このように下にインデントされているのはall、ビルド コマンドです。したがって、これは を展開し$(shell ls)、コマンド を実行しようとしますFILES ...

FILESが変数である場合make、これらの変数はレシピ部分の外部で割り当てられる必要があります。例:

FILES = $(shell ls)
all:
        echo $(FILES)

もちろん、それは「出力元」FILESに設定されることを意味しますls前に.tgzファイルを作成するコマンドを実行すると、カズのメモ変数は毎回再展開されるため、最終的には .tgz ファイルが含まれることになります。一部の make バリアントではFILES := ...、効率性や正確性のためにこれを回避する必要があります。1 )

がシェル変数である場合はFILES設定できますが、スペースを入れず引用符で囲んだシェル風に行う必要があります。

all:
        FILES="$(shell ls)"

ただし、各行は別々のシェルによって実行されるため、この変数は次の行まで存続しません。そのため、すぐに使用する必要があります。

        FILES="$(shell ls)"; echo $$FILES

そもそもシェルが展開 (および他のシェル glob 表現) してくれるので、これは少しばかげています*。そのため、次のようにすればよいのです。

        echo *

シェルコマンドとして。

最後に、一般的なルールとして(この例には当てはまりませんが):エスペラントコメントに注記があるように、 の出力を使用することはls完全に信頼できるわけではありません(一部の詳細はファイル名や のバージョンに依存します。 のlsバージョンによってlsは、出力をサニタイズしようとする場合があります)。したがって、いいえそして理想的注意: GNU make を使用している場合は、 と を使用して$(wildcard)$(subst ...)すべてを内部で実行できますmake(「ファイル名に奇妙な文字がある」問題を回避できます)。 (shスクリプト (makefile のレシピ部分を含む) では、別の方法として、 を使用するfind ... -print0 | xargs -0ことで、空白、改行、制御文字などに遭遇するのを回避できます。)


1GNU Makeのドキュメントには、POSIX makeが::=2012年に割り当てを追加したことがさらに記載されています。これに関する POSIX ドキュメントへのクイック リファレンス リンクは見つかりませんでした。また、どのmakeバリアントが::=代入をサポートしているかもすぐにはわかりませんが、GNU make は現在、 と同じ意味 (:=つまり、展開を使用して今すぐ代入を行う) で代入をサポートしています。

は、私が知る限り、すべての最新のGNUおよびBSDバリアントを含むいくつかのバリアントでVAR := $(shell command args...)綴られることに注意してください。これらの他のバリアントにはないので、 を使用すると、どちらも短くなるという点で優れています。VAR != command args...make$(shell)VAR != command args...そしてより多くのバリエーションで動作します。

おすすめ記事