CMakeポリシー「CMP0099」徹底解説!依存関係を持つターゲットのビルドを思い通りに制御

2024-04-02

CMakeのポリシー「CMP0099」の詳細解説

CMakeポリシー CMP0099 は、プロジェクト内のターゲットが依存関係を持つターゲットをどのように処理するかを制御します。具体的には、依存関係を持つターゲットがビルドされていない場合に、ビルドプロセスがどのように動作するかを決定します。

デフォルトの動作

このポリシーが設定されていない場合、デフォルトの動作は以下のようになります。

  • 依存関係を持つターゲットがビルドされていない場合、そのターゲットは自動的にビルドされます。
  • 依存関係を持つターゲットのビルドに失敗した場合、全体のビルドは失敗します。

CMP0099による動作の変更

このポリシーを設定することで、以下の動作を変更できます。

  • 依存関係を持つターゲットがビルドされていない場合の処理
    • OLD: デフォルトの動作と同じように、依存関係を持つターゲットは自動的にビルドされます。
    • NEW: 依存関係を持つターゲットはビルドされません。
  • 依存関係を持つターゲットのビルドに失敗した場合の処理
    • FATAL: デフォルトの動作と同じように、全体のビルドは失敗します。
    • NONFATAL: 依存関係を持つターゲットのビルドに失敗しても、全体のビルドは失敗しません。

設定方法

このポリシーは、CMakeLists.txtファイルで以下のコマンドを使用して設定できます。

set(CMAKE_POLICY CMP0099 NEW)

上記の例では、CMP0099ポリシーをNEWに設定しています。

使用例

このポリシーは、以下の様な状況で使用できます。

  • 依存関係を持つターゲットが常に必要なわけではない場合
  • 依存関係を持つターゲットのビルドに時間がかかる場合
  • 依存関係を持つターゲットのビルドが失敗しても、全体のビルドを続行したい場合

注意事項

このポリシーを使用する場合は、以下の点に注意する必要があります。

  • 依存関係を持つターゲットがビルドされない場合、そのターゲットを使用する他のターゲットもビルドされません。
  • 依存関係を持つターゲットのビルドに失敗しても、全体のビルドが失敗しない場合、エラーメッセージが表示されない可能性があります。

補足

  • 上記の説明は、CMakeバージョン3.15以降を対象としています。
  • CMakeのバージョンによって、ポリシーの動作が異なる場合があります。


CMakeポリシー「CMP0099」のサンプルコード

例1:デフォルトの動作

# 依存関係を持つターゲット `foo` が存在
add_library(foo STATIC foo.c)

# ターゲット `bar` は `foo` に依存
add_executable(bar bar.c)

target_link_libraries(bar PUBLIC foo)

この例では、CMP0099ポリシーが設定されていないため、デフォルトの動作になります。

  • ターゲット bar をビルドすると、依存関係を持つターゲット foo も自動的にビルドされます。
  • ターゲット foo のビルドに失敗した場合、ターゲット bar のビルドも失敗し、全体のビルドも失敗します。

例2:依存関係を持つターゲットをビルドしない

set(CMAKE_POLICY CMP0099 NEW)

# 依存関係を持つターゲット `foo` が存在
add_library(foo STATIC foo.c)

# ターゲット `bar` は `foo` に依存
add_executable(bar bar.c)

target_link_libraries(bar PUBLIC foo)

この例では、CMP0099ポリシーをNEWに設定しています。

  • ターゲット bar をビルドしても、依存関係を持つターゲット foo はビルドされません。
  • ターゲット foo が存在しない場合、ターゲット bar のビルドは成功します。

例3:依存関係を持つターゲットのビルド失敗を無視する

set(CMAKE_POLICY CMP0099 NEW)

# 依存関係を持つターゲット `foo` が存在
add_library(foo STATIC foo.c)

# ターゲット `bar` は `foo` に依存
add_executable(bar bar.c)

target_link_libraries(bar PUBLIC foo)

# ターゲット `foo` のビルドを意図的に失敗させる
set_target_properties(foo PROPERTIES COMPILE_FLAGS "-Werror")

この例では、CMP0099ポリシーをNEWに設定し、ターゲット foo のビルドを意図的に失敗させています。

例4:依存関係を持つターゲットのビルドを強制する

set(CMAKE_POLICY CMP0099 OLD)

# 依存関係を持つターゲット `foo` が存在
add_library(foo STATIC foo.c)

# ターゲット `bar` は `foo` に依存
add_executable(bar bar.c)

target_link_libraries(bar PUBLIC foo)

# ターゲット `foo` が存在しない場合、エラーを表示
if(NOT EXISTS "${CMAKE_SOURCE_DIR}/foo.c")
  message(FATAL_ERROR "依存関係を持つターゲット `foo` が存在しません")
endif()

この例では、CMP0099ポリシーをOLDに設定し、依存関係を持つターゲット foo が存在しない場合にエラーを表示しています。

  • ターゲット bar をビルドすると、依存関係を持つターゲット foo が存在しないため、エラーが表示され、全体のビルドが失敗します。

注意事項

これらのサンプルコードはあくまでも参考例であり、実際の使用状況に合わせて調整する必要があります。



CMakeで依存関係を持つターゲットをビルドするその他の方法

# 依存関係を持つターゲット `foo` が存在
add_library(foo STATIC foo.c)

# ターゲット `bar` は `foo` に依存
option(BUILD_FOO "Build foo" ON)

if(BUILD_FOO)
  add_executable(bar bar.c)
  target_link_libraries(bar PUBLIC foo)
endif()

