2016-12-05 1 views
0

(GNU)makeでは、特定のターゲットのビルドチェーンが開始されているときに変数に値を割り当てる必要があります。 a.sob.o両方のルールを実行するときcurrent値のみb.soを有しているcurrentは、値a.soを有し、ここでMake:どのターゲットをビルドするかによって変数を設定します。

# Rules 
all: a.so b.so 
a.so: b.o 
    @echo Current .so is $(current) 
    touch [email protected] 
b.so: b.o 
    @echo Current .so is $(current) 
    touch [email protected] 
b.o: 
    @echo Current .so is $(current) 
    touch [email protected] 

# Set the "current" variable based on which .so is being build 
a.so: current = a.so 
b.so: current = b.so 

を:ターゲットa.sob.sob.oに応じてそれぞれのために、私はこのように手動でこれを行うことができb.soのルールを実行するとき。これは私が欲しいものです。私が持っているメンタルモデルは、a.soまたはb.soのルールが実行される前に、a.soがビルドされていることがmakeが知るとすぐに、a.so: current = a.soという行がトリガされるということです。私が間違っているなら、私を修正してください。

私の実際のケースでは、私はもっと多くのファイルを持っているので、最後の2行をこのようなものに置き換えたいと思います。

%.so: current = [email protected] 

またはこれです。

しかし
sofiles = a b 
$(addsuffix .so, $(sofiles)): current = [email protected] 

、これらの結果の両方current変数はb.oターゲットがビルドされようとしている場合でも、新たに設定されますと同じ、間違った行動、インチb.oターゲットがこれらの行をトリガするのはなぜですか? .soごとに手作業でa.so: current = a.soと書くのと同じ振る舞いを実現するにはどうすればよいですか?.soごとに実際に配線する必要はありませんか?

:私はコード例に示されているユースケースは奇妙であり、効果の後に求められ、この厄介current変数なしに達成することができることを知っています。私はしかし、この変数を使用せずに問題を解決する任意のソリューションに興味がありません。

答えて

1

ここで議論するべきことがたくさんあります。まず、ターゲット固有の変数がどのように動作するかの精神モデルは、正確ではありません( "a.so:current = a.soは、makeがa.soをビルドする必要があることがわかるとすぐにトリガされます)。本当に起こるのは、それぞれのターゲット・メイキング・メイクが、そのターゲットとすべての前提条件が作成されている間にアクティブな新しい「有効範囲」を作成し、そのターゲットのターゲット固有の変数がその有効範囲内で有効であるということです。スコープが終了すると(ターゲットは終了しています)、それらの変数の設定はなくなります。上記のあなたの例では

currentb.oa.soの前提として作成されているのみときb.oするレシピ内の値a.soを持つことになります。 b.oを前提条件としてb.soとして作成する場合、currentb.soとなります。メイクファイルはa.soが最初に作成されるので、b.oは(makeの呼び出しごとに)1度しか構築されないため、currentの値として常にa.soを使用しているように見えますが、正確ではありません。この考えてみましょう:

$ make all 
Current .so is a.so 
touch b.o 
Current .so is a.so 
touch a.so 
Current .so is b.so 
touch b.so 

をしかし、また、この:

$ rm -f b.o 
$ make b.so 
Current .so is b.so 
touch b.o 
Current .so is b.so 
touch b.so 

b.o場合currentb.soに設定されている方法を参照してください、それはb.soないa.soの前提条件だから構築されています。

そしてまた、この:ここ

$ rm -f b.o 
$ make b.o 
Current .so is 
touch b.o 

b.oがどの.soの前提条件ではないので、その後、currentは全く設定されていません!それは、この行がb.oための「トリガー」されるというのは本当ではありません

%.so : current = [email protected] 

:考える

次のことは、この行です。しかし、これは([email protected]変数の展開にメモ、ませ!)値[email protected]にパターン固有の変数currentを設定します。これは、各時間$(current)はそれが現在ターゲット名は、それが中で使われているものは何でもレシピのために、ある[email protected]に拡大する展開されていることを意味している。現在のターゲット名が実際にa.soまたはb.soでない限り、これはa.soまたはb.soに展開されません。 。ターゲット名がb.oの場合、[email protected]b.oに展開されます。

あなたが[email protected]のような変数を使用することはできませんこれを実行したい場合は、あなたが本当の値を使用する必要があります。あなたは、例えば、evalでこれを行うことができます。

sofiles = a b 
$(foreach SO,$(sofiles),$(eval $(SO).so: current = $(SO).so)) 

をしかし、私は上記の最初のコメントに基づいてそれがあなたのニーズには十分だか分かりません。

+0

詳細な回答ありがとうございます。はい、 'current'は' .so'ファイルがビルドされているとき(あるいは他のファイルが '.so'ファイルの前提条件としてビルド中)にセットされます。これが意図です。また、 'eval'(変数展開を直ちに実行するように並べ替えるには、すぐに行えますか?)は完璧に機能します! –

+0

'eval'は、makefileの一部であるかのようにその引数を評価します。これは、インラインインクルードファイルとほぼ同じです。 https://www.gnu.org/software/make/manual/html_node/Eval-Function.htmlを参照してください。 – MadScientist

関連する問題