CMakeポリシー CMP0044 でソースファイル名の重複を検知する

2024-04-02

CMakeポリシー CMP0044 の詳細解説

CMakeポリシー CMP0044 は、CMake 3.13 で導入された新しいポリシーで、target_sources コマンドでソースファイルのリストを指定する際、ファイル名の重複を検知し、警告またはエラーを出力する機能を提供します。このポリシーは、プロジェクト内のソースファイル管理をより厳格にし、ビルドエラーを防ぐために役立ちます。

設定方法

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

cmake_policy(CMP0044 NEW)

このコマンドを実行すると、target_sources コマンドで指定されたソースファイル名の重複が検知された場合、警告またはエラーが出力されます。

動作

CMP0044 ポリシーが有効な場合、target_sources コマンドで指定されたソースファイル名の重複が検知されると、以下の動作が発生します。

  • CMAKE_POLICY_CMP0044_ALLOW_DUPLICATES オプションが設定されていない場合:
    • 警告またはエラーメッセージが出力されます。
    • 警告メッセージの場合は、ビルドは続行されます。
    • エラーメッセージの場合は、ビルドが中止されます。
  • CMAKE_POLICY_CMP0044_ALLOW_DUPLICATES オプションが設定されている場合:
    • 警告メッセージのみが出力されます。
    • ビルドは続行されます。

オプション

CMP0044 ポリシーには、以下のオプションが用意されています。

  • CMAKE_POLICY_CMP0044_ALLOW_DUPLICATES:
    • ソースファイル名の重複を許可するかどうかを指定します。
    • デフォルトは FALSE です。
    • TRUE に設定すると、警告メッセージのみが出力されます。

以下の例は、CMP0044 ポリシーを使用して、ソースファイル名の重複を検知する方法を示しています。

cmake_policy(CMP0044 NEW)

target_sources(my_target
    PUBLIC
        main.c
        foo.c
        bar.c
    PRIVATE
        baz.c
)

この例では、my_target ターゲットに対して、main.cfoo.cbar.cbaz.c の 4 つのソースファイルが指定されています。

  • main.cfoo.c は同じ名前のファイルなので、CMP0044 ポリシーによって警告またはエラーメッセージが出力されます。
  • bar.cbaz.c は異なる名前のファイルなので、警告またはエラーメッセージは出力されません。

注意事項

  • CMP0044 ポリシーは、CMake 3.13 以降でのみ使用できます。
  • CMP0044 ポリシーは、デフォルトで有効になっています。
  • CMP0044 ポリシーは、ソースファイル名の重複のみを検知します。ファイルの内容が重複していても、検知されません。


CMake ポリシー CMP0044 のサンプルコード

警告メッセージを出力する例

cmake_policy(CMP0044 NEW)

target_sources(my_target
    PUBLIC
        main.c
        foo.c
        bar.c
    PRIVATE
        baz.c
)
CMake Warning at CMakeLists.txt:10 (target_sources):
  Source file "foo.c" has already been listed for target "my_target".

エラーメッセージを出力する例

cmake_policy(CMP0044 NEW)
cmake_policy(SET CMP0044_ALLOW_DUPLICATES FALSE)

target_sources(my_target
    PUBLIC
        main.c
        foo.c
        bar.c
    PRIVATE
        baz.c
)

この例は、上記の例に CMAKE_POLICY_CMP0044_ALLOW_DUPLICATES オプションを追加したものです。このオプションを FALSE に設定すると、ソースファイル名の重複が検知された場合、エラーメッセージが出力されます。

CMake Error at CMakeLists.txt:10 (target_sources):
  Source file "foo.c" has already been listed for target "my_target".

重複を許可する例

cmake_policy(CMP0044 NEW)
cmake_policy(SET CMP0044_ALLOW_DUPLICATES TRUE)

target_sources(my_target
    PUBLIC
        main.c
        foo.c
        bar.c
    PRIVATE
        baz.c
)

この例は、上記の例に CMAKE_POLICY_CMP0044_ALLOW_DUPLICATES オプションを追加したものです。このオプションを TRUE に設定すると、ソースファイル名の重複が検知されても、警告メッセージのみが出力されます。

CMake Warning at CMakeLists.txt:10 (target_sources):
  Source file "foo.c" has already been listed for target "my_target".

複数ターゲットで重複を検知する例

cmake_policy(CMP0044 NEW)

target_sources(my_target1
    PUBLIC
        main.c
        foo.c
        bar.c
)

target_sources(my_target2
    PUBLIC
        foo.c
        baz.c
)

この例では、my_target1my_target2 の 2 つのターゲットに対して、main.cfoo.cbar.cbaz.c の 4 つのソースファイルが指定されています。

  • foo.cmy_target1my_target2 の両方のターゲットで指定されているので、CMP0044 ポリシーによって警告メッセージが出力されます。
CMake Warning at CMakeLists.txt:10 (target_sources):
  Source file "foo.c" has already been listed for target "my_target1".

CMake Warning at CMakeLists.txt:16 (target_sources):
  Source file "foo.c" has already been listed for target "my_target2".

特定のディレクトリ内の重複のみを検知する例

cmake_policy(CMP0044 NEW)

set(SRC_DIR "${CMAKE_CURRENT_SOURCE_DIR}/src")

