Commit a6982cff authored by Kyle Edwards's avatar Kyle Edwards

cmMakefile: Impose maximum recursion limit

In order to keep infinitely-recursive scripts from causing a stack
overflow in the CMake executable, CMake now imposes a maximum
recursion limit before issuing an error message. The limit can be
adjusted at runtime with CMAKE_MAXIMUM_RECURSION_DEPTH.

Fixes: #18694
parent a7f5cd45
Pipeline #128290 passed with stage
......@@ -190,6 +190,7 @@ Variables that Change Behavior
/variable/CMAKE_LIBRARY_PATH
/variable/CMAKE_LINK_DIRECTORIES_BEFORE
/variable/CMAKE_MFC_FLAG
/variable/CMAKE_MAXIMUM_RECURSION_DEPTH
/variable/CMAKE_MODULE_PATH
/variable/CMAKE_NOT_USING_CONFIG_FLAGS
/variable/CMAKE_POLICY_DEFAULT_CMPNNNN
......
max-recursion-depth
-------------------
* CMake now imposes a maximum recursion limit to prevent a stack overflow on
scripts that recurse infinitely. The limit can be adjusted at runtime with
:variable:`CMAKE_MAXIMUM_RECURSION_DEPTH`.
CMAKE_MAXIMUM_RECURSION_DEPTH
-----------------------------
Maximum recursion depth for CMake scripts. It is intended to be set on the
command line with ``-DCMAKE_MAXIMUM_RECURSION_DEPTH=<x>``, or within
``CMakeLists.txt`` by projects that require a large recursion depth. Projects
that set this variable should provide the user with a way to override it. For
example:
.. code-block:: cmake
# About to perform deeply recursive actions
if(NOT CMAKE_MAXIMUM_RECURSION_DEPTH)
set(CMAKE_MAXIMUM_RECURSION_DEPTH 2000)
endif()
If it is not set, or is set to a non-integer value, a sensible default limit is
used. If the recursion limit is reached, the script terminates immediately with
a fatal error.
Calling any of the following commands increases the recursion depth:
* :command:`include`
* :command:`find_package`
* :command:`add_subdirectory`
* :command:`try_compile`
* :command:`ctest_read_custom_files`
* :command:`ctest_run_script` (unless ``NEW_PROCESS`` is specified)
* User-defined :command:`function`'s and :command:`macro`'s (note that
:command:`function` and :command:`macro` themselves don't increase recursion
depth)
* Reading or writing variables that are being watched by a
:command:`variable_watch`
......@@ -31,6 +31,16 @@ else()
set(CMAKE_USE_ELF_PARSER)
endif()
if(NOT CMake_DEFAULT_RECURSION_LIMIT)
if(DEFINED ENV{DASHBOARD_TEST_FROM_CTEST})
set(CMake_DEFAULT_RECURSION_LIMIT 100)
elseif(MINGW)
set(CMake_DEFAULT_RECURSION_LIMIT 400)
else()
set(CMake_DEFAULT_RECURSION_LIMIT 1000)
endif()
endif()
if(APPLE)
set(CMAKE_USE_MACH_PARSER 1)
endif()
......
......@@ -39,7 +39,8 @@ bool cmCTestRunScriptCommand::InitialPass(std::vector<std::string> const& args,
++i;
} else {
int ret;
cmCTestScriptHandler::RunScript(this->CTest, args[i].c_str(), !np, &ret);
cmCTestScriptHandler::RunScript(this->CTest, this->Makefile,
args[i].c_str(), !np, &ret);
std::ostringstream str;
str << ret;
this->Makefile->AddDefinition(returnVariable, str.str().c_str());
......
......@@ -78,6 +78,7 @@ cmCTestScriptHandler::cmCTestScriptHandler()
this->EmptyBinDir = false;
this->EmptyBinDirOnce = false;
this->Makefile = nullptr;
this->ParentMakefile = nullptr;
this->CMake = nullptr;
this->GlobalGenerator = nullptr;
......@@ -117,6 +118,7 @@ void cmCTestScriptHandler::Initialize()
delete this->Makefile;
this->Makefile = nullptr;
this->ParentMakefile = nullptr;
delete this->GlobalGenerator;
this->GlobalGenerator = nullptr;
......@@ -292,6 +294,10 @@ void cmCTestScriptHandler::CreateCMake()
snapshot.GetDirectory().SetCurrentSource(cwd);
snapshot.GetDirectory().SetCurrentBinary(cwd);
this->Makefile = new cmMakefile(this->GlobalGenerator, snapshot);
if (this->ParentMakefile) {
this->Makefile->SetRecursionDepth(
this->ParentMakefile->GetRecursionDepth());
}
this->CMake->SetProgressCallback(ctestScriptProgressCallback, this->CTest);
......@@ -891,11 +897,13 @@ void cmCTestScriptHandler::RestoreBackupDirectories()
}
}
bool cmCTestScriptHandler::RunScript(cmCTest* ctest, const char* sname,
bool InProcess, int* returnValue)
bool cmCTestScriptHandler::RunScript(cmCTest* ctest, cmMakefile* mf,
const char* sname, bool InProcess,
int* returnValue)
{
cmCTestScriptHandler* sh = new cmCTestScriptHandler();
sh->SetCTestInstance(ctest);
sh->ParentMakefile = mf;
sh->AddConfigurationScript(sname, InProcess);
int res = sh->ProcessHandler();
if (returnValue) {
......
......@@ -72,8 +72,8 @@ public:
/*
* Run a script
*/
static bool RunScript(cmCTest* ctest, const char* script, bool InProcess,
int* returnValue);
static bool RunScript(cmCTest* ctest, cmMakefile* mf, const char* script,
bool InProcess, int* returnValue);
int RunCurrentScript();
/*
......@@ -166,6 +166,7 @@ private:
std::chrono::steady_clock::time_point ScriptStartTime;
cmMakefile* Makefile;
cmMakefile* ParentMakefile;
cmGlobalGenerator* GlobalGenerator;
cmake* CMake;
};
......
......@@ -20,6 +20,7 @@
#cmakedefine CMAKE_USE_ELF_PARSER
#cmakedefine CMAKE_USE_MACH_PARSER
#cmakedefine CMake_HAVE_CXX_MAKE_UNIQUE
#define CMake_DEFAULT_RECURSION_LIMIT @CMake_DEFAULT_RECURSION_LIMIT@
#define CMAKE_BIN_DIR "/@CMAKE_BIN_DIR@"
#define CMAKE_DATA_DIR "/@CMAKE_DATA_DIR@"
......
......@@ -98,6 +98,8 @@ cmGlobalGenerator::cmGlobalGenerator(cmake* cm)
this->ConfigureDoneCMP0026AndCMP0024 = false;
this->FirstTimeProgress = 0.0f;
this->RecursionDepth = 0;
cm->GetState()->SetIsGeneratorMultiConfig(false);
cm->GetState()->SetMinGWMake(false);
cm->GetState()->SetMSYSShell(false);
......@@ -1166,6 +1168,7 @@ void cmGlobalGenerator::Configure()
this->CMakeInstance->GetHomeOutputDirectory());
cmMakefile* dirMf = new cmMakefile(this, snapshot);
dirMf->SetRecursionDepth(this->RecursionDepth);
this->Makefiles.push_back(dirMf);
this->IndexMakefile(dirMf);
......
......@@ -432,6 +432,8 @@ public:
std::string MakeSilentFlag;
int RecursionDepth;
protected:
typedef std::vector<cmLocalGenerator*> GeneratorVector;
// for a project collect all its targets by following depend
......
......@@ -45,6 +45,8 @@
#include "cm_sys_stat.h"
#include "cmake.h"
#include "cmConfigure.h" // IWYU pragma: keep
#ifdef CMAKE_BUILD_WITH_CMAKE
# include "cmVariableWatch.h"
#endif
......@@ -83,6 +85,7 @@ cmMakefile::cmMakefile(cmGlobalGenerator* globalGenerator,
this->StateSnapshot =
this->StateSnapshot.GetState()->CreatePolicyScopeSnapshot(
this->StateSnapshot);
this->RecursionDepth = 0;
// Enter a policy level for this directory.
this->PushPolicy();
......@@ -333,12 +336,14 @@ public:
cmListFileContext const& lfc = cmListFileContext::FromCommandContext(
cc, this->Makefile->StateSnapshot.GetExecutionListFile());
this->Makefile->Backtrace = this->Makefile->Backtrace.Push(lfc);
++this->Makefile->RecursionDepth;
this->Makefile->ExecutionStatusStack.push_back(&status);
}
~cmMakefileCall()
{
this->Makefile->ExecutionStatusStack.pop_back();
--this->Makefile->RecursionDepth;
this->Makefile->Backtrace = this->Makefile->Backtrace.Pop();
}
......@@ -361,6 +366,24 @@ bool cmMakefile::ExecuteCommand(const cmListFileFunction& lff,
cmMakefileCall stack_manager(this, lff, status);
static_cast<void>(stack_manager);
// Check for maximum recursion depth.
int depth = CMake_DEFAULT_RECURSION_LIMIT;
const char* depthStr = this->GetDefinition("CMAKE_MAXIMUM_RECURSION_DEPTH");
if (depthStr) {
std::istringstream s(depthStr);
int d;
if (s >> d) {
depth = d;
}
}
if (this->RecursionDepth > depth) {
std::ostringstream e;
e << "Maximum recursion depth of " << depth << " exceeded";
this->IssueMessage(MessageType::FATAL_ERROR, e.str());
cmSystemTools::SetFatalErrorOccured();
return false;
}
// Lookup the command prototype.
if (cmCommand* proto =
this->GetState()->GetCommandByExactName(lff.Name.Lower)) {
......@@ -1369,6 +1392,9 @@ void cmMakefile::InitializeFromParent(cmMakefile* parent)
// Imported targets.
this->ImportedTargets = parent->ImportedTargets;
// Recursion depth.
this->RecursionDepth = parent->RecursionDepth;
}
void cmMakefile::PushFunctionScope(std::string const& fileName,
......@@ -2725,6 +2751,16 @@ bool cmMakefile::IsProjectFile(const char* filename) const
cmake::GetCMakeFilesDirectory()));
}
int cmMakefile::GetRecursionDepth() const
{
return this->RecursionDepth;
}
void cmMakefile::SetRecursionDepth(int recursionDepth)
{
this->RecursionDepth = recursionDepth;
}
MessageType cmMakefile::ExpandVariablesInStringNew(
std::string& errorstr, std::string& source, bool escapeQuotes,
bool noEscapes, bool atOnly, const char* filename, long line,
......@@ -3388,6 +3424,7 @@ int cmMakefile::TryCompile(const std::string& srcdir,
this->IsSourceFileTryCompile = false;
return 1;
}
gg->RecursionDepth = this->RecursionDepth;
cm.SetGlobalGenerator(gg);
// do a configure
......@@ -3407,6 +3444,12 @@ int cmMakefile::TryCompile(const std::string& srcdir,
cmStateEnums::STRING);
}
}
const char* recursionDepth =
this->GetDefinition("CMAKE_MAXIMUM_RECURSION_DEPTH");
if (recursionDepth) {
cm.AddCacheEntry("CMAKE_MAXIMUM_RECURSION_DEPTH", recursionDepth,
"Maximum recursion depth", cmStateEnums::STRING);
}
// if cmake args were provided then pass them in
if (cmakeArgs) {
// FIXME: Workaround to ignore unused CLI variables in try-compile.
......
......@@ -870,6 +870,9 @@ public:
const char* sourceFilename) const;
bool IsProjectFile(const char* filename) const;
int GetRecursionDepth() const;
void SetRecursionDepth(int recursionDepth);
protected:
// add link libraries and directories to the target
void AddGlobalLinkInformation(cmTarget& target);
......@@ -930,6 +933,7 @@ protected:
private:
cmStateSnapshot StateSnapshot;
cmListFileBacktrace Backtrace;
int RecursionDepth;
void ReadListFile(cmListFile const& listFile,
const std::string& filenametoread);
......
......@@ -215,6 +215,7 @@ endif()
add_RunCMake_test(CompatibleInterface)
add_RunCMake_test(Syntax)
add_RunCMake_test(WorkingDirectory)
add_RunCMake_test(MaxRecursionDepth)
add_RunCMake_test(add_custom_command)
add_RunCMake_test(add_custom_target)
......
cmake_minimum_required(VERSION 3.13)
if(DEFINED CMAKE_GENERATOR)
project(${RunCMake_TEST} NONE)
endif()
include("${CMAKE_CURRENT_LIST_DIR}/${TEST_NAME}.cmake")
cmake_minimum_required(VERSION 3.12)
project(MaxRecursionDepth NONE)
message("${x}")
math(EXPR x "${x} + 1")
ctest_read_custom_files("${CMAKE_CURRENT_LIST_DIR}")
message("${x}")
math(EXPR x "${x} + 1")
find_package(RecursivePackage)
include(RunCMake)
include(RunCTest)
function(run_cmake_recursive name)
set(RunCMake_TEST_OPTIONS "-DCMAKE_MODULE_PATH=${CMAKE_CURRENT_LIST_DIR}" -DTEST_NAME=${name})
run_cmake(${name}-default)
unset(RunCMake_TEST_OPTIONS)
set(RunCMake_TEST_OPTIONS "-DCMAKE_MODULE_PATH=${CMAKE_CURRENT_LIST_DIR}" -DTEST_NAME=${name} -DCMAKE_MAXIMUM_RECURSION_DEPTH=10)
run_cmake(${name}-var)
unset(RunCMake_TEST_OPTIONS)
set(RunCMake_TEST_OPTIONS "-DCMAKE_MODULE_PATH=${CMAKE_CURRENT_LIST_DIR}" -DTEST_NAME=${name} -DCMAKE_MAXIMUM_RECURSION_DEPTH=a)
run_cmake(${name}-invalid-var)
unset(RunCMake_TEST_OPTIONS)
run_cmake_command(${name}-default-script ${CMAKE_COMMAND} "-DCMAKE_MODULE_PATH=${CMAKE_CURRENT_LIST_DIR}" -DTEST_NAME=${name} -P "${CMAKE_CURRENT_LIST_DIR}/CMakeLists.txt")
run_cmake_command(${name}-var-script ${CMAKE_COMMAND} "-DCMAKE_MODULE_PATH=${CMAKE_CURRENT_LIST_DIR}" -DTEST_NAME=${name} -DCMAKE_MAXIMUM_RECURSION_DEPTH=10 -P "${CMAKE_CURRENT_LIST_DIR}/CMakeLists.txt")
run_cmake_command(${name}-invalid-var-script ${CMAKE_COMMAND} "-DCMAKE_MODULE_PATH=${CMAKE_CURRENT_LIST_DIR}" -DTEST_NAME=${name} -DCMAKE_MAXIMUM_RECURSION_DEPTH=a -P "${CMAKE_CURRENT_LIST_DIR}/CMakeLists.txt")
endfunction()
function(run_ctest_recursive name)
run_ctest(${name}-default "-DCMAKE_MODULE_PATH=${CMAKE_CURRENT_LIST_DIR}" -DTEST_NAME=${name})
run_ctest(${name}-var "-DCMAKE_MODULE_PATH=${CMAKE_CURRENT_LIST_DIR}" -DTEST_NAME=${name} -DCMAKE_MAXIMUM_RECURSION_DEPTH=10)
run_ctest(${name}-invalid-var "-DCMAKE_MODULE_PATH=${CMAKE_CURRENT_LIST_DIR}" -DTEST_NAME=${name} -DCMAKE_MAXIMUM_RECURSION_DEPTH=a)
endfunction()
run_cmake_recursive(function)
run_cmake_recursive(macro)
run_cmake_recursive(include)
run_cmake_recursive(find_package)
run_cmake_recursive(variable_watch)
# We run these tests separately and only with a small limit because they are
# taxing and slow. The "implicit" and "invalid" cases are already thoroughly
# covered by the other tests above.
set(RunCMake_TEST_OPTIONS "-DCMAKE_MODULE_PATH=${CMAKE_CURRENT_LIST_DIR}" -DTEST_NAME=add_subdirectory -DCMAKE_MAXIMUM_RECURSION_DEPTH=10)
run_cmake(add_subdirectory-var)
unset(RunCMake_TEST_OPTIONS)
set(RunCMake_TEST_OPTIONS "-DCMAKE_MODULE_PATH=${CMAKE_CURRENT_LIST_DIR}" -DTEST_NAME=try_compile -DCMAKE_MAXIMUM_RECURSION_DEPTH=10)
run_cmake(try_compile-var)
unset(RunCMake_TEST_OPTIONS)
run_ctest_recursive(ctest_read_custom_files)
# We run the ctest_run_script() test separately and only with an explicit limit
# because ctest_run_script() is taxing and slow, and because the implicit
# recursion limit is hit by CTestScriptMode.cmake before we can test it
# properly. The "implicit" and "invalid" cases are already thoroughly covered
# by the other tests above.
run_ctest(ctest_run_script-var "-DCMAKE_MODULE_PATH=${CMAKE_CURRENT_LIST_DIR}" -DTEST_NAME=ctest_run_script -DCMAKE_MAXIMUM_RECURSION_DEPTH=10)
^3
4
5
6
7
8
9
10
CMake Error at add_subdirectory/CMakeLists\.txt:1 \(message\):
Maximum recursion depth of 10 exceeded$
set(x 3)
add_subdirectory(add_subdirectory)
message("${x}")
math(EXPR x "${x} + 1")
add_subdirectory(. dir)
[0-9]+
CMake Error at .*/Tests/RunCMake/MaxRecursionDepth/CTestCustom\.cmake:1 \(message\):
Maximum recursion depth of [0-9]+ exceeded
Call Stack \(most recent call first\):
.*/Tests/RunCMake/MaxRecursionDepth/CTestCustom\.cmake:3 \(ctest_read_custom_files\)
[0-9]+
CMake Error at .*/Tests/RunCMake/MaxRecursionDepth/CTestCustom\.cmake:1 \(message\):
Maximum recursion depth of [0-9]+ exceeded
Call Stack \(most recent call first\):
.*/Tests/RunCMake/MaxRecursionDepth/CTestCustom\.cmake:3 \(ctest_read_custom_files\)
^2
3
4
5
6
7
8
9
10
CMake Error at .*/Tests/RunCMake/MaxRecursionDepth/CTestCustom\.cmake:1 \(message\):
Maximum recursion depth of 10 exceeded
Call Stack \(most recent call first\):
.*/Tests/RunCMake/MaxRecursionDepth/CTestCustom\.cmake:3 \(ctest_read_custom_files\)
.*/Tests/RunCMake/MaxRecursionDepth/CTestCustom\.cmake:3 \(ctest_read_custom_files\)
.*/Tests/RunCMake/MaxRecursionDepth/CTestCustom\.cmake:3 \(ctest_read_custom_files\)
.*/Tests/RunCMake/MaxRecursionDepth/CTestCustom\.cmake:3 \(ctest_read_custom_files\)
.*/Tests/RunCMake/MaxRecursionDepth/CTestCustom\.cmake:3 \(ctest_read_custom_files\)
.*/Tests/RunCMake/MaxRecursionDepth/CTestCustom\.cmake:3 \(ctest_read_custom_files\)
.*/Tests/RunCMake/MaxRecursionDepth/CTestCustom\.cmake:3 \(ctest_read_custom_files\)
.*/Tests/RunCMake/MaxRecursionDepth/CTestCustom\.cmake:3 \(ctest_read_custom_files\)
.*/Tests/RunCMake/MaxRecursionDepth/CTestCustom\.cmake:3 \(ctest_read_custom_files\)
.*/Tests/RunCMake/MaxRecursionDepth/ctest_read_custom_files-var/test\.cmake:10 \(ctest_read_custom_files\)
Problem reading custom configuration: .*/Tests/RunCMake/MaxRecursionDepth/CTestCustom\.cmake
Problem reading custom configuration: .*/Tests/RunCMake/MaxRecursionDepth/CTestCustom\.cmake
Problem reading custom configuration: .*/Tests/RunCMake/MaxRecursionDepth/CTestCustom\.cmake
Problem reading custom configuration: .*/Tests/RunCMake/MaxRecursionDepth/CTestCustom\.cmake
Problem reading custom configuration: .*/Tests/RunCMake/MaxRecursionDepth/CTestCustom\.cmake
Problem reading custom configuration: .*/Tests/RunCMake/MaxRecursionDepth/CTestCustom\.cmake
Problem reading custom configuration: .*/Tests/RunCMake/MaxRecursionDepth/CTestCustom\.cmake
Problem reading custom configuration: .*/Tests/RunCMake/MaxRecursionDepth/CTestCustom\.cmake
Problem reading custom configuration: .*/Tests/RunCMake/MaxRecursionDepth/CTestCustom\.cmake
Problem reading custom configuration: .*/Tests/RunCMake/MaxRecursionDepth/CTestCustom\.cmake$
^2
3
4
5
6
7
8
9
10
CMake Error at .*/Tests/RunCMake/MaxRecursionDepth/ctest_run_script_11\.cmake:1 \(cmake_minimum_required\):
Maximum recursion depth of 10 exceeded
CMake Error at .*/Tests/RunCMake/MaxRecursionDepth/ctest_run_script_10\.cmake:13 \(message\):
Nested script failed
CMake Error at .*/Tests/RunCMake/MaxRecursionDepth/ctest_run_script_9\.cmake:13 \(message\):
Nested script failed
CMake Error at .*/Tests/RunCMake/MaxRecursionDepth/ctest_run_script_8\.cmake:13 \(message\):
Nested script failed
CMake Error at .*/Tests/RunCMake/MaxRecursionDepth/ctest_run_script_7\.cmake:13 \(message\):
Nested script failed
CMake Error at .*/Tests/RunCMake/MaxRecursionDepth/ctest_run_script_6\.cmake:13 \(message\):
Nested script failed
CMake Error at .*/Tests/RunCMake/MaxRecursionDepth/ctest_run_script_5\.cmake:13 \(message\):
Nested script failed
CMake Error at .*/Tests/RunCMake/MaxRecursionDepth/ctest_run_script_4\.cmake:13 \(message\):
Nested script failed
CMake Error at .*/Tests/RunCMake/MaxRecursionDepth/ctest_run_script_3\.cmake:13 \(message\):
Nested script failed
CMake Error at .*/Tests/RunCMake/MaxRecursionDepth/ctest_run_script_2\.cmake:13 \(message\):
Nested script failed
CMake Error at .*/Tests/RunCMake/MaxRecursionDepth/ctest_run_script-var/test\.cmake:19 \(message\):
Nested script failed$
cmake_minimum_required(VERSION 3.12)
set(CTEST_RUN_CURRENT_SCRIPT 0)
message("@LEVEL_CURRENT@")
set(CTEST_SOURCE_DIRECTORY "@CTEST_SOURCE_DIRECTORY@")
set(CTEST_BINARY_DIRECTORY "@CTEST_BINARY_DIRECTORY@")
set(CTEST_COMMAND "@CTEST_COMMAND@")
ctest_run_script("${CMAKE_CURRENT_LIST_DIR}/ctest_run_script_@LEVEL_NEXT@.cmake" RETURN_VALUE val)
if(NOT val EQUAL 0)
message(FATAL_ERROR "Nested script failed")
endif()
[0-9]+
CMake Error at .*/FindRecursivePackage\.cmake:1 \(message\):
Maximum recursion depth of [0-9]+ exceeded
Call Stack \(most recent call first\):
.*/FindRecursivePackage\.cmake:3 \(find_package\)
[0-9]+
CMake Error at FindRecursivePackage\.cmake:1 \(message\):
Maximum recursion depth of [0-9]+ exceeded
Call Stack \(most recent call first\):
FindRecursivePackage\.cmake:3 \(find_package\)
[0-9]+
CMake Error at .*/FindRecursivePackage\.cmake:1 \(message\):
Maximum recursion depth of [0-9]+ exceeded
Call Stack \(most recent call first\):
.*/FindRecursivePackage\.cmake:3 \(find_package\)
[0-9]+
CMake Error at FindRecursivePackage\.cmake:1 \(message\):
Maximum recursion depth of [0-9]+ exceeded
Call Stack \(most recent call first\):
FindRecursivePackage\.cmake:3 \(find_package\)
^3
4
5
6
7
8
9
10
CMake Error at .*/FindRecursivePackage\.cmake:1 \(message\):
Maximum recursion depth of 10 exceeded
Call Stack \(most recent call first\):
.*/FindRecursivePackage\.cmake:3 \(find_package\)
.*/FindRecursivePackage\.cmake:3 \(find_package\)
.*/FindRecursivePackage\.cmake:3 \(find_package\)
.*/FindRecursivePackage\.cmake:3 \(find_package\)
.*/FindRecursivePackage\.cmake:3 \(find_package\)
.*/FindRecursivePackage\.cmake:3 \(find_package\)
.*/FindRecursivePackage\.cmake:3 \(find_package\)
.*/FindRecursivePackage\.cmake:3 \(find_package\)
.*/find_package\.cmake:2 \(find_package\)
.*/CMakeLists\.txt:5 \(include\)$
^3
4
5
6
7
8
9
10
CMake Error at FindRecursivePackage\.cmake:1 \(message\):
Maximum recursion depth of 10 exceeded
Call Stack \(most recent call first\):
FindRecursivePackage\.cmake:3 \(find_package\)
FindRecursivePackage\.cmake:3 \(find_package\)
FindRecursivePackage\.cmake:3 \(find_package\)
FindRecursivePackage\.cmake:3 \(find_package\)
FindRecursivePackage\.cmake:3 \(find_package\)
FindRecursivePackage\.cmake:3 \(find_package\)
FindRecursivePackage\.cmake:3 \(find_package\)
FindRecursivePackage\.cmake:3 \(find_package\)
find_package\.cmake:2 \(find_package\)
CMakeLists\.txt:5 \(include\)$
set(x 3)
find_package(RecursivePackage)
[0-9]+
CMake Error at .*/function\.cmake:2 \(message\):
Maximum recursion depth of [0-9]+ exceeded
Call Stack \(most recent call first\):
.*/function\.cmake:4 \(recursive\)
[0-9]+
CMake Error at function\.cmake:2 \(message\):
Maximum recursion depth of [0-9]+ exceeded
Call Stack \(most recent call first\):
function\.cmake:4 \(recursive\)
[0-9]+
CMake Error at .*/function\.cmake:2 \(message\):