Skip to content

Commit 9d85981

Browse files
Auto merge of #148685 - Zalathar:lldb-python, r=<try>
compiletest: Run the `lldb_batchmode.py` script in LLDB's embedded Python try-job: aarch64-apple
2 parents 4e0baae + 5a427eb commit 9d85981

File tree

10 files changed

+108
-110
lines changed

10 files changed

+108
-110
lines changed

bootstrap.example.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -320,7 +320,7 @@
320320
#build.npm = "npm"
321321

322322
# Python interpreter to use for various tasks throughout the build, notably
323-
# rustdoc tests, the lldb python interpreter, and some dist bits and pieces.
323+
# rustdoc tests, and some dist bits and pieces.
324324
#
325325
# Defaults to the Python interpreter used to execute x.py.
326326
#build.python = "python"

src/bootstrap/src/core/build_steps/test.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2094,11 +2094,11 @@ Please disable assertions with `rust.debug-assertions = false`.
20942094
cmd.arg("--gdb").arg(gdb);
20952095
}
20962096

2097-
if let Some(debuggers::Lldb { lldb_version, lldb_python_dir }) =
2097+
if let Some(debuggers::Lldb { lldb_exe, lldb_version }) =
20982098
debuggers::discover_lldb(builder)
20992099
{
2100+
cmd.arg("--lldb").arg(lldb_exe);
21002101
cmd.arg("--lldb-version").arg(lldb_version);
2101-
cmd.arg("--lldb-python-dir").arg(lldb_python_dir);
21022102
}
21032103
}
21042104

src/bootstrap/src/core/debuggers/lldb.rs

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@ use crate::core::builder::Builder;
44
use crate::utils::exec::command;
55

66
pub(crate) struct Lldb {
7+
pub(crate) lldb_exe: PathBuf,
78
pub(crate) lldb_version: String,
8-
pub(crate) lldb_python_dir: String,
99
}
1010