この例では、BUILD_FOOオプションを使用して、ターゲット foobar のビルドを制御しています。

  • オプション BUILD_FOO が有効の場合、ターゲット foobar は両方ともビルドされます。
  • オプション BUILD_FOO が無効の場合、ターゲット foo はビルドされず、ターゲット bar もビルドされません。

外部プロジェクトによるビルド

# 外部プロジェクト `foo` をビルド
ExternalProject_Add(foo
  SOURCE_DIR "${CMAKE_SOURCE_DIR}/foo"
  BUILD_DIR "${CMAKE_BINARY_DIR}/foo"
  BUILD_COMMAND make
)

# ターゲット `bar` は `foo` に依存
add_executable(bar bar.c)
target_link_libraries(bar PUBLIC foo)

この例では、ExternalProjectモジュールを使用して、外部プロジェクト foo をビルドしています。

  • 外部プロジェクト foo がビルドされると、ターゲット foo が生成されます。
  • ターゲット bar は、生成されたターゲット foo に依存してビルドされます。

サブディレクトリによるビルド

# サブディレクトリ `foo` をビルド
add_subdirectory(foo)

# ターゲット `bar` は `foo` に依存
add_executable(bar bar.c)
target_link_libraries(bar PUBLIC foo)

この例では、サブディレクトリ foo を別個のプロジェクトとしてビルドしています。

カスタムコマンドによるビルド

# 依存関係を持つターゲット `foo` をビルドするカスタムコマンド
add_custom_command(
  TARGET foo
  POST_BUILD
  COMMAND ${CMAKE_COMMAND} -E echo "Building foo"
)

# ターゲット `bar` は `foo` に依存
add_executable(bar bar.c)
add_dependencies(bar foo)

この例では、add_custom_commandを使用して、依存関係を持つターゲット foo をビルドするカスタムコマンドを定義しています。

  • ターゲット bar は、カスタムコマンドによって生成されたターゲット foo に依存してビルドされます。

注意事項

これらの方法は、それぞれ利点と欠点があります。使用する方法は、プロジェクトの状況に合わせて選択する必要があります。




CMake find_file() コマンドの代替方法:もっと柔軟なファイル検索

<variable>: 検索結果を格納する CMake 変数<file_names>: 検索するファイル名のリスト (スペース区切り)<path_list>: 検索するパス名のリスト (スペース区切り)<options>: 検索オプション (後述)



CMake try_compile() を使って特定のライブラリがインストールされているかどうかを確認する方法

try_compile() は、CMake の強力なコマンドの一つで、コードを実際にコンパイルすることなく、コンパイルが成功するかどうかを確認することができます。これは、特定のコンパイラやオプションがシステム上で使用可能かどうかをテストしたり、コードの移植性を検証したりする際に非常に便利です。


C++標準ライブラリ、テンプレートエンジン、シェルスクリプト... string()コマンドの代替方法を徹底比較

CMakeのstring()コマンドは、文字列処理を行うための強力なツールです。C++のstd::stringのような機能に加え、CMake特有の便利な機能も備えています。主な機能文字列の連結、分割、置換、比較大文字・小文字変換部分文字列の抽出


CMake: find_library()とtarget_link_directories()の連携

target_link_directories()コマンドは、CMakeプロジェクト内のターゲットに対して、リンカがライブラリを検索するディレクトリを指定するために使用されます。これは、ターゲットがリンクするライブラリが標準の検索パスに存在しない場合に特に重要です。


CMakeにおける"get_target_property()"コマンド: ターゲットの情報を自在に操る

get_target_property()コマンドは、CMakeプロジェクトで定義されたターゲットからプロパティを取得するために使用されます。ターゲットプロパティは、ターゲットのビルド方法や動作を制御するために使用される情報です。構文引数VAR: ターゲットプロパティの値を格納する変数名



【完全解説】CMakeモジュールFindPHP4でPHP4を使えるようにする

FindPHP4 は、CMake のモジュールの一つで、システム上に PHP4 がインストールされているかどうかを検知し、必要な情報を設定するものです。これにより、PHP4 を利用するプロジェクトのビルドを容易にすることができます。FindPHP4 が行う処理


CMake ポリシー CMP0060 とは?

CMake ポリシー CMP0060 は、CMake 3.3 で導入されたポリシーで、ライブラリのリンク方法に影響を与えます。このポリシーは、デフォルトで OLD 動作に設定されていますが、NEW 動作に変更することもできます。OLD 動作と NEW 動作の違い


【初心者向け解説】CMake の "Variables" に関連する "CMAKE_XCODE_BUILD_SYSTEM" のプログラミング

CMake は、クロスプラットフォームなビルドシステムを構築するためのオープンソースのツールです。Xcode は、Apple の macOS と iOS 向けの統合開発環境 (IDE) です。CMake の CMAKE_XCODE_BUILD_SYSTEM 変数は、Xcode を使用して CMake プロジェクトをビルドするように指示するために使用されます。


CMake の Variables に関連する CMAKE_FRAMEWORK_PATH のプログラミング解説

CMake の CMAKE_FRAMEWORK_PATH 変数は、フレームワークライブラリの場所を指定するために使用されます。これは、クロスプラットフォーム開発プロジェクトで特に重要であり、異なるオペレーティングシステムで異なるフレームワークパスが必要になる場合があります。


C/C++開発の鬼門、ヘッダーファイル検索を制覇せよ! CMakeの秘密兵器、CMAKE_LANG_IMPLICIT_INCLUDE_DIRECTORIES

CMAKE_LANG_IMPLICIT_INCLUDE_DIRECTORIES は、CMake の変数の一つで、コンパイラがヘッダーファイルの検索に使用する暗黙のインクルードディレクトリを指定します。この変数を設定することで、#include ディレクティブで指定されたヘッダーファイルが見つかりやすくなります。