makefileレシピに変数が見つかりません。

makefileレシピに変数が見つかりません。

この簡単なレシピはなぜ効果がないのですか?

.PHONY: test
test:
    foo := $(shell ls | grep makefile) ;\
    echo $(foo)

明らかにする

$> make test
makefile:65: warning: undefined variable 'foo'
foo := makefile ;\
echo 
/bin/sh: 1: foo: not found

それで、私が知っているのは、変数にfoo値が設定されているのにmakefile使用できないということですか?しかし、同じシェルで実行される単一行コマンドですか?

しかし、これはうまくいきます

@$(eval export foo := $(shell ls | grep makefile)) \
echo $(foo)

echoもしそうなら、私たちが試したときに割り当てがまだ評価されていないため、最初の例の変数にアクセスできないようです。

もっと詳しく見ると、どうすればこれを行うことができますか?

.PHONY: test
test:
    @$(eval export files = $(shell ls))
    for f in $(files) ; do \
        t = $(ls | grep $$f) ; \
        echo $$t;\
    done

ベストアンサー1

私はあなたのループを見ました...引用は次のとおりです。

.PHONY: test
test:
    @$(eval export files = $(shell ls))
    for f in $(files) ; do \
        t = $(ls | grep $$f) ; \
        echo $$t;\
    done

それでは... $(eval ... )makeでコマンドを実行してみてください。

$(shell ls)lsシェルでコマンドを実行し、出力を置き換えます。

したがって、実行されるコマンドは$(eval ... )次のとおりですexport files = file file2 makefile source.c。このコマンドは、filesという名前のmake変数を生成し、それをsubmakeにエクスポートします。したがって、エクスポートが必要ない場合があります。

全体を$(eval ... )置き換えて使用でき、ルールの外に配置files = $(wildcard *) できます。:=

このforループ(4行)はシェルで実行されます。最初にすることは、make変数と関数を置き換えることです。奇妙な点は$(ls | grep $$f)。 ls は make 関数ではないため、未定義の変数を拡張しようとします。これは空の文字列です。これがシェル$(...)演算子の場合は、$を2倍にする必要があります。 evalに基づいて.Extended $$に拡張されます。$$(files)

これは次のとおりです(前の例を使用した場合)。

for f in file file2 makefile source.c ; do
    t =
    echo $t;
done

一見すると、これは4つの空白行をエコーし​​ているように見えるかもしれませんが、そうではありません。このコマンドはt =実際にプログラムを実行し、t等号を引数として渡します。 tおそらく存在しないでしょう。したがって、tが有効なプログラムではないことを示す4つのエラーが発生します。各エラーの後には空行が続きます(tが他の場所で定義されていない場合)。

あなたが望むものに近いものは次のとおりです。

files := $(wildcard *)
.PHONY: test
test:
    for f in $(files) ; do \
        t=$$(ls | grep $$f) ; \
        echo $$t ; \
    done

すると、以下が出力されます。

file file2
file2
makefile
source.c

最初の行には名前に「file」が含まれているため、2つのファイルがリストされます。これが欲しいものではない場合は、次の点を検討してください。

files := $(wildcard *)
.PHONY: test
test:
    for f in $(files) ; do \
        echo $$f ; \
    done

または(GNU固有の場合もあります):

files := $(wildcard *)
.PHONY: test
test:
    $(foreach f, $(files), echo $f ; )

おすすめ記事