133

私は一般的にプログラミングに慣れていないので、C++で単純なベクトルクラスを作成することから始めることにしました。ただし、後でワークフローを変更するのではなく、最初から良い習慣を身に付けたいと思います。

私は現在2つのファイルvector3.hppvector3.cpp。このプロジェクトは、私がすべてに精通するにつれてゆっくりと成長し始めます(より一般的な線形代数ライブラリになります)。そのため、後で作業を楽にするために「標準」プロジェクトレイアウトを採用したいと思います。ですから、周りを見回した後、hppファイルとcppファイルを整理する2つの方法を見つけました。1つ目は次のとおりです。

project
└── src
    ├── vector3.hpp
    └── vector3.cpp

そして2番目は:

project
├── inc
│   └── project
│       └── vector3.hpp
└── src
    └── vector3.cpp

どちらをお勧めしますか、またその理由は何ですか?

次に、コードの単体テストにGoogle C ++テストフレームワークを使用したいと思います。これは、かなり使いやすいように思われるためです。これを私のコードとバンドルすることをお勧めしますか?たとえば、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++の本は見つかりませんでした。

4

4 に答える 4

90

C ++ビルドシステムは少しブラックアートであり、プロジェクトが古ければ古いほど奇妙なものを見つけることができるので、多くの質問が出てくるのは当然のことです。質問を1つずつ確認し、C++ライブラリの構築に関する一般的な事項について説明します。

ディレクトリ内のヘッダーとcppファイルを分離します。これは、実際のアプリケーションではなく、ライブラリとして使用されることになっているコンポーネントを構築する場合にのみ不可欠です。ヘッダーは、ユーザーが提供するものと対話するための基礎であり、インストールする必要があります。これは、それらがサブディレクトリにある必要があり(多くのヘッダーがトップレベルになることを誰も望んでいない/usr/include/)、ヘッダーがそのような設定に自分自身を含めることができる必要があることを意味します。

└── prj
    ├── include
    │   └── prj
    │       ├── header2.h
    │       └── header.h
    └── src
        └── x.cpp

インクルードパスが機能し、インストールターゲットに簡単なグロブを使用できるため、うまく機能します。

依存関係のバンドル:これは、依存関係を見つけて構成するビルドシステムの機能と、単一バージョンへのコードの依存度に大きく依存すると思います。また、ユーザーの能力と、プラットフォームへの依存関係のインストールのしやすさにも依存します。CMakeにはGoogleTestfind_package用のスクリプトが付属しています。これにより、作業が非常に簡単になります。必要な場合にのみバンドルを使用し、それ以外の場合は回避します。

ビルド方法:ソース内ビルドは避けてください。CMakeはソースビルドを簡単にし、生活をずっと楽にします。

また、CTestを使用してシステムのテストを実行したいとします(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)テスト実行可能ファイルとテストケースを構成します

サブコンポーネントがある場合は、別の階層を追加し、サブプロジェクトごとに上のツリーを使用することをお勧めします。次に、サブコンポーネントがそれらの依存関係を検索して構成するかどうか、またはそれをトップレベルで行うかどうかを決定する必要があるため、事態は複雑になります。これは、ケースバイケースで決定する必要があります。

add_custom_commandDoxygen:doxygenの構成ダンスをなんとか経験した後、CMakeを使用してドキュメントターゲットを追加するのは簡単です。

これが私のプロジェクトの最終的な結果であり、非常によく似たプロジェクトをいくつか見ましたが、もちろんこれがすべてを解決するわけではありません。

補遺ある時点でconfig.hpp 、バージョン定義と、バージョン管理識別子(GitハッシュまたはSVNリビジョン番号)への定義を含むファイルを生成する必要があります。CMakeには、その情報の検索を自動化し、ファイルを生成するためのモジュールがあります。CMakeを使用configure_fileして、テンプレートファイル内の変数を内で定義された変数に置き換えることができますCMakeLists.txt

ライブラリを構築している場合は、コンパイラ間の違いを正しく取得するためのエクスポート定義も必要になります。たとえば__declspec、MSVCとvisibilityGCC/clangの属性です。

于 2012-11-23T00:45:55.513 に答える
39

手始めに、無視できないディレクトリの従来の名前がいくつかあります。これらは、Unixファイルシステムの長い伝統に基づいています。これらは:

