私は、非再帰的なmakeシステムの一般的なルールを定義するのが難しいです。むしろ、私はあまりにも多くの既存の材料を再現するよりも、さらに読書については、名前が単純に展開された変数から計算される変数を使用して再帰的に展開された変数を定義する
背景
、this earlier questionを参照してください、かなりよく地面を覆っており、このシステムを構築する場合、以前に私を助けてくれました。
私が構築しているmakeシステムでは、システムコンポーネント間の依存関係を定義したいと思います。コンポーネントAはコンポーネントBに依存しています。その後、Aビルド・ステップで必要となる前にBビルド・プロセスの製品が構築されていることを確認するためにmakeシステムを終了します。 )しかし、私の使用事例では、使いやすさとビルド性能の間の快適なバランスポイントを満たしています。
システムで扱わなければならない問題は、メイクファイルの読み込み順序を制御できないことです。実際問題ではありません。しかし、このため、初期ロードされたメイクファイルで定義されたコンポーネントは、未読メークファイルで定義されたコンポーネントに依存することがあります。
すべてのコンポーネント定義メイクファイルに共通パターンを適用できるように、各コンポーネントは$(component_name)_SRC
などの変数を使用します。これは、再帰的ではない(ただし再帰的に含まれる)makeシステムの共通の解決策です。
GNU makeのさまざまな種類の変数については、the manualを参照してください。まとめると、単純に拡張された変数(SEV)は、makefileが読み込まれるときに展開され、命令型プログラミング言語に類似した動作を示します。再帰的に拡張された変数(REV)は、すべてのmakefileが読み込まれた後、makeの第2段階で展開されます。
問題
これらのコンポーネントが表すファイルのリストに依存-上のコンポーネントのリストをオンにしようとしたときに特定の問題が発生します。
私は実際のシステムの詳細をたくさん残しているこの実行可能な例に私のコードを書き留めました。私はこれが物質を失うことなく問題を実証するのに十分簡単だと思います。
rules.mk:
$(c)_src := $(src)
$(c)_dependencies := $(dependencies)
### This is the interesting line:
$(c)_dependencies_src := $(foreach dep, $($(c)_dependencies), $($(dep)_src))
$(c) : $($(c)_src) $($(c)_dependencies_src)
@echo $^
のMakefile:
.PHONY: foo_a.txt foo_b.txt bar_a.txt hoge_a.txt
### Bar
c := bar
src := bar_a.txt
dependencies :=
include rules.mk
### Foo
c := foo
src := foo_a.txt foo_b.txt
dependencies := bar hoge
include rules.mk
### Hoge
c := hoge
src := hoge_a.txt
dependencies := bar
include rules.mk
これらを与えることを実行します:
$ make foo
foo_a.txt foo_b.txt bar_a.txt
$
hoge_a.txtが原因で、出力に含まれていませんfoo_dependencies
がSEVと定義されている場合、hoge_src
はまだ存在しません。
拡張は、回転数が解決することができるはずの問題であり、私は以前REVとして$(c)_dependencies_src
を定義しようとしましたが、それが動作しないのいずれか$(c)
ので、その後の置換時間、ない定義で展開されていますそれはもはや正しい値を保持しません。
なぜターゲット固有の変数を使用していないのだろうかと疑問に思っている人は、このマニュアルで説明されているターゲットのすべての前提条件に変数を適用すると、 。
私が知りたいのです:
- は、この特定の問題への解決策はありますか? (つまり、その行が私が望むものを達成するための簡単な方法がありますか?)
- このようなmakeシステムを構築するより典型的な方法がありますか? (つまり、複数のメイクファイルからコンポーネントをロードし、それらのコンポーネント間の依存関係を定義する単一のメイクインスタンス)
- 複数のソリューションがある場合、それらの間のトレードオフは何ですか?
最終的なコメント:私の質問を書いたように、REV定義を構築するためにevalを使用することが可能な解決策があるかもしれないことを認識し始めました。そうでなければ、私は将来のサーチャーのために質問をする価値があると思っていました。さらに、このアプローチや他のアプローチに関する経験豊富なユーザーの考えを聞きたいと思います。
'$(c)_dependencies_src'を設定するときに' = 'の代わりに':= 'を使用しているのはなぜですか?ここで '='を使うと、あなたの問題を解決できます。 – MadScientist
個人的には、 'c:= foo'を割り当ててルールファイルを指定した後、' c:= bar'を割り当て、ルールファイルを含むようなグローバル変数を使用するシステムは決して作成しません。私は 'target + = foo'、' foo_c:= foo'、 'foo_src:= foo.x'など' targets + = bar'、 'bar_c:= bar'、' bar_src := bar.x'などです。これにより、同じ変数名を設定してリセットする前にそれらを確実に使用することがなくなります。 – MadScientist
投稿した例で試してみましたか?私が言ったように、少なくともREVは解決できなければならず、以前は$(c)_dependencies_srcをREVとして定義しようとしました... " –