summaryrefslogtreecommitdiffstats
path: root/Source/cmake.cxx
diff options
context:
space:
mode:
authorGlen Chung <kuchung@microsoft.com>2023-03-16 00:50:08 (GMT)
committerBrad King <brad.king@kitware.com>2023-05-30 13:46:12 (GMT)
commita9a592f96e6498da302f8e968be1db0ad3c32123 (patch)
tree0d75f16ee2eae99b1a3f063e575b3f5f8f2ee931 /Source/cmake.cxx
parentb0d1ddb7234950374977b83f8dbded806c15b356 (diff)
downloadCMake-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.cxx115
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)