summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKyle Edwards <kyle.edwards@kitware.com>2019-12-12 19:00:30 (GMT)
committerKitware Robot <kwrobot@kitware.com>2019-12-12 19:00:41 (GMT)
commit966a9eece32f55fab479ea6997dea68e1c2d6212 (patch)
treefcb8a3bfdcfb02ffab961e2e773da98ae333488b
parentf6e29e04051326861afc0b4fc98a77e20b366ff0 (diff)
parent24fdd51f4503ccee33c07881cc8dd487cdc8b347 (diff)
downloadCMake-966a9eece32f55fab479ea6997dea68e1c2d6212.zip
CMake-966a9eece32f55fab479ea6997dea68e1c2d6212.tar.gz
CMake-966a9eece32f55fab479ea6997dea68e1c2d6212.tar.bz2
Merge topic 'function-var-current'
24fdd51f45 Refactor: Replace CMAKE_CURRENT_LIST_DIR with CMAKE_CURRENT_FUNCTION_LIST_DIR 90e3e2a777 cmFunctionCommand: Introduce `CMAKE_CURRENT_FUNCTION*` variables dd54290dab Refactor: Modernize `function` command Acked-by: Kitware Robot <kwrobot@kitware.com> Acked-by: Ben Boeckel <ben.boeckel@kitware.com> Merge-request: !4000
-rw-r--r--Help/command/macro.rst6
-rw-r--r--Help/manual/cmake-variables.7.rst4
-rw-r--r--Help/release/dev/CMAKE_CURRENT_FUNCTION.rst9
-rw-r--r--Help/variable/CMAKE_CURRENT_FUNCTION.rst6
-rw-r--r--Help/variable/CMAKE_CURRENT_FUNCTION_LIST_DIR.rst33
-rw-r--r--Help/variable/CMAKE_CURRENT_FUNCTION_LIST_FILE.rst5
-rw-r--r--Help/variable/CMAKE_CURRENT_FUNCTION_LIST_LINE.rst5
-rw-r--r--Modules/AndroidTestUtilities.cmake4
-rw-r--r--Modules/CMakeAddFortranSubdirectory.cmake5
-rw-r--r--Modules/DeployQt4.cmake3
-rw-r--r--Modules/FetchContent.cmake5
-rw-r--r--Modules/UseJava.cmake3
-rw-r--r--Source/cmFunctionCommand.cxx78
-rw-r--r--Tests/RunCMake/CMakeLists.txt1
-rw-r--r--Tests/RunCMake/function/CMAKE_CURRENT_FUNCTION-stdout.txt7
-rw-r--r--Tests/RunCMake/function/CMAKE_CURRENT_FUNCTION.cmake94
-rw-r--r--Tests/RunCMake/function/CMakeLists.txt3
-rw-r--r--Tests/RunCMake/function/DummyMacro.cmake20
-rw-r--r--Tests/RunCMake/function/RunCMakeTest.cmake3
19 files changed, 253 insertions, 41 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 d4b855d..7a5e83e 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/Modules/AndroidTestUtilities.cmake b/Modules/AndroidTestUtilities.cmake
index e333cdb..95e2ef7 100644
--- a/Modules/AndroidTestUtilities.cmake
+++ b/Modules/AndroidTestUtilities.cmake
@@ -76,8 +76,6 @@ Module Functions
include(${CMAKE_CURRENT_LIST_DIR}/ExternalData.cmake)
-set(_AndroidTestUtilities_SELF_DIR "${CMAKE_CURRENT_LIST_DIR}")
-
# The parameters to this function should be set to the list of directories,
# files, and libraries that need to be installed prior to testing.
function(android_add_test_data test_name)
@@ -159,6 +157,6 @@ function(android_add_test_data test_name)
"-Darg_files=${processed_FILES}"
"-Darg_libs=${AST_LIBS}"
"-Darg_src_dir=${CMAKE_CURRENT_SOURCE_DIR}"
- -P ${_AndroidTestUtilities_SELF_DIR}/AndroidTestUtilities/PushToAndroidDevice.cmake)
+ -P ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/AndroidTestUtilities/PushToAndroidDevice.cmake)
endif()
endfunction()
diff --git a/Modules/CMakeAddFortranSubdirectory.cmake b/Modules/CMakeAddFortranSubdirectory.cmake
index 09e739d..c02aa2c 100644
--- a/Modules/CMakeAddFortranSubdirectory.cmake
+++ b/Modules/CMakeAddFortranSubdirectory.cmake
@@ -43,7 +43,6 @@ future version that supports installation of the external project
binaries during ``make install``.
#]=======================================================================]
-set(_MS_MINGW_SOURCE_DIR ${CMAKE_CURRENT_LIST_DIR})
include(CheckLanguage)
include(ExternalProject)
@@ -87,11 +86,11 @@ function(_setup_mingw_config_and_build source_dir build_dir)
file(TO_NATIVE_PATH "${MINGW_PATH}" MINGW_PATH)
string(REPLACE "\\" "\\\\" MINGW_PATH "${MINGW_PATH}")
configure_file(
- ${_MS_MINGW_SOURCE_DIR}/CMakeAddFortranSubdirectory/config_mingw.cmake.in
+ ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/CMakeAddFortranSubdirectory/config_mingw.cmake.in
${build_dir}/config_mingw.cmake
@ONLY)
configure_file(
- ${_MS_MINGW_SOURCE_DIR}/CMakeAddFortranSubdirectory/build_mingw.cmake.in
+ ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/CMakeAddFortranSubdirectory/build_mingw.cmake.in
${build_dir}/build_mingw.cmake
@ONLY)
endfunction()
diff --git a/Modules/DeployQt4.cmake b/Modules/DeployQt4.cmake
index 4a18927..9aa4383 100644
--- a/Modules/DeployQt4.cmake
+++ b/Modules/DeployQt4.cmake
@@ -106,7 +106,6 @@ and plugin installation. See documentation of FIXUP_QT4_BUNDLE.
# The functions defined in this file depend on the fixup_bundle function
# (and others) found in BundleUtilities.cmake
-set(DeployQt4_cmake_dir "${CMAKE_CURRENT_LIST_DIR}")
set(DeployQt4_apple_plugins_dir "PlugIns")
function(write_qt4_conf qt_conf_dir qt_conf_contents)
@@ -392,7 +391,7 @@ function(install_qt4_executable executable)
resolve_qt4_paths(libs "")
install(CODE
-"include(\"${DeployQt4_cmake_dir}/DeployQt4.cmake\")
+"include(\"${CMAKE_CURRENT_FUNCTION_LIST_DIR}/DeployQt4.cmake\")
set(BU_CHMOD_BUNDLE_ITEMS TRUE)
FIXUP_QT4_EXECUTABLE(\"\$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/${executable}\" \"\" \"${libs}\" \"${dirs}\" \"${plugins_dir}\" \"${request_qt_conf}\")"
${component}
diff --git a/Modules/FetchContent.cmake b/Modules/FetchContent.cmake
index 5716b01..f3e1b51 100644
--- a/Modules/FetchContent.cmake
+++ b/Modules/FetchContent.cmake
@@ -596,9 +596,6 @@ current working directory.
#]=======================================================================]
-
-set(__FetchContent_privateDir "${CMAKE_CURRENT_LIST_DIR}/FetchContent")
-
#=======================================================================
# Recording and retrieving content details for later population
#=======================================================================
@@ -888,7 +885,7 @@ function(__FetchContent_directPopulate contentName)
# anything to be updated, so extra rebuilds of the project won't occur.
# Make sure to pass through CMAKE_MAKE_PROGRAM in case the main project
# has this set to something not findable on the PATH.
- configure_file("${__FetchContent_privateDir}/CMakeLists.cmake.in"
+ configure_file("${CMAKE_CURRENT_FUNCTION_LIST_DIR}/FetchContent/CMakeLists.cmake.in"
"${ARG_SUBBUILD_DIR}/CMakeLists.txt")
execute_process(
COMMAND ${CMAKE_COMMAND} ${generatorOpts} .
diff --git a/Modules/UseJava.cmake b/Modules/UseJava.cmake
index 28f74ea..b668b9e 100644
--- a/Modules/UseJava.cmake
+++ b/Modules/UseJava.cmake
@@ -405,7 +405,6 @@ endfunction()
# define helper scripts
set(_JAVA_EXPORT_TARGETS_SCRIPT ${CMAKE_CURRENT_LIST_DIR}/javaTargets.cmake.in)
-set(_JAVA_CLASS_FILELIST_SCRIPT ${CMAKE_CURRENT_LIST_DIR}/UseJavaClassFilelist.cmake)
set(_JAVA_SYMLINK_SCRIPT ${CMAKE_CURRENT_LIST_DIR}/UseJavaSymlinks.cmake)
if (CMAKE_HOST_WIN32 AND NOT CYGWIN AND CMAKE_HOST_SYSTEM_NAME MATCHES "Windows")
@@ -627,7 +626,7 @@ function(add_jar _TARGET_NAME)
COMMAND ${CMAKE_COMMAND}
-DCMAKE_JAVA_CLASS_OUTPUT_PATH=${CMAKE_JAVA_CLASS_OUTPUT_PATH}
-DCMAKE_JAR_CLASSES_PREFIX="${CMAKE_JAR_CLASSES_PREFIX}"
- -P ${_JAVA_CLASS_FILELIST_SCRIPT}
+ -P ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/UseJavaClassFilelist.cmake
DEPENDS ${CMAKE_JAVA_CLASS_OUTPUT_PATH}/java_compiled_${_TARGET_NAME}
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
)
diff --git a/Source/cmFunctionCommand.cxx b/Source/cmFunctionCommand.cxx
index b3ddfe0..4b2f145 100644
--- a/Source/cmFunctionCommand.cxx
+++ b/Source/cmFunctionCommand.cxx
@@ -2,7 +2,6 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmFunctionCommand.h"
-#include <sstream>
#include <utility>
#include <cm/memory>
@@ -19,8 +18,20 @@
#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
{
@@ -36,8 +47,8 @@ public:
std::vector<cmListFileFunction> Functions;
cmPolicies::PolicyMap Policies;
std::string FilePath;
+ long Line;
};
-}
bool cmFunctionHelperCommand::operator()(
std::vector<cmListFileArgument> const& args,
@@ -52,9 +63,9 @@ bool cmFunctionHelperCommand::operator()(
// make sure the number of arguments passed is at least the number
// required by the signature
if (expandedArgs.size() < this->Args.size() - 1) {
- std::string errorMsg = cmStrCat(
+ auto const errorMsg = cmStrCat(
"Function invoked with incorrect arguments for function named: ",
- this->Args[0]);
+ this->Args.front());
inStatus.SetError(errorMsg);
return false;
}
@@ -63,30 +74,40 @@ bool cmFunctionHelperCommand::operator()(
this->Policies);
// set the value of argc
- makefile.AddDefinition("ARGC", std::to_string(expandedArgs.size()));
- makefile.MarkVariableAsUsed("ARGC");
+ makefile.AddDefinition(ARGC, std::to_string(expandedArgs.size()));
+ makefile.MarkVariableAsUsed(ARGC);
// set the values for ARGV0 ARGV1 ...
- for (unsigned int t = 0; t < expandedArgs.size(); ++t) {
- std::ostringstream tmpStream;
- tmpStream << "ARGV" << t;
- makefile.AddDefinition(tmpStream.str(), expandedArgs[t]);
- makefile.MarkVariableAsUsed(tmpStream.str());
+ for (auto t = 0u; t < expandedArgs.size(); ++t) {
+ auto const value = cmStrCat(ARGV, std::to_string(t));
+ makefile.AddDefinition(value, expandedArgs[t]);
+ makefile.MarkVariableAsUsed(value);
}
// define the formal arguments
- for (unsigned int j = 1; j < this->Args.size(); ++j) {
+ for (auto j = 1u; j < this->Args.size(); ++j) {
makefile.AddDefinition(this->Args[j], expandedArgs[j - 1]);
}
// define ARGV and ARGN
- std::string argvDef = cmJoin(expandedArgs, ";");
- auto eit = expandedArgs.begin() + (this->Args.size() - 1);
- std::string argnDef = cmJoin(cmMakeRange(eit, expandedArgs.end()), ";");
- makefile.AddDefinition("ARGV", argvDef);
- makefile.MarkVariableAsUsed("ARGV");
- makefile.AddDefinition("ARGN", argnDef);
- makefile.MarkVariableAsUsed("ARGN");
+ auto const argvDef = cmJoin(expandedArgs, ";");
+ auto const eit = expandedArgs.begin() + (this->Args.size() - 1);
+ auto const argnDef = cmJoin(cmMakeRange(eit, expandedArgs.end()), ";");
+ makefile.AddDefinition(ARGV, argvDef);
+ makefile.MarkVariableAsUsed(ARGV);
+ 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
@@ -100,7 +121,7 @@ bool cmFunctionHelperCommand::operator()(
return false;
}
if (status.GetReturnInvoked()) {
- return true;
+ break;
}
}
@@ -129,7 +150,8 @@ bool cmFunctionFunctionBlocker::ArgumentsMatch(cmListFileFunction const& lff,
std::vector<std::string> expandedArguments;
mf.ExpandArguments(lff.Arguments, expandedArguments,
this->GetStartingContext().FilePath.c_str());
- return expandedArguments.empty() || expandedArguments[0] == this->Args[0];
+ return expandedArguments.empty() ||
+ expandedArguments.front() == this->Args.front();
}
bool cmFunctionFunctionBlocker::Replay(
@@ -141,11 +163,14 @@ 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[0], std::move(f));
+ mf.GetState()->AddScriptedCommand(this->Args.front(), std::move(f));
return true;
}
+} // anonymous namespace
+
bool cmFunctionCommand(std::vector<std::string> const& args,
cmExecutionStatus& status)
{
@@ -155,10 +180,9 @@ bool cmFunctionCommand(std::vector<std::string> const& args,
}
// create a function blocker
- {
- auto fb = cm::make_unique<cmFunctionFunctionBlocker>();
- cmAppend(fb->Args, args);
- status.GetMakefile().AddFunctionBlocker(std::move(fb));
- }
+ auto fb = cm::make_unique<cmFunctionFunctionBlocker>();
+ cmAppend(fb->Args, args);
+ status.GetMakefile().AddFunctionBlocker(std::move(fb));
+
return true;
}
diff --git a/Tests/RunCMake/CMakeLists.txt b/Tests/RunCMake/CMakeLists.txt
index 1e0cb86..004dee6 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)