これは私の以前の質問に関連しています:Why does .PHONY not work in this situation?。私はメイクファイルをもっと独立したものにしたいです!
私はmakeに精通していない開発者が自分の仕事を簡単に行えるように書いたmakefileシステムを持っています。要するに、すべてのプロジェクトで共通する一般的な部分と、特定のプロジェクトに固有の一連のメイクファイルがあります。プロジェクト固有のものには一般的なものも含まれます。それは何らかの理由で3.80を作ったときにうまくいったが、私がそれを試してみたところ、私はいくつかの問題に遭遇した。それは上記の記事で言及された変更を私に余儀なくさせた。今私はいくつかの新しい問題を抱えているので、別の投稿をすることにしました。そのポストのように、私は問題を示すメークファイルをもっと小さく単純化しました。不幸なことに、「シンプルな」ケースは6つのファイルで構成されています。申し訳ありません。
メイク:
TARGETS:=\
Lib1.mk \
Lib2.mk \
my_prog.mk \
include generic/top.mk
Lib1.mk:
BINARY:=Lib1
TYPE:=LIB
LOCATION:=a/location
include generic/rules.mk
まず私は、 "プロジェクト固有" のもの(これらはシンプルであることを意味している)から始めましょうLib2.mk:
BINARY:=Lib2
TYPE:=LIB
LOCATION:=another/location
LIBS:=Lib1
include generic/rules.mk
my_prog.mk:
BINARY:=my_prog
TYPE:=EXE
LOCATION:=some/location
LIBS:=Lib1 Lib2
include generic/rules.mk
概要:Makefileのは、単純にすべてのターゲットの名前が表示されます。ターゲットは実行可能ファイルかライブラリです。 BINARYはライブラリまたは実行可能ファイルの名前です(拡張子は一般的な部分で追加されます)。 TYPEはEXEまたはLIBです。 LOCATIONは、バイナリを実行する場所です。 LIBSは、このバイナリが依存するライブラリです。本当のものは、ユーザーのためのすべての-L、rpathなどのものを作成します(Visual Studio用の同等物も同様です)。さて、一般的なもの(これらは実際の作業を行う)ために:
ジェネリック/ top.mk:
ALL_BINS:=
.PHONY: all
all:
include $(TARGETS)
all: $(ALL_BINS)
%.so %.exe:
mkdir -p $(dir [email protected])
touch [email protected]
clean:
rm -rf out
と最後に...
ジェネリック/ rules.mk:
ifeq (EXE,$(TYPE))
$(BINARY).FULL_FILE_NAME:=out/$(LOCATION)/$(BINARY).exe
else
$(BINARY).FULL_FILE_NAME:=out/$(LOCATION)/lib$(BINARY).so
endif
$(BINARY).DEP_LIBS:=$(foreach a,$(LIBS),$($(a).FULL_FILE_NAME))
ALL_BINS+=$(BINARY)
$(BINARY): $($(BINARY).FULL_FILE_NAME)
$($(BINARY).FULL_FILE_NAME): $($(BINARY).DEP_LIBS)
BINARY:=
LOCATION:=
LIBS:=
この状態では正常に動作します。 Makeはすべての依存関係を正しく処理します。ファイルのいずれかに触れると、それは正しくビルドされます。
TARGETS:=\
my_prog.mk \
Lib1.mk \
Lib2.mk \
問題は、そのは、rules.mk通過している間、ということのようです:あなたがそうのように、メイクからm_prog.mkラインを取ると、リストの一番上に移動したときに問題が起こりますmy_prog.mk Lib1とLib2(空文字列)の完全なライブラリパスはまだわかりません。最終的には、my_progは何にも依存せず、順不同に構築しようとします。この例では、最初にmy_progを最初に、次にもう一方を「タッチ」しています。もちろん、そこに実際のコンパイラとリンカのコマンドがあると、エラーがスローされます。
私は単純に.PHONYターゲットが互いに依存していたので(my_progはLib1とLib2に依存していました)、人生は簡単で調和的でした。私はそれをすることができないので、人生はより困難になった。
あなたは「ちょうどそれを正しい順序で入れてください!」と言うかもしれません。これまでは、これはエンドユーザのmakeによって自動的に処理されていました。実際、ほとんどの顧客は物事をアルファベット順に並べています。彼らは、彼らがお互いに依存する順序を知らない、または気にしない。今すぐすべてを並べ替えるように言わなければならないのは悪臭を放つだろう。このポストの長さは申し訳ありません。私はどんな答えにも感謝しています!
これに伴う問題を、私は、各ターゲットのmakefileの変数BINARY、種類、場所、&LIBSを再利用するということです(私はその後を含む前rules.mkの最後に空にするためにそれらをリセット次の顧客.mkファイル)。ですから、もし私がそれを=の代わりに=に変更するならば、その変数の最後の値セットを使うと仮定します。もしそうなら、それは望ましい結果ではありません。確かに、私は上記の例でそれを試して、私は循環依存関係を取得します。 – user545226
私はmakeを使用するこの方法に慣れていません。各makefileは、基本的に、それがインクルードされるたびに展開され、何度もインクルードされるマクロですが、makefileはターゲットを設定し、top.mkを含みます。 BINARY/LOCATION/LIBSを設定し、rules.mkを含み、多くのものを定義します。そして最後に "すべて"のターゲットを定義します。とにかく。あなたはバイナリ、タイプ、場所、LIBSがすぐに評価されるようにしたいので、= =それらは良いです。ただし、ALL_BINSは+ =を使用して構築されており、遅延評価がすでに使用されています。 – metamatt
$(BINARY).DEP_LIBS(その代わりに= =の代わりにuse =)に遅延評価を使いたいと思っています。これは唯一必要な変更かもしれません。 – metamatt