2012-05-04 6 views
4

現在、適切なMakefileをビルドしようとしています。メイクファイルの改善、依存関係の生成が機能しない

私が欲しいのは、何が起こっているのかを完全にコントロールしているため、サードパーティのソフトウェアは必要ありません。

私の現在の試みは私にとって論理的だと思われますが、依存関係の生成は有効ではないので、私は固執しています。

読みやすさを向上させるために、完全なMakefileは小さな断片に分割されています。改善すべきことがあれば、どのセクションにもコメントしていただければ幸いです。すべての

まず、私は、この私の知る限り、以下の静的な定義

CXX = g++ 
CXXFLAGS = -Wall \ 
      -Wextra \ 
      -Wuninitialized \ 
      -Wmissing-declarations \ 
      -pedantic \ 
      -O3 \ 
      -p -g -pg 
LDFLAGS = -p -g -pg 
DEPFLAGS = -MM 

は問題ないはずです。プロファイルフラグをオプションにすることは完璧ですが、それは重要ではありません。

SRC_DIR = ./src 
OBJ_DIR = ./obj 
SRC_EXT = .cpp 
OBJ_EXT = .o 

TARGET = ./bin/my_target 

SRCS = $(wildcard $(SRC_DIR)/*$(SRC_EXT)) 
OBJS = $(subst $(SRC_DIR), $(OBJ_DIR), $(SRCS:$(SRC_EXT)=$(OBJ_EXT))) 
DEP = depend.main 

基本的に、これは単なるサブフォルダsrcのうち、すべての*.cppファイルを抽出し、さらにオブジェクトの名前として.o./obj.cpp./srcを置き換える必要があります。

.PHONY: clean all depend 

all: $(TARGET) 

$(TARGET): $(OBJS) 
    @echo "-> linking [email protected]" 
    @$(CXX) $^ $(LDFLAGS) -o [email protected] 

$(OBJ_DIR)/%.$(EXT_OBJ): 
    @echo "-> compiling [email protected]" 
    @$(CXX) $(CXXFLAGS) -c $< -o [email protected] 

Afaikこのブロックは、有効な依存ファイルが存在するため、必要なコンパイルとリンクをすべて行う必要があります。

clean: 
    @echo "removing objects and main file" 
    @rm -f $(OBJS) $(TARGET)  

ここには何かが欠けていますか?

$(SRC_DIR)/%.$(SRC_EXT): 
    $(CXX) $(DEPFLAGS) -MT \ 
    "$(subst $(SRC_DIR),$(OBJ_DIR),$(subst $(SRC_EXT),$(OBJ_EXT),[email protected]))" \ 
    $(addprefix ,[email protected]) >> $(DEP); 

clear_dependencies: 
    @echo "-> (re-)building dependencies"; 
    @$(RM) $(DEP) 

depend: clear_dependencies $(SRCS) 

これは機能しない部分です。私が行うことは、g++コンパイラフラグ-MMを使用して依存関係を自動作成し、-MTを使用してデフォルトのパスとは異なるパスを使用することです。 は、得られた依存関係が

./obj/main.o: ./src/main.cpp ./src/some_header_file.h 

のようになります。残念ながら、これは呼び出されませんし、私はこれが事実である理由の知識が不足しています。 similar questionでは、ユーザーBetaは.Phonyを追加して喜んで一時的な解決策を提供しましたが、これは変更なしですべてのオブジェクトを再構築する副作用があります。

は最後に、ちょうど1行

-include $(DEP) 

は、一度作成された依存関係ファイルを含めることがあります。

どの部分についてのヒントも提供する回答は大歓迎です。 私の質問は次のとおりです:どうすればよいでしょうか、あるいは「きれいにする」ことができます。なぜ依存関係の生成は機能しませんか?

+0

Hmph!私は 'PHONY'のやり方はちょっと止まらないと言っていました。私たちは次の反復で依存関係をカバーします。あなたが他の意見を呼びたい場合は、罰金、しかし私はあなたにスリップホップのアドバイスを与えた人々に伝えていない。 – Beta

+0

申し訳ありませんが、これは誤解です。私はあなたの答えを持ってうれしいですが、より詳細な質問を作りたいと思っていました。これはちょうど古いものを更新すれば面倒です。私はあなたの努力と答えに非常に感謝します。 – stefan

答えて

9

ここになります。定義で参照される任意の機能が毎回実行されることである

[再帰的に展開変数の]別の欠点:

SRCS := $(wildcard $(SRC_DIR)/*$(SRC_EXT)) 

GNU Make manualより:可能


割り当てsimply expanded variables変数が展開されます。これにより、makeが遅く実行されます。悪化すると、wildcardshellの関数は、呼び出しのタイミングや回数を簡単に制御できないため、予測できない結果を引き起こします。オブジェクトにソースを変換する


使用substitution referencesまたはpatsubst function

OBJS := $(SRCS:$(SRC_DIR)/%$(SRC_EXT)=$(OBJ_DIR)/%$(OBJ_EXT)) 

コンパイルパターンルールで適切な前提条件を指定してください。これはです。を取得するオブジェクトファイルを最新の状態に保ち、ソースの変更でそれらを更新するようにします。

$(OBJ_DIR)/%$(OBJ_EXT) : $(SRC_DIR)/%$(SRC_EXT) 
    @echo "-> compiling [email protected]" 
    @$(CXX) $(CXXFLAGS) -o [email protected] -c $< 

ソースをコンパイルすると同時に、それらの依存ファイルを生成します。物事を取り戻すには-MMD -MPフラグを使用してください(ちょうどCXXFLAGSに追加してください)。 GCC manualから

CXXFLAGS += -MMD -MP 

-include $(OBJS:$(OBJ_EXT)=.d) 

-MD

-MD-Eが暗示されていないことを除いて、-M -MFファイルに相当します。ドライバは、-oオプションが指定されているかどうかに基づいてファイルを決定します。そうである場合、ドライバはその引数を使用しますが、接尾辞は.dです。それ以外の場合は、入力ファイルの名前を取り、ディレクトリコンポーネントと接尾辞を削除し、接尾辞.dを適用します。言及のみ、ユーザヘッダファイルではなく、システムヘッダファイルを除く-MD同様

-MMD

-MP

このオプションは、CPPが何に依存するように各を引き起こし、メインファイル以外の各依存関係のために偽のターゲットを追加するように指示します。これらのダミールールは、エラーmakeが、Makefileを更新せずにヘッダファイルを削除した場合に発生します。

また、Paul Smithの(彼はGNU Makeのメンテナ)を勉強することを検討してください。これは、さまざまなオートデスク生成アプローチのかなり良い概要を示しています。

+0

お返事ありがとうございます、それはかなりうまく動作します。変数が「シンプル」なのか、潜在的な改善が残っているのか、これが最適なのか分かりません。 – stefan

+1

@stefan、再帰的な変数の代わりに単純に展開された変数を使うと、その値が 'wildcard'のような非自明な関数を呼び出すときに、より速くなる可能性があります。個人的には、再帰的に展開された変数は、カスタム関数を定義するためにのみ使用されます。これは['call'関数](http://www.gnu.org/software/make/manual/make.html#Call-Function)を使って呼び出されます。 –

+0

@stefan、これは素晴らしい答えです。Paul Smithの記事は、私が取り組んできたものです。追加するものがあるかどうかを確認し、他の質問で回答を編集します。 – Beta

関連する問題