チュートリアル:CMake のインストールと find_package() を簡単にサポート

バージョン 0.5 の時点で、私のメモリ ライブラリはシステム全体のインストールと CMake の 273 をサポートするようになりました .

何時間もの試行錯誤を経てこのライブラリを作成したので、ここに記録します。この投稿では、ライブラリを他のプロジェクトで簡単に使用できるようにインストールする方法を紹介します。特に、システムは、インストールされた複数のバージョンと複数の構成を処理できます。

この投稿全体を通して、3.x CMake バージョンと既存の CMake プロジェクトを想定しています。

セットアップ

チュートリアルの範囲として、次の CMake 構造を持つライブラリがあるとします。

- include/
 - my_library/
 - header-a.hpp
 - header-b.hpp
 - config.hpp
 - ...
- src/
 - source-a.cpp
 - source-b.cpp
 - config.hpp.in
 - ...
 - CMakeLists.txt
- example/
 - example-a.cpp
 - ...
 - CMakeLists.txt
- tool/
 - tool.cpp
 - CMakeLists.txt
- test/
 - test.cpp
 - CMakeLists.txt
- CMakeLists.txt
- ...

そのため、さまざまなヘッダー ファイルとソース ファイルで構成されるライブラリがあります。また、いくつかの例、ツール、単体テストも付属しています。

ライブラリ、例、およびツールには、それぞれ独自の 282 があります。 サブディレクトリでターゲットと関連コードを定義します。ルート 293 構成オプションを定義し、サブディレクトリを追加します。

構成はファイル 300 に設定されます 319 に前処理されます 321 に含まれています .

ルート CMakeLists.txt は次のようになります:

cmake_minimum_required(VERSION 3.0)
project(MY_LIBRARY)

# define library version (update: apparently you can also do it in project()!)
set(MY_LIBRARY_VERSION_MAJOR 1 CACHE STRING "major version" FORCE)
set(MY_LIBRARY_VERSION_MINOR 0 CACHE STRING "minor version" FORCE)
set(MY_LIBRARY_VERSION ${MY_LIBRARY_VERSION_MAJOR}.${MY_LIBRARY_VERSION_MINOR} CACHE STRING "version" FORCE)

# some options
option(MY_LIBRARY_USE_FANCY_NEW_CLASS "whether or not to use fancy new class" ON)
option(MY_LIBRARY_DEBUG_MODE "whether or not debug mode is activated" OFF)

# add subdiretories
add_subdirectory(src)
add_subdirectory(example)
add_subdirectory(tool)
add_subdirectory(test)

336 経由で使用できるいくつかのオプションを定義します または同様の 349 .

そして 359 :

# set headers
set(header_path "${MY_LIBRARY_SOURCE_DIR}/include/my_library")
set(header ${header_path}/header-a.hpp
 ${header_path}/header-b.hpp
 ${header_path}/config.hpp
 ...)

# set source files
set(src source-a.cpp
 source-b.cpp
 ...)
 
# configure config.hpp.in
configure_file("config.hpp.in" "${CMAKE_CURRENT_BINARY_DIR}/config_impl.hpp")

# define library target
add_library(my_library ${header} ${src})
target_include_directories(my_library PUBLIC ${MY_LIBRARY_SOURCE_DIR}/include
 ${CMAKE_CURRENT_BINARY_DIR})

最初に、すべてのヘッダーとソース ファイルのリストを変数で定義します。これは後で役立ちます。

362 も生成します 372 内に含めることができます 現在のバイナリディレクトリで、指定されたファイルでライブラリを定義します.その 383 インクルード ディレクトリは 両方 391 サブフォルダと現在のバイナリ ディレクトリ。後者は、生成された 406 にアクセスするために必要です。 .

もう一方の 419

クライアント コードで 428 を呼び出せるようになりました ライブラリ フォルダの 435 を呼び出します .これにより、インクルード パスも設定され、441 が許可されます。

しかし、それをインストールして 452 をサポートしたい .

インストール

ライブラリを使用するには、次のものをインストールする必要があります:ヘッダー ファイル、ツールの実行可能ファイル、およびビルドされたライブラリ。これは、466 コマンドです。ファイルを 476 にコピーするだけです。 (487 Linux では) 499 を入力するとき ターミナルでコマンドを実行してください。

まず、ルート CMakeLists.txt で場所を変数として定義します:

set(tool_dest "bin")
set(include_dest "include/my_library-${MY_LIBRARY_VERSION}")
set(main_lib_dest "lib/my_library-${MY_LIBRARY_VERSION}")

次に 501 を追加します コマンド:

# in tool/CMakeLists.txt
install(TARGETS my_library_tool DESTINATION "${tool_dest}")

# in src/CMakeLists.txt
install(TARGETS my_library DESTINATION "${main_lib_dest}")
install(FILES ${header} DESTINATION "${include_dest}")
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/config_impl.hpp DESTINATION "${include_dest}")

