CMake: ビルドプロセスをもっと自由に!「CMAKE_PROJECT_INCLUDE」でカスタムコードを挿入する方法


"CMAKE_PROJECT_INCLUDE" は、CMake の "project()" コマンドで呼び出されるすべてのプロジェクトの最後に CMake 言語ファイルまたはモジュールをインクルードするために使用される変数です。これは、ソースコードを変更することなく、プロジェクトのビルドにカスタムコードを挿入するために役立ちます。

バージョン

"CMAKE_PROJECT_INCLUDE" は CMake 3.15 で導入されました。

構文

set(CMAKE_PROJECT_INCLUDE <path-to-cmake-file> [; <another-path-to-cmake-file>])
  • 複数のファイルまたはモジュールをインクルードするには、セミコロンで区切ってリストします。
  • <path-to-cmake-file> は、インクルードする CMake 言語ファイルまたはモジュールのパスです。

set(CMAKE_PROJECT_INCLUDE ${CMAKE_SOURCE_DIR}/my_project/custom_code.cmake)

この例では、my_project ディレクトリ内の custom_code.cmake ファイルがすべてのプロジェクトの最後にインクルードされます。

モジュール名によるインクルード

CMake 3.29 以降では、"CMAKE_PROJECT_INCLUDE" でモジュール名を指定することもできます。モジュール名は CMAKE_MODULE_PATH または組み込みの CMake モジュールとして検索されます。

set(CMAKE_PROJECT_INCLUDE FindPkgConfig)

この例では、FindPkgConfig モジュールがすべてのプロジェクトの最後にインクルードされます。

"CMAKE_PROJECT_<PROJECT-NAME>_INCLUDE" と "CMAKE_PROJECT_INCLUDE_BEFORE"

"CMAKE_PROJECT_INCLUDE" に加えて、以下の変数も使用できます。

  • "CMAKE_PROJECT_INCLUDE_BEFORE": "CMAKE_PROJECT_INCLUDE" の前にインクルードされる CMake 言語ファイルまたはモジュールのリストです。
  • "CMAKE_PROJECT_<PROJECT-NAME>_INCLUDE": 特定のプロジェクトにのみカスタムコードを挿入するために使用されます。

用途

"CMAKE_PROJECT_INCLUDE" は、さまざまな目的に使用できます。以下はいくつかの例です。

  • カスタムビルドルールを追加する
  • 外部ライブラリの依存関係を管理する
  • ターゲット固有のソースコードをインクルードする
  • プロジェクト固有のビルド設定を定義する

利点

"CMAKE_PROJECT_INCLUDE" を使用すると、以下の利点があります。

  • ビルドプロセスをより柔軟にカスタマイズできる
  • プロジェクト固有のコードを簡単に管理できる
  • ソースコードを変更する必要がない

注意点

"CMAKE_PROJECT_INCLUDE" を使用するときは、以下の点に注意する必要があります。

  • "CMAKE_PROJECT_INCLUDE" を使用してビルドシステムを複雑にしすぎないようにしてください。
  • 複数のプロジェクトで同じ "CMAKE_PROJECT_INCLUDE" を使用している場合は、潜在的な競合に注意してください。
  • インクルードする CMake 言語ファイルまたはモジュールが存在し、アクセス可能であることを確認してください。


例 1: プロジェクト固有のビルド設定を定義する

この例では、my_project ディレクトリ内の custom_build_settings.cmake ファイルを使用して、プロジェクト固有のビルド設定を定義します。

# CMakeLists.txt

set(CMAKE_PROJECT_INCLUDE ${CMAKE_SOURCE_DIR}/my_project/custom_build_settings.cmake)

project(my_project)

add_executable(my_program main.cpp)
# custom_build_settings.cmake

# プロジェクト固有のビルド設定を定義する
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -std=c++17")

例 2: ターゲット固有のソースコードをインクルードする

この例では、my_target ターゲットにのみ custom_target_code.c ファイルをインクルードします。

# CMakeLists.txt

