CMake: 関数リストファイルを自在に操る「CMAKE_CURRENT_FUNCTION_LIST_FILE」の使い方


CMAKE_CURRENT_FUNCTION_LIST_FILE は CMake 3.17 以降で導入された変数で、現在実行中の関数を定義したリストファイルのフルパス を格納します。これは、function() コマンド内でコードを実行している場合にのみ使用できます。

用途

この変数は、以下の用途に役立ちます。

  • 関数を再定義する: CMakeLists.txt ファイル内の複数の場所から同じ関数を呼び出す場合、CMAKE_CURRENT_FUNCTION_LIST_FILE を使用して、それぞれの場所における関数の定義を区別することができます。
  • 現在実行中の関数の場所を特定する: デバッグやログ出力時に、現在実行中の関数がどのファイルに定義されているのかを特定するために使用できます。

使用例

function(my_function)
  message(STATUS "Current function list file: ${CMAKE_CURRENT_FUNCTION_LIST_FILE}")

  # 関数の処理を行う
endfunction()

my_function()

この例では、my_function() 関数を実行すると、その関数を定義したリストファイルのフルパスが表示されます。

  • この変数は、CMake 3.17 以降でのみ使用できます。
  • この変数は、CMakeLists.txt ファイル内のディレクトリパスを基準とした相対パスで格納されます。
  • CMAKE_CURRENT_FUNCTION_LIST_FILE は、function() コマンド内でコードを実行している場合にのみ使用できます。
  • CMAKE_CURRENT_FUNCTION_LIST_LINE 変数は、現在実行中の行数を格納します。
  • CMAKE_CURRENT_FUNCTION_LIST_DIR 変数は、CMAKE_CURRENT_FUNCTION_LIST_FILE と同様に、現在実行中の関数を定義したリストファイルのディレクトリパスを格納します。


# CMakeLists.txt

cmake_minimum_required(VERSION 3.17)

function(my_function)
  message(STATUS "Current function list file: ${CMAKE_CURRENT_FUNCTION_LIST_FILE}")

  # 関数の処理を行う
endfunction()

my_function()
# CMakeLists.txt

cmake_minimum_required(VERSION 3.17)

function(my_function)
  if(CMAKE_CURRENT_FUNCTION_LIST_FILE MATCHES "^/path/to/CMakeLists.txt$")
    # リストファイル "/path/to/CMakeLists.txt" で定義された関数
    message(STATUS "Calling my_function from /path/to/CMakeLists.txt")
  else()
    # 他のリストファイルで定義された関数
    message(STATUS "Calling my_function from another CMakeLists.txt file")
  endif()

  # 関数の処理を行う
endfunction()

my_function()

# 別のディレクトリにある CMakeLists.txt ファイルで my_function() を呼び出す
file(GLOB_RECURSE OTHER_CMAKELISTS_TXT "/other/directory/*.cmake")
foreach(cmakelists_txt ${OTHER_CMAKELISTS_TXT})
  include(${cmakelists_txt})
  my_function()
endforeach()

この例では、my_function() 関数は、CMakeLists.txt ファイルと /other/directory ディレクトリ内の他の CMakeLists.txt ファイルから呼び出されます。CMAKE_CURRENT_FUNCTION_LIST_FILE を使用して、それぞれの場所における関数の定義を区別することができます。

# CMakeLists.txt

cmake_minimum_required(VERSION 3.17)

function(my_function)
  message(STATUS "Calling my_function from ${CMAKE_CURRENT_FUNCTION_LIST_FILE} (line ${CMAKE_CURRENT_FUNCTION_LIST_LINE})")

  # 関数の処理を行う
endfunction()

my_function()


代替方法

以下に、CMAKE_CURRENT_FUNCTION_LIST_FILE の代替方法をいくつか紹介します。

CMAKE_SCRIPT_CURRENT_DIR と CMAKE_SCRIPT_NAME を組み合わせる

この方法は、現在実行中のスクリプトのディレクトリパススクリプトファイル名 を取得して、リストファイルのパスを推測する方法です。

function(my_function)
  set(list_file_path "${CMAKE_SCRIPT_CURRENT_DIR}/${CMAKE_SCRIPT_NAME}.cmake")

  if(EXISTS "${list_file_path}")
    message(STATUS "Current function list file: ${list_file_path}")
  else()
    message(STATUS "Could not find list file for current function")
  endif()

  # 関数の処理を行う
endfunction()

my_function()

CMAKE_CALLER_DIR と CMAKE_CALLER_SCRIPT_NAME を組み合わせる

この方法は、現在実行中の関数を呼び出したスクリプトのディレクトリパススクリプトファイル名 を取得して、リストファイルのパスを推測する方法です。

function(my_function)
  set(list_file_path "${CMAKE_CALLER_DIR}/${CMAKE_CALLER_SCRIPT_NAME}.cmake")

  if(EXISTS "${list_file_path}")
    message(STATUS "Current function list file: ${list_file_path}")
  else()
    message(STATUS "Could not find list file for current function")
  endif()

  # 関数の処理を行う
endfunction()

my_function()

カスタム変数を使用する

この方法は、現在実行中の関数を定義したリストファイルのフルパス を格納するカスタム変数を作成する方法です。

function(my_function)
  set(current_function_list_file "${CMAKE_CURRENT_FUNCTION_LIST_FILE}")

  message(STATUS "Current function list file: ${current_function_list_file}")

  # 関数の処理を行う
endfunction()

my_function()

注意点

これらの代替方法は、CMAKE_CURRENT_FUNCTION_LIST_FILE と完全に同じように動作するとは限りません。また、これらの方法は、すべての CMake バージョンで使用できるわけではありません。

CMAKE_CURRENT_FUNCTION_LIST_FILE は、現在実行中の関数を定義したリストファイルのフルパスを取得する便利な変数です。しかし、この変数は常に利用できるわけではありません。上記に紹介した代替方法を使用することで、CMAKE_CURRENT_FUNCTION_LIST_FILE が利用できない場合でも、同様の情報を取得することができます。

  • CMAKE_CALLER_DIRCMAKE_CALLER_SCRIPT_NAME は、現在実行中の関数を呼び出したスクリプト に関する情報を取得する変数です。
  • CMAKE_SCRIPT_CURRENT_DIRCMAKE_SCRIPT_NAME は、現在実行中のスクリプト に関する情報を取得する変数です。