【保存版】CMake: CMAKE_CURRENT_SOURCE_DIR を使いこなしてスマートな CMakeLists.txt を作成


用途

CMAKE_CURRENT_SOURCE_DIR は、さまざまな場面で役立ちます。以下はその例です。

  • ソースファイルへのパス指定
add_executable(myprogram main.cpp)

上記の例では、main.cpp ファイルは CMAKE_CURRENT_SOURCE_DIR ディレクトリにあると仮定されます。

  • ヘッダーファイルへのパス指定
target_include_directories(myprogram PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include)

上記の例では、myprogram ターゲットは CMAKE_CURRENT_SOURCE_DIR/include ディレクトリにあるすべてのヘッダーファイルを含むようになります。

  • サブディレクトリの処理
add_subdirectory(subdirectory)

上記の例では、subdirectory ディレクトリ内の CMakeLists.txt ファイルが処理されます。この場合、CMAKE_CURRENT_SOURCE_DIRsubdirectory ディレクトリに設定されます。

CMAKE_CURRENT_SOURCE_DIRCMAKE_CURRENT_LIST_DIR の違い

CMAKE_CURRENT_SOURCE_DIR と似ている変数に CMAKE_CURRENT_LIST_DIR があります。この変数は、現在処理されている CMakeLists.txt ファイルのディレクトリへのパスを格納します。

file(GLOB_RECURSE SOURCES *.cpp *.h)


ソースファイルへのパス指定

cmake_minimum_required(VERSION 3.10)

project(myproject)

add_executable(myprogram main.cpp)

この例では、main.cpp ファイルは CMAKE_CURRENT_SOURCE_DIR ディレクトリにあると仮定されます。もし main.cpp ファイルが別のディレクトリにある場合は、次のように変更する必要があります。

add_executable(myprogram ../src/main.cpp)

ヘッダーファイルへのパス指定

cmake_minimum_required(VERSION 3.10)

project(myproject)

add_executable(myprogram main.cpp)

target_include_directories(myprogram PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include)

この例では、myprogram ターゲットは CMAKE_CURRENT_SOURCE_DIR/include ディレクトリにあるすべてのヘッダーファイルを含むようになります。もしヘッダーファイルが別のディレクトリにある場合は、次のように変更する必要があります。

target_include_directories(myprogram PRIVATE ../include)

サブディレクトリの処理

cmake_minimum_required(VERSION 3.10)

project(myproject)

add_subdirectory(subdirectory)

この例では、subdirectory ディレクトリ内の CMakeLists.txt ファイルが処理されます。この場合、CMAKE_CURRENT_SOURCE_DIRsubdirectory ディレクトリに設定されます。もし subdirectory が別のディレクトリにある場合は、次のように変更する必要があります。

add_subdirectory(../subdirectory)

生成されたファイルのパスを取得

cmake_minimum_required(VERSION 3.10)

project(myproject)

add_executable(myprogram main.cpp)

get_target_property(MYPROGRAM_OUTPUT_NAME myprogram OUTPUT_NAME)

message(STATUS "The output filename is: ${MYPROGRAM_OUTPUT_NAME}")

この例では、myprogram ターゲットの出力ファイル名を MYPROGRAM_OUTPUT_NAME 変数に格納します。その後、message コマンドを使用してその名前を出力します。

カスタムコマンドの実行

cmake_minimum_required(VERSION 3.10)

project(myproject)

add_custom_command(
  COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/data/myfile.txt ${CMAKE_CURRENT_BINARY_DIR}/data
  DEPENDS myprogram
)

この例では、myprogram ターゲットがビルドされた後に data/myfile.txt ファイルを CMAKE_CURRENT_BINARY_DIR/data ディレクトリにコピーするカスタムコマンドを作成します。



明示的なパス指定

add_executable(myprogram ../src/main.cpp)
target_include_directories(myprogram PRIVATE ../include)

この方法は、CMAKE_CURRENT_SOURCE_DIR を使用するよりも冗長になる可能性がありますが、ビルドスクリプトの移植性を向上させることができます。

プロジェクトルートディレクトリからの相対パス

プロジェクトのルートディレクトリからの相対パスを使用してファイルを指定することもできます。これは、プロジェクト内のすべてのファイルがルートディレクトリに対して相対的な位置にある場合に役立ちます。

set(PROJECT_ROOT ${CMAKE_BINARY_DIR}/../)

add_executable(myprogram ${PROJECT_ROOT}/src/main.cpp)
target_include_directories(myprogram PRIVATE ${PROJECT_ROOT}/include)

この方法は、CMAKE_CURRENT_SOURCE_DIR を使用するよりも柔軟性がありますが、プロジェクトのレイアウトが変更された場合に手動で更新する必要があるという欠点があります。

カスタム変数

ソースファイルやヘッダーファイルへのパスを格納するカスタム変数を作成することもできます。これは、複数のターゲットで同じパスを使用する必要がある場合に役立ちます。

set(MY_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src/main.cpp)
set(MY_HEADERS ${CMAKE_CURRENT_SOURCE_DIR}/include)

add_executable(myprogram ${MY_SOURCES})
target_include_directories(myprogram PRIVATE ${MY_HEADERS})

この方法は、CMAKE_CURRENT_SOURCE_DIR を使用するよりも可読性と保守性を向上させることができますが、変数の定義と更新の手間が増えます。

CMake の組み込みモジュール

CMake には、ソースファイルやヘッダーファイルを検索するのに役立つ組み込みモジュールがいくつか用意されています。これらのモジュールを使用すると、CMAKE_CURRENT_SOURCE_DIR を明示的に使用する必要がなくなります。

  • list モジュール
    リストを操作するための関数を提供します。
  • glob コマンド
    特定の基準に一致するファイルを再帰的に検索します。
  • find_package モジュール
    外部ライブラリとヘッダーファイルを検索します。

これらのモジュールを使用するには、CMake のドキュメントを参照してください。

ユーティリティスクリプト

複雑なパス処理が必要な場合は、ユーティリティスクリプトを作成して、必要なパスを生成することができます。このスクリプトを CMakeLists.txt ファイルから呼び出すことができます。

# utility.cmake

set(MY_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/get_sources.sh)

add_executable(myprogram ${MY_SOURCES})
# get_sources.sh

# ソースファイルのリストを生成するロジックを記述する

この方法は、柔軟性と制御性に優れていますが、実装と保守の手間が増えます。