CMake - インクルード
概要
CMakeにおいて、インクルードに関するコマンドには主に以下の3つがある。
- 特定のターゲットに対してインクルードディレクトリを設定する場合 :
target_include_directories
コマンド- ターゲットごとに異なるインクルードディレクトリを設定できるため、より細かい制御が可能である。
- インクルードディレクトリと共に、スコープ (PRIVATE, PUBLIC, INTERFACE) を指定する。
target_include_directories(my_target PRIVATE ${CMAKE_SOURCE_DIR}/include)
target_include_directories(my_target PUBLIC ${CMAKE_SOURCE_DIR}/include ${CMAKE_SOURCE_DIR}/src)
- プロジェクト全体に対してインクルードディレクトリを設定する場合 :
include_directories
コマンド- 指定されたディレクトリは、全てのターゲットに適用される。
include_directories(${CMAKE_SOURCE_DIR}/include)
include_directories(${CMAKE_SOURCE_DIR}/src ${CMAKE_SOURCE_DIR}/third_party)
- 別のCMakeスクリプトを読み込む場合 :
include
コマンド- 別のCMakeスクリプトファイルを読み込むためのコマンドである。
- インクルードディレクトリの設定とは異なり、CMake構成の再利用やモジュールの分割に使用される。
- 指定したファイルを読み込み、その中に定義されたCMakeコマンドを実行する。
include(${CMAKE_SOURCE_DIR}/cmake/my_module.cmake)
これらのコマンドを使い分けることにより、CMakeを使用したプロジェクトの構成やビルド設定を効率的に行うことができる。
非ターゲットのインクルード (target_include_directoriesコマンド)
find_package
コマンドは、include
コマンドで手動で行う設定を、REQUIRED
オプション等を使用して自動で行うことができる。
find_package(PkgConfig)
find_package
コマンドは、pkg_search_module
コマンドよりも柔軟でより多くのオプションが存在する。
また、CMakeには豊富なパッケージ定義が付属しており、パッケージ管理システムからインストールしたソフトウェアは/usr/share/cmake/Modules/Find*.cmakeファイルにある。
target_include_directories(<ターゲット名> PUBLIC ...)
コマンドは、
<ターゲット名>を使用する全てのターゲットにおいて、自動的にインクルードディレクトリが使用されるようになる。
ただし、CMakeLists.txtファイル内のターゲットにのみ有効であり、pkg_search_module
コマンドで取得したライブラリに対しては機能しない。
# pkg-configコマンドの使用
find_package(PkgConfig REQUIRED)
# pkg-configコマンドを使用してライブラリとヘッダファイルを自動的に設定
pkg_check_modules(<任意の変数名> <.pcファイル内の[Name]セクション名 例. sdl2> REQUIRED IMPORTED_TARGET)
# ...略
target_link_libraries(<ターゲット名>
${<任意の変数名>_LIBRARIES}
)
target_include_directories(<ターゲット名> PUBLIC
${<任意の変数名>_INCLUDE_DIRS}
)
target_compile_options(<ターゲット名> PUBLIC
${<任意の変数名>_CFLAGS}
# または
${<任意の変数名>_CFLAGS_OTHER}
)
インクルードパスの指定
target_include_directoriesコマンド (推奨)
インクルードパスを指定する場合、target_include_directories
コマンドを使用する。
target_include_directories
コマンドを使用することにより、ターゲット単位でインクルードパスを適切に管理できる。
特定のターゲットに対してのみインクルードディレクトリを設定する場合は、target_include_directories
コマンドを使用することを推奨する。
- PUBLIC
- このターゲット、および、このターゲットに依存する他のターゲットでも使用する。
- PRIVATE
- このターゲットでのみ使用する。
- INTERFACE
- このターゲットには使用せず、このターゲットに依存する他のターゲットでのみ使用する。
- $<BUILD_INTERFACE:...>
- ビルド時のインクルードパス
- $<INSTALL_INTERFACE:...>
- インストール後のインクルードパス
- ${PROJECT_SOURCE_DIR}
- CMakeが自動的に設定する変数であり、プロジェクトのトップレベルのソースディレクトリへの絶対パスを表す。
- CMakeプロジェクトのトップレベル (
project()
コマンドを実行したディレクトリ) の絶対パスが格納されている。 - サブディレクトリからこの変数を参照すると、トップレベルのディレクトリパスが返される。
# ターゲットの定義
add_library(my_library
source1.cpp
source2.cpp
)
# ターゲットのインクルードディレクトリを指定
target_include_directories(my_library
PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
$<INSTALL_INTERFACE:include>
PRIVATE
${PROJECT_SOURCE_DIR}/external/lib1/include
${PROJECT_SOURCE_DIR}/external/lib2/include
)
include_directoriesコマンド (非推奨)
include_directories
コマンドの使用は避けるべきである。
これは、プロジェクト全体で共通のインクルードパスを設定するため、意図しないインクルードが発生する可能性があるからである。
include_directories
コマンドは、プロジェクト内の全てのターゲットに対して指定されたディレクトリを適用する。
include_directories(/path/to/include)
include_directories
コマンドを複数使用する場合、デフォルトでは、指定したパスは最後尾となる。
ただし、include_directories
コマンドにBEFORE
オプションを付加した場合は最前となる。
以下の例では、"-I/path1/to/include -I/path2/to/include"となる。
include_directories(/path1/to/include)
include_directories(/path2/to/include)
以下の例では、"-I/path2/to/include -I/path1/to/include" となる。
include_directories(/path1/to/include)
include_directories(BEFORE /path2/to/include)
include(CMakePackageConfigHelpers)
このコマンドは、パッケージ設定ファイルの作成を支援するためのヘルパ関数を提供する。
このコマンドは、CMakeのビルドプロセスをより柔軟かつ強力にするための追加機能を提供する。
プロジェクトの要件に応じて適切に使用することにより、より管理しやすく、他のプロジェクトとの統合も容易になる。
主な機能は以下の通りである。
- write_basic_package_version_file()
- パッケージのバージョン情報ファイルを生成する。
- configure_package_config_file()
- パッケージの設定ファイルを生成する。
これらの関数を使用することにより、他のプロジェクトがfind_package
コマンドを使用して自身のプロジェクトを簡単に見つけて使用できる。
include(GenerateExportHeader)
このコマンドは、ライブラリのシンボルをエクスポートするためのヘッダファイルを自動生成する機能を提供する。
このコマンドは、CMakeのビルドプロセスをより柔軟かつ強力にするための追加機能を提供する。
プロジェクトの要件に応じて適切に使用することにより、より管理しやすく、他のプロジェクトとの統合も容易になる。
主な用途は以下の通りである。
- generate_export_header()
- ライブラリのシンボルをエクスポートするマクロを含むヘッダファイルを生成する。
これにより、特にWindows環境での動的ライブラリ (DLL) の作成時に必要となるシンボルのエクスポート / インポート宣言を簡単に管理できる。
include(FeatureSummary)
このコマンドは、プロジェクトの機能や依存関係の概要を表示するための関数を提供する。
このコマンドは、CMakeのビルドプロセスをより柔軟かつ強力にするための追加機能を提供する。
プロジェクトの要件に応じて適切に使用することにより、より管理しやすく、他のプロジェクトとの統合も容易になる。
主な機能は以下の通りである。
- add_feature_info()
- プロジェクトの機能情報を追加する。
- set_package_properties()
- パッケージの属性を設定する。
- feature_summary()
- 追加された機能や依存関係の概要を表示する。
これらの関数を使用することにより、プロジェクトの構成や必要な依存関係を簡単に把握して、ユーザに分かりやすく表示することができる。
set(CMAKE_INCLUDE_CURRENT_DIR ON)
CMakeのビルド設定において、
現在のディレクトリ (CMakeLists.txtファイルが存在するディレクトリ) とビルドディレクトリを自動的にインクルードパスに追加するオプションである。
CMake変数CMAKE_INCLUDE_CURRENT_DIR
をONに指定することにより、以下に示す2つのディレクトリが自動的にインクルードパスに追加される。
- 現在のソースディレクトリ (CMakeLists.txtファイルが存在するディレクトリ) の自動追加
- 現在処理中のソースディレクトリが、インクルードパスに追加する。
- 現在のビルドディレクトリの自動追加
- CMakeによって生成されたファイル (例: 設定ファイルや自動生成されたヘッダファイル等) が配置されるビルドディレクトリをインクルードパスに追加する。
この変数を有効にする場合、以下に示すような特徴がある。
- 利便性の向上
- ソースファイル内でヘッダファイルをインクルードする時に、フルパスを指定する必要がなくなる。
- 自動生成ファイルの取り扱い
- 特に、CMakeやQtのような自動生成ツールによって生成されるファイルを簡単にインクルードできるようになる。
- そのため、開発者は明示的に
include_directories
コマンドで指定する必要がない。
- サブディレクトリへの影響
- この設定は、現在のディレクトリとそのサブディレクトリに対して有効になる。
この変数を有効にする場合、以下に示すようなメリットがある。
- Qtプロジェクトで、moc (Meta-Object Compiler) によって生成されたファイルを容易に見つけることができる。
- CMakeのconfigure_fileコマンドで生成されたヘッダファイルを簡単にインクルードすることができる。
ただし、大規模なプロジェクトでは不要なディレクトリもインクルードパスに追加される可能性があるため、明示的にインクルードディレクトリを指定する方が管理しやすい。
また、同名のヘッダファイルが異なるディレクトリに存在する場合、予期せぬ衝突が発生する可能性がある。
そのため、大規模なプロジェクトや複雑なディレクトリ構造を持つプロジェクトでは、
より明示的なインクルードパスの管理 (target_include_directories
コマンドの使用等) を検討すること推奨する。