diff options
author | Glen Chung <kuchung@microsoft.com> | 2023-03-16 00:50:08 (GMT) |
---|---|---|
committer | Brad King <brad.king@kitware.com> | 2023-05-30 13:46:12 (GMT) |
commit | a9a592f96e6498da302f8e968be1db0ad3c32123 (patch) | |
tree | 0d75f16ee2eae99b1a3f063e575b3f5f8f2ee931 /Source/cmake.cxx | |
parent | b0d1ddb7234950374977b83f8dbded806c15b356 (diff) | |
download | CMake-a9a592f96e6498da302f8e968be1db0ad3c32123.zip CMake-a9a592f96e6498da302f8e968be1db0ad3c32123.tar.gz CMake-a9a592f96e6498da302f8e968be1db0ad3c32123.tar.bz2 |
cmake: Add debugger
- Depends on cppdap and jsoncpp.
- Add --debugger argument to enable the Debugger.
- Add --debugger-pipe argument for DAP traffics over named pipes.
- Support breakpoints by filenames and line numbers.
- Support exception breakpoints.
- Call stack shows filenames and line numbers.
- Show Cache Variables.
- Show the state of currently defined targets,
tests and directories with their properties.
- Add cmakeVersion to DAP initialize response.
- Include unit tests.
Co-authored-by: Ben McMorran <bemcmorr@microsoft.com>
Diffstat (limited to 'Source/cmake.cxx')
-rw-r--r-- | Source/cmake.cxx | 115 |
1 files changed, 114 insertions, 1 deletions
diff --git a/Source/cmake.cxx b/Source/cmake.cxx index c5b467d..0a1e7ab 100644 --- a/Source/cmake.cxx +++ b/Source/cmake.cxx @@ -38,6 +38,10 @@ #include "cmCMakePresetsGraph.h" #include "cmCommandLineArgument.h" #include "cmCommands.h" +#ifdef CMake_ENABLE_DEBUGGER +# include "cmDebuggerAdapter.h" +# include "cmDebuggerPipeConnection.h" +#endif #include "cmDocumentation.h" #include "cmDocumentationEntry.h" #include "cmDuration.h" @@ -411,6 +415,11 @@ Json::Value cmake::ReportCapabilitiesJson() const obj["fileApi"] = cmFileAPI::ReportCapabilities(); obj["serverMode"] = false; obj["tls"] = static_cast<bool>(curlVersion->features & CURL_VERSION_SSL); +# ifdef CMake_ENABLE_DEBUGGER + obj["debugger"] = true; +# else + obj["debugger"] = false; +# endif return obj; } @@ -617,6 +626,13 @@ bool cmake::SetCacheArgs(const std::vector<std::string>& args) }; auto ScriptLambda = [&](std::string const& path, cmake* state) -> bool { +#ifdef CMake_ENABLE_DEBUGGER + // Script mode doesn't hit the usual code path in cmake::Run() that starts + // the debugger, so start it manually here instead. + if (!this->StartDebuggerIfEnabled()) { + return false; + } +#endif // Register fake project commands that hint misuse in script mode. GetProjectCommandsInScriptMode(state->GetState()); // Documented behavior of CMAKE{,_CURRENT}_{SOURCE,BINARY}_DIR is to be @@ -1233,7 +1249,52 @@ void cmake::SetArgs(const std::vector<std::string>& args) "CMAKE_COMPILE_WARNING_AS_ERROR variable.\n"; state->SetIgnoreWarningAsError(true); return true; - } } + } }, + CommandArgument{ "--debugger", CommandArgument::Values::Zero, + [](std::string const&, cmake* state) -> bool { +#ifdef CMake_ENABLE_DEBUGGER + std::cout << "Running with debugger on.\n"; + state->SetDebuggerOn(true); + return true; +#else + static_cast<void>(state); + cmSystemTools::Error( + "CMake was not built with support for --debugger"); + return false; +#endif + } }, + CommandArgument{ "--debugger-pipe", + "No path specified for --debugger-pipe", + CommandArgument::Values::One, + [](std::string const& value, cmake* state) -> bool { +#ifdef CMake_ENABLE_DEBUGGER + state->DebuggerPipe = value; + return true; +#else + static_cast<void>(value); + static_cast<void>(state); + cmSystemTools::Error("CMake was not built with support " + "for --debugger-pipe"); + return false; +#endif + } }, + CommandArgument{ + "--debugger-dap-log", "No file specified for --debugger-dap-log", + CommandArgument::Values::One, + [](std::string const& value, cmake* state) -> bool { +#ifdef CMake_ENABLE_DEBUGGER + std::string path = cmSystemTools::CollapseFullPath(value); + cmSystemTools::ConvertToUnixSlashes(path); + state->DebuggerDapLogFile = path; + return true; +#else + static_cast<void>(value); + static_cast<void>(state); + cmSystemTools::Error( + "CMake was not built with support for --debugger-dap-log"); + return false; +#endif + } }, }; #if defined(CMAKE_HAVE_VS_GENERATORS) @@ -2618,6 +2679,52 @@ void cmake::PreLoadCMakeFiles() } } +#ifdef CMake_ENABLE_DEBUGGER + +bool cmake::StartDebuggerIfEnabled() +{ + if (!this->GetDebuggerOn()) { + return true; + } + + if (DebugAdapter == nullptr) { + if (this->GetDebuggerPipe().empty()) { + std::cerr + << "Error: --debugger-pipe must be set when debugging is enabled.\n"; + return false; + } + + try { + DebugAdapter = std::make_shared<cmDebugger::cmDebuggerAdapter>( + std::make_shared<cmDebugger::cmDebuggerPipeConnection>( + this->GetDebuggerPipe()), + this->GetDebuggerDapLogFile()); + } catch (const std::runtime_error& error) { + std::cerr << "Error: Failed to create debugger adapter.\n"; + std::cerr << error.what() << "\n"; + return false; + } + Messenger->SetDebuggerAdapter(DebugAdapter); + } + + return true; +} + +void cmake::StopDebuggerIfNeeded(int exitCode) +{ + if (!this->GetDebuggerOn()) { + return; + } + + // The debug adapter may have failed to start (e.g. invalid pipe path). + if (DebugAdapter != nullptr) { + DebugAdapter->ReportExitCode(exitCode); + DebugAdapter.reset(); + } +} + +#endif + // handle a command line invocation int cmake::Run(const std::vector<std::string>& args, bool noconfigure) { @@ -2707,6 +2814,12 @@ int cmake::Run(const std::vector<std::string>& args, bool noconfigure) return 0; } +#ifdef CMake_ENABLE_DEBUGGER + if (!this->StartDebuggerIfEnabled()) { + return -1; + } +#endif + int ret = this->Configure(); if (ret) { #if defined(CMAKE_HAVE_VS_GENERATORS) |