CMake: シンボリックリンクの処理を柔軟に制御! CMP0009 と GLOB/CMAKE_FIND_FILE/READ_DIR の使い分け


CMake ポリシー CMP0009 は、FILE(GLOB_RECURSE) コマンドがシンボリックリンクを処理する方法を制御します。このポリシーは、CMake 2.6 で導入され、デフォルトでは "OLD" 動作に設定されています。

OLD 動作

"OLD" 動作では、FILE(GLOB_RECURSE) コマンドはデフォルトでシンボリックリンクをたどります。つまり、シンボリックリンクが指すファイルやディレクトリも結果に含まれます。

NEW 動作

"NEW" 動作では、FILE(GLOB_RECURSE) コマンドはデフォルトでシンボリックリンクをたどりません。つまり、結果にはシンボリックリンク自身が含まれ、シンボリックリンクが指すファイルやディレクトリは含まれません。

シンボリックリンクの処理を制御する方法

FILE(GLOB_RECURSE) コマンドには、FOLLOW_SYMLINKS オプションを指定することで、シンボリックリンクの処理を制御することができます。

  • FOLLOW_SYMLINKS オプションを省略すると、シンボリックリンクはたどられず、結果にはシンボリックリンク自身が含まれます。
  • FOLLOW_SYMLINKS オプションを指定すると、シンボリックリンクがたどられ、シンボリックリンクが指すファイルやディレクトリも結果に含まれます。

CMP0009 ポリシーを設定する方法

CMP0009 ポリシーを設定するには、以下のコマンドを使用します。

CMAKE_POLICY(SET CMP0009 NEW)

このコマンドを実行すると、FILE(GLOB_RECURSE) コマンドはデフォルトでシンボリックリンクをたどらなくなります。

以下の例は、CMP0009 ポリシーを "NEW" に設定し、FILE(GLOB_RECURSE) コマンドを使用してシンボリックリンクを含むディレクトリからすべてのファイルを検索する方法を示しています。

CMAKE_POLICY(SET CMP0009 NEW)

FILE(GLOB_RECURSE SOURCES *.c *.h)

foreach(SOURCE ${SOURCES})
  message(STATUS "Found source file: ${SOURCE}")
endforeach()

この例では、CMAKE_POLICY(SET CMP0009 NEW) コマンドによって、FILE(GLOB_RECURSE) コマンドはデフォルトでシンボリックリンクをたどらなくなります。そのため、SOURCES 変数にはシンボリックリンク自身が含まれず、シンボリックリンクが指すファイルのみが含まれます。

  • CMP0009 ポリシーを設定すると、既存の CMake プロジェクトで問題が発生する可能性があります。既存のプロジェクトを更新する場合は、注意が必要です。
  • CMP0009 ポリシーは、CMake 2.6 以降でのみ使用できます。


シンボリックリンクを含むディレクトリからすべてのファイルを検索する

CMAKE_POLICY(SET CMP0009 NEW)

FILE(GLOB_RECURSE SOURCES *.c *.h)

foreach(SOURCE ${SOURCES})
  message(STATUS "Found source file: ${SOURCE}")
endforeach()
  • foreach ループは、SOURCES 変数内の各ファイルに対して反復処理し、そのファイル名をメッセージとして出力します。
  • FILE(GLOB_RECURSE SOURCES *.c *.h) コマンドは、SOURCES 変数にシンボリックリンクが指すすべての .c ファイルと .h ファイルを格納します。
  • CMAKE_POLICY(SET CMP0009 NEW) コマンドによって、FILE(GLOB_RECURSE) コマンドはデフォルトでシンボリックリンクをたどらなくなります。
  • このコードは、CMP0009 ポリシーを "NEW" に設定し、FILE(GLOB_RECURSE) コマンドを使用してシンボリックリンクを含むディレクトリからすべてのファイルを検索します。

シンボリックリンクを含むディレクトリからすべてのファイルを検索し、シンボリックリンク自身も結果に含める

FILE(GLOB_RECURSE SOURCES *.c *.h FOLLOW_SYMLINKS)

foreach(SOURCE ${SOURCES})
  message(STATUS "Found source file: ${SOURCE}")
endforeach()