1111
pub(crate) fn discover_lldb(builder: &Builder<'_>) -> Option<Lldb> {
@@ -21,12 +21,5 @@ pub(crate) fn discover_lldb(builder: &Builder<'_>) -> Option<Lldb> {
2121
.stdout_if_ok()
2222
.and_then(|v| if v.trim().is_empty() { None } else { Some(v) })?;
2323

24-
let lldb_python_dir = command(&lldb_exe)
25-
.allow_failure()
26-
.arg("-P")
27-
.run_capture_stdout(builder)
28-
.stdout_if_ok()
29-
.map(|p| p.lines().next().expect("lldb Python dir not found").to_string())?;
30-
31-
Some(Lldb { lldb_version, lldb_python_dir })
24+
Some(Lldb { lldb_exe, lldb_version })
3225
}

src/etc/lldb_batchmode.py

Lines changed: 68 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -176,77 +176,85 @@ def watchdog():
176176
watchdog_thread.start()
177177

178178

179+
def get_env_arg(name):
180+
value = os.environ.get(name)
181+
if value is None:
182+
print("must set %s" % name)
183+
sys.exit(1)
184+
return value
185+
186+
179187
####################################################################################################
180188
# ~main
181189
####################################################################################################
182190

183191

184-
if len(sys.argv) != 3:
185-
print("usage: python lldb_batchmode.py target-path script-path")
186-
sys.exit(1)
192+
def main():
193+
target_path = get_env_arg("LLDB_BATCHMODE_TARGET_PATH")
194+
script_path = get_env_arg("LLDB_BATCHMODE_SCRIPT_PATH")
187195

188-
target_path = sys.argv[1]
189-
script_path = sys.argv[2]
196+
print("LLDB batch-mode script")
197+
print("----------------------")
198+
print("Debugger commands script is '%s'." % script_path)
199+
print("Target executable is '%s'." % target_path)
200+
print("Current working directory is '%s'" % os.getcwd())
190201

191-
print("LLDB batch-mode script")
192-
print("----------------------")
193-
print("Debugger commands script is '%s'." % script_path)
194-
print("Target executable is '%s'." % target_path)
195-
print("Current working directory is '%s'" % os.getcwd())
202+
# Start the timeout watchdog
203+
start_watchdog()
196204

197-
# Start the timeout watchdog
198-
start_watchdog()
205+
# Create a new debugger instance
206+
debugger = lldb.SBDebugger.Create()
199207

200-
# Create a new debugger instance
201-
debugger = lldb.SBDebugger.Create()
208+
# When we step or continue, don't return from the function until the process
209+
# stops. We do this by setting the async mode to false.
210+
debugger.SetAsync(False)
202211

203-
# When we step or continue, don't return from the function until the process
204-
# stops. We do this by setting the async mode to false.
205-
debugger.SetAsync(False)
212+
# Create a target from a file and arch
213+
print("Creating a target for '%s'" % target_path)
214+
target_error = lldb.SBError()
215+
target = debugger.CreateTarget(target_path, None, None, True, target_error)
206216

207-
# Create a target from a file and arch
208-
print("Creating a target for '%s'" % target_path)
209-
target_error = lldb.SBError()
210-
target = debugger.CreateTarget(target_path, None, None, True, target_error)
211-
212-
if not target:
213-
print(
214-
"Could not create debugging target '"
215-
+ target_path
216-
+ "': "
217-
+ str(target_error)
218-
+ ". Aborting.",
219-
file=sys.stderr,
220-
)
221-
sys.exit(1)
217+
if not target:
218+
print(
219+
"Could not create debugging target '"
220+
+ target_path
221+
+ "': "
222+
+ str(target_error)
223+
+ ". Aborting.",
224+
file=sys.stderr,
225+
)
226+
sys.exit(1)
222227

228+
# Register the breakpoint callback for every breakpoint
229+
start_breakpoint_listener(target)
223230

224-
# Register the breakpoint callback for every breakpoint
225-
start_breakpoint_listener(target)
231+
command_interpreter = debugger.GetCommandInterpreter()
226232

227-
command_interpreter = debugger.GetCommandInterpreter()
228-
229-
try:
230-
script_file = open(script_path, "r")
231-
232-
for line in script_file:
233-
command = line.strip()
234-
if (
235-
command == "run"
236-
or command == "r"
237-
or re.match(r"^process\s+launch.*", command)
238-
):
239-
# Before starting to run the program, let the thread sleep a bit, so all
240-
# breakpoint added events can be processed
241-
time.sleep(0.5)
242-
if command != "":
243-
execute_command(command_interpreter, command)
244-
245-
except IOError as e:
246-
print("Could not read debugging script '%s'." % script_path, file=sys.stderr)
247-
print(e, file=sys.stderr)
248-
print("Aborting.", file=sys.stderr)
249-
sys.exit(1)
250-
finally:
251-
debugger.Terminate()
252-
script_file.close()
233+
try:
234+
script_file = open(script_path, "r")
235+
236+
for line in script_file:
237+
command = line.strip()
238+
if (
239+
command == "run"
240+
or command == "r"
241+
or re.match(r"^process\s+launch.*", command)
242+
):
243+
# Before starting to run the program, let the thread sleep a bit, so all
244+
# breakpoint added events can be processed
245+
time.sleep(0.5)
246+
if command != "":
247+
execute_command(command_interpreter, command)
248+
249+
except IOError as e:
250+
print("Could not read debugging script '%s'." % script_path, file=sys.stderr)
251+
print(e, file=sys.stderr)
252+
print("Aborting.", file=sys.stderr)
253+
sys.exit(1)
254+
finally:
255+
debugger.Terminate()
256+
script_file.close()
257+
258+
259+
if __name__ == "__main__":
260+
main()

src/tools/compiletest/src/common.rs

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -311,10 +311,7 @@ pub struct Config {
311311
/// Path to the `src/tools/coverage-dump/` bootstrap tool executable.
312312
pub coverage_dump_path: Option<Utf8PathBuf>,
313313

314-
/// Path to the Python 3 executable to use for LLDB and htmldocck.
315-
///
316-
/// FIXME: the `lldb` setup currently requires I believe Python 3.10 **exactly**, it can't even
317-
/// be Python 3.11 or 3.9...
314+
/// Path to the Python 3 executable to use for htmldocck and some run-make tests.
318315
pub python: String,
319316

320317
/// Path to the `src/tools/jsondocck/` bootstrap tool executable.
@@ -540,6 +537,9 @@ pub struct Config {
540537
/// FIXME: `gdb_version` is *derived* from gdb, but it's *not* technically a config!
541538
pub gdb_version: Option<u32>,
542539

540+
/// Path to or name of the LLDB executable to use for debuginfo tests.
541+
pub lldb: Option<Utf8PathBuf>,
542+
543543
/// Version of LLDB.
544544
///
545545
/// FIXME: `lldb_version` is *derived* from lldb, but it's *not* technically a config!
@@ -586,11 +586,6 @@ pub struct Config {
586586
/// FIXME: take a look at this; this also influences adb in gdb code paths in a strange way.
587587
pub adb_device_status: bool,
588588

589-
/// Path containing LLDB's Python module.
590-
///
591-
/// FIXME: `PYTHONPATH` takes precedence over this flag...? See `runtest::run_lldb`.
592-
pub lldb_python_dir: Option<String>,
593-
594589
/// Verbose dump a lot of info.
595590
///
596591
/// FIXME: this is *way* too coarse; the user can't select *which* info to verbosely dump.

src/tools/compiletest/src/debuggers.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ pub(crate) fn configure_gdb(config: &Config) -> Option<Arc<Config>> {
4949
}
5050

5151
pub(crate) fn configure_lldb(config: &Config) -> Option<Arc<Config>> {
52-
config.lldb_python_dir.as_ref()?;
52+
config.lldb.as_ref()?;
5353

5454
Some(Arc::new(Config { debugger: Some(Debugger::Lldb), ..config.clone() }))
5555
}

src/tools/compiletest/src/lib.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -141,13 +141,13 @@ fn parse_config(args: Vec<String>) -> Config {
141141
.optopt("", "host", "the host to build for", "HOST")
142142
.optopt("", "cdb", "path to CDB to use for CDB debuginfo tests", "PATH")
143143
.optopt("", "gdb", "path to GDB to use for GDB debuginfo tests", "PATH")
144+
.optopt("", "lldb", "path to LLDB to use for LLDB debuginfo tests", "PATH")
144145
.optopt("", "lldb-version", "the version of LLDB used", "VERSION STRING")
145146
.optopt("", "llvm-version", "the version of LLVM used", "VERSION STRING")
146147
.optflag("", "system-llvm", "is LLVM the system LLVM")
147148
.optopt("", "android-cross-path", "Android NDK standalone path", "PATH")
148149
.optopt("", "adb-path", "path to the android debugger", "PATH")
149150
.optopt("", "adb-test-dir", "path to tests for the android debugger", "PATH")
150-
.optopt("", "lldb-python-dir", "directory containing LLDB's python module", "PATH")
151151
.reqopt("", "cc", "path to a C compiler", "PATH")
152152
.reqopt("", "cxx", "path to a C++ compiler", "PATH")
153153
.reqopt("", "cflags", "flags for the C compiler", "FLAGS")
@@ -264,6 +264,7 @@ fn parse_config(args: Vec<String>) -> Config {
264264
let gdb = debuggers::discover_gdb(matches.opt_str("gdb"), &target, &android_cross_path);
265265
let gdb_version = gdb.as_deref().and_then(debuggers::query_gdb_version);
266266
// FIXME: `lldb_version` is *derived* from lldb, but it's *not* technically a config!
267+
let lldb = matches.opt_str("lldb").map(Utf8PathBuf::from);
267268
let lldb_version =
268269
matches.opt_str("lldb-version").as_deref().and_then(debuggers::extract_lldb_version);
269270
let color = match matches.opt_str("color").as_deref() {
@@ -435,6 +436,7 @@ fn parse_config(args: Vec<String>) -> Config {
435436
cdb_version,
436437
gdb,
437438
gdb_version,
439+
lldb,
438440
lldb_version,
439441
llvm_version,
440442
system_llvm: matches.opt_present("system-llvm"),
@@ -444,7 +446,6 @@ fn parse_config(args: Vec<String>) -> Config {
444446
adb_device_status: opt_str2(matches.opt_str("target")).contains("android")
445447
&& "(none)" != opt_str2(matches.opt_str("adb-test-dir"))
446448
&& !opt_str2(matches.opt_str("adb-test-dir")).is_empty(),
447-
lldb_python_dir: matches.opt_str("lldb-python-dir"),
448449
verbose: matches.opt_present("verbose"),
449450
only_modified: matches.opt_present("only-modified"),
450451
color,

src/tools/compiletest/src/runtest.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -200,10 +200,11 @@ pub fn compute_stamp_hash(config: &Config) -> String {
200200
}
201201

202202
Some(Debugger::Lldb) => {
203-
config.python.hash(&mut hash);
204-
config.lldb_python_dir.hash(&mut hash);
203+
// LLDB debuginfo tests now use LLDB's embedded Python, with an
204+
// explicit PYTHONPATH, so they don't depend on `--python` or
205+
// the ambient PYTHONPATH.
206+
config.lldb.hash(&mut hash);
205207
env::var_os("PATH").hash(&mut hash);
206-
env::var_os("PYTHONPATH").hash(&mut hash);
207208
}
208209

209210
None => {}

src/tools/compiletest/src/runtest/debuginfo.rs

Lines changed: 22 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -326,9 +326,9 @@ impl TestCx<'_> {
326326
}
327327

328328
fn run_debuginfo_lldb_test(&self) {
329-
if self.config.lldb_python_dir.is_none() {
330-
self.fatal("Can't run LLDB test because LLDB's python path is not set.");
331-
}
329+
let Some(ref lldb) = self.config.lldb else {
330+
self.fatal("Can't run LLDB test because LLDB's path is not set.");
331+
};
332332

333333
// compile test file (it should have 'compile-flags:-g' in the directive)
334334
let should_run = self.run_if_enabled();
@@ -434,7 +434,7 @@ impl TestCx<'_> {
434434
let debugger_script = self.make_out_name("debugger.script");
435435

436436
// Let LLDB execute the script via lldb_batchmode.py
437-
let debugger_run_result = self.run_lldb(&exe_file, &debugger_script);
437+
let debugger_run_result = self.run_lldb(lldb, &exe_file, &debugger_script);
438438

439439
if !debugger_run_result.status.success() {
440440
self.fatal_proc_rec("Error while running LLDB", &debugger_run_result);
@@ -445,23 +445,23 @@ impl TestCx<'_> {
445445
}
446446
}
447447

448-
fn run_lldb(&self, test_executable: &Utf8Path, debugger_script: &Utf8Path) -> ProcRes {
449-
// Prepare the lldb_batchmode which executes the debugger script
450-
let lldb_script_path = self.config.src_root.join("src/etc/lldb_batchmode.py");
451-
452-
// FIXME: `PYTHONPATH` takes precedence over the flag...?
453-
let pythonpath = if let Ok(pp) = std::env::var("PYTHONPATH") {
454-
format!("{pp}:{}", self.config.lldb_python_dir.as_ref().unwrap())
455-
} else {
456-
self.config.lldb_python_dir.clone().unwrap()
457-
};
458-
self.run_command_to_procres(
459-
Command::new(&self.config.python)
460-
.arg(&lldb_script_path)
461-
.arg(test_executable)
462-
.arg(debugger_script)
463-
.env("PYTHONUNBUFFERED", "1") // Help debugging #78665
464-
.env("PYTHONPATH", pythonpath),
465-
)
448+
fn run_lldb(
449+
&self,
450+
lldb: &Utf8Path,
451+
test_executable: &Utf8Path,
452+
debugger_script: &Utf8Path,
453+
) -> ProcRes {
454+
// Path containing `lldb_batchmode.py`, so that the `script` command can import it.
455+
let pythonpath = self.config.src_root.join("src/etc");
456+
457+
let mut cmd = Command::new(lldb);
458+
cmd.arg("--one-line")
459+
.arg("script -- import lldb_batchmode; lldb_batchmode.main()")
460+
.env("LLDB_BATCHMODE_TARGET_PATH", test_executable)
461+
.env("LLDB_BATCHMODE_SCRIPT_PATH", debugger_script)
462+
.env("PYTHONUNBUFFERED", "1") // Help debugging #78665
463+
.env("PYTHONPATH", pythonpath);
464+
465+
self.run_command_to_procres(&mut cmd)
466466
}
467467
}

src/tools/compiletest/src/rustdoc_gui_test.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,14 +99,14 @@ fn incomplete_config_for_rustdoc_gui_test() -> Config {
9999
cdb_version: Default::default(),
100100
gdb: Default::default(),
101101
gdb_version: Default::default(),
102+
lldb: Default::default(),
102103
lldb_version: Default::default(),
103104
llvm_version: Default::default(),
104105
system_llvm: Default::default(),
105106
android_cross_path: Default::default(),
106107
adb_path: Default::default(),
107108
adb_test_dir: Default::default(),
108109
adb_device_status: Default::default(),
109-
lldb_python_dir: Default::default(),
110110
verbose: Default::default(),
111111
color: Default::default(),
112112
remote_test_client: Default::default(),

0 commit comments

Comments
 (0)