set(CMAKE_PROJECT_INCLUDE ${CMAKE_SOURCE_DIR}/my_project/custom_target_code.c)

project(my_project)

add_executable(my_program main.cpp)

target_sources(my_program PRIVATE ${CMAKE_PROJECT_INCLUDE})

例 3: 外部ライブラリの依存関係を管理する

この例では、FindPkgConfig モジュールを使用して、my_library ライブラリの依存関係を管理します。

# CMakeLists.txt

set(CMAKE_PROJECT_INCLUDE FindPkgConfig)

project(my_project)

find_package(MyLibrary REQUIRED)

add_executable(my_program main.cpp)

target_link_libraries(my_program MyLibrary::Depends)

例 4: カスタムビルドルールを追加する

この例では、custom_build_rule.cmake ファイルを使用して、カスタムビルドルールを追加します。

# CMakeLists.txt

set(CMAKE_PROJECT_INCLUDE ${CMAKE_SOURCE_DIR}/my_project/custom_build_rule.cmake)

project(my_project)

add_executable(my_program main.cpp)

add_custom_command(
    TARGET my_program
    POST_BUILD
    COMMAND ${CMAKE_COMMAND} -E cmake_run_command <custom_build_rule.cmake>
)
# custom_build_rule.cmake

# カスタムビルドルールを実行する
message(STATUS "Running custom build rule")

# ビルドディレクトリを取得する
get_property(BUILD_DIR DIRECTORY CURRENT_SOURCE_DIR)

# カスタムコマンドを実行する
execute_process(
    COMMAND my_custom_command ${BUILD_DIR}
    WORKING_DIRECTORY ${BUILD_DIR}
)


"add_custom_command" を使用する

"add_custom_command" コマンドを使用して、プロジェクトのビルドプロセスにカスタムステップを追加できます。この方法は、"CMAKE_PROJECT_INCLUDE" よりも柔軟性が高く、より複雑なタスクを実行するために使用できます。

add_custom_command(
    TARGET my_program
    POST_BUILD
    COMMAND my_custom_command
)

"ExternalProject_Add" を使用する

"ExternalProject_Add" モジュールを使用して、外部プロジェクトを CMake プロジェクトに統合できます。この方法は、別の CMake プロジェクトを依存関係として管理する場合に役立ちます。

ExternalProject_Add(my_external_project
    SOURCE_DIR ${MY_EXTERNAL_PROJECT_SOURCE_DIR}
    BUILD_DIR ${MY_EXTERNAL_PROJECT_BUILD_DIR}
    INSTALL_DIR ${MY_EXTERNAL_PROJECT_INSTALL_DIR}
)

target_link_libraries(my_program my_external_project)

"target_sources" または "target_link_libraries" を使用する

"target_sources" または "target_link_libraries" プロパティを使用して、プロジェクトのソースコードまたはライブラリの依存関係を直接指定できます。この方法は、シンプルな依存関係を管理する場合に役立ちます。

target_sources(my_program my_custom_code.c)

target_link_libraries(my_program MyLibrary::Depends)

CMake モジュールを使用する

特定のタスクを実行するために設計された CMake モジュールを使用できます。たとえば、"FindPkgConfig" モジュールを使用して外部ライブラリの依存関係を管理したり、"CPack" モジュールを使用してインストーラーを作成したりできます。

find_package(MyLibrary REQUIRED)

target_link_libraries(my_program MyLibrary::Depends)

CPack_Generate(my_project)

最適な方法の選択

"CMAKE_PROJECT_INCLUDE" の代替方法を選択する際には、以下の要素を考慮する必要があります。

  • メンテナンス性: 使用する方法は、プロジェクトのメンテナンス性を考慮する必要があります。
  • 複雑性: "add_custom_command" や "ExternalProject_Add" のような方法は、より複雑なタスクを実行するために適していますが、"target_sources" や "target_link_libraries" のような方法はよりシンプルです。
  • 必要な機能: 使用する方法は、必要な機能によって異なります。