1

C++ コードを作成したかったのです。依存関係を自動的に計算できる魔法の Makefile を既に持っていましたが、オブジェクト ファイルを別のディレクトリに保持したかったのです。したがって、構造は次のようになります。

  • Makefile
  • ソース/a/
  • ソース/b/
  • ソース/c/
  • オブジェクト/

obj/ プレフィックスを使用してソースをオブジェクトに変換する Makefile を実行することはできましたが、依存関係の計算をバックポートしたいときに事態が混乱しました。

問題は、ほとんどすべての Makefile の例が、.cpp から .d を作成する 1 つのステップで行われていることです ( %.d: %.cpp)。Makefile を理解し、試行錯誤しながら修正することに時間を費やしました。最後に、私は実用的なスクリプトを手に入れました:

DIRS := a b c
SOURCES := $(foreach dir,$(DIRS),$(wildcard source/$(dir)/*.cpp))
OBJECTS := $(patsubst %.cpp,obj/%.o,$(SOURCES))

obj/%.d: %.cpp
    @mkdir -p $(@D)
    @$(CXX) -E $(CXXFLAGS) -MM -MP -MF $@ -MQ $(@:.d=.o) -MQ $@ $<

obj/%.o: %.cpp obj/%.d
    @$(CXX) $(CXXFLAGS) -o $@ -c $<

project: $(OBJECTS)
    ...

-include $(OBJECTS:.o=.d)

しかし、なぜ cpp->d と cpp&d -> o に対して別々の手順を実行する必要があるのか​​ 、まだわかりません(または、理解できるかもしれませんが、ほとんどの例でこれが必要ない理由がわかりません)。

4

1 に答える 1

2

ソース ファイルがfoo.cppとで、bar.cppヘッダーがfoo.hbar.hであるとしfoo.cppます。foo.hbar.hbar.cppbar.h

依存ファイルをまったく含まない単純なメイクファイルを作成できます。

project: $(OBJECTS)
    ...

%.o: %.cpp
    ...

を変更するfoo.cppと、Make はfoo.o(およびproject) を再構築します。を変更するbar.cppと、Make はbar.o(およびproject) を再構築します。ヘッダーを変更しても、オブジェクトが何らかの方法でヘッダーに依存していることを Make は認識しないため、Make は何もしません。

依存ファイルのルールを入れることができます:

project: $(OBJECTS)
    ...

%.o: %.cpp
    ...

%.d:
    ...

-include *.d

これで、Make は依存関係ファイルを構築して使用します。これを行うと、Make は、変更時には を再構築する必要があり、変更時には および をfoo.h再構築する必要があることを認識します。foo.obar.hfoo.obar.o

依存ファイルを再構築することを覚えておくのは面倒です。Makeに任せたほうがいいでしょう。いつ再構築する必要foo.dがありますか?が変更されると、確かfoo.cppに:

project: $(OBJECTS)
    ...

%.o: %.cpp
    ...

%.d: %.cpp
    ...

-include *.d

ただし、 (または)foo.dのその他の前提条件が変更された場合は、再構築する必要もあります。ルール内のコマンドを詳しく説明していません (ルール内のコマンドの意味がよくわかりません) が、単純なルールを作成すると、次のようになります。foo.ofoo.hbar.h%.dfoo.d

foo.o: foo.cpp foo.h bar.h

foo.d次のようなを生成するコマンドを書くことができます。

foo.o: foo.cpp foo.h bar.h

foo.d: foo.cpp foo.h bar.h

もっと洗練された方法もありますが、今日はこれで十分です。

多くの例の makefile が特定の次善の機能を共有している理由については、すべての機能を厳密に調べたり理解したりせずに、人々が互いの makefile をコピーしているためです。

于 2012-11-24T18:28:41.477 に答える