GitHub - uyamae/CMakeFindProjectTest: testing to resolve CMake find_project() chain
Skip to content

uyamae/CMakeFindProjectTest

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

8 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

CMake のパッケージの依存関係の解決サンプル

CMake を利用したライブラリで、find_package() により参照されたパッケージがさらに別のパッケージをfind_package() で参照している場合の依存先パッケージの解決についてのサンプルプロジェクトです。

このサンプルプロジェクトはWindows 環境を想定しています。

モジュールの依存関係

graph TD;
    test_app --> test_depending
    test_depending --> test_static
    test_depending --> test_interface
Loading

test_static はスタティックライブラリです。

test_interface はヘッダのみのライブラリです。

test_depending はtest_static, test_interface に依存しているスタティックライブラリです。

test_app はtest_depending を利用するアプリケーションです。

それぞれ別々のCMake プロジェクトになっています。

ライブラリのインストール先

このプロジェクトの各ライブラリは、ビルド後にcmake --install コマンドでインストールを行います。

インストールしたライブラリを他のプロジェクトから利用する場合、CMakeLists.txt でfind_package(パッケージ名) を使用します。このコマンドはConfig Mode Search Procedure で説明されているルールに沿ってパッケージ名-config.cmake という名前のファイルを探して実行します。

Windows 環境の場合、デフォルトのインストール先はc:/Program Files/${PROJECT_NAME} となりますが、都合の悪い場合も多いため環境変数などで変更します。このプロジェクトでは、この README.md と同じ階層にshared というディレクトリを作成し、各プロジェクトのライブラリをまとめてインストールします。

ライブラリのインストールはCMakeLists.txt 内のinstall() コマンドで制御します。またinstall(EXPORT) コマンドによりパッケージ名-config.cmake ファイルも生成します。利用側プロジェクトのfind_package()パッケージ名-config.cmake を見つけられるようなインストール配置になるようcmake --install コマンドの--prefix オプションとinstall()DESTINATION オプションを指定します。

結果として、例えばtest_depening からtest_static を利用する場合には次のような指定となりました。(CMakeLists.txt やバッチファイルから一部を抜粋)

# test_static のCMakeLists.txt
install(
    EXPORT test_static-config
        NAMESPACE test_static::
        DESTINATION lib/cmake/test_static
)
cmake --install test_static/build --prefix=%CD%\shared\test_static
# ディレクトリ構成
+---shared
|   +---test_static
|       +---include
|       +---lib
|           +---cmake
|               +---test_static
|                   +---test_static-config.cmake
+---test_depending
+---test_static
# test_depending のCMakeLists.txt
find_package(test_static)
target_link_libraries(
    test_depending
        PRIVATE
            test_static::test_static
)
set CMAKE_INSTALL_PREFIX=%CD%\shared
cmake -S test_depending -B test_depending/build

依存先の依存先パッケージのためのfind_package()

このプロジェクトのtest_app が直接利用しているのはtest_depending だけです。しかし、test_app のCMakeLists.txt にfind_package(test_depending) だけを記述した場合、エラーとなります。

  The link interface of target "test_depending::test_depending" contains:

    test_static::test_static

  but the target was not found.  Possible reasons include:

    * There is a typo in the target name.
    * A find_package call is missing for an IMPORTED target.
    * An ALIAS target is missing.

test_app のCMakeLists.txt にfind_package(test_static), find_package(test_interface) を追加すれば解決しますが、間接的な参照先の分までfind_package() を指定しなければならないのは不便です。

参考のためlibclang がどうなっているのかを見てみました。llvm-project のClang はLLVM に依存していますが、find_package(Clang) だけでlibclang が利用できるようになっています。

ソースコードからビルドしたlib/cmake/clang/ClangConfig.cmake の内容を見たところ、find_package(LLVM) が含まれていました。このClangConfig.cmake はCMake の機能ではなくllvm-project 側で作成しているようです。

一方でinstall(EXPORT) で生成したtest_depending-config.cmake にはfind_package() は含まれていません。

CMake の機能で解決する方法がないか調べてみたところinstall(EXPORT)EXPORT_PACKAGE_DEPENDENCIES オプションが用意されていました。このオプションを指定すると依存するパッケージを探すためのfind_dependency()パッケージ名-config.cmake に追加されます。find_dependency() が依存先を見つけるためには、パッケージが検索可能なパスに配置されている必要があります。そのため依存するライブラリをCMAKE_INSTALL_PREFIX で指定するディレクトリ以下にまとめて、パッケージ名-config.cmake${CMAKE_INSTALL_PREFIX}/パッケージ名/lib/cmake/パッケージ名 に配置するとうまくいきます。

なお、CMake 3.31 の時点でEXPORT_PACKAGE_DEPENDENCIES オプションは実験的機能で、CMAKE_EXPERIMENTAL_EXPORT_PACKAGE_DEPENDENCIES が必要という記載があります。しかし、set(CMAKE_EXPERIMENTAL_EXPORT_PACKAGE_DEPENDENCIES TRUE)cmake -DCMAKE_EXPERIMENTAL_EXPORT_PACKAGE_DEPENDENCIES=TRUE など試してもうまく動きません。

CMake のソースコードを確認したところ、内部で定義している実験的機能ごとのUUID の値を設定しておく必要があるようでした。実際にset(CMAKE_EXPERIMENTAL_EXPORT_PACKAGE_DEPENDENCIES ソースコードからコピーしたUUID の値) とすると動作しました。UUID の値は定期的に変更される、とソースコード中のコメントに記述があるため利用時には確認が必要そうです。

About

testing to resolve CMake find_project() chain

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published