7

プロジェクトには次のディレクトリ構造があります。

bin/
dist/
include/
├── module_a/
└── module_b/
Makefile
src/
├── module_a/
└── module_b/

'sがにある間、フォルダには'sinclude/が含まれます。すべてのソースをにコンパイルしてから、それらをにリンクしたいと思います。私にとってはかなり合理的な願いのようです。*.hpp*.cppsrc/bin/dist/

この場合のMakefileのベストプラクティスを知りたいです。私が見つけることができるのは%.o: %.cppターゲットだけですが、ソースとバイナリフォルダーが異なるため、実際には機能しません。

私はこのようなものを使おうとしていました:

D_SRC = src
D_BIN=bin

F_CPP   :=  $(shell find $(D_SRC) -iname '*.cpp' -type f)
F_OBJ   :=  $(shell echo $(F_CPP) | sed s:\ :\\n:g | sed s:$(D_SRC):$(D_BIN): | sed 's:^\(.*\)\.cpp$$:\1\.o:')

$(F_OBJ): $(F_SRC)                                                                  
    $(foreach file, $(F_SRC), \                                                     
        $(GXX) $(CXXFLAGS) -c $(file)\                                              
    )

$(F_OBJ)パスは。で始まり、bin/ソースforeachを現在の作業ディレクトリにコンパイルするため、このターゲットは機能しません。にコンパイルすることもできますがbin/、それはさらにいくつかの式でのみ発生し、sedそのままでは醜いです。

よくわからないので難しいかもしれませんmakeが、このプロジェクトを立ち上げたのは私だけではありません。私の意見では、それはかなり一般的なものでなければなりません。Makefileモジュールごとに個別にを書くことができることは知っていますが、それは本当にここでの最良の選択ですか?

編集:私は今、いくつかのMakefileで何を達成できるのか疑問に思っていました。1つがルートにあり、もう1つがにある場合src/module_a、後者はどのようにしてbin/?を使用して実行する場合はmake -f src/module_a/Makefile、ルートディレクトリから実行するのと同じになります。これは、作業ディレクトリがルートになるためです。別の方法は、次のように、実行する前にディレクトリを変更することだと思いますmake -C include/module_a。しかし、その場合、どのように見つけるのでしょうbin/か。D_BIN = ../../binMakefileのようなものは使いたくありません。

4

1 に答える 1

7

私が通常行うことは、srcディレクトリにMakefileを置き(必要に応じてトップレベルのMakefileから呼び出すことができます)、次のようなルールを使用することです。

D_BIN = ../bin
$(D_BIN)/%.o: %.cpp

トップレベルのディレクトリでmakefileだけを試して、次のようなルールを使用することもできます。

D_BIN = bin
D_SRC = src
$(D_BIN)/%.o: $(D_SRC)/%.cpp

しかし、私はそのようなルールを使用したことがないので、私は通常の方法と比較して長所/短所を知りません。私が通常行う方法は正常に機能し、次のようにビルドするルールもあります。

$(D_BIN)/%.d: %.cpp 

リンクルールは次のようになります。

../dist/outexe: $(F_OBJ)

foreachの使用は、通常のmakefileルールに組み込まれているすべての機能を利用していないため(つまり、ファイルごとに依存チェックがないため、すべてをビルドするか、何もビルドしないか)、通常は眉をひそめます。最後の手段として使用されますが、この場合、foreachなしで動作させることができます。

これに加えて、ファイルリストを作成するためのはるかに簡単な方法があり、シェルやsedを使用する必要はありません。

F_CPP = $(wildcard *.cpp)
F_OBJ = $(F_CPP:.cpp=.o)

更新:これは私が通常再帰的なmakeを発行する方法です:

SUBDIRS = src
.PHONY: $(SUBDIRS)
all: $(SUBDIRS)

$(SUBDIRS):
    @echo "Building $@..."
    $(MAKE) -C $@ $(MFLAGS)

次に、実際にサブメイクで、たとえば../binを使用する必要があります。

ただし、プロジェクトが自分のプロジェクトと同じくらい単純な場合は、ルートレベルに1つのmakefileを用意し、次のようなルールを使用する方がよい場合があります。

D_BIN = bin
D_SRC = src
$(D_BIN)/%.o: $(D_SRC)/%.cpp

非常に複雑なディレクトリ構造があり、時間が経つにつれて新しいdirツリーを追加/削除/変更する場合は、再帰的なmakefileは問題ありません(ただし、あまり良くありません)。しかし、コードとオブジェクト用に別々のディレクトリが必要な単純なプロジェクトの場合、それはおそらくやり過ぎです。

于 2012-12-03T19:55:34.087 に答える