【保存版】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_DIR
は subdirectory
ディレクトリに設定されます。
CMAKE_CURRENT_SOURCE_DIR
と CMAKE_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_DIR
は subdirectory
ディレクトリに設定されます。もし 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
# ソースファイルのリストを生成するロジックを記述する
この方法は、柔軟性と制御性に優れていますが、実装と保守の手間が増えます。