これにより、ツールの実行可能ファイルが 515 の下にインストールされます 、 528 の下のヘッダー ライブラリ自体は 535 の下にあります .これは、上で設定した目標の 1 つをすでに満たしています。異なるライブラリ バージョンは、異なる場所にインストールされるため、競合が発生しません。バージョンはフォルダの一部です。

ただし、これはライブラリのさまざまな構成を処理しません。その場所に存在できるのは 1 つだけです。もちろん、バージョンに対して行ったように構成ごとに一意の識別子を追加することでこれを防ぐことができますが、これはほとんどのファイルには不要です。

再びツールを無視すると、構成に依存するファイルは 2 つだけです。ビルドされたライブラリと生成された 543 です。 ライブラリ オプションに対応するマクロが設定されているため、構成に応じて、これら 2 つのファイルのみを別の場所に配置する必要があります。

しかし、識別子として何を使用するのでしょうか?

558 の値を選択しました .562 の値のコンパイラ フラグが既に選択されています 、 572588 および 594 .他のすべてのオプションをそれに結合することも理にかなっています.

したがって、新しい変数 607 を追加します ルート CMakeLists.txt:

set(lib_dest ${main_lib_dest}/${CMAKE_BUILD_TYPE}")

615 の宛先も変更します そして 625 630 をターゲットに .これにより、これらの 2 つのファイルが構成に応じて異なるフォルダーに配置され、複数の構成をインストールできるようになります。たとえば、645 ライブラリは 658 の下にインストールされます など

ターゲットのエクスポート

現在のセットアップでは、ライブラリを使用するために必要なものはすべてインストールされていますが、他の CMake ベースのプロジェクトに統合することはできません。インクルード ディレクトリを手動で指定し、ネイティブ ライブラリに手動でリンクする必要があります。

これは快適ではありません。

CMake はエクスポートする機能を提供します ただし、ターゲットをエクスポートすると、現在のプロジェクトで定義されているかのように、ターゲットを他の CMake プロジェクトで再利用できます。これを有効にするには、ファイル 666 インストール時に作成されます。これには、インストールされたビルド ファイルと構成への参照を含むすべてのターゲットの定義が含まれています。ユーザーは 670 を実行するだけで済みます。 そのファイルであり、通常どおりターゲットを使用できます。

my_library のエクスポートを有効にするには 2 つのことを行う必要があります:

  • まず、ターゲットごとに、それがエクスポート グループに追加されることを指定します。これは、689 を追加することによって実現されます。 694 で たとえば、メイン ライブラリ ターゲットの場合、ターゲット インストール コマンドは次のようになります:
install(TARGETS my_library EXPORT my_library DESTINATION "${lib_dest}")
  • 次に、エクスポート グループもインストールする必要があります。これは、708 で実行できます。 ルート 713 で呼び出されるコマンド .ターゲットは 721 のビルドタイプ固有の場所を参照するため ライブラリ ファイルはビルド タイプに依存し、730 にインストールされます。 :
install(EXPORT my_library DESTINATION "${lib_dest}")

ただし、まだ小さな問題があります:ライブラリは 743 を設定しています リンクされたターゲットに、インストール前のソースが保存されているディレクトリに渡されます!また、ビルド用のインクルード ディレクトリが間違っているため、ディレクトリを変更できません。

ジェネレータ式という名前の醜い機能 ここで助けてください。ライブラリがインストールされているか、現在ビルド中であるかにかかわらず、異なるインクルード ディレクトリを設定できます。756 の呼び出し 769 で 次のように変更する必要があります:

target_include_directories(my_library PUBLIC
 $<BUILD_INTERFACE:${MY_LIBRARY_SOURCE_DIR}/include> # for headers when building
 $<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}> # for config_impl.hpp when building
 $<INSTALL_INTERFACE:${include_dest}> # for client in install mode
 $<INSTALL_INTERFACE:${lib_dest}> # for config_impl.hpp in install mode)

これで 773 ができました ライブラリを 781 の宛先として使用するために含める必要があるタイプ いつものように。しかし、行く前に 792 を追加してください。 ステートメント、パッケージ サポートを有効にして自動化しましょう。

最終ステップ:パッケージング

CMake は 807 を提供します ここでは詳しく説明しませんが、その基本的な形式はここで役立ちます。

816 と書くと 、 822 という名前のファイルを探しに行きます (特に) 832 という名前のディレクトリ 848 の下 (多くの中 その他)

インストール ディレクトリ名 852 - 863 - この表現に一致します。

875 を指定するだけです file.ファイルの内容は、883 の呼び出しスクリプトで利用できるようになります。 .通常、ターゲットを定義するコードが含まれていますが、そのコードは既にあります!それは 899 にあります 900 によって作成されたファイル .911 するだけです。 920 の中 ファイル。

ここでは、ビルド タイプを照合することもできます。現在のビルド タイプと一致するエクスポート ファイルのバージョンを含めます。

# my_library-config.cmake - package configuration file

get_filename_component(SELF_DIR "${CMAKE_CURRENT_LIST_FILE}" PATH)
include(${SELF_DIR}/${CMAKE_BUILD_TYPE}/my_library.cmake)

このファイルはライブラリ リポジトリ内に保存できます。インストールすることを忘れないでください。931 のすぐ横で実行できます。 コマンド:

install(FILES my_library-config.cmake DESTINATION ${main_lib_dest})
install(EXPORT ...)

これで、クライアントは 946 を呼び出すことができます ライブラリが検索され、見つかります (957 の場合) がインストールされている)、エクスポートされたすべてのターゲットが利用可能になり、単純な 968 が許可されます .これは、一致するビルド タイプのライブラリ バージョンにリンクします。