説明

  • foreach ループは、SOURCES 変数内の各ファイルに対して反復処理し、そのファイル名をメッセージとして出力します。
  • FILE(GLOB_RECURSE SOURCES *.c *.h FOLLOW_SYMLINKS) コマンドは、SOURCES 変数にシンボリックリンクを含むディレクトリ内のすべての .c ファイル、.h ファイル、およびシンボリックリンク自身を格納します。
  • このコードは、FILE(GLOB_RECURSE) コマンドの FOLLOW_SYMLINKS オプションを使用して、シンボリックリンクを含むディレクトリからすべてのファイルを検索し、シンボリックリンク自身も結果に含めます。
CMAKE_POLICY(SET CMP0009 NEW)

FILE(GLOB_RECURSE SOURCES *.c)

foreach(SOURCE ${SOURCES})
  message(STATUS "Found source file: ${SOURCE}")
endforeach()

説明

  • foreach ループは、SOURCES 変数内の各ファイルに対して反復処理し、そのファイル名をメッセージとして出力します。
  • FILE(GLOB_RECURSE SOURCES *.c) コマンドは、SOURCES 変数にシンボリックリンクを含むディレクトリ内のすべての .c ファイルを格納し、シンボリックリンク自身は格納しません。
  • CMAKE_POLICY(SET CMP0009 NEW) コマンドによって、FILE(GLOB_RECURSE) コマンドはデフォルトでシンボリックリンクをたどらなくなります。
  • このコードは、CMP0009 ポリシーを "NEW" に設定し、FILE(GLOB_RECURSE) コマンドを使用してシンボリックリンクを含むディレクトリからすべての .c ファイルを検索し、シンボリックリンク自身は結果に含まないことを示しています。
  • CMP0009 ポリシーを設定すると、既存の CMake プロジェクトで問題が発生する可能性があります。既存のプロジェクトを更新する場合は、注意が必要です。
  • CMake ポリシー CMP0009 は、CMake 2.6 以降でのみ使用できます。
  • 上記のコード例はあくまでも例であり、実際のプロジェクトで使用する場合には、必要に応じて修正する必要があります。


CMP0009 ポリシーの代替方法として、以下の方法が考えられます。

GLOB コマンドを使用する

GLOB コマンドは、FILE(GLOB_RECURSE) コマンドと同様に、ファイルやディレクトリのリストを生成することができます。ただし、GLOB コマンドは、デフォルトでシンボリックリンクをたどりません。

FILE(GLOB SOURCES *.c *.h)

foreach(SOURCE ${SOURCES})
  message(STATUS "Found source file: ${SOURCE}")
endforeach()

このコード例は、GLOB コマンドを使用してシンボリックリンクを含むディレクトリからすべての .c ファイルと .h ファイルを検索する方法を示しています。

CMAKE_FIND_FILE モジュールを使用する

CMAKE_FIND_FILE モジュールは、特定のファイルやディレクトリを検索するために使用することができます。このモジュールは、シンボリックリンクを処理するように設定することができます。

find_file(HEADER_FILE main.h
  PATHS "${CMAKE_SOURCE_DIR}"
  NO_PATH_REQUIRED)

if(HEADER_FILE)
  message(STATUS "Found header file: ${HEADER_FILE}")
else()
  message(STATUS "Header file not found: main.h")
endif()

このコード例は、CMAKE_FIND_FILE モジュールを使用して main.h ヘッダーファイルを検索する方法を示しています。

手動でシンボリックリンクを処理する

FILE モジュールの READ_DIR コマンドを使用して、ディレクトリ内のすべてのエントリを列挙し、シンボリックリンクかどうかを確認することができます。

file(READ_DIR DIR_PATH FILES)

foreach(FILE ${FILES})
  if(NOT IS_DIRECTORY "${DIR_PATH}/${FILE}")
    message(STATUS "Found source file: ${DIR_PATH}/${FILE}")
  endif()
endforeach()

このコード例は、DIR_PATH ディレクトリ内のすべてのファイルを検索し、シンボリックリンクかどうかを確認する方法を示しています。

  • CMP0009 ポリシーを設定すると、既存の CMake プロジェクトで問題が発生する可能性があります。既存のプロジェクトを更新する場合は、注意が必要です。
  • CMake ポリシー CMP0009 は、CMake 2.6 以降でのみ使用できます。
  • 上記の代替方法は、それぞれ一長一短があります。状況に応じて適切な方法を選択してください。