[lldb] Dump build configuration with version -v (#170772)

Add a verbose option to the version command and include the "build
configuration" in the command output. This allows users to quickly
identify if their version of LLDB was built with support for
xml/curl/python/lua etc. This data is already available through the SB
API using SBDebugger::GetBuildConfiguration, but this makes it more
discoverable.

```
(lldb) version -v
lldb version 22.0.0git (git@github.com:llvm/llvm-project.git revision 21a2aac5e5456f9181384406f3b3fcad621a7076)
  clang revision 21a2aac5e5456f9181384406f3b3fcad621a7076
  llvm revision 21a2aac5e5456f9181384406f3b3fcad621a7076
  editline_wchar: yes
  lzma: yes
  curses: yes
  editline: yes
  fbsdvmcore: yes
  xml: yes
  lua: yes
  python: yes
  targets: [AArch64, AMDGPU, ARM, AVR, BPF, Hexagon, Lanai, LoongArch, Mips, MSP430, NVPTX, PowerPC, RISCV, Sparc, SPIRV, SystemZ, VE, WebAssembly, X86, XCore]
  curl: yes
```

Resolves #170727
This commit is contained in:
Jonas Devlieghere
2025-12-08 10:11:39 -08:00
committed by GitHub
parent 3e008cb333
commit bc9f96a5e6
7 changed files with 155 additions and 54 deletions

View File

@@ -107,6 +107,9 @@ public:
static void Destroy(lldb::DebuggerSP &debugger_sp);
/// Get the build configuration as structured data.
static StructuredData::DictionarySP GetBuildConfiguration();
static lldb::DebuggerSP FindDebuggerWithID(lldb::user_id_t id);
static lldb::DebuggerSP

View File

@@ -709,61 +709,11 @@ const char *SBDebugger::StateAsCString(StateType state) {
return lldb_private::StateAsCString(state);
}
static void AddBoolConfigEntry(StructuredData::Dictionary &dict,
llvm::StringRef name, bool value,
llvm::StringRef description) {
auto entry_up = std::make_unique<StructuredData::Dictionary>();
entry_up->AddBooleanItem("value", value);
entry_up->AddStringItem("description", description);
dict.AddItem(name, std::move(entry_up));
}
static void AddLLVMTargets(StructuredData::Dictionary &dict) {
auto array_up = std::make_unique<StructuredData::Array>();
#define LLVM_TARGET(target) \
array_up->AddItem(std::make_unique<StructuredData::String>(#target));
#include "llvm/Config/Targets.def"
auto entry_up = std::make_unique<StructuredData::Dictionary>();
entry_up->AddItem("value", std::move(array_up));
entry_up->AddStringItem("description", "A list of configured LLVM targets.");
dict.AddItem("targets", std::move(entry_up));
}
SBStructuredData SBDebugger::GetBuildConfiguration() {
LLDB_INSTRUMENT();
auto config_up = std::make_unique<StructuredData::Dictionary>();
AddBoolConfigEntry(
*config_up, "xml", XMLDocument::XMLEnabled(),
"A boolean value that indicates if XML support is enabled in LLDB");
AddBoolConfigEntry(
*config_up, "curl", LLVM_ENABLE_CURL,
"A boolean value that indicates if CURL support is enabled in LLDB");
AddBoolConfigEntry(
*config_up, "curses", LLDB_ENABLE_CURSES,
"A boolean value that indicates if curses support is enabled in LLDB");
AddBoolConfigEntry(
*config_up, "editline", LLDB_ENABLE_LIBEDIT,
"A boolean value that indicates if editline support is enabled in LLDB");
AddBoolConfigEntry(*config_up, "editline_wchar", LLDB_EDITLINE_USE_WCHAR,
"A boolean value that indicates if editline wide "
"characters support is enabled in LLDB");
AddBoolConfigEntry(
*config_up, "lzma", LLDB_ENABLE_LZMA,
"A boolean value that indicates if lzma support is enabled in LLDB");
AddBoolConfigEntry(
*config_up, "python", LLDB_ENABLE_PYTHON,
"A boolean value that indicates if python support is enabled in LLDB");
AddBoolConfigEntry(
*config_up, "lua", LLDB_ENABLE_LUA,
"A boolean value that indicates if lua support is enabled in LLDB");
AddBoolConfigEntry(*config_up, "fbsdvmcore", LLDB_ENABLE_FBSDVMCORE,
"A boolean value that indicates if fbsdvmcore support is "
"enabled in LLDB");
AddLLVMTargets(*config_up);
SBStructuredData data;
data.m_impl_up->SetObjectSP(std::move(config_up));
data.m_impl_up->SetObjectSP(Debugger::GetBuildConfiguration());
return data;
}

View File

@@ -8,13 +8,21 @@
#include "CommandObjectVersion.h"
#include "lldb/Core/Debugger.h"
#include "lldb/Interpreter/CommandReturnObject.h"
#include "lldb/Version/Version.h"
#include "llvm/ADT/StringExtras.h"
using namespace lldb;
using namespace lldb_private;
// CommandObjectVersion
#define LLDB_OPTIONS_version
#include "CommandOptions.inc"
llvm::ArrayRef<OptionDefinition>
CommandObjectVersion::CommandOptions::GetDefinitions() {
return llvm::ArrayRef(g_version_options);
}
CommandObjectVersion::CommandObjectVersion(CommandInterpreter &interpreter)
: CommandObjectParsed(interpreter, "version",
@@ -22,7 +30,45 @@ CommandObjectVersion::CommandObjectVersion(CommandInterpreter &interpreter)
CommandObjectVersion::~CommandObjectVersion() = default;
// Dump the array values on a single line.
static void dump(const StructuredData::Array &array, Stream &s) {
std::vector<std::string> values;
array.ForEach([&](StructuredData::Object *object) -> bool {
values.emplace_back(object->GetStringValue().str());
return true;
});
s << '[' << llvm::join(values, ", ") << ']';
}
// The default dump output is too verbose.
static void dump(const StructuredData::Dictionary &config, Stream &s) {
config.ForEach(
[&](llvm::StringRef key, StructuredData::Object *object) -> bool {
assert(object);
StructuredData::Dictionary *value_dict = object->GetAsDictionary();
assert(value_dict);
StructuredData::ObjectSP value_sp = value_dict->GetValueForKey("value");
assert(value_sp);
s << " " << key << ": ";
if (StructuredData::Boolean *boolean = value_sp->GetAsBoolean())
s << (boolean ? "yes" : "no");
else if (StructuredData::Array *array = value_sp->GetAsArray())
dump(*array, s);
s << '\n';
return true;
});
}
void CommandObjectVersion::DoExecute(Args &args, CommandReturnObject &result) {
result.AppendMessageWithFormat("%s\n", lldb_private::GetVersion());
if (m_options.verbose)
dump(*Debugger::GetBuildConfiguration(), result.GetOutputStream());
result.SetStatus(eReturnStatusSuccessFinishResult);
}

View File

@@ -9,20 +9,56 @@
#ifndef LLDB_SOURCE_COMMANDS_COMMANDOBJECTVERSION_H
#define LLDB_SOURCE_COMMANDS_COMMANDOBJECTVERSION_H
#include "lldb/Host/OptionParser.h"
#include "lldb/Interpreter/CommandObject.h"
#include "lldb/Interpreter/Options.h"
namespace lldb_private {
// CommandObjectVersion
class CommandObjectVersion : public CommandObjectParsed {
public:
CommandObjectVersion(CommandInterpreter &interpreter);
~CommandObjectVersion() override;
class CommandOptions : public Options {
public:
CommandOptions() = default;
~CommandOptions() override = default;
Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
ExecutionContext *execution_context) override {
Status error;
const int short_option = m_getopt_table[option_idx].val;
switch (short_option) {
case 'v':
verbose = true;
break;
default:
llvm_unreachable("Unimplemented option");
}
return error;
}
void OptionParsingStarting(ExecutionContext *execution_context) override {
verbose = false;
}
llvm::ArrayRef<OptionDefinition> GetDefinitions() override;
bool verbose;
};
Options *GetOptions() override { return &m_options; }
protected:
void DoExecute(Args &args, CommandReturnObject &result) override;
private:
CommandOptions m_options;
};
} // namespace lldb_private

View File

@@ -2558,3 +2558,8 @@ let Command = "statistics dump" in {
"enabled state. Defaults to true for both summary and default "
"mode.">;
}
let Command = "version" in {
def version_verbose : Option<"verbose", "v">,
Desc<"Include build configuration in version output.">;
}

View File

@@ -21,12 +21,14 @@
#include "lldb/Core/Telemetry.h"
#include "lldb/DataFormatters/DataVisualization.h"
#include "lldb/Expression/REPL.h"
#include "lldb/Host/Config.h"
#include "lldb/Host/File.h"
#include "lldb/Host/FileSystem.h"
#include "lldb/Host/HostInfo.h"
#include "lldb/Host/StreamFile.h"
#include "lldb/Host/Terminal.h"
#include "lldb/Host/ThreadLauncher.h"
#include "lldb/Host/XML.h"
#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Interpreter/CommandReturnObject.h"
#include "lldb/Interpreter/OptionValue.h"
@@ -2442,3 +2444,56 @@ llvm::ThreadPoolInterface &Debugger::GetThreadPool() {
"Debugger::GetThreadPool called before Debugger::Initialize");
return *g_thread_pool;
}
static void AddBoolConfigEntry(StructuredData::Dictionary &dict,
llvm::StringRef name, bool value,
llvm::StringRef description) {
auto entry_up = std::make_unique<StructuredData::Dictionary>();
entry_up->AddBooleanItem("value", value);
entry_up->AddStringItem("description", description);
dict.AddItem(name, std::move(entry_up));
}
static void AddLLVMTargets(StructuredData::Dictionary &dict) {
auto array_up = std::make_unique<StructuredData::Array>();
#define LLVM_TARGET(target) \
array_up->AddItem(std::make_unique<StructuredData::String>(#target));
#include "llvm/Config/Targets.def"
auto entry_up = std::make_unique<StructuredData::Dictionary>();
entry_up->AddItem("value", std::move(array_up));
entry_up->AddStringItem("description", "A list of configured LLVM targets.");
dict.AddItem("targets", std::move(entry_up));
}
StructuredData::DictionarySP Debugger::GetBuildConfiguration() {
auto config_up = std::make_unique<StructuredData::Dictionary>();
AddBoolConfigEntry(
*config_up, "xml", XMLDocument::XMLEnabled(),
"A boolean value that indicates if XML support is enabled in LLDB");
AddBoolConfigEntry(
*config_up, "curl", LLVM_ENABLE_CURL,
"A boolean value that indicates if CURL support is enabled in LLDB");
AddBoolConfigEntry(
*config_up, "curses", LLDB_ENABLE_CURSES,
"A boolean value that indicates if curses support is enabled in LLDB");
AddBoolConfigEntry(
*config_up, "editline", LLDB_ENABLE_LIBEDIT,
"A boolean value that indicates if editline support is enabled in LLDB");
AddBoolConfigEntry(*config_up, "editline_wchar", LLDB_EDITLINE_USE_WCHAR,
"A boolean value that indicates if editline wide "
"characters support is enabled in LLDB");
AddBoolConfigEntry(
*config_up, "lzma", LLDB_ENABLE_LZMA,
"A boolean value that indicates if lzma support is enabled in LLDB");
AddBoolConfigEntry(
*config_up, "python", LLDB_ENABLE_PYTHON,
"A boolean value that indicates if python support is enabled in LLDB");
AddBoolConfigEntry(
*config_up, "lua", LLDB_ENABLE_LUA,
"A boolean value that indicates if lua support is enabled in LLDB");
AddBoolConfigEntry(*config_up, "fbsdvmcore", LLDB_ENABLE_FBSDVMCORE,
"A boolean value that indicates if fbsdvmcore support is "
"enabled in LLDB");
AddLLVMTargets(*config_up);
return config_up;
}

View File

@@ -0,0 +1,6 @@
RUN: %lldb -b -o 'version -v' | FileCheck %s
CHECK: lldb version
CHECK: xml: {{yes|no}}
CHECK: python: {{yes|no}}
CHECK: targets: [{{.*}}]