いいね。

シュガーの追加:バージョン管理

インストールされたライブラリのバージョン互換性チェックは、良い点の 1 つです。これは、974 でもサポートされています。 、2 番目の引数としてバージョンを指定できます。

チェックは 987 という名前のファイルによって行われます (または類似) 997 のように 、現在のセットアップで提供してインストールする必要があります。

要求されたバージョンを 1000 の形式で取得します 変数 1010 を設定する必要があります また、1021 でフル バージョンを設定する必要があります。 .しない ことの 1 つ get は、インストールされているライブラリのバージョンです。そのため、ルート 1039 で定義されているバージョン変数を参照する必要があります。 インストール前に構成する必要があります。

メジャー バージョンの一致とそれ以降のマイナー バージョンが必要な簡単なスクリプトを次に示します。

# my_library-config-version.cmake - checks version: major must match, minor must be less than or equal

set(PACKAGE_VERSION @MY_LIBRARY_VERSION@)

if("${PACKAGE_FIND_VERSION_MAJOR}" EQUAL "@MY_LIBRARY_VERSION_MAJOR@")
 if ("${PACKAGE_FIND_VERSION_MINOR}" EQUAL "@MY_LIBRARY_VERSION_MINOR@")
 set(PACKAGE_VERSION_EXACT TRUE)
 elseif("${PACKAGE_FIND_VERSION_MINOR}" LESS "@MY_LIBRARY_VERSION_MINOR@")
 set(PACKAGE_VERSION_COMPATIBLE TRUE)
 else()
 set(PACKAGE_VERSION_UNSUITABLE TRUE)
 endif()
else()
 set(PACKAGE_VERSION_UNSUITABLE TRUE)
endif()

構成 (1044 を置き換えるため) -正しいバージョンの変数) で、インストールはルートの CMakeLists.txt で行われます:

configure_file(my_library-config-version.cmake.in ${CMAKE_CURRENT_BINARY_DIR}/my_library-config-version.cmake @ONLY)

install(FILES my_library-config.cmake ${CMAKE_CURRENT_BINARY_DIR}/my_library-config-version.cmake DESTINATION ${main_lib_dest})
install(EXPORT ...)

1057になりました 1066 形式の呼び出し 1.0 または互換性のある (「互換性がある」と定義した) ライブラリ バージョンを探します。

まとめ

要約すると、インストールと 1073 をサポートするために CMake では、次のことを行う必要があります:

    <リ>

    呼び出しを 1089 に変更します 1099 を使用するように および 1103 正しいインクルード ディレクトリを設定するジェネレータ式。インストール モードでは、これはヘッダー ファイルがインストールされる場所です (すぐ下を参照)。

    <リ>

    ヘッダー ファイルを 1119 にインストールします 1120経由 .

    <リ>

    構成されたヘッダー ファイル (または構成/ビルド タイプに応じて他のすべてのヘッダー ファイル) を 1132 にインストールします。 1142経由 .

    <リ>

    ライブラリ ターゲットを 1159 にインストールします。 1161経由 .これにより、エクスポート グループにも追加されます。

    <リ>

    1176 という名前のファイルを定義します 対応する 1186 のみを含む ファイル(上記を参照してください。コピーして貼り付けるだけです)。 1191 も定義します バージョンの互換性チェックについては上記と同様です。

    <リ>

    1203 を介して正しいバージョンを使用するように、バージョン インストール ファイルを構成します。 構成されたバージョンのインストール ファイルと 1215 をインストールします。 1221 へのファイル 1234経由 .

    <リ>

    エクスポート グループを 1240 にインストールします 1255経由 .

クライアントは次のように書くだけです:

find_package(my_library 1.0 REQUIRED)
target_link_libraries(client_target PUBLIC my_library)

また、適切なライブラリ バージョンが自動的に検出され、一致するビルド タイプのライブラリにリンクされます。

実際の完全な例については、メモリ自体のソース コードを参照してください。同様のディレクトリ構造を提供しますが、CMake に依存するものは 1269 に配置されることに注意してください。


No