From 1082b9cb9a51749dd24a866cc18798434c2eaff5 Mon Sep 17 00:00:00 2001 From: leha-bot Date: Mon, 12 Jun 2023 19:09:40 +0300 Subject: cmExecutionStatus: Add ability to set optional custom exit code --- Source/cmExecutionStatus.h | 8 ++++++++ 1 file changed, 8 insertions(+) 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 #include +#include + 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 ExitCode; std::vector Variables; }; -- cgit v0.12 From 9f6c937408e7680a6b6bc01e13b4efe8aeca4623 Mon Sep 17 00:00:00 2001 From: leha-bot Date: Tue, 2 Jan 2024 21:11:43 +0300 Subject: Source/cmake.h: Add ScriptModeExitCode for proper storing exit code From executed CMake script in SCRIPT_MODE. --- Source/cmake.h | 6 ++++++ 1 file changed, 6 insertions(+) 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 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]; }; -- cgit v0.12 From 3d9d5046467dffe1ba7a22c89c67bf7b6632d9c2 Mon Sep 17 00:00:00 2001 From: leha-bot Date: Tue, 2 Jan 2024 21:13:26 +0300 Subject: cmMakefile: Store the exit code from cmExecutionStatus to cmake instance --- Source/cmMakefile.cxx | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx index 936b282..36bd69b 100644 --- a/Source/cmMakefile.cxx +++ b/Source/cmMakefile.cxx @@ -898,6 +898,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. -- cgit v0.12 From b62dcbf5d2f99dd5f258be9955df6ed605657f70 Mon Sep 17 00:00:00 2001 From: leha-bot Date: Fri, 5 Jan 2024 04:21:48 +0300 Subject: cmMakefile: check cmake script mode exit code after command Which potentially may set it, and forward it to the cmExecutionStatus for proper handling in caller. --- Source/cmMakefile.cxx | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx index 36bd69b..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()) { -- cgit v0.12 From 4f160f7906ef8075dad54b9bf2e0ba204a1c41fc Mon Sep 17 00:00:00 2001 From: leha-bot Date: Tue, 2 Jan 2024 21:13:53 +0300 Subject: cmakemain: Return the SCRIPT_MODE exit code if it was set We determine it via checking cmake.Run() return code and ScriptModeExitCode. If ScriptModeExitCode is zero, then we would return 1 if retcode was non-zero. Otherwise it will be returned if retcode was also non-zero. --- Source/cmake.cxx | 2 +- Source/cmakemain.cxx | 11 +++++++---- 2 files changed, 8 insertions(+), 5 deletions(-) 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& 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/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); -- cgit v0.12 From 1bb17692359d675eee12996c43446fa9c9fe5175 Mon Sep 17 00:00:00 2001 From: leha-bot Date: Fri, 5 Jan 2024 19:12:22 +0300 Subject: cmake_language: Add EXIT subcommand Add tests to cover these cases: * run as regular CMake module, in NORMAL_MODE (expected to fail); * run as CMake script in SCRIPT_MODE (expected to exit with given code); * run as CMake script that `include()`-s another script with EXIT subcommand; * run as CMake script which EVAL-uates EXIT subcommand via `cmake_language(EVAL CODE "")`. Fixes: #23162 --- Help/command/cmake_language.rst | 23 +++++++++++++++++++ Help/release/dev/cmake-language-exit.rst | 5 +++++ Source/cmCMakeLanguageCommand.cxx | 26 ++++++++++++++++++++++ Tests/RunCMake/cmake_language/RunCMakeTest.cmake | 7 ++++++ Tests/RunCMake/cmake_language/exit_0-result.txt | 1 + Tests/RunCMake/cmake_language/exit_0-stderr.txt | 2 ++ Tests/RunCMake/cmake_language/exit_0.cmake | 1 + .../cmake_language/exit_0_script-result.txt | 1 + .../cmake_language/exit_0_script-stderr.txt | 0 Tests/RunCMake/cmake_language/exit_0_script.cmake | 1 + .../exit_0_script_with_command-result.txt | 1 + .../exit_0_script_with_command-stderr.txt | 0 .../exit_0_script_with_command.cmake | 3 +++ Tests/RunCMake/cmake_language/exit_5-result.txt | 1 + Tests/RunCMake/cmake_language/exit_5-stderr.txt | 2 ++ Tests/RunCMake/cmake_language/exit_5.cmake | 1 + .../cmake_language/exit_5_script-result.txt | 1 + .../cmake_language/exit_5_script-stderr.txt | 0 Tests/RunCMake/cmake_language/exit_5_script.cmake | 1 + .../exit_5_script_with_command-result.txt | 1 + .../exit_5_script_with_command-stderr.txt | 0 .../exit_5_script_with_command.cmake | 3 +++ .../exit_7_script_in_include-result.txt | 1 + .../exit_7_script_in_include-stderr.txt | 0 .../cmake_language/exit_7_script_in_include.cmake | 3 +++ .../exit_7_script_included_with_exit.cmake | 3 +++ ...8_script_in_recursive_cmake_language-result.txt | 1 + ...8_script_in_recursive_cmake_language-stderr.txt | 1 + ...exit_8_script_in_recursive_cmake_language.cmake | 3 +++ 29 files changed, 93 insertions(+) create mode 100644 Help/release/dev/cmake-language-exit.rst create mode 100644 Tests/RunCMake/cmake_language/exit_0-result.txt create mode 100644 Tests/RunCMake/cmake_language/exit_0-stderr.txt create mode 100644 Tests/RunCMake/cmake_language/exit_0.cmake create mode 100644 Tests/RunCMake/cmake_language/exit_0_script-result.txt create mode 100644 Tests/RunCMake/cmake_language/exit_0_script-stderr.txt create mode 100644 Tests/RunCMake/cmake_language/exit_0_script.cmake create mode 100644 Tests/RunCMake/cmake_language/exit_0_script_with_command-result.txt create mode 100644 Tests/RunCMake/cmake_language/exit_0_script_with_command-stderr.txt create mode 100644 Tests/RunCMake/cmake_language/exit_0_script_with_command.cmake create mode 100644 Tests/RunCMake/cmake_language/exit_5-result.txt create mode 100644 Tests/RunCMake/cmake_language/exit_5-stderr.txt create mode 100644 Tests/RunCMake/cmake_language/exit_5.cmake create mode 100644 Tests/RunCMake/cmake_language/exit_5_script-result.txt create mode 100644 Tests/RunCMake/cmake_language/exit_5_script-stderr.txt create mode 100644 Tests/RunCMake/cmake_language/exit_5_script.cmake create mode 100644 Tests/RunCMake/cmake_language/exit_5_script_with_command-result.txt create mode 100644 Tests/RunCMake/cmake_language/exit_5_script_with_command-stderr.txt create mode 100644 Tests/RunCMake/cmake_language/exit_5_script_with_command.cmake create mode 100644 Tests/RunCMake/cmake_language/exit_7_script_in_include-result.txt create mode 100644 Tests/RunCMake/cmake_language/exit_7_script_in_include-stderr.txt create mode 100644 Tests/RunCMake/cmake_language/exit_7_script_in_include.cmake create mode 100644 Tests/RunCMake/cmake_language/exit_7_script_included_with_exit.cmake create mode 100644 Tests/RunCMake/cmake_language/exit_8_script_in_recursive_cmake_language-result.txt create mode 100644 Tests/RunCMake/cmake_language/exit_8_script_in_recursive_cmake_language-stderr.txt create mode 100644 Tests/RunCMake/cmake_language/exit_8_script_in_recursive_cmake_language.cmake 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`_ ... CALL [...]) cmake_language(`SET_DEPENDENCY_PROVIDER`_ SUPPORTED_METHODS ...) cmake_language(`GET_MESSAGE_LOG_LEVEL`_ ) + cmake_language(`EXIT`_ ) 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 ) + + Terminate the current :option:`cmake -P` script and exit with ````. + + This command works only in :ref:`script mode