さよなら迷い道! CMake ポリシー CMP0021 で INCLUDE_DIRECTORIES の相対パスをスッキリ解決
CMakeポリシーCMP0021は、INCLUDE_DIRECTORIES
ターゲットプロパティにおける相対パスの処理方法を制御します。このポリシーは、CMake 2.8 で導入され、CMake 3.29.4 以降では動作が変更されました。
旧動作(CMake 2.8 ~ 3.29.3)
このポリシーが設定されていない場合、または OLD
に設定されている場合、CMake は INCLUDE_DIRECTORIES
ターゲットプロパティで指定された相対パスを、プロジェクトディレクトリを基準とした相対パスとして解釈します。
例:
target_include_directories(mytarget PRIVATE include)
上記の例では、mytarget
ターゲットは project_directory/include
ディレクトリにあるヘッダーファイルにアクセスできます。
新動作(CMake 3.29.4 以降)
このポリシーが NEW
に設定されている場合、CMake は INCLUDE_DIRECTORIES
ターゲットプロパティで指定された相対パスを、ソースファイルの親ディレクトリを基準とした相対パスとして解釈します。
target_include_directories(mytarget PRIVATE include)
上記の例では、mytarget
ターゲットは、ソースファイルの親ディレクトリにある include
ディレクトリにあるヘッダーファイルにアクセスできます。
変更の理由
この変更は、CMake の動作をより一貫性のあるものにし、予期せぬ動作を防ぐために行われました。相対パスをソースファイルの親ディレクトリを基準として解釈することで、異なるディレクトリ構造を持つプロジェクト間で移植性を向上させることができます。
影響を受けるプロジェクト
このポリシーの変更は、INCLUDE_DIRECTORIES
ターゲットプロパティで相対パスを使用しているプロジェクトに影響を与えます。影響を受けるプロジェクトを修正するには、以下のいずれかの方法を実行する必要があります。
- ソースファイルの親ディレクトリにある
include
ディレクトリにヘッダーファイルを移動します。 INCLUDE_DIRECTORIES
ターゲットプロパティで絶対パスを使用します。cmake_policy
コマンドを使用してポリシーをNEW
に設定します。
推奨事項
将来的に互換性を保つために、cmake_policy
コマンドを使用してポリシーを NEW
に設定することをお勧めします。
- このポリシーの旧動作は、将来の CMake バージョンで非推奨となり、削除される可能性があります。
- このポリシーは、CMake 3.16.3 以降で警告を発し、設定されていない場合は旧動作を使用します。
# CMakeLists.txt
cmake_minimum_required(VERSION 3.0)
project(myproject)
target_include_directories(mytarget PRIVATE include)
add_executable(myprogram main.cpp)
target_link_libraries(myprogram mytarget)
新動作の例
# CMakeLists.txt
cmake_minimum_required(VERSION 3.29.4)
project(myproject)
cmake_policy(CMP0021 NEW)
target_include_directories(mytarget PRIVATE include)
add_executable(myprogram main.cpp)
target_link_libraries(myprogram mytarget)
上記の例では、mytarget
ターゲットは、ソースファイル main.cpp
の親ディレクトリにある include
ディレクトリにあるヘッダーファイルにアクセスできます。
絶対パスを使用する例
# CMakeLists.txt
cmake_minimum_required(VERSION 3.0)
project(myproject)
target_include_directories(mytarget PRIVATE /path/to/include)
add_executable(myprogram main.cpp)
target_link_libraries(myprogram mytarget)
上記の例では、mytarget
ターゲットは /path/to/include
ディレクトリにあるヘッダーファイルにアクセスできます。
ヘッダーファイルを移動する例
# project_directory/src/main.cpp
#include "include/myheader.h"
int main() {
// ...
}
# project_directory/include/myheader.h
// ...
上記の例では、mytarget
ターゲットは project_directory/src
ディレクトリにある include
ディレクトリにあるヘッダーファイル myheader.h
にアクセスできます。
cmake_policy コマンドを使用する
cmake_policy
コマンドを使用して、ポリシーを NEW
に設定することで、CMake が相対パスをソースファイルの親ディレクトリを基準として解釈するようにすることができます。
cmake_policy(CMP0021 NEW)
この方法は、最も簡単で、将来の CMake バージョンとの互換性を保つことができます。
INCLUDE_DIRECTORIES ターゲットプロパティで絶対パスを使用する
INCLUDE_DIRECTORIES
ターゲットプロパティで絶対パスを使用することで、CMake が相対パスの解釈方法に左右されないようにすることができます。
target_include_directories(mytarget PRIVATE /path/to/include)
この方法は、常に確実に動作しますが、プロジェクトの移植性を低くする可能性があります。
ソースファイルの親ディレクトリにある include ディレクトリにヘッダーファイルを移動する
ソースファイルの親ディレクトリにある include
ディレクトリにヘッダーファイルを移動することで、CMake が相対パスを正しく解釈できるようにすることができます。
# project_directory/src/main.cpp
#include "include/myheader.h"
int main() {
// ...
}
# project_directory/include/myheader.h
// ...
この方法は、プロジェクトの構造を変更する必要があり、すべてのヘッダーファイルがソースファイルの親ディレクトリにある include
ディレクトリにあることを確認する必要があります。
サードパーティのライブラリを使用する
add_subdirectory
コマンドを使用してサードパーティのライブラリを追加する場合、CMake はそのライブラリの include
ディレクトリを自動的に検索します。この場合、CMP0021 ポリシーの影響を受けません。
add_subdirectory(thirdparty_lib)
この方法は、サードパーティのライブラリを使用している場合に有効です。
カスタム CMake モジュールを使用する
カスタム CMake モジュールを作成して、INCLUDE_DIRECTORIES
ターゲットプロパティで指定された相対パスを処理することができます。このモジュールは、ソースファイルの親ディレクトリを基準とした相対パスを解釈するように設計することができます。
この方法は、高度な制御が必要な場合に有効ですが、複雑でメンテナンスが困難になる可能性があります。
最適な代替方法の選択
最適な代替方法は、プロジェクトの要件と状況によって異なります。一般的には、cmake_policy
コマンドを使用するのが最も簡単で、将来の CMake バージョンとの互換性を保つことができます。
- CMake の将来のバージョでは、CMP0021 ポリシーの動作がさらに変更される可能性があります。
- プロジェクトが他のプロジェクトに依存している場合は、依存プロジェクトもポリシー設定を一致させる必要があります。
- プロジェクトに複数の CMakeLists.txt ファイルがある場合は、すべてのファイルでポリシー設定を一致させる必要があります。