【保存版】 CMAKE_MATCH_COUNT を駆使して CMake スクリプトをレベルアップ


CMake 変数 CMAKE_MATCH_COUNT は、正規表現マッチング操作の結果を格納するために使用されます。具体的には、以下の情報を保持します。

  • マッチング結果
    CMAKE_MATCH_<n> 変数群に格納された個々のマッチング結果。
  • 正規表現マッチングの成功回数
    最後の正規表現マッチング操作で、対象となる文字列に一致したパターン数。

機能

CMAKE_MATCH_COUNT 変数は、以下の機能を提供します。

  • マッチング結果の取得
    CMAKE_MATCH_<n> 変数群にアクセスすることで、個々のマッチング結果を取得できます。
  • 正規表現マッチングの成否判定
    CMAKE_MATCH_COUNT がゼロ以外の値であれば、正規表現マッチングが成功したことを示します。

使い方

CMAKE_MATCH_COUNT 変数は、以下の手順で使用できます。

  1. 正規表現マッチング操作を実行する
    CMAKE_MATCH コマンドを使用して、対象となる文字列と正規表現を指定します。
  2. CMAKE_MATCH_COUNT 変数の値を確認する: if ステートメントなどを用いて、CMAKE_MATCH_COUNT 変数の値がゼロかどうかを判定します。
  3. CMAKE_MATCH_<n> 変数群にアクセスする: CMAKE_MATCH_<n> 変数群にアクセスすることで、個々のマッチング結果を取得できます。
# 対象となる文字列
set(TARGET_STRING "Hello, world!")

# 正規表現マッチング操作
string(MATCH TARGET_STRING "world" WORLD_MATCH)

# CMAKE_MATCH_COUNT 変数の値を確認
if(CMAKE_MATCH_COUNT GREATER 0)
  message(STATUS "The regular expression 'world' matched the target string.")
  # CMAKE_MATCH_<n> 変数群にアクセス
  message(STATUS "Matched world: ${CMAKE_MATCH_1}")
else()
  message(STATUS "The regular expression 'world' did not match the target string.")
endif()
  • CMAKE_MATCH_<n> 変数群は、最大 9 個まで存在します。
  • CMAKE_MATCH_COUNT 変数は、CMake バージョン 3.2 以降で使用できます。


# 対象となるファイル名
set(FILENAME "myfile.cpp")

# ファイル名から拡張子を抽出
string(REGEX MATCH FILENAME "^([^.]+)\.[^.]+$" EXTENSION)

# CMAKE_MATCH_COUNT 変数の値を確認
if(CMAKE_MATCH_COUNT GREATER 0)
  message(STATUS "Extracted extension: ${CMAKE_MATCH_1}")
else()
  message(STATUS "Failed to extract extension from filename.")
endif()

このコードでは、以下の処理が行われます。

  1. FILENAME 変数に、対象となるファイル名 "myfile.cpp" が設定されます。
  2. string(REGEX MATCH) コマンドを使用して、正規表現 "^([^.]+)\.[^.]+$" でファイル名をマッチングします。この正規表現は、ファイル名と拡張子を分離するパターンを表しています。
  3. CMAKE_MATCH_COUNT 変数の値を確認します。この変数がゼロ以外の値であれば、正規表現マッチングが成功したことを示します。
  4. マッチング結果が成功した場合、CMAKE_MATCH_1 変数に格納された拡張子を出力します。

この例は、CMAKE_MATCH_COUNT 変数を使用して、文字列から特定のパターンを抽出する方法を示しています。この変数は、様々な用途で活用できる強力なツールです。

  • ログファイルからエラーメッセージを抽出する
  • URL からホスト名とパスを抽出する
  • 特定の文字列を含むすべてのファイルをディレクトリから検索する


CMAKE_FOREACH と正規表現を使用したループ

CMAKE_FOREACH ループと正規表現を使用して、個々のマッチング結果を処理することができます。

# 対象となる文字列
set(TARGET_STRING "Hello, world! This is a test.")

# 正規表現パターン
set(REGEX_PATTERN "world")

# CMAKE_FOREACH ループを使用してマッチング結果を処理
foreach(MATCH ${TARGET_STRING})
  string(REGEX MATCH MATCH "${REGEX_PATTERN}" CURRENT_MATCH)
  if(CMAKE_MATCH_COUNT GREATER 0)
    message(STATUS "Matched world: ${CURRENT_MATCH}")
  endif()
endforeach()

list(FIND) を使用したマッチング結果の検索

list(FIND) 関数を使用して、list 変数内に格納された文字列の中から正規表現パターンに一致する要素を検索することができます。

# 対象となる文字列
set(TARGET_STRING "Hello, world! This is a test.")

# 正規表現パターン
set(REGEX_PATTERN "world")

# list(FIND) を使用してマッチング結果を検索
list(FIND TARGET_STRING "${REGEX_PATTERN}" MATCH_INDEX)

if(MATCH_INDEX GREATER THAN -1)
  message(STATUS "Matched world at index: ${MATCH_INDEX}")
endif()

外部ライブラリの使用

Boost.Regex など、外部ライブラリを使用して正規表現マッチングを行うこともできます。

CMakeLists.txt ファイル内での正規表現マッチング

CMakeLists.txt ファイル内の configure_file コマンドを使用して、正規表現マッチングを直接実行することもできます。

CMake スクリプトファイルの使用

独立した CMake スクリプトファイルを作成し、その中で正規表現マッチングを行うこともできます。

それぞれの方法の利点と欠点

  • CMake スクリプトファイルの使用
    再利用性とモジュール性を向上させることができる。
  • CMakeLists.txt ファイル内での正規表現マッチング
    コードを簡潔に記述できる。
  • 外部ライブラリの使用
    より複雑な正規表現マッチングに対応できる。
  • list(FIND) を使用したマッチング結果の検索
    特定のマッチング結果のみを抽出したい場合に有効。
  • CMAKE_FOREACH と正規表現を使用したループ
    処理が比較的単純で分かりやすい。

選択の指針

具体的な状況に応じて、最適な代替方法を選択する必要があります。

  • 再利用性とモジュール性
    CMake スクリプトファイルを使用すると良いでしょう。
  • コードの簡潔性
    CMakeLists.txt ファイル内でのマッチングが適しています。
  • 複雑なマッチング
    外部ライブラリを使用すると良いでしょう。
  • 単純なマッチング
    CMAKE_FOREACH または list(FIND) が適しています。