3

いくつかのC++ファイルをコンパイルしたいので、すべてのオブジェクトファイルを別のビルドディレクトリに配置する必要がありますが、完全にフラットに保存されます。つまり、サブディレクトリはありません。私はVPATHを使用した一般的な解決策を知っています。これは次のようになります。

SOURCES = foo/one.cpp \
    foo/bar/two.cpp \
    foo/bar/sub/three.cpp

OBJDIR = obj

VPATH=$(dir $(SOURCES))

OBJECTS = $(addprefix $(OBJDIR)/, $(notdir $(SOURCES:%.cpp=%.o)))

$(OBJDIR)/%.o : %.cpp
    @echo Should compile: $(filter %/$*.cpp, $(SOURCES))
    @echo Compiling $<

all: $(OBJECTS)

この例はほとんど機能します。「obj」サブディレクトリに3つのオブジェクトファイルone.o、two.o、three.oがあります(存在しているとみなすことができます)。

VPATHを使用する場合の注意点は次のとおりです。ファイル「foo/three.cpp」がある場合、これはSOURCES変数で指定されている「foo / bar / sub/three.cpp」の代わりにコンパイルされます。いいえ、どちらのファイルの名前も変更できません。この名前の衝突は単に存在し、私はそれについて何もできません。

だから私の質問は: SOURCES変数に表示される「.cpp」ファイルのみを使用するようにMakeに指示するにはどうすればよいですか?最善の解決策は、ターゲットの前提条件でその「filter」ステートメントを使用することだと思います。これは二次拡張を使用して可能になるはずですが、「%」をどうすればよいかわかりません。たとえば、私は試しました

 .SECONDEXPANSION:
$(OBJDIR)/%.o : $$(filter %/$$*.cpp, $(SOURCES))

しかし、それは機能しません。


更新:tripleeの助けを借りて、私はこれを次のように機能させることができました:

define make-deps
$(OBJDIR)/$(notdir $(1:%.cpp=%.o)): $1
endef

$(foreach d, $(SOURCES), $(eval $(call make-deps,$d)))

%.o : 
    @echo Should compile $^ into $@
    @echo Compiling $^
4

1 に答える 1

3

あなたの問題に対する最も簡単な解決策は、VPATH各依存関係を明示的に取り除き、文書化することだと思います。SOURCESこれはあなたの定義から簡単に得ることができます。おそらくあなたは関数を定義したいのですが、それは本当にこれに要約されます:

obj/one.o: foo/one.cpp
obj/two.o: foo/bar/two.cpp
obj/three.o: foo/bar/sub/three.cpp

実際のルールはそのままにしておくことができますが、依存関係がインラインに含まれなくなった場合にのみ、obj/サブディレクトリをスキップできます。これは、各依存関係で明示的に宣言されているためです。

%.o : # Dependencies declared above
    @echo Should compile $^ into $@
    @echo Compiling $^

複数の依存関係がある場合に備えて、$^代わりに使用するルールを変更しました。$<これはあなたの状況にとって正しいか間違っているかもしれません。必要なものでない場合は、変更を元に戻します。

依存関係を手動で維持する必要がないように、ファイル%.dごとに生成することをお勧めし%.cppます。GNUMakeのマニュアルを参照してください。(私はを使用してこれを実行しようとしましたが、ループdefineで依存関係を宣言できないようです。)foreach

コメントの質問に答えて、これは並列ビルドに影響を与えるべきではありません。に同じ名前の複数のbiuld候補があった場合に、元のMakefileがあいまいであった依存関係を明確にするだけVPATHです。新しい依存関係や新しいルールはありません。

于 2012-11-27T20:42:05.857 に答える