1. ホーム
  2. c++

[解決済み] C++プロジェクトの構成 (gtest, cmake, doxygenを使用)

2022-06-28 07:54:19

質問

私はプログラミング全般が初めてなので、C++で簡単なベクタークラスを作ることから始めようと思いました。 しかし、私は後で私のワークフローを修正しようとするのではなく、最初から良い習慣を身につけたいと思います。

現在、私は2つのファイル vector3.hppvector3.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 はどのようにすればライブラリだけ、あるいはライブラリとテストをビルドできるようになるのでしょうか? また、私は多くのプロジェクトで buildbin というディレクトリがあります。 ビルドはビルドディレクトリで行われ、その後バイナリは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リビジョン番号)を含むファイルを生成したいと思うでしょう。CMakeには モジュールがあり、その情報を自動的に見つけて ファイルを生成するモジュールがあります。あなたはCMakeの configure_file を使って、テンプレートファイル内の変数を の中で定義された変数に置き換えることができます。 CMakeLists.txt .

ライブラリをビルドする場合、コンパイラ間の違いを正しく理解するために、エクスポート定義も必要です。 コンパイラ間の違いを正しく理解するために、例えば __declspec は MSVC と visibility 属性があります。