diff options
Diffstat (limited to 'Source/cmake.cxx')
-rw-r--r-- | Source/cmake.cxx | 135 |
1 files changed, 125 insertions, 10 deletions
diff --git a/Source/cmake.cxx b/Source/cmake.cxx index 284c5e7..f30d4d3 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) @@ -2205,7 +2266,7 @@ int cmake::HandleDeleteCacheVariables(const std::string& var) this->LoadCache(); // restore the changed compilers for (SaveCacheEntry const& i : saved) { - this->AddCacheEntry(i.key, i.value, i.help.c_str(), i.type); + this->AddCacheEntry(i.key, i.value, i.help, i.type); } cmSystemTools::Message(warning.str()); // avoid reconfigure if there were errors @@ -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) @@ -2775,7 +2888,7 @@ int cmake::Generate() } void cmake::AddCacheEntry(const std::string& key, cmValue value, - const char* helpString, int type) + cmValue helpString, int type) { this->State->AddCacheEntry(key, value, helpString, static_cast<cmStateEnums::CacheEntryType>(type)); @@ -3261,10 +3374,6 @@ void cmake::GenerateGraphViz(const std::string& fileName) const #endif } -void cmake::SetProperty(const std::string& prop, const char* value) -{ - this->State->SetGlobalProperty(prop, value); -} void cmake::SetProperty(const std::string& prop, cmValue value) { this->State->SetGlobalProperty(prop, value); @@ -3623,7 +3732,6 @@ int cmake::Build(int jobs, std::string dir, std::vector<std::string> targets, return 1; } } - std::string output; std::string projName; cmValue cachedProjectName = this->State->GetCacheEntryValue("CMAKE_PROJECT_NAME"); @@ -3697,10 +3805,17 @@ int cmake::Build(int jobs, std::string dir, std::vector<std::string> targets, } this->GlobalGenerator->PrintBuildCommandAdvice(std::cerr, jobs); - return this->GlobalGenerator->Build( - jobs, "", dir, projName, targets, output, "", config, buildOptions, + std::stringstream ostr; + // `cmGlobalGenerator::Build` logs metadata about what directory and commands + // are being executed to the `output` parameter. If CMake is verbose, print + // this out. + std::ostream& verbose_ostr = verbose ? std::cout : ostr; + int buildresult = this->GlobalGenerator->Build( + jobs, "", dir, projName, targets, verbose_ostr, "", config, buildOptions, verbose, cmDuration::zero(), cmSystemTools::OUTPUT_PASSTHROUGH, nativeOptions); + + return buildresult; } bool cmake::Open(const std::string& dir, bool dryRun) |