target_sources(my_target
    PUBLIC
        ${SRC_DIR}/main.c
        ${SRC_DIR}/foo.c
        bar.c
)

target_sources(my_target2
    PUBLIC
        ${SRC_DIR}/foo.c
        baz.c
)

この例は、上記の例に SRC_DIR



手動でチェックする

すべてのソースファイルの名前をリストアップし、重複がないことを手動で確認します。この方法は、プロジェクト規模が小さい場合にのみ有効です。

スクリプトを使用する

重複を検知するためのスクリプトを作成します。スクリプトは、すべてのソースファイルの名前をリストアップし、重複がないことを確認します。この方法は、プロジェクト規模が大きくなってきた場合に有効です。

外部ツールを使用する

重複を検知するための外部ツールを使用します。いくつかの外部ツールが公開されています。

以下は、CMake 3.13 以前のバージョンの CMake でソースファイル名の重複を検知するために使用できる外部ツールの例です。

これらのツールは、ソースファイル名の重複だけでなく、その他の潜在的な問題も検知することができます。

CMake のカスタムターゲットを使用する

以下の例は、CMake のカスタムターゲットを使用して、ソースファイル名の重複を検知する方法を示しています。

add_custom_target(check_source_file_duplicates
    COMMAND ${CMAKE_COMMAND} -E
        list(REMOVE_DUPLICATES SOURCE_FILES)
    COMMAND ${CMAKE_COMMAND} -E
        message("The following source files have duplicate names:")
    COMMAND ${CMAKE_COMMAND} -E
        foreach(FILE ${SOURCE_FILES})
            message("    ${FILE}")
        endforeach()
)

add_dependencies(my_target check_source_file_duplicates)

この例では、check_source_file_duplicates という名前のカスタムターゲットを作成しています。このターゲットは、以下のコマンドを実行します。

  1. SOURCE_FILES 変数から重複するファイル名を削除します。
  2. 重複するファイル名のリストを出力します。

my_target ターゲットは、check_source_file_duplicates ターゲットに依存しています。このため、my_target ターゲットをビルドする前に、check_source_file_duplicates ターゲットが実行されます。

注意事項

  • 上記の方法を使用する場合は、CMake のバージョンによって動作が異なる場合があります。
  • 外部ツールを使用する場合は、ツールの使い方を理解する必要があります。

これらの点を考慮して、プロジェクトに合った方法を選択してください。




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

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



CMake の if() コマンド: デバッグとトラブルシューティング

構文条件式if() コマンドの引数には、条件式を指定します。条件式は、以下のいずれかの形式で記述できます。変数の比較: <variable> <operator> <value>コマンドの存在チェック: COMMAND <command-name>


CMake include() で効率的なビルドを実現

include() は CMake の重要なコマンドの一つで、他の CMake ファイルやモジュールを読み込むために使用されます。 これにより、コードを分割し、再利用性と保守性を向上させることができます。機能他の CMake ファイルを読み込んで、その中のコマンドを実行する


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

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


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

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



CMakeでVS_IOT_EXTENSIONS_VERSIONを使用する際のトラブルシューティング

VS_IOT_EXTENSIONS_VERSION は、CMake のターゲットプロパティで、Visual Studio ソリューションに含める Windows 10 IoT 拡張のバージョンを指定します。設定方法バージョンは、4 つの数字で構成される文字列で指定します。例:


GCC-XMLを使ってC++ソースコードからXMLドキュメントを生成する

FindGCCXMLは、CMakeのモジュールの一つで、GCC-XMLフロントエンドの実行ファイルを検出するためのものです。このモジュールは、以下の変数を定義します。GCCXML: GCC-XMLの実行ファイルへのパスGCCXML_FOUND: GCC-XMLが見つかったかどうかを示すブール値


CMAKE_LANG_LINK_LIBRARY_FLAG 変数を設定するその他の方法:ターゲットプロパティ、キャッシュ変数、環境変数、コマンドラインオプション

CMAKE_LANG_LINK_LIBRARY_FLAG は、CMake の "Variables" における重要な変数のひとつです。これは、特定の言語で記述された共有ライブラリや実行ファイルにライブラリをリンクするために使用されるフラグを指定します。


複雑なプロジェクトにおける長いファイルパス問題の解決策:CMAKE_OBJECT_PATH_MAX を活用

CMAKE_OBJECT_PATH_MAX は、CMake 変数の一つで、Windows システムにおける オブジェクトファイルのフルパス における 最大文字数 を設定します。これは、Windows のデフォルトの最大パス長制限である 260 文字を超えるパスを含むプロジェクトをビルドする場合に重要となります。


新しいCMakeポリシー CMP0141:MSVCデバッグ情報フォーマットの互換性を向上

CMakeポリシー CMP0141は、CMake 3.25で導入された新しいポリシーで、MSVCデバッグ情報フォーマットの扱いに関する互換性を提供します。背景CMake 3.24 以前では、デバッグ情報フォーマットフラグは自動的にデフォルトの CMAKE_<LANG>_FLAGS_<CONFIG> キャッシュエントリに追加されていました。しかし、CMake 3.25 以降では、これらのフラグはデフォルト値から除外され、代わりに抽象化された方法で提供されるようになりました。