trunk
├── bin     : for all executables (applications)
├── lib     : for all other binaries (static and shared libraries (.so or .dll))
├── include : for all header files
├── src     : for source files
└── doc     : for documentation

少なくともトップレベルでは、この基本的なレイアウトに固執することをお勧めします。

ヘッダーファイルとソースファイル(cpp)の分割については、どちらのスキームもかなり一般的です。しかし、私はそれらを一緒に保つことを好む傾向があります。ファイルを一緒にすることは、日常のタスクでより実用的です。また、すべてのコードが1つのトップレベルフォルダー、つまりフォルダーの下にある場合、トップレベルにtrunk/src/ある他のすべてのフォルダー(bin、lib、include、doc、および場合によってはいくつかのテストフォルダー)に気付くことができます。ソース外ビルドの「ビルド」ディレクトリは、ビルドプロセスで生成されたファイルのみを含むすべてのフォルダです。したがって、srcフォルダーのみをバックアップする必要があります。または、バージョン管理システム/サーバー(GitやSVNなど)の下に保持する必要があります。

そして、宛先システムにヘッダーファイルをインストールする場合(最終的にライブラリを配布したい場合)、CMakeにはファイルをインストールするコマンドがあります(「インストール」ターゲットを暗黙的に作成し、「makeinstall」を実行します)。を使用して、すべてのヘッダーを/usr/include/ディレクトリに配置できます。この目的のために、次のcmakeマクロを使用します。

# custom macro to register some headers as target for installation:
#  setup_headers("/path/to/header/something.h" "/relative/install/path")
macro(setup_headers HEADER_FILES HEADER_PATH)
  foreach(CURRENT_HEADER_FILE ${HEADER_FILES})
    install(FILES "${SRCROOT}${CURRENT_HEADER_FILE}" DESTINATION "${INCLUDEROOT}${HEADER_PATH}")
  endforeach(CURRENT_HEADER_FILE)
endmacro(setup_headers)

SRCROOTsrcフォルダーに設定したcmake変数はどこINCLUDEROOTにあり、ヘッダーの移動先に設定したcmake変数はどこにありますか。もちろん、これを行うには他にも多くの方法がありますが、私の方法は最善ではないと確信しています。重要なのは、ターゲットシステムにヘッダーのみをインストールする必要があるという理由だけでヘッダーとソースを分割する理由はないということです。これは、特にCMake(またはCPack)を使用すると、ヘッダーを選択して構成するのが非常に簡単だからです。別のディレクトリに配置しなくてもインストールできます。そして、これは私がほとんどの図書館で見たものです。

引用:次に、コードの単体テストにGoogle C ++テストフレームワークを使用したいと思います。これは、かなり使いやすいように思われるためです。これを私のコード、たとえば「inc/gtest」または「contrib/gtest」フォルダーにバンドルすることをお勧めしますか?バンドルされている場合は、fuse_gtest_files.pyスクリプトを使用してファイル数を減らすか、そのままにしておくことをお勧めしますか?バンドルされていない場合、この依存関係はどのように処理されますか?

依存関係をライブラリにバンドルしないでください。これは一般的にかなり恐ろしい考えであり、それを行うライブラリを構築しようとして立ち往生しているときはいつもそれを嫌います。それはあなたの最後の手段であるべきであり、落とし穴に注意してください。多くの場合、ひどい開発環境(Windowsなど)をターゲットにしているため、または問題のライブラリの古い(非推奨)バージョン(依存関係)のみをサポートしているため、依存関係をライブラリにバンドルします。主な落とし穴は、バンドルされた依存関係が、同じライブラリ/アプリケーションのすでにインストールされているバージョンと衝突する可能性があることです(たとえば、gtestをバンドルしているが、ライブラリをビルドしようとしている人は、新しい(または古い)バージョンのgtestをすでにインストールしています。 2つが衝突し、その人に非常に厄介な頭痛を与える可能性があります)。だから、私が言ったように、あなた自身の責任でそれをしてください、そして私は最後の手段としてのみ言うでしょう。ライブラリをコンパイルする前にいくつかの依存関係をインストールするように人々に依頼することは、バンドルされた依存関係と既存のインストールとの間の衝突を解決しようとするよりもはるかに害が少ないです。

引用:テストを書くことになると、これらは一般的にどのように構成されていますか?クラスごとに1つのcppファイル(たとえば、test_vector3.cpp)を作成することを考えていましたが、すべてを1つのバイナリにコンパイルして、すべてを簡単に一緒に実行できるようにしましたか?

