[解決済み] C++プロジェクトの構成 (gtest, cmake, doxygenを使用)
質問
私はプログラミング全般が初めてなので、C++で簡単なベクタークラスを作ることから始めようと思いました。 しかし、私は後で私のワークフローを修正しようとするのではなく、最初から良い習慣を身につけたいと思います。
現在、私は2つのファイル
vector3.hpp
と
vector3.cpp
. このプロジェクトは徐々に大きくなり(一般的な線形代数ライブラリになる)、私がすべてに精通するようになるので、後々の生活を楽にするために、標準的なプロジェクトのレイアウトを採用したいと思います。 そこで、いろいろ探した結果、hppとcppのファイルを整理するための2つの方法を見つけました。
project
└── src
├── vector3.hpp
└── vector3.cpp
であり、2番目は
project
├── inc
│ └── project
│ └── vector3.hpp
└── src
└── vector3.cpp
どちらがお勧めですか、またその理由は?
第二に、私は自分のコードをユニットテストするためにGoogle C++ Testing Frameworkを使いたいと思っています。これを私のコードにバンドルすることをお勧めします。
inc/gtest
または
contrib/gtest
フォルダーを使用しますか?バンドルされている場合は
fuse_gtest_files.py
スクリプトを使用してファイル数を減らすか、またはそのままにしておくことをお勧めしますか? バンドルされていない場合、この依存関係はどのように処理されますか?
テストを書くとき、これらは一般的にどのように構成されていますか? 私は、各クラスに1つのcppファイルを持っていると考えていました(
test_vector3.cpp
など)しかし、それらはすべて簡単に一緒に実行できるように、1つのバイナリにコンパイルされていますか?
gtestライブラリは一般的にcmakeとmakeを使用してビルドされるので、私のプロジェクトもこのようにビルドされるのが理にかなっていると思いましたか? 私が以下のプロジェクト レイアウトを使用することに決めた場合。
├── CMakeLists.txt
├── contrib
│ └── gtest
│ ├── gtest-all.cc
│ └── gtest.h
├── docs
│ └── Doxyfile
├── inc
│ └── project
│ └── vector3.cpp
├── src
│ └── vector3.cpp
└── test
└── test_vector3.cpp
どのように
CMakeLists.txt
はどのようにすればライブラリだけ、あるいはライブラリとテストをビルドできるようになるのでしょうか? また、私は多くのプロジェクトで
build
と
bin
というディレクトリがあります。 ビルドはビルドディレクトリで行われ、その後バイナリはbinディレクトリに移動されるのでしょうか? テスト用とライブラリ用のバイナリは同じ場所にあるのでしょうか?それとも、次のように構成するのがより理にかなっているのでしょうか。
test
├── bin
├── build
└── src
└── test_vector3.cpp
また、doxygenを使用してコードを文書化したいと思います。 これをcmakeとmakeで自動的に実行させることは可能でしょうか?
多くの質問で申し訳ありませんが、私はこの種の質問に満足に答えてくれるC++の本を見つけられませんでした。
どのように解決するのですか?
C++ ビルド システムはちょっとしたブラックアートであり、プロジェクトが古ければ古いほど、より多くの奇妙なものを見つけることができます。 プロジェクトが古ければ古いほど、より多くの奇妙なものを見つけることができるので、多くの質問が出るのは驚くことではありません。 質問が出てくるのも不思議ではありません。ここでは、質問を 1 つずつ解決し、C++ ライブラリのビルドに関する一般的な事柄について言及したいと思います。
ヘッダーと cpp ファイルをディレクトリで分離すること。これは
実際の使用ではなく、ライブラリとして使用されることを想定したコンポーネントを構築している場合にのみ重要です。
実際のアプリケーションとは対照的に、ライブラリとして使用されることを想定したコンポーネントを構築する場合にのみ必要です。ヘッダは
ヘッダは、ユーザがあなたの提供するものと対話するための基礎であり、インストールされなければなりません。
インストールされなければなりません。これは、ヘッダがサブディレクトリになければならないことを意味します (誰もヘッダがトップディレクトリにあることを望んでいません)。
にあることを誰も望んでいません。
/usr/include/
の中で終わるたくさんのヘッダは誰も望みません)、そしてあなたの
ヘッダはそのようなセットアップで自分自身を含めることができなければなりません。
└── prj
├── include
│ └── prj
│ ├── header2.h
│ └── header.h
└── src
└── x.cpp
はうまく機能します。なぜなら、インクルードパスがうまく機能し、インストールターゲットに簡単に グロビングが使えるからです。
依存関係をバンドルする。これは主に、ビルドシステムが依存関係を見つけ、設定する能力と、どのように依存関係を設定するかに依存すると思います。
これは、ビルドシステムが依存関係を見つけ、設定する能力と、コードが1つのバージョンにどれだけ依存しているかに大きく依存すると思います。
一つのバージョンにどの程度依存しているかに依存します。また、ユーザーがどれだけ
また、ユーザーがどれだけ有能であるか、そして彼らのプラットフォームにどれだけ簡単に依存関係をインストールできるかに依存します。
プラットフォームにも依存します。CMake には
find_package
スクリプトが付属しており、Google
のテストを行います。これを使えば、かなり楽になります。私はバンドルは必要なときだけ行い
バンドルは必要なときだけにして、それ以外は避けたほうがいいと思います。
ビルドの仕方 インソースビルドを避ける。CMakeはソース外ビルドを簡単にします。 を容易にし、生活をより楽にしてくれます。
あなたのシステムのテストを実行するために CTest も使いたいと思います (これは GTest のビルドインサポートも備えています)。
GTest のビルドイン サポートも提供されています)。ディレクトリのレイアウトとテストの構成に関する重要な決定事項は
ディレクトリのレイアウトとテストの構成に関する重要な決定となります。最終的に
サブプロジェクトで終わるか?もしそうなら、CMakeLists をセットアップする際にもう少し作業が必要です。
を設定する際にもう少し工夫が必要で、サブプロジェクトをサブディレクトリに分割し、それぞれに
独自の
include
そして
src
ファイルを作成します。もしかしたら、独自のdoxygenの実行と出力もあるかもしれません。
出力(複数のdoxygenプロジェクトを結合することは可能ですが、簡単ではありません。
またはきれいではありません)。
このようなものに行き着くでしょう。
└── prj
├── CMakeLists.txt <-- (1)
├── include
│ └── prj
│ ├── header2.hpp
│ └── header.hpp
├── src
│ ├── CMakeLists.txt <-- (2)
│ └── x.cpp
└── test
├── CMakeLists.txt <-- (3)
├── data
│ └── testdata.yyy
└── testcase.cpp
ここで
- (1) 依存性、プラットフォーム仕様、出力パスの設定
- (2) ビルドしようとするライブラリの設定
- (3) テスト実行ファイルとテストケースを設定します。
サブコンポーネントがある場合、別の階層を追加して、各サブプロジェクトに上記のツリーを使用することをお勧めします。なぜなら、サブコンポーネントがその依存関係を検索および設定するか、あるいはトップレベルでそれを行うかを決定する必要があるからです。これは、ケースバイケースで決定されるべきです。
Doxygenです。のコンフィギュレーションダンスをなんとかこなした後は
を使うのは簡単です。
add_custom_command
を使って
doc ターゲットを追加します。
これは私のプロジェクトがどのように終わるかであり、非常によく似たプロジェクトをいくつか見てきましたが、もちろんこれは万能ではありません。
追記
ある時点で、あなたは
config.hpp
ファイルを生成したいと思うでしょう。このファイルにはバージョン定義と、バージョン管理識別子(GitハッシュやSVNリビジョン番号)の定義が含まれています。
バージョン管理識別子(GitハッシュやSVNリビジョン番号)を含むconfigure_file
を使って、テンプレートファイル内の変数を
の中で定義された変数に置き換えることができます。
CMakeLists.txt
.
ライブラリをビルドする場合、コンパイラ間の違いを正しく理解するために、エクスポート定義も必要です。
コンパイラ間の違いを正しく理解するために、例えば
__declspec
は MSVC
と
visibility
属性があります。
関連
-
[解決済み】Visual Studio 2015で「非標準の構文。'&'を使用してメンバーへのポインターを作成します」エラー
-
[解決済み】クラステンプレートの引数リストがない
-
[解決済み】C++ 式はポインタからオブジェクトへの型を持っている必要があります。
-
[解決済み】cc1plus:エラー:g++で認識されないコマンドラインオプション"-std=c++11"
-
[解決済み] 非静的データメンバの無効な使用
-
[解決済み】指定範囲内の乱数で配列を埋める(C++)
-
[解決済み】エラー。引数リストに一致するコンストラクタのインスタンスがない
-
[解決済み】CMakeの出力を'bin'ディレクトリにする方法は?
-
[解決済み] CMake:ユニットテストによるプロジェクト構造
-
[解決済み] GTestとCMakeを使った作業の始め方
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み】C++エラー。アーキテクチャ x86_64 に対して未定義のシンボル
-
[解決済み】getline()が何らかの入力の後に使用されると動作しない 【重複あり
-
[解決済み】LLVMで暗黙のうちに削除されたコピーコンストラクタの呼び出し
-
[解決済み】非静的メンバ関数への参照を呼び出す必要がある
-
[解決済み】C++ - 解放されるポインタが割り当てられていないエラー
-
[解決済み】関数名の前に期待されるイニシャライザー
-
[解決済み】c++でstd::vectorを返すための効率的な方法
-
[解決済み】クラスのコンストラクタへの未定義参照、.cppファイルの修正も含む
-
[解決済み】なぜ、サイズ8の初期化されていない値を使用するのでしょうか?
-
[解決済み】変数やフィールドがvoid宣言されている