web-dev-qa-db-ja.com

Makefileを使用した大規模なC ++プロジェクトに適したディレクトリ構造は何ですか?

Makefileを使用した大規模なC++プロジェクトに適したディレクトリ構造は何ですか?

これは私のディレクトリ構造が今どのように見えるかです:

lib/ (class implementations *.cpp)
include/ (class definitions *.h)
tests/ (main.cpp for quick tests)

現在、Makefileがどのように見えるのかわかりません... .cppファイルと.hファイルが同じディレクトリにない場合は動作しないようです。誰も私が車輪を再発明しないように、付随するMakefileで共通のディレクトリ構造を指すことができますか?

48
Olivier Lalonde

.hファイルの.cppを分離することが常に良い解決策とは限りません。通常、ライブラリとして使用する場合は両方を分離します(インクルードのパブリックヘッダーとソースコードのプライベートヘッダー)。

ライブラリである場合、この構造は問題ありません。

lib/ (class implementations *.cpp .h)
include/ (class definitions *.h) <- Only those to be installed in your system
tests/ (main.cpp for quick tests)
doc/ (doxygen or any kind of documentation)

アプリケーションの場合

src/ (source for the application)
lib/ (source for the application library *.cpp *.hpp)
include/ (interface for the library *.h)
tests/ (main.cpp for quick tests) <- use cppunit for this part
doc/ (doxygen or any kind of documentation)

フラグ-I $(PROJECT_BASE)/ includeを使用して、コンパイルのインクルードパスを指定します

大きなプロジェクトの場合は、autoconf/automakeまたはcmakeなどのツールを使用してすべてをビルドするとよいでしょう。開発が容易になります。

57
Phong

特定または必須のディレクトリ構造はありません。

好きなように設定できます。あなたの問題は簡単に解決できます。現在のディレクトリだけを使用する代わりに、Makefileにサブディレクトリを調べるように指示するか、コンパイルされたオブジェクトをサブディレクトリに入れるだけです。

Makefileパスで使用するだけです:

%.o : %.cpp

と置換する

bin/%.o : %.cpp

そのため、ディレクトリbinにバイナリファイルが存在するかどうかをチェックし、以下同様に、ファイルがコンパイルされる場所に同じファイルを適用できます。

ソースファイルとオブジェクトファイルのパスを追加/削除/変更する方法があります。

gnu make manual 、特にセクション8.3ファイル名の関数とその前のもの8.2文字列の置換と分析のための関数

次のようなことができます:

現在のディレクトリにあるソースファイルのリストからオブジェクトのリストを取得します。

OBJ     = $(patsubst %.cpp, %.o, $(wildcard *.cpp))

出力:

Application.o Market.o ordermatch.o

バイナリオブジェクトがサブディレクトリbinにあるが、ソースコードが現在のディレクトリにある場合、生成されるオブジェクトファイルにプレフィックスbinを適用できます。

OBJ     = $(addprefix bin/,$(patsubst %.cpp, %.o, $(wildcard *.cpp)))

出力:

bin/Application.o bin/Market.o bin/ordermatch.o

等々。

12
stefanB

ソースファイルが多数ある場合は、ソースディレクトリをさらに細分化することをお勧めします。たとえば、アプリケーションのコア機能用のサブディレクトリ、GUI用のサブディレクトリなど。

src/core
src/database
src/effects
src/gui
...

また、そうすることで、「モジュール」間の不要な関係を回避せざるを得ません。これは、ニースと再利用可能なコードの前提条件です。

12
Gnurou

「適切なディレクトリ構造」はありません。快適な構造を選び、それに固執します。ソースファイル(ヘッダーと実装ファイル)をsrc/ディレクトリに配置するようなものもあります。そのため、プロジェクトのルートディレクトリには、メイクファイル、readmeなどがあります。ヘルパーライブラリをlib/ディレクトリの下に配置したり、unittestsをtest/またはsrc/test/の下に配置したり、ドキュメントをdoc/の下に配置したりすることができます。

ただし、ヘッダーファイルと実装ファイルを2つの別個のディレクトリに分割することを聞いたことはありません。個人的には、ファイルをディレクトリに分割することはあまり好きではありません。通常、すべてのソースを単一のディレクトリに配置し、すべてのドキュメントを別のディレクトリに配置します。とにかく優れた検索ツールに依存している場合、複雑なディレクトリ構造は必要ありません。

makeは、メイクファイルがソースとは異なるディレクトリにあるような構造を処理できます。唯一のことは、メイクファイルのディレクトリからルールを呼び出すことです。通常、コンパイラは、サブディレクトリにあるソースのコンパイルに問題はありません。 #includesで相対パスを指定する必要はありません。コンパイラフラグ(gccの-Iフラグなど)でインクルードパスを指定するだけです。

6
wilhelmtell

読む前にそれを見たことがない場合 再帰的に有害と見なされる

短い、短いバージョン:非常に一般的ですが、再帰的なmakeのイディオムは最適ではなく、プロジェクトが大きく複雑になるにつれて悪化します。代替案が提示されます。

関連リンク: 非再帰makeでの経験は?

3
dmckee