私の意見では、クラスごとに1つのcppファイル(またはクラスと関数の小さなまとまりのあるグループ)がより一般的で実用的です。ただし、「すべてを一緒に実行できるようにする」ためだけに、すべてを1つのバイナリにコンパイルしないでください。それは本当に悪い考えです。一般に、コーディングに関しては、合理的な範囲で分割する必要があります。単体テストの場合、1つのバイナリですべてのテストを実行する必要はありません。これは、ライブラリ内の何かに少し変更を加えると、その単体テストプログラムがほぼ完全に再コンパイルされる可能性があるためです。 、そしてそれは再コンパイルを待つのにちょうど数分/時間失われました。単純なスキームに固執するだけです:1ユニット=1ユニットテストプログラム。それで、

引用:gtestライブラリは通常cmakeとmakeを使用してビルドされるので、私のプロジェクトもこのようにビルドするのが理にかなっていると思いましたか?次のプロジェクトレイアウトを使用することにした場合:

私はむしろこのレイアウトを提案したいと思います:

trunk
├── bin
├── lib
│   └── project
│       └── libvector3.so
│       └── libvector3.a        products of installation / building
├── docs
│   └── Doxyfile
├── include
│   └── project
│       └── vector3.hpp
│_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
│
├── src
│   └── CMakeLists.txt
│   └── Doxyfile.in
│   └── project                 part of version-control / source-distribution
│       └── CMakeLists.txt
│       └── vector3.hpp
│       └── vector3.cpp
│       └── test
│           └── test_vector3.cpp
│_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
│
├── build
└── test                        working directories for building / testing
    └── test_vector3

ここで注意すべき点がいくつかあります。まず、srcディレクトリのサブディレクトリはincludeディレクトリのサブディレクトリをミラーリングする必要があります。これは、物事を直感的に保つためです(また、フォルダのネストが深いため、サブディレクトリの構造を適度にフラット(浅い)に保つようにしてください)多くの場合、他の何よりも面倒です)。次に、「include」ディレクトリは単なるインストールディレクトリであり、その内容はsrcディレクトリから選択されたヘッダーにすぎません。

第3に、CMakeシステムは、トップレベルの1つのCMakeLists.txtファイルとしてではなく、ソースサブディレクトリに分散されることを目的としています。これは物事をローカルに保ち、それは良いことです(物事を独立した部分に分割するという精神で)。新しいソース、新しいヘッダー、または新しいテストプログラムを追加する場合、必要なのは、問題のサブディレクトリにある1つの小さくて単純なCMakeLists.txtファイルを、他に影響を与えることなく編集することだけです。これにより、ディレクトリを簡単に再構築することもできます(CMakeListはローカルであり、移動するサブディレクトリに含まれています)。トップレベルのCMakeListには、宛先ディレクトリ、カスタムコマンド(またはマクロ)の設定、システムにインストールされているパッケージの検索など、ほとんどのトップレベルの構成が含まれている必要があります。下位レベルのCMakeListには、ヘッダー、ソース、

引用:CMakeLists.txtは、ライブラリのみ、またはライブラリとテストのいずれかを構築できるように、どのように見える必要がありますか?

基本的な答えは、CMakeを使用すると、「すべて」(「make」と入力したときに作成されるもの)から特定のターゲットを明確に除外でき、特定のターゲットのバンドルを作成することもできます。ここではCMakeチュートリアルを行うことはできませんが、自分で調べるのはかなり簡単です。ただし、この特定のケースでは、もちろん、推奨される解決策はCTestを使用することです。これは、CMakeListsファイルでユニットとしてマークされた多数のターゲット(プログラム)を登録するために使用できるコマンドの追加セットです。テスト。したがって、CMakeはすべてのテストをビルドの特別なカテゴリに配置します。これはまさにあなたが求めていたものであり、問​​題は解決しました。

引用:また、ビルドとbinディレクトリを持つプロジェクトをかなり多く見ました。ビルドはビルドディレクトリで行われ、バイナリはbinディレクトリに移動されますか?テスト用のバイナリとライブラリは同じ場所にありますか?または、次のように構成する方が理にかなっています。

