diff options
-rw-r--r-- | Help/command/macro.rst | 6 | ||||
-rw-r--r-- | Help/manual/cmake-variables.7.rst | 4 | ||||
-rw-r--r-- | Help/release/dev/CMAKE_CURRENT_FUNCTION.rst | 9 | ||||
-rw-r--r-- | Help/variable/CMAKE_CURRENT_FUNCTION.rst | 6 | ||||
-rw-r--r-- | Help/variable/CMAKE_CURRENT_FUNCTION_LIST_DIR.rst | 33 | ||||
-rw-r--r-- | Help/variable/CMAKE_CURRENT_FUNCTION_LIST_FILE.rst | 5 | ||||
-rw-r--r-- | Help/variable/CMAKE_CURRENT_FUNCTION_LIST_LINE.rst | 5 | ||||
-rw-r--r-- | Source/cmFunctionCommand.cxx | 21 | ||||
-rw-r--r-- | Tests/RunCMake/CMakeLists.txt | 1 | ||||
-rw-r--r-- | Tests/RunCMake/function/CMAKE_CURRENT_FUNCTION-stdout.txt | 7 | ||||
-rw-r--r-- | Tests/RunCMake/function/CMAKE_CURRENT_FUNCTION.cmake | 94 | ||||
-rw-r--r-- | Tests/RunCMake/function/CMakeLists.txt | 3 | ||||
-rw-r--r-- | Tests/RunCMake/function/DummyMacro.cmake | 20 | ||||
-rw-r--r-- | Tests/RunCMake/function/RunCMakeTest.cmake | 3 |
14 files changed, 217 insertions, 0 deletions
diff --git a/Help/command/macro.rst b/Help/command/macro.rst index 05e5d79..3f6f2f9 100644 --- a/Help/command/macro.rst +++ b/Help/command/macro.rst @@ -91,6 +91,12 @@ just terminate execution of the macro; rather, control is returned from the scope of the macro call. To avoid confusion, it is recommended to avoid :command:`return()` in macros altogether. +Unlike a function, the :variable:`CMAKE_CURRENT_FUNCTION`, +:variable:`CMAKE_CURRENT_FUNCTION_LIST_DIR`, +:variable:`CMAKE_CURRENT_FUNCTION_LIST_FILE`, +:variable:`CMAKE_CURRENT_FUNCTION_LIST_LINE` variables are not +set for macro. + .. _`Argument Caveats`: Argument Caveats diff --git a/Help/manual/cmake-variables.7.rst b/Help/manual/cmake-variables.7.rst index 84018b7..4c797a5 100644 --- a/Help/manual/cmake-variables.7.rst +++ b/Help/manual/cmake-variables.7.rst @@ -37,6 +37,10 @@ Variables that Provide Information /variable/CMAKE_CROSSCOMPILING_EMULATOR /variable/CMAKE_CTEST_COMMAND /variable/CMAKE_CURRENT_BINARY_DIR + /variable/CMAKE_CURRENT_FUNCTION + /variable/CMAKE_CURRENT_FUNCTION_LIST_DIR + /variable/CMAKE_CURRENT_FUNCTION_LIST_FILE + /variable/CMAKE_CURRENT_FUNCTION_LIST_LINE /variable/CMAKE_CURRENT_LIST_DIR /variable/CMAKE_CURRENT_LIST_FILE /variable/CMAKE_CURRENT_LIST_LINE diff --git a/Help/release/dev/CMAKE_CURRENT_FUNCTION.rst b/Help/release/dev/CMAKE_CURRENT_FUNCTION.rst new file mode 100644 index 0000000..a15e63d --- /dev/null +++ b/Help/release/dev/CMAKE_CURRENT_FUNCTION.rst @@ -0,0 +1,9 @@ +CMAKE_CURRENT_FUNCTION +---------------------- + +* Define the following variables inside a function: + + - :variable:`CMAKE_CURRENT_FUNCTION` + - :variable:`CMAKE_CURRENT_FUNCTION_LIST_DIR` + - :variable:`CMAKE_CURRENT_FUNCTION_LIST_FILE` + - :variable:`CMAKE_CURRENT_FUNCTION_LIST_LINE` diff --git a/Help/variable/CMAKE_CURRENT_FUNCTION.rst b/Help/variable/CMAKE_CURRENT_FUNCTION.rst new file mode 100644 index 0000000..aa2936c --- /dev/null +++ b/Help/variable/CMAKE_CURRENT_FUNCTION.rst @@ -0,0 +1,6 @@ +CMAKE_CURRENT_FUNCTION +---------------------- + +When executing code inside a :command:`function`, this variable +contains the name of the current function. It can be used for +diagnostic or debug messages. diff --git a/Help/variable/CMAKE_CURRENT_FUNCTION_LIST_DIR.rst b/Help/variable/CMAKE_CURRENT_FUNCTION_LIST_DIR.rst new file mode 100644 index 0000000..0119381 --- /dev/null +++ b/Help/variable/CMAKE_CURRENT_FUNCTION_LIST_DIR.rst @@ -0,0 +1,33 @@ +CMAKE_CURRENT_FUNCTION_LIST_DIR +------------------------------- + +When executing code inside a :command:`function`, this variable +contains the full directory of the listfile defining the current function. + +It is quite common practice in CMake that modules use some additional files +(e.g., templates to render). And the code typically did the following: + +.. code-block:: cmake + :caption: Bad + + set(_THIS_MODULE_BASE_DIR "${CMAKE_CURRENT_LIST_DIR}") + + function(foo) + configure_file( + "${_THIS_MODULE_BASE_DIR}/some.template.in" + some.output + ) + endfunction() + +Using this variable inside a function eliminates the neccessity of the +additional one with "global" scope: + +.. code-block:: cmake + :caption: Good + + function(foo) + configure_file( + "${CMAKE_CURRENT_FUNCTION_LIST_DIR}/some.template.in" + some.output + ) + endfunction() diff --git a/Help/variable/CMAKE_CURRENT_FUNCTION_LIST_FILE.rst b/Help/variable/CMAKE_CURRENT_FUNCTION_LIST_FILE.rst new file mode 100644 index 0000000..d2c846a --- /dev/null +++ b/Help/variable/CMAKE_CURRENT_FUNCTION_LIST_FILE.rst @@ -0,0 +1,5 @@ +CMAKE_CURRENT_FUNCTION_LIST_FILE +-------------------------------- + +When executing code inside a :command:`function`, this variable +contains the full path to the listfile declaring a current function. diff --git a/Help/variable/CMAKE_CURRENT_FUNCTION_LIST_LINE.rst b/Help/variable/CMAKE_CURRENT_FUNCTION_LIST_LINE.rst new file mode 100644 index 0000000..5a7cd13 --- /dev/null +++ b/Help/variable/CMAKE_CURRENT_FUNCTION_LIST_LINE.rst @@ -0,0 +1,5 @@ +CMAKE_CURRENT_FUNCTION_LIST_LINE +-------------------------------- + +When executing code inside a :command:`function`, this variable +contains the line number in the listfile where a current function has defined. diff --git a/Source/cmFunctionCommand.cxx b/Source/cmFunctionCommand.cxx index bd96115..4b2f145 100644 --- a/Source/cmFunctionCommand.cxx +++ b/Source/cmFunctionCommand.cxx @@ -18,11 +18,19 @@ #include "cmRange.h" #include "cmState.h" #include "cmStringAlgorithms.h" +#include "cmSystemTools.h" namespace { std::string const ARGC = "ARGC"; std::string const ARGN = "ARGN"; std::string const ARGV = "ARGV"; +std::string const CMAKE_CURRENT_FUNCTION = "CMAKE_CURRENT_FUNCTION"; +std::string const CMAKE_CURRENT_FUNCTION_LIST_FILE = + "CMAKE_CURRENT_FUNCTION_LIST_FILE"; +std::string const CMAKE_CURRENT_FUNCTION_LIST_DIR = + "CMAKE_CURRENT_FUNCTION_LIST_DIR"; +std::string const CMAKE_CURRENT_FUNCTION_LIST_LINE = + "CMAKE_CURRENT_FUNCTION_LIST_LINE"; // define the class for function commands class cmFunctionHelperCommand @@ -39,6 +47,7 @@ public: std::vector<cmListFileFunction> Functions; cmPolicies::PolicyMap Policies; std::string FilePath; + long Line; }; bool cmFunctionHelperCommand::operator()( @@ -89,6 +98,17 @@ bool cmFunctionHelperCommand::operator()( makefile.AddDefinition(ARGN, argnDef); makefile.MarkVariableAsUsed(ARGN); + makefile.AddDefinition(CMAKE_CURRENT_FUNCTION, this->Args.front()); + makefile.MarkVariableAsUsed(CMAKE_CURRENT_FUNCTION); + makefile.AddDefinition(CMAKE_CURRENT_FUNCTION_LIST_FILE, this->FilePath); + makefile.MarkVariableAsUsed(CMAKE_CURRENT_FUNCTION_LIST_FILE); + makefile.AddDefinition(CMAKE_CURRENT_FUNCTION_LIST_DIR, + cmSystemTools::GetFilenamePath(this->FilePath)); + makefile.MarkVariableAsUsed(CMAKE_CURRENT_FUNCTION_LIST_DIR); + makefile.AddDefinition(CMAKE_CURRENT_FUNCTION_LIST_LINE, + std::to_string(this->Line)); + makefile.MarkVariableAsUsed(CMAKE_CURRENT_FUNCTION_LIST_LINE); + // Invoke all the functions that were collected in the block. // for each function for (cmListFileFunction const& func : this->Functions) { @@ -143,6 +163,7 @@ bool cmFunctionFunctionBlocker::Replay( f.Args = this->Args; f.Functions = std::move(functions); f.FilePath = this->GetStartingContext().FilePath; + f.Line = this->GetStartingContext().Line; mf.RecordPolicies(f.Policies); mf.GetState()->AddScriptedCommand(this->Args.front(), std::move(f)); return true; diff --git a/Tests/RunCMake/CMakeLists.txt b/Tests/RunCMake/CMakeLists.txt index 31b280b..18ac6f9 100644 --- a/Tests/RunCMake/CMakeLists.txt +++ b/Tests/RunCMake/CMakeLists.txt @@ -272,6 +272,7 @@ add_RunCMake_test(find_package) add_RunCMake_test(find_path) add_RunCMake_test(find_program -DCMAKE_SYSTEM_NAME=${CMAKE_SYSTEM_NAME}) add_RunCMake_test(foreach) +add_RunCMake_test(function) add_RunCMake_test(get_filename_component) add_RunCMake_test(get_property) add_RunCMake_test(if) diff --git a/Tests/RunCMake/function/CMAKE_CURRENT_FUNCTION-stdout.txt b/Tests/RunCMake/function/CMAKE_CURRENT_FUNCTION-stdout.txt new file mode 100644 index 0000000..5ebc89a --- /dev/null +++ b/Tests/RunCMake/function/CMAKE_CURRENT_FUNCTION-stdout.txt @@ -0,0 +1,7 @@ +function\(print_self\) + file\(STRINGS "\${CMAKE_CURRENT_FUNCTION_LIST_FILE}" _lines\) + math\(EXPR _begin "\${CMAKE_CURRENT_FUNCTION_LIST_LINE} - 1"\) + list\(SUBLIST _lines \${_begin} 7 _lines\) # This function has 7 lines only + list\(JOIN _lines "\\n" _lines\) + message\(STATUS "Print the `\${CMAKE_CURRENT_FUNCTION}` function:\\n\${_lines}"\) +endfunction\(\) diff --git a/Tests/RunCMake/function/CMAKE_CURRENT_FUNCTION.cmake b/Tests/RunCMake/function/CMAKE_CURRENT_FUNCTION.cmake new file mode 100644 index 0000000..38c032f --- /dev/null +++ b/Tests/RunCMake/function/CMAKE_CURRENT_FUNCTION.cmake @@ -0,0 +1,94 @@ +set(_THIS_FILE "${CMAKE_CURRENT_LIST_FILE}") +set(_THIS_DIR "${CMAKE_CURRENT_LIST_DIR}") + +if(CMAKE_CURRENT_FUNCTION) + message(SEND_ERROR "`CMAKE_CURRENT_FUNCTION` is not expected to be set here") +endif() +if(CMAKE_CURRENT_FUNCTION_LIST_FILE) + message(SEND_ERROR "`CMAKE_CURRENT_FUNCTION_LIST_FILE` is not expected to be set here") +endif() +if(CMAKE_CURRENT_FUNCTION_LIST_DIR) + message(SEND_ERROR "`CMAKE_CURRENT_FUNCTION_LIST_DIR` is not expected to be set here") +endif() +if(CMAKE_CURRENT_FUNCTION_LIST_LINE) + message(SEND_ERROR "`CMAKE_CURRENT_FUNCTION_LIST_LINE` is not expected to be set here") +endif() + +function(bar) + if(NOT CMAKE_CURRENT_FUNCTION STREQUAL "bar") + message(SEND_ERROR "Bad value of `CMAKE_CURRENT_FUNCTION`") + endif() + if(NOT CMAKE_CURRENT_FUNCTION_LIST_FILE MATCHES "^.*/CMAKE_CURRENT_FUNCTION.cmake$") + message(SEND_ERROR "Bad value of `CMAKE_CURRENT_FUNCTION_LIST_FILE`") + endif() + if(NOT CMAKE_CURRENT_FUNCTION_LIST_FILE STREQUAL _THIS_FILE) + message(SEND_ERROR "Bad value of `CMAKE_CURRENT_FUNCTION_LIST_FILE`") + endif() + if(NOT CMAKE_CURRENT_FUNCTION_LIST_DIR MATCHES "^.*/Tests/RunCMake/function$") + message(SEND_ERROR "Bad value of `CMAKE_CURRENT_FUNCTION_LIST_DIR`") + endif() + if(NOT CMAKE_CURRENT_FUNCTION_LIST_DIR STREQUAL _THIS_DIR) + message(SEND_ERROR "Bad value of `CMAKE_CURRENT_FUNCTION_LIST_DIR`") + endif() + if(NOT CMAKE_CURRENT_FUNCTION_LIST_LINE EQUAL 17) + message(SEND_ERROR "Bad value of `CMAKE_CURRENT_FUNCTION_LIST_LINE`") + endif() +endfunction() + +function(foo) + if(NOT CMAKE_CURRENT_FUNCTION STREQUAL "foo") + message(SEND_ERROR "Bad value of `CMAKE_CURRENT_FUNCTION`") + endif() + if(NOT CMAKE_CURRENT_FUNCTION_LIST_FILE MATCHES "^.*/function/CMAKE_CURRENT_FUNCTION.cmake$") + message(SEND_ERROR "Bad value of `CMAKE_CURRENT_FUNCTION_LIST_FILE`") + endif() + if(NOT CMAKE_CURRENT_FUNCTION_LIST_FILE STREQUAL _THIS_FILE) + message(SEND_ERROR "Bad value of `CMAKE_CURRENT_FUNCTION_LIST_FILE`") + endif() + if(NOT CMAKE_CURRENT_FUNCTION_LIST_DIR MATCHES "^.*/Tests/RunCMake/function$") + message(SEND_ERROR "Bad value of `CMAKE_CURRENT_FUNCTION_LIST_DIR`") + endif() + if(NOT CMAKE_CURRENT_FUNCTION_LIST_LINE EQUAL 38) + message(SEND_ERROR "Bad value of `CMAKE_CURRENT_FUNCTION_LIST_LINE`") + endif() + if(NOT CMAKE_CURRENT_FUNCTION_LIST_DIR STREQUAL _THIS_DIR) + message(SEND_ERROR "Bad value of `CMAKE_CURRENT_FUNCTION_LIST_DIR`") + endif() + bar() +endfunction() + +foo() + +if(CMAKE_CURRENT_FUNCTION) + message(SEND_ERROR "`CMAKE_CURRENT_FUNCTION` is not expected to be set here") +endif() +if(CMAKE_CURRENT_FUNCTION_LIST_FILE) + message(SEND_ERROR "`CMAKE_CURRENT_FUNCTION_LIST_FILE` is not expected to be set here") +endif() +if(CMAKE_CURRENT_FUNCTION_LIST_DIR) + message(SEND_ERROR "`CMAKE_CURRENT_FUNCTION_LIST_DIR` is not expected to be set here") +endif() +if(CMAKE_CURRENT_FUNCTION_LIST_LINE) + message(SEND_ERROR "`CMAKE_CURRENT_FUNCTION_LIST_LINE` is not expected to be set here") +endif() + +include("${CMAKE_CURRENT_LIST_DIR}/DummyMacro.cmake") + +function(calling_macro) + dummy() +endfunction() + +calling_macro() + +cmake_policy(SET CMP0007 NEW) + +# ATTENTION `CMAKE_CURRENT_LIST_LINE` can't be used in `math()' +function(print_self) + file(STRINGS "${CMAKE_CURRENT_FUNCTION_LIST_FILE}" _lines) + math(EXPR _begin "${CMAKE_CURRENT_FUNCTION_LIST_LINE} - 1") + list(SUBLIST _lines ${_begin} 7 _lines) # This function has 7 lines only + list(JOIN _lines "\n" _lines) + message(STATUS "Print the `${CMAKE_CURRENT_FUNCTION}` function:\n${_lines}") +endfunction() + +print_self() diff --git a/Tests/RunCMake/function/CMakeLists.txt b/Tests/RunCMake/function/CMakeLists.txt new file mode 100644 index 0000000..2632ffa --- /dev/null +++ b/Tests/RunCMake/function/CMakeLists.txt @@ -0,0 +1,3 @@ +cmake_minimum_required(VERSION 3.16) +project(${RunCMake_TEST} NONE) +include(${RunCMake_TEST}.cmake) diff --git a/Tests/RunCMake/function/DummyMacro.cmake b/Tests/RunCMake/function/DummyMacro.cmake new file mode 100644 index 0000000..1ab53e4 --- /dev/null +++ b/Tests/RunCMake/function/DummyMacro.cmake @@ -0,0 +1,20 @@ +macro(dummy) + if(NOT CMAKE_CURRENT_FUNCTION STREQUAL "calling_macro") + message(SEND_ERROR "Bad value of `CMAKE_CURRENT_FUNCTION`") + endif() + if(NOT CMAKE_CURRENT_FUNCTION_LIST_FILE MATCHES "^.*/function/CMAKE_CURRENT_FUNCTION.cmake$") + message(SEND_ERROR "Bad value of `CMAKE_CURRENT_FUNCTION_LIST_FILE`") + endif() + if(NOT CMAKE_CURRENT_FUNCTION_LIST_FILE STREQUAL _THIS_FILE) + message(SEND_ERROR "Bad value of `CMAKE_CURRENT_FUNCTION_LIST_FILE`") + endif() + if(NOT CMAKE_CURRENT_FUNCTION_LIST_DIR MATCHES "^.*/Tests/RunCMake/function$") + message(SEND_ERROR "Bad value of `CMAKE_CURRENT_FUNCTION_LIST_DIR`") + endif() + if(NOT CMAKE_CURRENT_FUNCTION_LIST_LINE EQUAL 77) + message(SEND_ERROR "Bad value of `CMAKE_CURRENT_FUNCTION_LIST_LINE`") + endif() + if(NOT CMAKE_CURRENT_FUNCTION_LIST_DIR STREQUAL _THIS_DIR) + message(SEND_ERROR "Bad value of `CMAKE_CURRENT_FUNCTION_LIST_DIR`") + endif() +endmacro() diff --git a/Tests/RunCMake/function/RunCMakeTest.cmake b/Tests/RunCMake/function/RunCMakeTest.cmake new file mode 100644 index 0000000..88f48af --- /dev/null +++ b/Tests/RunCMake/function/RunCMakeTest.cmake @@ -0,0 +1,3 @@ +include(RunCMake) + +run_cmake(CMAKE_CURRENT_FUNCTION) |