126

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 $$FILESecho ${FILES}およびを使用してみましたがecho $(FILES)、うまくいきませんでした。

4

2 に答える 2

197

と:

FILES = $(shell ls)

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

FILESが変数であると想定される場合make、これらの変数はレシピ部分の外で割り当てる必要があります。たとえば、次のようになります。

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

もちろん、これは、.tgz ファイルを作成するコマンドを実行する前にFILES、"output from ls"に設定されることを意味します。( Kaz が指摘しているように、変数は毎回再展開されるため、最終的には .tgz ファイルが含まれます。一部の make バリアントでは、効率および/または正確さのために、これを回避する必要があります。1 )FILES := ...

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

all:
        FILES="$(shell ls)"

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

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

*そもそもシェルが(および他のシェルグロブ式を)展開するので、これはすべて少しばかげているので、次のことができます。

        echo *

シェルコマンドとして。

最後に、一般的なルールとして (この例には実際には当てはまりません):エスペラントがコメントで指摘しているように、 からの出力を使用することlsは完全に信頼できるわけではありません (一部の詳細はファイル名に依存し、場合によっては のバージョンにも依存しますls。一部のバージョンの のls出力はサニタイズを試みます)ある場合には)。したがって、l0b0idelic note のように、GNU make を使用している場合は、それ自体ですべてを実行するため$(wildcard)に andを使用できます(「ファイル名の奇妙な文字」の問題を回避します)。( makefile のレシピ部分を含むスクリプトでは、別の方法を使用して、空白、改行、制御文字などのつまずきを回避します。)$(subst ...)makeshfind ... -print0 | xargs -0


1 GNU Make のドキュメントには、POSIX makeが 2012 年に割り当てを追加したことがさらに記されてい::=ます。このための POSIX ドキュメントへのクイック リファレンス リンクは見つかりませんでした。また、代入をmakeサポートするバリアントがどれかをすぐに知ることもできません。::=:=

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

于 2012-04-05T07:39:00.367 に答える
63

また、torek の回答に加えて、際立っていることの 1 つは、遅延評価されたマクロ割り当てを使用していることです。

GNU Make を使用している場合は、:=代わりに代入を使用し=ます。この割り当てにより、右側がすぐに展開され、左側の変数に格納されます。

FILES := $(shell ...)  # expand now; FILES is now the result of $(shell ...)

FILES = $(shell ...)   # expand later: FILES holds the syntax $(shell ...)

割り当てを使用すると、 が=出現するたび$(FILES)に構文が展開され$(shell ...)、シェル コマンドが呼び出されることになります。これにより、make ジョブの実行が遅くなるか、驚くべき結果が生じることさえあります。

于 2012-04-09T23:22:03.363 に答える