ソースの外にビルドディレクトリを置くこと(「ソース外」ビルド)は、実際に行うべき唯一の正しいことであり、最近のデファクトスタンダードです。したがって、CMakeの人々が推奨するように、そして私が今まで出会ったすべてのプログラマーがそうであるように、間違いなく、ソースディレクトリの外に別の「ビルド」ディレクトリがあります。binディレクトリに関しては、これは慣例であり、この投稿の冒頭で述べたように、これに固執することをお勧めします。

引用:コードを文書化するためにdoxygenも使用したいと思います。これをcmakeとmakeで自動的に実行することは可能ですか?

はい。それは可能以上です、それは素晴らしいです。あなたがどれだけ空想を得たいかに応じて、いくつかの可能性があります。CMakeにはDoxygen用のモジュール(つまりfind_package(Doxygen))があり、一部のファイルでDoxygenを実行するターゲットを登録できます。Doxyfileのバージョン番号を更新したり、ソースファイルの日付/作成者スタンプを自動的に入力したりするなど、もっと凝ったことをしたい場合は、少しのCMakeカンフーですべて可能です。一般に、これを行うには、CMakeの解析コマンドによって検出および置換されるトークンを含むソースDoxyfile(たとえば、上記のフォルダーレイアウトに配置した「Doxyfile.in」)を保持する必要があります。私のトップレベルのCMakeListsファイルには、cmake-doxygenを使用していくつかの凝ったことを行うCMakekung-fuのそのような部分が1つあります。

于 2012-11-23T03:47:22.397 に答える
17

プロジェクトの構造化

私は一般的に次のことを好みます:

├── CMakeLists.txt
|
├── docs/
│   └── Doxyfile
|
├── include/
│   └── project/
│       └── vector3.hpp
|
├── src/
    └── project/
        └── vector3.cpp
        └── test/
            └── test_vector3.cpp

これは、ライブラリに対して非常に明確に定義されたAPIファイルのセットがあることを意味し、構造は、ライブラリのクライアントが実行することを意味します。

#include "project/vector3.hpp"

あまり明確ではなく

#include "vector3.hpp"


/srcツリーの構造が/includeツリーの構造と一致するのが好きですが、それは本当に個人的な好みです。ただし、プロジェクトが拡張されて/ include / project内にサブディレクトリが含まれる場合は、通常、/srcツリー内のサブディレクトリと一致させると役立ちます。

テストでは、テストするファイルに「近い」状態に保つことを好みます。/src内にサブディレクトリがある場合、特定のファイルのテストコードを見つけたい場合は、他の人が従うのは非常に簡単なパラダイムです。


テスト

次に、コードの単体テストにGoogle C ++テストフレームワークを使用したいと思います。これは、かなり使いやすいように思われるためです。

Gtestは確かに使い方が簡単で、その機能に関してはかなり包括的です。gmockと一緒に使用すると、その機能を非常に簡単に拡張できますが、私自身のgmockの経験はあまり好意的ではありませんでした。これは私自身の欠点によるものかもしれないことを受け入れる準備ができていますが、gmockテストは作成がより難しく、保守がはるかに脆弱/困難になる傾向があります。gmock棺の大きな釘は、スマートポインターではうまく機能しないことです。

これは、巨大な質問(おそらく実際にはSOに属していない)に対する非常に些細で主観的な答えです。

これを私のコード、たとえば「inc/gtest」または「contrib/gtest」フォルダーにバンドルすることをお勧めしますか?バンドルされている場合は、fuse_gtest_files.pyスクリプトを使用してファイル数を減らすか、そのままにしておくことをお勧めしますか?バンドルされていない場合、この依存関係はどのように処理されますか?

私はCMakeのExternalProject_Addモジュールを使用することを好みます。これにより、gtestのソースコードをリポジトリに保存したり、どこにでもインストールしたりする必要がなくなります。ダウンロードされ、ビルドツリーに自動的に組み込まれます。

ここで詳細を扱っている私の答えを参照してください。

テストを書くことになると、これらは一般的にどのように構成されていますか?クラスごとに1つのcppファイル(たとえば、test_vector3.cpp)を作成することを考えていましたが、すべてを1つのバイナリにコンパイルして、すべてを簡単に一緒に実行できるようにしましたか?

いい計画。


建物

私はCMakeのファンですが、テスト関連の質問と同様に、SOはそのような主観的な問題について意見を求めるのにおそらく最適な場所ではありません。

