web-dev-qa-db-ja.com

cmakeプロジェクトでサードパーティのライブラリを使用する正しい方法

一部のサードパーティライブラリを使用するプロジェクトに取り組んでいます。それらを_git submodule_としてクローンしてプロジェクトに入れ、_add_subdirectory_を使用してプロジェクトで使用できます。しかし、これらのライブラリのコンパイルには時間がかかり、プロジェクトでcmake変数を管理できません。また、install()コマンドを使用すると、パッケージに不要なものがたくさん含まれます。

私のプロジェクトでサードパーティのライブラリを使用する正しい方法は何ですか?プロジェクトの依存関係としてこれらのライブラリをインストールするようにクライアントに指示できません。

6

この質問に答えるには、いくつかの側面をカバーする必要があります。以下の2つのセクションがあります。

  • 構成ファイルパッケージ
  • ExternalProject CMakeモジュール

構成ファイルパッケージ

プロジェクトのスコープ内でビルドされていないライブラリの統合を検討している場合、最初のステップは、すべてのライブラリが構成ファイルパッケージを提供していることを確認することです。

構成ファイルパッケージには通常、_FooConfig.cmake_、_FooConfigVersion.cmake_、_FooTargets.cmake_などのファイルが含まれています。

一般的に言って、ライブラリFooがすでにCMakeを使用しており、すでに構成ファイルパッケージを提供している場合、_-DFoo_DIR:PATH=/path/to/build-or-install-dir/_を使用してプロジェクトを構成すると、独自のプロジェクトからfind_package(Foo REQUIRED)を呼び出すことができます。これにより、独自のライブラリまたは実行可能ファイルに対してリンクできるCMakeターゲットがインポートされます。

ライブラリFooがまだCMakeを使用していない場合は、オプションがあります。

  • ケース1:

    • (a)ライブラリFooはすでにCMakeを使用しています
    • (b)しかし、[〜#〜]しない[〜#〜]構成ファイルパッケージを提供します
    • action:ビルドシステムを改善することをお勧めします
  • ケース2:

    • (1)ライブラリFooは、CMakeを使用してnotです
    • (2)とFooのメンテナーは、CMakeに移行する用意があります(または、少なくとも現在のビルドシステムと一緒に_CMakeLists.txt_を持っています)
    • action:ビルドシステムを改善することをお勧めします
  • ケース3:

    • (1)ライブラリFooは、CMakeを使用してnotです
    • (2)FooのメンテナはCMakeへの移行を望まない
    • (3)しかし、メンテナは現在のビルドシステムからconfig-fileパッケージを生成することをいとわない
    • action:私は彼らを助けることを提案します。これは、たとえばQt5で行われたものであり、config-fileパッケージを提供します。
  • ケース4:

    • (1)ライブラリFooは、CMakeを使用してnotです
    • (2)およびFooのメンテナは、CMakeへの移行を望まない(または準備ができていない)。
    • (3)現在のビルドシステムがうまく機能していない、またはライブラリがより広範囲のコンパイラでビルドすることが困難である、またはクロスコンパイルをサポートしていない
    • action:_foo-cmake-buildsystem_という名前のプロジェクトを(理想的にはGitHubに)作成します。

      • 既存のソースツリーへのパスを使用してプロジェクトを構成する
      • プロジェクトにソースをダウンロードさせる
      • これは、たとえばCPythonに対して行われます。 GitHubに_python-cmake-buildsystem_というプロジェクトがあります
  • ケース5:

    • (1)何らかの理由でFooのメンテナが移行したくない、または代替ビルドシステムを維持できない、またはシステム上でライブラリがすでに利用可能である
    • action:インポートされたターゲットを作成する_FindFoo.cmake_を作成できます。
      • このようなファイルはプロジェクトに固有であるか、CMakeに直接提供される可能性があります
      • これは、たとえば、_FindOpenSSL.cmake_、_FindGit.cmake_、...の場合です。

Config-fileパッケージの詳細については、 https://cmake.org/cmake/help/latest/manual/cmake-packages.7.html を参照してください

ExternalProject CMakeモジュール

ライブラリFooが次の場合:*(1)システムで使用できません:*またはパッケージマネージャーを使用してインストールできない*またはコミュニティメンテナンスパッケージ(debian、conda-forge、chocolateyなど)を使用してインストールできない。)そのようなパッケージを持つことは不可能です*(2)またはあなたのプロジェクトのために特別にコンパイルする必要があります

次に、ExternalProject CMakeモジュールを使用すると、独自のプロジェクト内からこれらのプロジェクトをダウンロード、構成、ビルドできます。

これを実現するためのアプローチはほとんどありません。

これはうまく機能しているものです:SuperBuildと呼ばれる2レベルのビルドシステムをセットアップできます。

SuperBuildアプローチをサポートするために、CMakeLists.txtは次の構造を持つことができます。

_project(AwesomeProject)

[...]

option(Awesome_ENABLE_EXTRA "Enable more awesome stuff" OFF)

option(AwesomeProject_SUPERBUILD "Build ${PROJECT_NAME} and the projects it depends on." ON)

[...]

if(AwesomeProject_SUPERBUILD)
  include("${CMAKE_CURRENT_SOURCE_DIR}/SuperBuild.cmake")
  return()
endif()

find_package(Foo REQUIRED)

add_library(AwesomeLib ....)
target_library_libraries(AwesomeLib PUBLIC Foo)

[...]
_

次に、ファイル_SuperBuild.cmake_で、おおよそ次の2つの呼び出しを行います。

_ExternalProject_Add(Foo
  GIT_REPOSITORY "git://github.com/Foo/Foo"
  GIT_TAG "123456"
  SOURCE_DIR ${CMAKE_BINARY_DIR}/Foo
  BINARY_DIR ${CMAKE_BINARY_DIR}/Foo-build
  CMAKE_CACHE_ARGS
    -DFOO_ENABLE_BAR:BOOL=1
  INSTALL_COMMAND ""
  )


ExternalProject_Add(AwesomeProject
  SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}
  BINARY_DIR ${CMAKE_BINARY_DIR}/AwesomeProject-build
  DOWNLOAD_COMMAND ""
  UPDATE_COMMAND ""
  CMAKE_CACHE_ARGS
    -Foo_DIR:PATH=${CMAKE_BINARY_DIR}/Foo-build
    -DAwesome_ENABLE_EXTRA:BOOL=${Awesome_ENABLE_EXTRA}
  INSTALL_COMMAND ""
  )
_

これは、通常のビルドツリーがサブディレクトリ_AwesomeProject-build_にあることを意味します。

_Foo-build_と_AwesomeProject-build_は2つの独立したビルドツリーであり、これらの間のリンクは上記のconfig-fileパッケージであることに注意してください。

これは、AwesomeProjectサブプロジェクトを_-Foo_DIR:PATH=${CMAKE_BINARY_DIR}/Foo-build_および呼び出しfind_package(Foo REQUIRED)で構成することで可能になります。

VisualStudioなどのツールを使用する場合、これらのサブディレクトリのいずれかにあるソリューションファイルを開くことができます。

外部プロジェクトの詳細について: https://cmake.org/cmake/help/latest/module/ExternalProject.html

結論

さらに多くの詳細がありますが、これにより、何が可能かをよりよく理解できるようになることを願っています。

16
J-Christophe