2011-01-26 5 views
1

これは私の以前の質問に関連しています: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によって自動的に処理されていました。実際、ほとんどの顧客は物事をアルファベット順に並べています。彼らは、彼らがお互いに依存する順序を知らない、または気にしない。今すぐすべてを並べ替えるように言わなければならないのは悪臭を放つだろう。このポストの長さは申し訳ありません。私はどんな答えにも感謝しています!

答えて

1

:=代入演算子を使用して変数を設定した場合、代入はすぐに評価されます。

代入演算子としてjust =を使用して変数を設定すると、できるだけ遅く(実際の使用時に)遅れて評価されます。

http://www.gnu.org/software/automake/manual/make/Flavors.htmlを参照してください。

+0

これに伴う問題を、私は、各ターゲットのmakefileの変数BINARY、種類、場所、&LIBSを再利用するということです(私はその後を含む前rules.mkの最後に空にするためにそれらをリセット次の顧客.mkファイル)。ですから、もし私がそれを=の代わりに=に変更するならば、その変数の最後の値セットを使うと仮定します。もしそうなら、それは望ましい結果ではありません。確かに、私は上記の例でそれを試して、私は循環依存関係を取得します。 – user545226

+0

私はmakeを使用するこの方法に慣れていません。各makefileは、基本的に、それがインクルードされるたびに展開され、何度もインクルードされるマクロですが、makefileはターゲットを設定し、top.mkを含みます。 BINARY/LOCATION/LIBSを設定し、rules.mkを含み、多くのものを定義します。そして最後に "すべて"のターゲットを定義します。とにかく。あなたはバイナリ、タイプ、場所、LIBSがすぐに評価されるようにしたいので、= =それらは良いです。ただし、ALL_BINSは+ =を使用して構築されており、遅延評価がすでに使用されています。 – metamatt

+0

$(BINARY).DEP_LIBS(その代わりに= =の代わりにuse =)に遅延評価を使いたいと思っています。これは唯一必要な変更かもしれません。 – metamatt

0

希望することを行うにはいくつかの方法があります。最もきれいなのはおそらくvpathです。ただ、rules.mkを変更します。

$(BINARY).DEP_LIBS:=$(foreach a,$(LIBS),$(a).so) 
ALL_BINS+=$(BINARY) 

vpath %.so out/$(LOCATION) 
+0

ありがとうございます。私はこれが近づいているかもしれないと思うが、まだそこにはない。まず、最初の行 "$(BINARY).DEP_LIBS:= $(foreach a、$(LIBS)、lib $(a).so)"を作ったが、残りはあなたが言った方法と同じである。今では、/ some/location/my_prog.exeをビルドする前にlibLib1.soとlibLib2.soを "ビルド"していますが、それぞれの場所ではなくプロジェクトのルートにあります。その後、2つのライブラリをその場所に構築します。 3の代わりに5つのターゲットがあるかのように。my_progの最初の2人の扶養者を考慮しているようですが、後者2はそうではないと思います。 – user545226

+0

私は今この方法がうまくいかないと確信しています。私はプロジェクトのルートディレクトリに.soファイルをビルドしようとする以外の何かをすることはできません。 これを行うためにvpathを使用する以外に、ややクリーンな方法はありますか? – user545226

関連する問題