CMakeLists.txtは、ライブラリのみ、またはライブラリとテストのいずれかを構築できるように、どのように見える必要がありますか?

add_library(ProjectLibrary <All library sources and headers>)
add_executable(ProjectTest <All test files>)
target_link_libraries(ProjectTest ProjectLibrary)

ライブラリはターゲット「ProjectLibrary」として表示され、テストスイートはターゲット「ProjectTest」として表示されます。ライブラリをテストexeの依存関係として指定することにより、テストexeをビルドすると、ライブラリが古くなった場合にライブラリが自動的に再構築されます。

また、ビルドとbinディレクトリを持つプロジェクトをかなり多く見ました。ビルドはビルドディレクトリで行われ、バイナリはbinディレクトリに移動されますか?テスト用のバイナリとライブラリは同じ場所にありますか?

CMakeは、「ソース外」ビルドをお勧めします。つまり、プロジェクトの外部に独自のビルドディレクトリを作成し、そこからCMakeを実行します。これにより、ビルドファイルでソースツリーが「汚染」されるのを防ぐことができます。vcsを使用している場合は非常に望ましい方法です。

バイナリは、ビルド後に別のディレクトリに移動またはコピーするか、デフォルトで別のディレクトリに作成するかを指定できますが、通常は必要ありません。CMakeは、必要に応じてプロジェクトをインストールする包括的な方法を提供します。または、他のCMakeプロジェクトがプロジェクトの関連ファイルを簡単に「検索」できるようにします。

gtestテストを見つけて実行するためのCMake自身のサポートに関しては、プロジェクトの一部としてgtestをビルドする場合、これはほとんど不適切です。このFindGtestモジュールは、gtestがプロジェクトの外部で個別にビルドされている場合に使用するように実際に設計されています。

CMakeは独自のテストフレームワーク(CTest)を提供し、理想的には、すべてのgtestケースがCTestケースとして追加されます。

ただし、個々のctestケースとしてgtestケースを簡単に追加できるようにするためにGTEST_ADD_TESTS提供されるマクロは、とFindGtest以外のgtestのマクロでは機能しないという点でやや欠けています。 、などを使用したまたはタイプパラメータ化されたテストはまったく処理されません。TESTTEST_FTEST_PTYPED_TEST_P

この問題には、私が知っている簡単な解決策がありません。gtestケースのリストを取得する最も堅牢な方法は、フラグを指定してtestexeを実行すること--gtest_list_testsです。ただし、これはexeがビルドされた後にのみ実行できるため、CMakeはこれを利用できません。これには2つの選択肢があります。CMakeは、C ++コードを解析して、テストの名前を推測する必要があります(すべてのgtestマクロ、コメントアウトされたテスト、無効なテストを考慮したい場合は、極端に重要です)。または、テストケースを手動で追加します。 CMakeLists.txtファイル。

また、doxygenを使用してコードを文書化したいと思います。これをcmakeとmakeで自動的に実行することは可能ですか?

はい-私はこの面での経験はありませんが。CMakeはFindDoxygenこの目的のために提供しています。

于 2012-11-23T01:43:46.057 に答える
6

他の(優れた)回答に加えて、私が比較的大規模なプロジェクトに使用している構造について説明します。
他の回答で述べられていることを繰り返すだけなので、Doxygenに関するサブ質問には対処しません。


理論的根拠

モジュール性と保守性のために、プロジェクトは小さなユニットのセットとして編成されています。わかりやすくするために、それらにUnitXという名前を付けましょう。X= A、B、C、...(ただし、任意の一般的な名前を付けることができます)。次に、ディレクトリ構造はこの選択を反映するように編成され、必要に応じてユニットをグループ化することができます。

解決

基本的なディレクトリレイアウトは次のとおりです(ユニットの内容については後で詳しく説明します)。

project
├── CMakeLists.txt
├── UnitA
├── UnitB
├── GroupA
│   └── CMakeLists.txt
│   └── GroupB
│       └── CMakeLists.txt
│       └── UnitC
│       └── UnitD
│   └── UnitE

project/CMakeLists.txt次のものを含めることができます。

cmake_minimum_required(VERSION 3.0.2)
project(project)
enable_testing() # This will be necessary for testing (details below)

add_subdirectory(UnitA)
add_subdirectory(UnitB)
add_subdirectory(GroupA)

およびproject/GroupA/CMakeLists.txt

