summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBrad King <brad.king@kitware.com>2024-01-17 14:53:24 (GMT)
committerKitware Robot <kwrobot@kitware.com>2024-01-17 14:53:46 (GMT)
commitfa4a499238502dead01c482a168eb52b6599dc22 (patch)
treebf5979cea353f228c43b993194e22555928afaab
parentc7ebec770f19faa7b16df280a1f4804fa98b1011 (diff)
parent1bb17692359d675eee12996c43446fa9c9fe5175 (diff)
downloadCMake-fa4a499238502dead01c482a168eb52b6599dc22.zip
CMake-fa4a499238502dead01c482a168eb52b6599dc22.tar.gz
CMake-fa4a499238502dead01c482a168eb52b6599dc22.tar.bz2
Merge topic 'cmake-language-exit-code'
1bb1769235 cmake_language: Add EXIT subcommand 4f160f7906 cmakemain: Return the SCRIPT_MODE exit code if it was set b62dcbf5d2 cmMakefile: check cmake script mode exit code after command 3d9d504646 cmMakefile: Store the exit code from cmExecutionStatus to cmake instance 9f6c937408 Source/cmake.h: Add ScriptModeExitCode for proper storing exit code 1082b9cb9a cmExecutionStatus: Add ability to set optional custom exit code Acked-by: Kitware Robot <kwrobot@kitware.com> Acked-by: buildbot <buildbot@kitware.com> Acked-by: Leonid Pospelov <pospelovlm@yandex.ru> Acked-by: NoMaY (a user of Renesas Rulz Japanese Forum) <nomay-jp@outlook.com> Merge-request: !8228
-rw-r--r--Help/command/cmake_language.rst23
-rw-r--r--Help/release/dev/cmake-language-exit.rst5
-rw-r--r--Source/cmCMakeLanguageCommand.cxx26
-rw-r--r--Source/cmExecutionStatus.h8
-rw-r--r--Source/cmMakefile.cxx11
-rw-r--r--Source/cmake.cxx2
-rw-r--r--Source/cmake.h6
-rw-r--r--Source/cmakemain.cxx11
-rw-r--r--Tests/RunCMake/cmake_language/RunCMakeTest.cmake7
-rw-r--r--Tests/RunCMake/cmake_language/exit_0-result.txt1
-rw-r--r--Tests/RunCMake/cmake_language/exit_0-stderr.txt2
-rw-r--r--Tests/RunCMake/cmake_language/exit_0.cmake1
-rw-r--r--Tests/RunCMake/cmake_language/exit_0_script-result.txt1
-rw-r--r--Tests/RunCMake/cmake_language/exit_0_script-stderr.txt0
-rw-r--r--Tests/RunCMake/cmake_language/exit_0_script.cmake1
-rw-r--r--Tests/RunCMake/cmake_language/exit_0_script_with_command-result.txt1
-rw-r--r--Tests/RunCMake/cmake_language/exit_0_script_with_command-stderr.txt0
-rw-r--r--Tests/RunCMake/cmake_language/exit_0_script_with_command.cmake3
-rw-r--r--Tests/RunCMake/cmake_language/exit_5-result.txt1
-rw-r--r--Tests/RunCMake/cmake_language/exit_5-stderr.txt2
-rw-r--r--Tests/RunCMake/cmake_language/exit_5.cmake1
-rw-r--r--Tests/RunCMake/cmake_language/exit_5_script-result.txt1
-rw-r--r--Tests/RunCMake/cmake_language/exit_5_script-stderr.txt0
-rw-r--r--Tests/RunCMake/cmake_language/exit_5_script.cmake1
-rw-r--r--Tests/RunCMake/cmake_language/exit_5_script_with_command-result.txt1
-rw-r--r--Tests/RunCMake/cmake_language/exit_5_script_with_command-stderr.txt0
-rw-r--r--Tests/RunCMake/cmake_language/exit_5_script_with_command.cmake3
-rw-r--r--Tests/RunCMake/cmake_language/exit_7_script_in_include-result.txt1
-rw-r--r--Tests/RunCMake/cmake_language/exit_7_script_in_include-stderr.txt0
-rw-r--r--Tests/RunCMake/cmake_language/exit_7_script_in_include.cmake3
-rw-r--r--Tests/RunCMake/cmake_language/exit_7_script_included_with_exit.cmake3
-rw-r--r--Tests/RunCMake/cmake_language/exit_8_script_in_recursive_cmake_language-result.txt1
-rw-r--r--Tests/RunCMake/cmake_language/exit_8_script_in_recursive_cmake_language-stderr.txt1
-rw-r--r--Tests/RunCMake/cmake_language/exit_8_script_in_recursive_cmake_language.cmake3
34 files changed, 126 insertions, 5 deletions
diff --git a/Help/command/cmake_language.rst b/Help/command/cmake_language.rst
index 4b64eb6..45ac569 100644
--- a/Help/command/cmake_language.rst
+++ b/Help/command/cmake_language.rst
@@ -15,6 +15,7 @@ Synopsis
cmake_language(`DEFER`_ <options>... CALL <command> [<arg>...])
cmake_language(`SET_DEPENDENCY_PROVIDER`_ <command> SUPPORTED_METHODS <methods>...)
cmake_language(`GET_MESSAGE_LOG_LEVEL`_ <out-var>)
+ cmake_language(`EXIT`_ <exit-code>)
Introduction
^^^^^^^^^^^^
@@ -506,3 +507,25 @@ Getting current message log level
If both the command line option and the variable are set, the command line
option takes precedence. If neither are set, the default logging level
is returned.
+
+Terminating Scripts
+^^^^^^^^^^^^^^^^^^^
+
+.. versionadded:: 3.29
+
+.. _EXIT:
+.. _exit-code:
+
+.. code-block:: cmake
+
+.. signature::
+ cmake_language(EXIT <exit-code>)
+
+ Terminate the current :option:`cmake -P` script and exit with ``<exit-code>``.
+
+ This command works only in :ref:`script mode <Script Processing Mode>`.
+
+ The ``<exit-code>`` should be non-negative.
+ If ``<exit-code>`` is negative then the behavior
+ is unspecified (e.g., on Windows the error code -1
+ becomes ``0xffffffff``, and on Linux it becomes ``255``).
diff --git a/Help/release/dev/cmake-language-exit.rst b/Help/release/dev/cmake-language-exit.rst
new file mode 100644
index 0000000..42e8ae2
--- /dev/null
+++ b/Help/release/dev/cmake-language-exit.rst
@@ -0,0 +1,5 @@
+cmake-language-exit
+-------------------
+
+* The :command:`cmake_language()` command gained a new ``EXIT``
+ sub-command to exit scripts with a specified exit code.
diff --git a/Source/cmCMakeLanguageCommand.cxx b/Source/cmCMakeLanguageCommand.cxx
index 329427c..9ffc363 100644
--- a/Source/cmCMakeLanguageCommand.cxx
+++ b/Source/cmCMakeLanguageCommand.cxx
@@ -398,6 +398,32 @@ bool cmCMakeLanguageCommand(std::vector<cmListFileArgument> const& args,
if (!moreArgs()) {
return FatalError(status, "called with incorrect number of arguments");
}
+ if (expArgs[expArg] == "EXIT"_s) {
+ ++expArg; // consume "EXIT".
+
+ if (!moreArgs()) {
+ return FatalError(status, "EXIT requires one argument");
+ }
+
+ auto workingMode =
+ status.GetMakefile().GetCMakeInstance()->GetWorkingMode();
+ if (workingMode != cmake::SCRIPT_MODE) {
+ return FatalError(status, "EXIT can be used only in SCRIPT mode");
+ }
+
+ long retCode = 0;
+
+ if (!cmStrToLong(expArgs[expArg], &retCode)) {
+ return FatalError(status,
+ cmStrCat("EXIT requires one integral argument, got \"",
+ expArgs[expArg], '\"'));
+ }
+
+ if (workingMode == cmake::SCRIPT_MODE) {
+ status.SetExitCode(static_cast<int>(retCode));
+ }
+ return true;
+ }
if (expArgs[expArg] == "SET_DEPENDENCY_PROVIDER"_s) {
finishArgs();
diff --git a/Source/cmExecutionStatus.h b/Source/cmExecutionStatus.h
index ced3548..e023971 100644
--- a/Source/cmExecutionStatus.h
+++ b/Source/cmExecutionStatus.h
@@ -7,6 +7,8 @@
#include <string>
#include <vector>
+#include <cm/optional>
+
class cmMakefile;
/** \class cmExecutionStatus
@@ -53,6 +55,11 @@ public:
void SetNestedError() { this->NestedError = true; }
bool GetNestedError() const { return this->NestedError; }
+ void SetExitCode(int code) noexcept { this->ExitCode = code; }
+ bool HasExitCode() const noexcept { return this->ExitCode.has_value(); }
+ void CleanExitCode() noexcept { this->ExitCode.reset(); }
+ int GetExitCode() const noexcept { return this->ExitCode.value_or(-1); }
+
private:
cmMakefile& Makefile;
std::string Error;
@@ -60,5 +67,6 @@ private:
bool BreakInvoked = false;
bool ContinueInvoked = false;
bool NestedError = false;
+ cm::optional<int> ExitCode;
std::vector<std::string> Variables;
};
diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx
index 936b282..6fb7734 100644
--- a/Source/cmMakefile.cxx
+++ b/Source/cmMakefile.cxx
@@ -529,6 +529,12 @@ bool cmMakefile::ExecuteCommand(const cmListFileFunction& lff,
cmSystemTools::SetFatalErrorOccurred();
}
}
+ if (this->GetCMakeInstance()->HasScriptModeExitCode() &&
+ this->GetCMakeInstance()->GetWorkingMode() == cmake::SCRIPT_MODE) {
+ // pass-through the exit code from inner cmake_language(EXIT) ,
+ // possibly from include() or similar command...
+ status.SetExitCode(this->GetCMakeInstance()->GetScriptModeExitCode());
+ }
}
} else {
if (!cmSystemTools::GetFatalErrorOccurred()) {
@@ -898,6 +904,11 @@ void cmMakefile::RunListFile(cmListFile const& listFile,
if (cmSystemTools::GetFatalErrorOccurred()) {
break;
}
+ if (status.HasExitCode()) {
+ // cmake_language EXIT was requested, early break.
+ this->GetCMakeInstance()->SetScriptModeExitCode(status.GetExitCode());
+ break;
+ }
if (status.GetReturnInvoked()) {
this->RaiseScope(status.GetReturnVariables());
// Exit early due to return command.
diff --git a/Source/cmake.cxx b/Source/cmake.cxx
index 32064b4..7ab7600 100644
--- a/Source/cmake.cxx
+++ b/Source/cmake.cxx
@@ -2820,7 +2820,7 @@ int cmake::Run(const std::vector<std::string>& args, bool noconfigure)
if (cmSystemTools::GetErrorOccurredFlag()) {
return -1;
}
- return 0;
+ return this->HasScriptModeExitCode() ? this->GetScriptModeExitCode() : 0;
}
// If MAKEFLAGS are given in the environment, remove the environment
diff --git a/Source/cmake.h b/Source/cmake.h
index 58f90c9..ccf5154 100644
--- a/Source/cmake.h
+++ b/Source/cmake.h
@@ -835,7 +835,13 @@ private:
std::string DebuggerDapLogFile;
#endif
+ cm::optional<int> ScriptModeExitCode;
+
public:
+ bool HasScriptModeExitCode() const { return ScriptModeExitCode.has_value(); }
+ void SetScriptModeExitCode(int code) { ScriptModeExitCode = code; }
+ int GetScriptModeExitCode() const { return ScriptModeExitCode.value_or(-1); }
+
static cmDocumentationEntry CMAKE_STANDARD_OPTIONS_TABLE[18];
};
diff --git a/Source/cmakemain.cxx b/Source/cmakemain.cxx
index ced83dc..8462734 100644
--- a/Source/cmakemain.cxx
+++ b/Source/cmakemain.cxx
@@ -389,13 +389,16 @@ int do_cmake(int ac, char const* const* av)
}
}
- // Always return a non-negative value. Windows tools do not always
- // interpret negative return values as errors.
+ // Always return a non-negative value (except exit code from SCRIPT_MODE).
+ // Windows tools do not always interpret negative return values as errors.
if (res != 0) {
+ auto scriptModeExitCode =
+ cm.HasScriptModeExitCode() ? cm.GetScriptModeExitCode() : 0;
+ res = scriptModeExitCode ? scriptModeExitCode : 1;
#ifdef CMake_ENABLE_DEBUGGER
- cm.StopDebuggerIfNeeded(1);
+ cm.StopDebuggerIfNeeded(res);
#endif
- return 1;
+ return res;
}
#ifdef CMake_ENABLE_DEBUGGER
cm.StopDebuggerIfNeeded(0);
diff --git a/Tests/RunCMake/cmake_language/RunCMakeTest.cmake b/Tests/RunCMake/cmake_language/RunCMakeTest.cmake
index 38ce10b..ac4aec8 100644
--- a/Tests/RunCMake/cmake_language/RunCMakeTest.cmake
+++ b/Tests/RunCMake/cmake_language/RunCMakeTest.cmake
@@ -84,6 +84,13 @@ run_cmake(defer_get_call_id_var)
run_cmake(defer_missing_arg)
run_cmake(defer_missing_call)
run_cmake(defer_unknown_option)
+run_cmake(exit_0)
+run_cmake(exit_5)
+run_cmake_script(exit_0_script)
+run_cmake_script(exit_5_script)
+run_cmake_script(exit_0_script_with_command)
+run_cmake_script(exit_7_script_in_include)
+run_cmake_script(exit_8_script_in_recursive_cmake_language)
# Default log level
run_cmake_command(
diff --git a/Tests/RunCMake/cmake_language/exit_0-result.txt b/Tests/RunCMake/cmake_language/exit_0-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/cmake_language/exit_0-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/cmake_language/exit_0-stderr.txt b/Tests/RunCMake/cmake_language/exit_0-stderr.txt
new file mode 100644
index 0000000..04a586e
--- /dev/null
+++ b/Tests/RunCMake/cmake_language/exit_0-stderr.txt
@@ -0,0 +1,2 @@
+CMake Error at exit_0.cmake:1 \(cmake_language\):
+ cmake_language EXIT can be used only in SCRIPT mode
diff --git a/Tests/RunCMake/cmake_language/exit_0.cmake b/Tests/RunCMake/cmake_language/exit_0.cmake
new file mode 100644
index 0000000..53a150e
--- /dev/null
+++ b/Tests/RunCMake/cmake_language/exit_0.cmake
@@ -0,0 +1 @@
+cmake_language(EXIT 0)
diff --git a/Tests/RunCMake/cmake_language/exit_0_script-result.txt b/Tests/RunCMake/cmake_language/exit_0_script-result.txt
new file mode 100644
index 0000000..573541a
--- /dev/null
+++ b/Tests/RunCMake/cmake_language/exit_0_script-result.txt
@@ -0,0 +1 @@
+0
diff --git a/Tests/RunCMake/cmake_language/exit_0_script-stderr.txt b/Tests/RunCMake/cmake_language/exit_0_script-stderr.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/Tests/RunCMake/cmake_language/exit_0_script-stderr.txt
diff --git a/Tests/RunCMake/cmake_language/exit_0_script.cmake b/Tests/RunCMake/cmake_language/exit_0_script.cmake
new file mode 100644
index 0000000..53a150e
--- /dev/null
+++ b/Tests/RunCMake/cmake_language/exit_0_script.cmake
@@ -0,0 +1 @@
+cmake_language(EXIT 0)
diff --git a/Tests/RunCMake/cmake_language/exit_0_script_with_command-result.txt b/Tests/RunCMake/cmake_language/exit_0_script_with_command-result.txt
new file mode 100644
index 0000000..573541a
--- /dev/null
+++ b/Tests/RunCMake/cmake_language/exit_0_script_with_command-result.txt
@@ -0,0 +1 @@
+0
diff --git a/Tests/RunCMake/cmake_language/exit_0_script_with_command-stderr.txt b/Tests/RunCMake/cmake_language/exit_0_script_with_command-stderr.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/Tests/RunCMake/cmake_language/exit_0_script_with_command-stderr.txt
diff --git a/Tests/RunCMake/cmake_language/exit_0_script_with_command.cmake b/Tests/RunCMake/cmake_language/exit_0_script_with_command.cmake
new file mode 100644
index 0000000..ebc4ca7
--- /dev/null
+++ b/Tests/RunCMake/cmake_language/exit_0_script_with_command.cmake
@@ -0,0 +1,3 @@
+cmake_language(EXIT 0)
+
+message(FATAL_ERROR "cmake_language(EXIT 0) doesn't work")
diff --git a/Tests/RunCMake/cmake_language/exit_5-result.txt b/Tests/RunCMake/cmake_language/exit_5-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/cmake_language/exit_5-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/cmake_language/exit_5-stderr.txt b/Tests/RunCMake/cmake_language/exit_5-stderr.txt
new file mode 100644
index 0000000..ad232f8
--- /dev/null
+++ b/Tests/RunCMake/cmake_language/exit_5-stderr.txt
@@ -0,0 +1,2 @@
+CMake Error at exit_5.cmake:1 \(cmake_language\):
+ cmake_language EXIT can be used only in SCRIPT mode
diff --git a/Tests/RunCMake/cmake_language/exit_5.cmake b/Tests/RunCMake/cmake_language/exit_5.cmake
new file mode 100644
index 0000000..5e5c147
--- /dev/null
+++ b/Tests/RunCMake/cmake_language/exit_5.cmake
@@ -0,0 +1 @@
+cmake_language(EXIT 5)
diff --git a/Tests/RunCMake/cmake_language/exit_5_script-result.txt b/Tests/RunCMake/cmake_language/exit_5_script-result.txt
new file mode 100644
index 0000000..7ed6ff8
--- /dev/null
+++ b/Tests/RunCMake/cmake_language/exit_5_script-result.txt
@@ -0,0 +1 @@
+5
diff --git a/Tests/RunCMake/cmake_language/exit_5_script-stderr.txt b/Tests/RunCMake/cmake_language/exit_5_script-stderr.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/Tests/RunCMake/cmake_language/exit_5_script-stderr.txt
diff --git a/Tests/RunCMake/cmake_language/exit_5_script.cmake b/Tests/RunCMake/cmake_language/exit_5_script.cmake
new file mode 100644
index 0000000..5e5c147
--- /dev/null
+++ b/Tests/RunCMake/cmake_language/exit_5_script.cmake
@@ -0,0 +1 @@
+cmake_language(EXIT 5)
diff --git a/Tests/RunCMake/cmake_language/exit_5_script_with_command-result.txt b/Tests/RunCMake/cmake_language/exit_5_script_with_command-result.txt
new file mode 100644
index 0000000..7ed6ff8
--- /dev/null
+++ b/Tests/RunCMake/cmake_language/exit_5_script_with_command-result.txt
@@ -0,0 +1 @@
+5
diff --git a/Tests/RunCMake/cmake_language/exit_5_script_with_command-stderr.txt b/Tests/RunCMake/cmake_language/exit_5_script_with_command-stderr.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/Tests/RunCMake/cmake_language/exit_5_script_with_command-stderr.txt
diff --git a/Tests/RunCMake/cmake_language/exit_5_script_with_command.cmake b/Tests/RunCMake/cmake_language/exit_5_script_with_command.cmake
new file mode 100644
index 0000000..4400307
--- /dev/null
+++ b/Tests/RunCMake/cmake_language/exit_5_script_with_command.cmake
@@ -0,0 +1,3 @@
+cmake_language(EXIT 5)
+
+message(FATAL_ERROR "cmake_language(EXIT 5) doesn't work")
diff --git a/Tests/RunCMake/cmake_language/exit_7_script_in_include-result.txt b/Tests/RunCMake/cmake_language/exit_7_script_in_include-result.txt
new file mode 100644
index 0000000..7f8f011
--- /dev/null
+++ b/Tests/RunCMake/cmake_language/exit_7_script_in_include-result.txt
@@ -0,0 +1 @@
+7
diff --git a/Tests/RunCMake/cmake_language/exit_7_script_in_include-stderr.txt b/Tests/RunCMake/cmake_language/exit_7_script_in_include-stderr.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/Tests/RunCMake/cmake_language/exit_7_script_in_include-stderr.txt
diff --git a/Tests/RunCMake/cmake_language/exit_7_script_in_include.cmake b/Tests/RunCMake/cmake_language/exit_7_script_in_include.cmake
new file mode 100644
index 0000000..e65fa5c
--- /dev/null
+++ b/Tests/RunCMake/cmake_language/exit_7_script_in_include.cmake
@@ -0,0 +1,3 @@
+include(${CMAKE_CURRENT_LIST_DIR}/exit_7_script_included_with_exit.cmake)
+
+message(FATAL_ERROR "The cmake_language(EXIT 7) from include()-d script doesn't work")
diff --git a/Tests/RunCMake/cmake_language/exit_7_script_included_with_exit.cmake b/Tests/RunCMake/cmake_language/exit_7_script_included_with_exit.cmake
new file mode 100644
index 0000000..ee36ca0
--- /dev/null
+++ b/Tests/RunCMake/cmake_language/exit_7_script_included_with_exit.cmake
@@ -0,0 +1,3 @@
+cmake_language(EXIT 7)
+
+message(FATAL_ERROR "The include()-d script with EXIT 7 doesn't work")
diff --git a/Tests/RunCMake/cmake_language/exit_8_script_in_recursive_cmake_language-result.txt b/Tests/RunCMake/cmake_language/exit_8_script_in_recursive_cmake_language-result.txt
new file mode 100644
index 0000000..45a4fb7
--- /dev/null
+++ b/Tests/RunCMake/cmake_language/exit_8_script_in_recursive_cmake_language-result.txt
@@ -0,0 +1 @@
+8
diff --git a/Tests/RunCMake/cmake_language/exit_8_script_in_recursive_cmake_language-stderr.txt b/Tests/RunCMake/cmake_language/exit_8_script_in_recursive_cmake_language-stderr.txt
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/Tests/RunCMake/cmake_language/exit_8_script_in_recursive_cmake_language-stderr.txt
@@ -0,0 +1 @@
+
diff --git a/Tests/RunCMake/cmake_language/exit_8_script_in_recursive_cmake_language.cmake b/Tests/RunCMake/cmake_language/exit_8_script_in_recursive_cmake_language.cmake
new file mode 100644
index 0000000..96daf86
--- /dev/null
+++ b/Tests/RunCMake/cmake_language/exit_8_script_in_recursive_cmake_language.cmake
@@ -0,0 +1,3 @@
+cmake_language(EVAL CODE "cmake_language(EXIT 8)")
+
+message(FATAL_ERROR "The cmake_language EVAL of EXIT 8 test doesn't work")