C++ と CMake - 永遠の兄弟、パート II

C++ と CMake - 永遠の兄弟、パート II

前の部分で この楽しいストーリーでは、CMake ビルド システム ジェネレーター内のヘッダー ライブラリの編成について説明しました。

今回はそれにコンパイル済みのライブラリを追加し、モジュール間のリンクについても説明します。

前回同様、せっかちな人はすぐに 更新されたリポジトリに移動します そしてすべてを自分の手で触ってください。


ページ内容

  1. 分ける
  2. 征服する

分ける

私たちの高い目標を達成するために最初に行う必要があるのは、開発するソフトウェアを、ユーザーの観点から見て統一された、普遍的で独立したブロックに分割することです。

最初の部分では、そのような標準ブロック、つまりヘッダー ライブラリを備えたプロジェクトについて説明しました。 次に、コンパイルされたライブラリをプロジェクトに追加しましょう。

これを行うには、関数の実装を取り出してみましょう myfunc 別個に .cpp-ファイル:

diff --git a/include/mylib/myfeature.hpp b/include/mylib/myfeature.hpp
index 43db388..ba62b4f 100644
--- a/include/mylib/myfeature.hpp
+++ b/include/mylib/myfeature.hpp
@@ -46,8 +46,5 @@ namespace mylib

         ~  see mystruct
      */
-    inline bool myfunc (mystruct)
-    {
-        return true;
-    }
+    bool myfunc (mystruct);
 }
diff --git a/src/mylib/myfeature.cpp b/src/mylib/myfeature.cpp
new file mode 100644
index 0000000..abb5004
--- /dev/null
+++ b/src/mylib/myfeature.cpp
@@ -0,0 +1,9 @@
+#include <mylib/myfeature.hpp>
+
+namespace mylib
+{
+    bool myfunc (mystruct)
+    {
+        return true;
+    }
+}

次に、コンパイルするライブラリを定義します (myfeature)、前のステップで取得したもので構成されます .cpp-ファイル。 新しいライブラリには明らかに既存のヘッダーが必要であり、これを提供するには、既存の目的に関連付けることができ、またそうする必要があります。 mylib。 さらに、それらの間の接続はパブリックです。これは、ターゲットが接続されるすべてのものを意味します。 myfeature、ロードとターゲットを自動的に受け取ります mylib (編み方についてもっと詳しく).

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 108045c..0de77b8 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -64,6 +64,17 @@ target_compile_features(mylib INTERFACE cxx_std_17)

 add_library(Mylib::mylib ALIAS mylib)

+###################################################################################################
+##
+##      Компилируемая библиотека
+##
+###################################################################################################
+
+add_library(myfeature src/mylib/myfeature.cpp)
+target_link_libraries(myfeature PUBLIC mylib)
+
+add_library(Mylib::myfeature ALIAS myfeature)
+

次に、新しいライブラリもシステムにインストールされていることを確認します。

@@ -72,7 +83,7 @@ add_library(Mylib::mylib ALIAS mylib)

 install(DIRECTORY include/mylib DESTINATION include)

-install(TARGETS mylib EXPORT MylibConfig)
+install(TARGETS mylib myfeature EXPORT MylibConfig)
 install(EXPORT MylibConfig NAMESPACE Mylib:: DESTINATION share/Mylib/cmake)

 include(CMakePackageConfigHelpers)

なお、目的としては、 myfeature、 はどうかと言うと mylib プレフィックス付きのエイリアスが作成されました Mylib::。 システムにインストールするためにエクスポートするときに、どちらの目的でも同じことが書き込まれます。 これにより、どのような目標に対しても均一に取り組むことが可能になります。 バインディングスキーム.

この後は、単体テストを新しいライブラリ (関数) にリンクするだけです。 myfunc タイトルから削除されているため、リンクする必要があります):

diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index 5620be4..bc1266c 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -4,7 +4,7 @@ add_executable(mylib-unit-tests test_main.cpp)
 target_sources(mylib-unit-tests PRIVATE mylib/myfeature.cpp)
 target_link_libraries(mylib-unit-tests
     PRIVATE
-        Mylib::mylib
+        Mylib::myfeature
         doctest::doctest
 )

見出し (Mylib::mylib) すでに述べたように、ライブラリ (Mylib::myfeature).

そして、新しく到着したライブラリを考慮してカバレッジ測定を確実にするために、いくつかのニュアンスを追加しましょう。

@@ -15,11 +15,16 @@ if(MYLIB_COVERAGE AND GCOVR_EXECUTABLE)
     target_compile_options(mylib-unit-tests PRIVATE --coverage)
     target_link_libraries(mylib-unit-tests PRIVATE gcov)

+    target_compile_options(myfeature PRIVATE --coverage)
+    target_link_libraries(myfeature PRIVATE gcov)
+
     add_custom_target(coverage
         COMMAND
             ${GCOVR_EXECUTABLE}
-                --root=${PROJECT_SOURCE_DIR}/include/
-                --object-directory=${CMAKE_CURRENT_BINARY_DIR}
+                --root=${PROJECT_SOURCE_DIR}/
+                --filter=${PROJECT_SOURCE_DIR}/include
+                --filter=${PROJECT_SOURCE_DIR}/src
+                --object-directory=${PROJECT_BINARY_DIR}
         DEPENDS
             check
     )

さらにライブラリや実行可能ファイルなどを追加できます。 プロジェクト内でそれらがどれだけ正確に相互に接続されているかは問題ではありません。 唯一重要なことは、どのターゲットがモジュールのインターフェイスであるか、つまり、それらが突き出ているかです。

征服する

現在では標準的なブロック モジュールがあり、それらを制御して、任意の複雑な構造を構成し、システムにインストールしたり、単一のアセンブリ システム内で相互にリンクしたりすることができます。

システムへのインストール

モジュールを使用するオプションの XNUMX つは、モジュールをシステムにインストールすることです。

cmake --build путь/к/сборочной/директории --target install

その後、コマンドを使用して他のプロジェクトに接続します。 find_package.

find_package(Mylib 1.0 REQUIRED)

サブモジュールとしての接続

別のオプションは、次のコマンドを使用して、プロジェクトが含まれるフォルダーをサブモジュールとして別のプロジェクトに接続することです。 add_subdirectory.

使用

バインド方法は異なりますが、結果は同じです。 どちらの場合も、モジュールを使用してプロジェクトで目標を利用できます。 Mylib::myfeature и Mylib::mylib、たとえば次のように使用できます。

add_executable(some_executable some.cpp sources.cpp)
target_link_libraries(some_executable PRIVATE Mylib::myfeature)

特に私たちの場合、ライブラリは Mylib::myfeature ライブラリと連携する必要がある場合に接続する必要があります libmyfeature。 十分なヘッダーがある場合は、ライブラリを使用する価値があります Mylib::mylib.

CMake ターゲットは、一部のプロパティや依存関係などを転送することのみを目的としている場合など、扱いにくい場合があります。 同時に、それらとの作業も同様に行われます。

それが私たちが得る必要があったものです。

出所: habr.com

コメントを追加します