add_subdirectory(GroupB)
add_subdirectory(UnitE)

およびproject/GroupB/CMakeLists.txt

add_subdirectory(UnitC)
add_subdirectory(UnitD)

次に、さまざまなユニットの構造について説明します(例として、UnitDを取り上げます)。

project/GroupA/GroupB/UnitD
├── README.md
├── CMakeLists.txt
├── lib
│   └── CMakeLists.txt
│   └── UnitD
│       └── ClassA.h
│       └── ClassA.cpp
│       └── ClassB.h
│       └── ClassB.cpp
├── test
│   └── CMakeLists.txt
│   └── ClassATest.cpp
│   └── ClassBTest.cpp
│   └── [main.cpp]

さまざまなコンポーネントへ:

  • ソース(.cpp)とヘッダー(.h)を同じフォルダーに入れるのが好きです。これにより、ディレクトリ階層の重複が回避され、メンテナンスが容易になります。インストールの場合、ヘッダーファイルをフィルタリングするだけで問題ありません(特にCMakeの場合)。
  • ディレクトリの役割は、UnitD後で.を含むファイルを含めることを許可することです#include <UnitD/ClassA.h>。また、本機を設置する際は、ディレクトリ構造をそのままコピーすることができます。ソースファイルをサブディレクトリに整理することもできることに注意してください。
  • 私はREADME、ユニットが何であるかを要約し、それに関する有用な情報を指定するファイルが好きです。
  • CMakeLists.txt単に含むことができます:

    add_subdirectory(lib)
    add_subdirectory(test)
    
  • lib/CMakeLists.txt

    project(UnitD)
    
    set(headers
        UnitD/ClassA.h
        UnitD/ClassB.h
        )
    
    set(sources
        UnitD/ClassA.cpp
        UnitD/ClassB.cpp    
        )
    
    add_library(${TARGET_NAME} STATIC ${headers} ${sources})
    
    # INSTALL_INTERFACE: folder to which you will install a directory UnitD containing the headers
    target_include_directories(UnitD
                               PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
                               PUBLIC $<INSTALL_INTERFACE:include/SomeDir>
                               )
    
    target_link_libraries(UnitD
                          PUBLIC UnitA
                          PRIVATE UnitC
                          )
    

    UnitAここで、とのインクルードディレクトリが必要であることをCMakeに伝える必要はないことに注意してくださいUnitC。これは、これらのユニットを構成するときにすでに指定されているためです。また、依存してPUBLICいるすべてのターゲットに、依存関係UnitDを自動的に含める必要があることを通知しますが、その場合は必須ではありません()。UnitAUnitCPRIVATE

  • test/CMakeLists.txt(GTestを使用する場合は、以下を参照してください):

    project(UnitDTests)
    
    add_executable(UnitDTests
                   ClassATest.cpp
                   ClassBTest.cpp
                   [main.cpp]
                   )
    
    target_link_libraries(UnitDTests
                          PUBLIC UnitD
    )
    
    add_test(
            NAME UnitDTests
            COMMAND UnitDTests
    )
    

GoogleTestの使用

Google Testの場合、最も簡単なのは、ソースがソースディレクトリのどこかにある場合ですが、実際にそこに追加する必要はありません。私はこのプロジェクトを使用して自動的にダウンロードしてきましたが、複数のテストターゲットがある場合でも、その使用法を関数でラップして、一度だけダウンロードされるようにします。

このCMake関数は次のとおりです。

function(import_gtest)
  include (DownloadProject)
  if (NOT TARGET gmock_main)
    include(DownloadProject)
    download_project(PROJ                googletest
                     GIT_REPOSITORY      https://github.com/google/googletest.git
                     GIT_TAG             release-1.8.0
                     UPDATE_DISCONNECTED 1
                     )
    set(gtest_force_shared_crt ON CACHE BOOL "" FORCE) # Prevent GoogleTest from overriding our compiler/linker options when building with Visual Studio
    add_subdirectory(${googletest_SOURCE_DIR} ${googletest_BINARY_DIR} EXCLUDE_FROM_ALL)
  endif()
endfunction()

次に、テストターゲットの1つで使用する場合は、次の行を追加しますCMakeLists.txt(これは上記の例の場合ですtest/CMakeLists.txt)。

import_gtest()
target_link_libraries(UnitDTests gtest_main gmock_main)
于 2017-07-02T07:36:54.660 に答える