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

基本的に、これはすべての*.cppファイルをサブフォルダーから抽出し、さらにオブジェクトの名前としておよびにsrc置き換えます。./src./obj.cpp.o

.PHONY: clean all depend

all: $(TARGET)

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

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

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),$@))" \
    $(addprefix ,$@) >> $(DEP);

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

depend: clear_dependencies $(SRCS)

これは非機能部分です。私がやろうとしているのは、g++Compiler フラグ-MMを使用して依存関係を自動作成し-MT、デフォルトとは異なるパスを使用することです。結果の依存関係は次のようになります

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

残念ながら、これが呼び出されることはありません。なぜそうなのか、私にはわかりません。同様の質問で、ベータ版ユーザーはaを追加することで一時的な解決策を喜んで提供しました.Phonyが、これには変更を加えずにすべてのオブジェクトを再構築するという副作用があります。

最後に、1行だけです

-include $(DEP)

一度作成された依存関係ファイルを含めます。

任意の部分に関するヒントを提供する回答は大歓迎です。だから私の質問は次のとおりです。どうすればもっとうまくできるか、おそらく「よりクリーン」になり、依存関係の生成が機能しないのはなぜですか?

4

1 に答える 1

9

ここに行きます。


可能であれば、単純に展開された変数を割り当てます。

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

GNU Makeマニュアルから:

[再帰的に展開された変数の] もう 1 つの欠点は、変数が展開されるたびに、定義で参照されているすべての関数が実行されることです。これにより、make実行が遅くなります。さらに悪いことに、いつ呼び出されるか、または何回呼び出されるかを簡単に制御できないため、 関数wildcardと関数が予測できない結果をもたらす原因となります。shell


ソースをオブジェクトに変換するには、置換参照またはpatsubst関数を使用します。

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

コンパイル パターン ルールで適切な前提条件を指定します。これは、Make がオブジェクト ファイルを最新の状態に保ち、ソースの変更時にそれらを更新するために必須です。

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

ソースをコンパイルし、それらの依存ファイルを同時に生成します。フラグを使用-MMD -MPして物事を機能させます (フラグを に追加するだけCXXFLAGSです)。

CXXFLAGS += -MMD -MP

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

GCCマニュアルから:

-MD

-MD暗示されていないことを除いて、-M -MF fileと同等です。-Eドライバーは、-o オプションが指定されているかどうかに基づいてファイルを判別します。そうでない場合、ドライバーはその引数を使用しますが、サフィックスは です.d。それ以外の場合は、入力ファイルの名前を取得し、ディレクトリ コンポーネントとサフィックスを削除して、サフィックスを適用し.dます。

-MMD

同様-MDに、システム ヘッダー ファイルではなく、ユーザー ヘッダー ファイルのみに言及します。

-MP

このオプションは、メイン ファイル以外の依存関係ごとに偽のターゲットを追加するように CPP に指示し、それぞれが何にも依存しないようにします。makeこれらのダミー ルールは、一致するように更新せずにヘッダー ファイルを削除した場合に発生するエラーを回避しますMakefile

また、Paul Smith (彼は GNU Make のメンテナーです) のこの記事を検討することを検討してください。さまざまな autodep 生成アプローチのかなり良い概要を提供します。

于 2012-05-04T21:25:27.453 に答える