From 58c4b3ce4ae067c054bcb57a6890701eb827ef62 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=AE=B8=E6=9D=B0=E5=8F=8B=20Jieyou=20Xu=20=28Joe=29?= <39484203+jieyouxu@users.noreply.github.com> Date: Wed, 15 Jan 2025 19:23:07 +0800 Subject: [PATCH] tests: port `split-debuginfo` to rmake.rs Co-authored-by: Oneirical --- .../tidy/src/allowed_run_make_makefiles.txt | 1 - tests/run-make/split-debuginfo/Makefile | 368 ---- tests/run-make/split-debuginfo/rmake.rs | 1618 +++++++++++++++++ 3 files changed, 1618 insertions(+), 369 deletions(-) delete mode 100644 tests/run-make/split-debuginfo/Makefile create mode 100644 tests/run-make/split-debuginfo/rmake.rs diff --git a/src/tools/tidy/src/allowed_run_make_makefiles.txt b/src/tools/tidy/src/allowed_run_make_makefiles.txt index 45b40b17ea3..e69de29bb2d 100644 --- a/src/tools/tidy/src/allowed_run_make_makefiles.txt +++ b/src/tools/tidy/src/allowed_run_make_makefiles.txt @@ -1 +0,0 @@ -run-make/split-debuginfo/Makefile diff --git a/tests/run-make/split-debuginfo/Makefile b/tests/run-make/split-debuginfo/Makefile deleted file mode 100644 index abb1fab7141..00000000000 --- a/tests/run-make/split-debuginfo/Makefile +++ /dev/null @@ -1,368 +0,0 @@ -# ignore-cross-compile -# ignore-riscv64 On this platform only `-Csplit-debuginfo=off` is supported, see #120518 - -include ../tools.mk - -all: off packed unpacked - -ifeq ($(UNAME),Darwin) - # If disabled, don't run `dsymutil`. - off: - rm -rf $(TMPDIR)/*.dSYM - $(RUSTC) foo.rs -g -C split-debuginfo=off - [ ! -d $(TMPDIR)/foo.dSYM ] - - # Packed by default, but only if debuginfo is requested - packed: - rm -rf $(TMPDIR)/*.dSYM - $(RUSTC) foo.rs - [ ! -d $(TMPDIR)/foo.dSYM ] - rm -rf $(TMPDIR)/*.dSYM - $(RUSTC) foo.rs -g - [ -d $(TMPDIR)/foo.dSYM ] - rm -rf $(TMPDIR)/*.dSYM - $(RUSTC) foo.rs -g -C split-debuginfo=packed - [ -d $(TMPDIR)/foo.dSYM ] - rm -rf $(TMPDIR)/*.dSYM - - # Object files are preserved with unpacked and `dsymutil` isn't run - unpacked: - $(RUSTC) foo.rs -g -C split-debuginfo=unpacked - ls $(TMPDIR)/*.o - [ ! -d $(TMPDIR)/foo.dSYM ] -else ifdef IS_WINDOWS - # Windows only supports packed debuginfo - nothing to test. - off: - packed: - unpacked: -else # Some non-Windows, non-Darwin platforms are not stable, and some are. - ifeq ($(UNAME),Linux) - UNSTABLEOPTS := - else - UNSTABLEOPTS := -Zunstable-options - endif - - # - Debuginfo in `.o` files - # - `.o` deleted - # - `.dwo` never created - # - `.dwp` never created - off: - $(RUSTC) foo.rs -g $(UNSTABLEOPTS) -C split-debuginfo=off - [ ! -f $(TMPDIR)/*.dwp ] - [ ! -f $(TMPDIR)/*.dwo ] - $(RUSTC) foo.rs -g - [ ! -f $(TMPDIR)/*.dwp ] - [ ! -f $(TMPDIR)/*.dwo ] - - packed: packed-split packed-single packed-lto packed-remapped packed-crosscrate - - # - Debuginfo in `.dwo` files - # - `.o` deleted - # - `.dwo` deleted - # - `.dwp` present - packed-split: - $(RUSTC) foo.rs -g $(UNSTABLEOPTS) -C split-debuginfo=packed -Zsplit-dwarf-kind=split - ls $(TMPDIR)/*.o && exit 1 || exit 0 - ls $(TMPDIR)/*.dwo && exit 1 || exit 0 - rm $(TMPDIR)/foo.dwp - rm $(TMPDIR)/$(call BIN,foo) - - # - Debuginfo in `.o` files - # - `.o` deleted - # - `.dwo` never created - # - `.dwp` present - packed-single: - $(RUSTC) foo.rs -g $(UNSTABLEOPTS) -C split-debuginfo=packed -Zsplit-dwarf-kind=single - ls $(TMPDIR)/*.o && exit 1 || exit 0 - ls $(TMPDIR)/*.dwo && exit 1 || exit 0 - rm $(TMPDIR)/foo.dwp - rm $(TMPDIR)/$(call BIN,foo) - - packed-lto: packed-lto-split packed-lto-single - - # - rmeta file added to rlib, no object files are generated and thus no debuginfo is generated - # - `.o` never created - # - `.dwo` never created - # - `.dwp` never created - packed-lto-split: - $(RUSTC) baz.rs -g $(UNSTABLEOPTS) -Csplit-debuginfo=packed -Zsplit-dwarf-kind=split \ - --crate-type=rlib -Clinker-plugin-lto - ls $(TMPDIR)/*.o && exit 1 || exit 0 - ls $(TMPDIR)/*.dwo && exit 1 || exit 0 - ls $(TMPDIR)/*.dwp && exit 1 || exit 0 - rm $(TMPDIR)/libbaz.rlib - - # - rmeta file added to rlib, no object files are generated and thus no debuginfo is generated - # - `.o` never created - # - `.dwo` never created - # - `.dwp` never created - packed-lto-single: - $(RUSTC) baz.rs -g $(UNSTABLEOPTS) -Csplit-debuginfo=packed -Zsplit-dwarf-kind=single \ - --crate-type=rlib -Clinker-plugin-lto - ls $(TMPDIR)/*.o && exit 1 || exit 0 - ls $(TMPDIR)/*.dwo && exit 1 || exit 0 - ls $(TMPDIR)/*.dwp && exit 1 || exit 0 - rm $(TMPDIR)/libbaz.rlib - - packed-remapped: packed-remapped-split packed-remapped-single packed-remapped-scope packed-remapped-wrong-scope - - # - Debuginfo in `.dwo` files - # - `.o` and binary refer to remapped `.dwo` paths which do not exist - # - `.o` deleted - # - `.dwo` deleted - # - `.dwp` present - packed-remapped-split: - $(RUSTC) $(UNSTABLEOPTS) -C split-debuginfo=packed -g \ - -Z split-dwarf-kind=split --remap-path-prefix $(TMPDIR)=/a foo.rs - objdump -Wi $(TMPDIR)/foo | grep DW_AT_GNU_dwo_name | (! grep $(TMPDIR)) || exit 1 - ls $(TMPDIR)/*.o && exit 1 || exit 0 - ls $(TMPDIR)/*.dwo && exit 1 || exit 0 - rm $(TMPDIR)/foo.dwp - rm $(TMPDIR)/$(call BIN,foo) - - # - Debuginfo in `.o` files - # - `.o` and binary refer to remapped `.o` paths which do not exist - # - `.o` deleted - # - `.dwo` never created - # - `.dwp` present - packed-remapped-single: - $(RUSTC) $(UNSTABLEOPTS) -C split-debuginfo=packed -g \ - -Z split-dwarf-kind=single --remap-path-prefix $(TMPDIR)=/a foo.rs - objdump -Wi $(TMPDIR)/foo | grep DW_AT_GNU_dwo_name | (! grep $(TMPDIR)) || exit 1 - ls $(TMPDIR)/*.o && exit 1 || exit 0 - ls $(TMPDIR)/*.dwo && exit 1 || exit 0 - rm $(TMPDIR)/foo.dwp - rm $(TMPDIR)/$(call BIN,foo) - - # - Debuginfo in `.o` files - # - `.o` and binary refer to remapped `.o` paths which do not exist - # - `.o` deleted - # - `.dwo` never created - # - `.dwp` present - packed-remapped-scope: - $(RUSTC) $(UNSTABLEOPTS) -C split-debuginfo=packed -g \ - -Z split-dwarf-kind=single --remap-path-prefix $(TMPDIR)=/a \ - -Z remap-path-scope=debuginfo foo.rs - objdump -Wi $(TMPDIR)/foo | grep DW_AT_GNU_dwo_name | (! grep $(TMPDIR)) || exit 1 - ls $(TMPDIR)/*.o && exit 1 || exit 0 - ls $(TMPDIR)/*.dwo && exit 1 || exit 0 - rm $(TMPDIR)/foo.dwp - rm $(TMPDIR)/$(call BIN,foo) - - # - Debuginfo in `.o` files - # - `.o` and binary refer to un-remapped `.o` because the remap path scope is for macros. - # - `.o` deleted - # - `.dwo` never created - # - `.dwp` present - packed-remapped-wrong-scope: - $(RUSTC) $(UNSTABLEOPTS) -C split-debuginfo=packed -g \ - -Z split-dwarf-kind=single --remap-path-prefix $(TMPDIR)=/a \ - -Z remap-path-scope=macro foo.rs - objdump -Wi $(TMPDIR)/foo | grep DW_AT_GNU_dwo_name | (grep $(TMPDIR)) || exit 1 - ls $(TMPDIR)/*.o && exit 1 || exit 0 - ls $(TMPDIR)/*.dwo && exit 1 || exit 0 - rm $(TMPDIR)/foo.dwp - rm $(TMPDIR)/$(call BIN,foo) - - packed-crosscrate: packed-crosscrate-split packed-crosscrate-single - - # - Debuginfo in `.dwo` files - # - (bar) `.rlib` file created, contains `.dwo` - # - (bar) `.o` deleted - # - (bar) `.dwo` deleted - # - (bar) `.dwp` never created - # - (main) `.o` deleted - # - (main) `.dwo` deleted - # - (main) `.dwp` present - packed-crosscrate-split: - $(RUSTC) --crate-type lib $(UNSTABLEOPTS) -C split-debuginfo=packed \ - -Zsplit-dwarf-kind=split -g bar.rs - ls $(TMPDIR)/*.rlib - ls $(TMPDIR)/*.o && exit 1 || exit 0 - ls $(TMPDIR)/*.dwo && exit 1 || exit 0 - ls $(TMPDIR)/*.dwp && exit 1 || exit 0 - $(RUSTC) --extern bar=$(TMPDIR)/libbar.rlib $(UNSTABLEOPTS) \ - -C split-debuginfo=packed -Zsplit-dwarf-kind=split -g main.rs - ls $(TMPDIR)/*.o && exit 1 || exit 0 - ls $(TMPDIR)/*.dwo && exit 1 || exit 0 - rm $(TMPDIR)/main.dwp - rm $(TMPDIR)/$(call BIN,main) - - # - Debuginfo in `.o` files - # - (bar) `.rlib` file created, contains `.o` - # - (bar) `.o` deleted - # - (bar) `.dwo` never created - # - (bar) `.dwp` never created - # - (main) `.o` deleted - # - (main) `.dwo` never created - # - (main) `.dwp` present - packed-crosscrate-single: - $(RUSTC) --crate-type lib $(UNSTABLEOPTS) -C split-debuginfo=packed \ - -Zsplit-dwarf-kind=single -g bar.rs - ls $(TMPDIR)/*.rlib - ls $(TMPDIR)/*.o && exit 1 || exit 0 - ls $(TMPDIR)/*.dwo && exit 1 || exit 0 - ls $(TMPDIR)/*.dwp && exit 1 || exit 0 - $(RUSTC) --extern bar=$(TMPDIR)/libbar.rlib $(UNSTABLEOPTS) \ - -C split-debuginfo=packed -Zsplit-dwarf-kind=single -g main.rs - ls $(TMPDIR)/*.o && exit 1 || exit 0 - ls $(TMPDIR)/*.dwo && exit 1 || exit 0 - rm $(TMPDIR)/main.dwp - rm $(TMPDIR)/$(call BIN,main) - - unpacked: unpacked-split unpacked-single unpacked-lto unpacked-remapped unpacked-crosscrate - - # - Debuginfo in `.dwo` files - # - `.o` deleted - # - `.dwo` present - # - `.dwp` never created - unpacked-split: - $(RUSTC) foo.rs -g $(UNSTABLEOPTS) -C split-debuginfo=unpacked -Zsplit-dwarf-kind=split - ls $(TMPDIR)/*.o && exit 1 || exit 0 - rm $(TMPDIR)/*.dwo - ls $(TMPDIR)/*.dwp && exit 1 || exit 0 - rm $(TMPDIR)/$(call BIN,foo) - - # - Debuginfo in `.o` files - # - `.o` present - # - `.dwo` never created - # - `.dwp` never created - unpacked-single: - $(RUSTC) foo.rs -g $(UNSTABLEOPTS) -C split-debuginfo=unpacked -Zsplit-dwarf-kind=single - ls $(TMPDIR)/*.o - ls $(TMPDIR)/*.dwo && exit 1 || exit 0 - ls $(TMPDIR)/*.dwp && exit 1 || exit 0 - rm $(TMPDIR)/$(call BIN,foo) - - unpacked-lto: unpacked-lto-split unpacked-lto-single - - # - rmeta file added to rlib, no object files are generated and thus no debuginfo is generated - # - `.o` not present - # - `.dwo` never created - # - `.dwp` never created - unpacked-lto-split: - $(RUSTC) baz.rs -g $(UNSTABLEOPTS) -Csplit-debuginfo=unpacked -Zsplit-dwarf-kind=split \ - --crate-type=rlib -Clinker-plugin-lto - rm $(TMPDIR)/*.o - ls $(TMPDIR)/*.dwo && exit 1 || exit 0 - ls $(TMPDIR)/*.dwp && exit 1 || exit 0 - rm $(TMPDIR)/libbaz.rlib - - # - rmeta file added to rlib, no object files are generated and thus no debuginfo is generated - # - `.o` present (bitcode) - # - `.dwo` never created - # - `.dwp` never created - unpacked-lto-single: - $(RUSTC) baz.rs -g $(UNSTABLEOPTS) -Csplit-debuginfo=unpacked -Zsplit-dwarf-kind=single \ - --crate-type=rlib -Clinker-plugin-lto - rm $(TMPDIR)/*.o - ls $(TMPDIR)/*.dwo && exit 1 || exit 0 - ls $(TMPDIR)/*.dwp && exit 1 || exit 0 - rm $(TMPDIR)/libbaz.rlib - - unpacked-remapped: unpacked-remapped-split unpacked-remapped-single unpacked-remapped-scope unpacked-remapped-wrong-scope - - # - Debuginfo in `.dwo` files - # - `.o` and binary refer to remapped `.dwo` paths which do not exist - # - `.o` deleted - # - `.dwo` present - # - `.dwp` never created - unpacked-remapped-split: - $(RUSTC) $(UNSTABLEOPTS) -C split-debuginfo=unpacked -g \ - -Z split-dwarf-kind=split --remap-path-prefix $(TMPDIR)=/a foo.rs - objdump -Wi $(TMPDIR)/foo | grep DW_AT_GNU_dwo_name | (! grep $(TMPDIR)) || exit 1 - ls $(TMPDIR)/*.o && exit 1 || exit 0 - rm $(TMPDIR)/*.dwo - ls $(TMPDIR)/*.dwp && exit 1 || exit 0 - rm $(TMPDIR)/$(call BIN,foo) - - # - Debuginfo in `.o` files - # - `.o` and binary refer to remapped `.o` paths which do not exist - # - `.o` present - # - `.dwo` never created - # - `.dwp` never created - unpacked-remapped-single: - $(RUSTC) $(UNSTABLEOPTS) -C split-debuginfo=unpacked -g \ - -Z split-dwarf-kind=single --remap-path-prefix $(TMPDIR)=/a foo.rs - objdump -Wi $(TMPDIR)/foo | grep DW_AT_GNU_dwo_name | (! grep $(TMPDIR)) || exit 1 - rm $(TMPDIR)/*.o - ls $(TMPDIR)/*.dwo && exit 1 || exit 0 - ls $(TMPDIR)/*.dwp && exit 1 || exit 0 - rm $(TMPDIR)/$(call BIN,foo) - - # - Debuginfo in `.o` files - # - `.o` and binary refer to remapped `.o` paths which do not exist - # - `.o` present - # - `.dwo` never created - # - `.dwp` never created - unpacked-remapped-scope: - $(RUSTC) $(UNSTABLEOPTS) -C split-debuginfo=unpacked -g \ - -Z split-dwarf-kind=single --remap-path-prefix $(TMPDIR)=/a \ - -Z remap-path-scope=debuginfo foo.rs - objdump -Wi $(TMPDIR)/foo | grep DW_AT_GNU_dwo_name | (! grep $(TMPDIR)) || exit 1 - rm $(TMPDIR)/*.o - ls $(TMPDIR)/*.dwo && exit 1 || exit 0 - ls $(TMPDIR)/*.dwp && exit 1 || exit 0 - rm $(TMPDIR)/$(call BIN,foo) - - # - Debuginfo in `.o` files - # - `.o` and binary refer to remapped `.o` paths which do not exist - # - `.o` present - # - `.dwo` never created - # - `.dwp` never created - unpacked-remapped-wrong-scope: - $(RUSTC) $(UNSTABLEOPTS) -C split-debuginfo=unpacked -g \ - -Z split-dwarf-kind=single --remap-path-prefix $(TMPDIR)=/a \ - -Z remap-path-scope=macro foo.rs - objdump -Wi $(TMPDIR)/foo | grep DW_AT_GNU_dwo_name | (grep $(TMPDIR)) || exit 1 - rm $(TMPDIR)/*.o - ls $(TMPDIR)/*.dwo && exit 1 || exit 0 - ls $(TMPDIR)/*.dwp && exit 1 || exit 0 - rm $(TMPDIR)/$(call BIN,foo) - - unpacked-crosscrate: unpacked-crosscrate-split unpacked-crosscrate-single - - # - Debuginfo in `.dwo` files - # - (bar) `.rlib` file created, contains `.dwo` - # - (bar) `.o` deleted - # - (bar) `.dwo` present - # - (bar) `.dwp` never created - # - (main) `.o` deleted - # - (main) `.dwo` present - # - (main) `.dwp` never created - unpacked-crosscrate-split: - $(RUSTC) --crate-type lib $(UNSTABLEOPTS) -C split-debuginfo=unpacked \ - -Zsplit-dwarf-kind=split -g bar.rs - ls $(TMPDIR)/*.rlib - ls $(TMPDIR)/*.o && exit 1 || exit 0 - ls $(TMPDIR)/*.dwo - ls $(TMPDIR)/*.dwp && exit 1 || exit 0 - $(RUSTC) --extern bar=$(TMPDIR)/libbar.rlib $(UNSTABLEOPTS) \ - -C split-debuginfo=unpacked -Zsplit-dwarf-kind=split -g main.rs - ls $(TMPDIR)/*.o && exit 1 || exit 0 - rm $(TMPDIR)/*.dwo - ls $(TMPDIR)/*.dwp && exit 1 || exit 0 - rm $(TMPDIR)/$(call BIN,main) - - # - Debuginfo in `.o` files - # - (bar) `.rlib` file created, contains `.o` - # - (bar) `.o` present - # - (bar) `.dwo` never created - # - (bar) `.dwp` never created - # - (main) `.o` present - # - (main) `.dwo` never created - # - (main) `.dwp` never created - unpacked-crosscrate-single: - $(RUSTC) --crate-type lib $(UNSTABLEOPTS) -C split-debuginfo=unpacked \ - -Zsplit-dwarf-kind=single -g bar.rs - ls $(TMPDIR)/*.rlib - ls $(TMPDIR)/*.o - ls $(TMPDIR)/*.dwo && exit 1 || exit 0 - ls $(TMPDIR)/*.dwp && exit 1 || exit 0 - $(RUSTC) --extern bar=$(TMPDIR)/libbar.rlib $(UNSTABLEOPTS) \ - -C split-debuginfo=unpacked -Zsplit-dwarf-kind=single -g main.rs - ls $(TMPDIR)/*.o - ls $(TMPDIR)/*.dwo && exit 1 || exit 0 - ls $(TMPDIR)/*.dwp && exit 1 || exit 0 - rm $(TMPDIR)/$(call BIN,main) -endif diff --git a/tests/run-make/split-debuginfo/rmake.rs b/tests/run-make/split-debuginfo/rmake.rs new file mode 100644 index 00000000000..530a5d119f1 --- /dev/null +++ b/tests/run-make/split-debuginfo/rmake.rs @@ -0,0 +1,1618 @@ +// ignore-tidy-linelength +//! Basic smoke tests for behavior of `-C split-debuginfo` and the combined behavior when used in +//! conjunction with other flags such as: +//! +//! - `--remap-path-prefix`: see +//! . +//! - `-Z remap-path-scope`: see +//! - +//! - +//! - RFC #3127 trim-paths: +//! - `-Z split-dwarf-kind`: see . +//! - `-Clinker-plugin-lto`: see . +//! +//! # Test implementation remark +//! +//! - The pattern match on enum variants are intentional, because I find that they are very +//! revealing with respect to the kind of test coverage that we have and don't have. +//! +//! # Known limitations +//! +//! - The linux test coverage of cross-interactions between `-C split-debuginfo` and other flags are +//! significantly higher than the lack of such coverage for Windows and Darwin. +//! - windows-gnu is not tested at all, see the `FIXME(#135531)`s below. +//! - This test for the most part merely checks for existence/absence of certain artifacts, it does +//! not sanity check if the debuginfo artifacts are actually usable or contains the expected +//! amount/quality of debuginfo, especially on windows-msvc and darwin. +//! - FIXME(#111540): this test has insufficient coverage in relation to trim-paths RFC, see also +//! the comment . The +//! basic `llvm-dwarfdump` textual output inspection here is very fragile. The original `Makefile` +//! version used `objdump` (not to be confused with `llvm-objdump`) but inspected the wrong line +//! because it was looking at `DW_AT_GNU_dwo_name` when it should've been looking at +//! `DW_AT_comp_dir`. +//! - This test does not have good coverage for what values of `-Csplit-debuginfo` are stable vs +//! non-stable for the various targets, i.e. which values *should* be gated behind +//! `-Zunstable-options` for a given target. The `Makefile` version yolo'd a `-Zunstable-options` +//! for non-windows + non-linux + non-darwin, but had a misplaced interpolation which suggested to +//! me that that conditional `-Zunstable-options` never actually materialized. +//! +//! # Additional references +//! +//! - Apple `.dSYM` debug symbol bundles: . +//! - LLVM `dsymutil`: . + +// NOTE: this is a host test +//@ ignore-cross-compile + +// NOTE: this seems to be a host test, and testing on host `riscv64-gc-unknown-linux-gnu` reveals +// that this test is failing because of [MC: "error: A dwo section may not contain relocations" when +// building with fission + RISCV64 #56642](https://github.com/llvm/llvm-project/issues/56642). This +// test is ignored for now to unblock efforts to bring riscv64 targets to be exercised in CI, cf. +// [Enable riscv64gc-gnu testing #126641](https://github.com/rust-lang/rust/pull/126641). +//@ ignore-riscv64 (https://github.com/llvm/llvm-project/issues/56642) + +// FIXME(#135531): the `Makefile` version practically didn't test `-C split-debuginfo` on Windows +// at all, and lumped windows-msvc and windows-gnu together at that. +//@ ignore-windows-gnu + +#![deny(warnings)] + +use std::collections::BTreeSet; + +use run_make_support::rustc::Rustc; +use run_make_support::{ + cwd, has_extension, is_darwin, is_msvc, is_windows, llvm_dwarfdump, run_in_tmpdir, rustc, + shallow_find_directories, shallow_find_files, uname, +}; + +/// `-C debuginfo`. See . +#[derive(Debug, PartialEq, Copy, Clone)] +enum DebuginfoLevel { + /// `-C debuginfo=0` or `-C debuginfo=none` aka no debuginfo at all, default. + None, + /// `-C debuginfo=2` aka full debuginfo, aliased via `-g`. + Full, + /// The cli flag is not explicitly provided; default. + Unspecified, +} + +impl DebuginfoLevel { + fn cli_value(&self) -> &'static str { + // `-Cdebuginfo=...` + match self { + DebuginfoLevel::None => "none", + DebuginfoLevel::Full => "2", + DebuginfoLevel::Unspecified => unreachable!(), + } + } +} + +/// `-C split-debuginfo`. See +/// . +/// +/// Note that all three options are supported on Linux and Apple platforms, packed is supported on +/// Windows-MSVC, and all other platforms support off. Attempting to use an unsupported option +/// requires using the nightly channel with the `-Z unstable-options` flag. +#[derive(Debug, PartialEq, Copy, Clone)] +enum SplitDebuginfo { + /// `-C split-debuginfo=off`. Default for platforms with ELF binaries and windows-gnu (not + /// Windows MSVC and not macOS). Typically DWARF debug information can be found in the final + /// artifact in sections of the executable. + /// + /// - Not supported on Windows MSVC. + /// - On macOS this options prevents the final execution of `dsymutil` to generate debuginfo. + Off, + /// `-C split-debuginfo=unpacked`. Debug information will be found in separate files for each + /// compilation unit (object file). + /// + /// - Not supported on Windows MSVC. + /// - On macOS this means the original object files will contain debug information. + /// - On other Unix platforms this means that `*.dwo` files will contain debug information. + Unpacked, + /// `-C split-debuginfo=packed`. Default for Windows MSVC and macOS. "Packed" here means that + /// all the debug information is packed into a separate file from the main executable. + /// + /// - On Windows MSVC this is a `*.pdb` file. + /// - On macOS this is a `*.dSYM` folder. + /// - On other platforms this is a `*.dwp` file. + Packed, + /// The cli flag is not explicitly provided; uses platform default. + Unspecified, +} + +impl SplitDebuginfo { + fn cli_value(&self) -> &'static str { + // `-Csplit-debuginfo=...` + match self { + SplitDebuginfo::Off => "off", + SplitDebuginfo::Unpacked => "unpacked", + SplitDebuginfo::Packed => "packed", + SplitDebuginfo::Unspecified => unreachable!(), + } + } +} + +/// `-Z split-dwarf-kind` +#[derive(Debug, PartialEq, Copy, Clone)] +enum SplitDwarfKind { + /// `-Zsplit-dwarf-kind=split` + Split, + /// `-Zsplit-dwarf-kind=single` + Single, + Unspecified, +} + +impl SplitDwarfKind { + fn cli_value(&self) -> &'static str { + // `-Zsplit-dwarf-kind=...` + match self { + SplitDwarfKind::Split => "split", + SplitDwarfKind::Single => "single", + SplitDwarfKind::Unspecified => unreachable!(), + } + } +} + +/// `-C linker-plugin-lto` +#[derive(Debug, PartialEq, Copy, Clone)] +enum LinkerPluginLto { + /// Pass `-C linker-plugin-lto`. + Yes, + /// Don't pass `-C linker-plugin-lto`. + Unspecified, +} + +/// `--remap-path-prefix` or not. +#[derive(Debug, Clone)] +enum RemapPathPrefix { + /// `--remap-path-prefix=$prefix=$remapped_prefix`. + Yes { remapped_prefix: &'static str }, + /// Don't pass `--remap-path-prefix`. + Unspecified, +} + +/// `-Zremap-path-scope`. See +/// . +#[derive(Debug, Clone)] +enum RemapPathScope { + /// Comma-separated list of remap scopes: `macro`, `diagnostics`, `debuginfo`, `object`, `all`. + Yes(&'static str), + Unspecified, +} + +/// Whether to pass `-Zunstable-options`. +#[derive(Debug, PartialEq, Copy, Clone)] +enum UnstableOptions { + Yes, + Unspecified, +} + +#[track_caller] +fn cwd_filenames() -> BTreeSet { + let files = shallow_find_files(cwd(), |path| { + // Fiilter out source files + !has_extension(path, "rs") + }); + files.iter().map(|p| p.file_name().unwrap().to_os_string().into_string().unwrap()).collect() +} + +#[track_caller] +fn cwd_dwo_filenames() -> BTreeSet { + let files = shallow_find_files(cwd(), |path| has_extension(path, "dwo")); + files.iter().map(|p| p.file_name().unwrap().to_os_string().into_string().unwrap()).collect() +} + +#[track_caller] +fn cwd_object_filenames() -> BTreeSet { + let files = shallow_find_files(cwd(), |path| has_extension(path, "o")); + files.iter().map(|p| p.file_name().unwrap().to_os_string().into_string().unwrap()).collect() +} + +#[must_use] +struct FileAssertions<'expected> { + expected_files: BTreeSet<&'expected str>, +} + +impl<'expected> FileAssertions<'expected> { + #[track_caller] + fn assert_on(self, found_files: &BTreeSet) { + let found_files: BTreeSet<_> = found_files.iter().map(|f| f.as_str()).collect(); + assert!( + found_files.is_superset(&self.expected_files), + "expected {:?} to exist, but only found {:?}", + self.expected_files, + found_files + ); + + let unexpected_files: BTreeSet<_> = + found_files.difference(&self.expected_files).copied().collect(); + assert!(unexpected_files.is_empty(), "found unexpected files: {:?}", unexpected_files); + } +} + +/// Windows MSVC only supports packed debuginfo. +mod windows_msvc_tests { + use super::*; + + pub(crate) fn split_debuginfo(split_kind: SplitDebuginfo, level: DebuginfoLevel) { + // NOTE: `-C debuginfo` and other flags are not exercised here on Windows MSVC. + run_in_tmpdir(|| { + println!("checking: split_kind={:?} + level={:?}", split_kind, level); + match (split_kind, level) { + (SplitDebuginfo::Off, _) => { + rustc() + .input("foo.rs") + .split_debuginfo(split_kind.cli_value()) + .run_fail() + .assert_stderr_contains( + "error: `-Csplit-debuginfo=off` is unstable on this platform", + ); + } + (SplitDebuginfo::Unpacked, _) => { + rustc() + .input("foo.rs") + .split_debuginfo(split_kind.cli_value()) + .run_fail() + .assert_stderr_contains( + "error: `-Csplit-debuginfo=unpacked` is unstable on this platform", + ); + } + (SplitDebuginfo::Packed, _) => { + rustc().input("foo.rs").split_debuginfo(split_kind.cli_value()).run(); + + let found_files = cwd_filenames(); + FileAssertions { expected_files: BTreeSet::from(["foo.exe", "foo.pdb"]) } + .assert_on(&found_files); + } + (split_kind, level) => { + panic!( + "split_kind={:?} + level={:?} is not handled on Windows MSVC", + split_kind, level + ) + } + } + }); + } +} + +mod darwin_tests { + use super::*; + + pub(crate) fn split_debuginfo(split_kind: SplitDebuginfo, level: DebuginfoLevel) { + run_in_tmpdir(|| { + println!("checking: split_kind={:?} + level={:?}", split_kind, level); + + let dsym_directories = + || shallow_find_directories(cwd(), |path| has_extension(path, "dSYM")); + + match (split_kind, level) { + (_, DebuginfoLevel::Unspecified) => { + rustc().input("foo.rs").run(); + let directories = + shallow_find_directories(cwd(), |path| has_extension(path, "dSYM")); + assert!( + directories.is_empty(), + "expected no `*.dSYM` folder to be generated when `-Cdebuginfo` is not specified" + ); + } + (_, DebuginfoLevel::None) => { + rustc().input("foo.rs").debuginfo(level.cli_value()).run(); + let directories = dsym_directories(); + assert!( + directories.is_empty(), + "expected no `*.dSYM` folder to be generated when `-Cdebuginfo=none`" + ); + } + (SplitDebuginfo::Off, _) => { + rustc() + .input("foo.rs") + .split_debuginfo(split_kind.cli_value()) + .debuginfo(level.cli_value()) + .run(); + let directories = dsym_directories(); + assert!( + directories.is_empty(), + "expected no `*.dSYM` folder to be generated since we expect `-Csplit-debuginfo=off` to inhibit final debuginfo generation on macOS" + ); + } + (SplitDebuginfo::Unpacked, _) => { + rustc().input("foo.rs").split_debuginfo(split_kind.cli_value()).run(); + let directories = dsym_directories(); + assert!( + directories.is_empty(), + "expected no `*.dSYM` folder to be generated since we expect on macOS the object files to contain debuginfo instead" + ); + } + (SplitDebuginfo::Packed, DebuginfoLevel::Full) => { + rustc() + .input("foo.rs") + .split_debuginfo(split_kind.cli_value()) + .debuginfo(level.cli_value()) + .run(); + let directories = shallow_find_directories(cwd(), |path| { + path.file_name().unwrap() == "foo.dSYM" + }); + assert_eq!(directories.len(), 1, "failed to find `foo.dSYM`"); + } + (SplitDebuginfo::Unspecified, DebuginfoLevel::Full) => { + rustc().input("foo.rs").debuginfo(level.cli_value()).run(); + let directories = shallow_find_directories(cwd(), |path| { + path.file_name().unwrap() == "foo.dSYM" + }); + assert_eq!(directories.len(), 1, "failed to find `foo.dSYM`"); + } + } + }); + } +} + +mod shared_linux_other_tests { + use std::path::PathBuf; + + use super::*; + + fn rustc(unstable_options: UnstableOptions) -> Rustc { + if unstable_options == UnstableOptions::Yes { + let mut rustc = run_make_support::rustc(); + rustc.arg("-Zunstable-options"); + rustc + } else { + run_make_support::rustc() + } + } + + #[derive(PartialEq)] + pub(crate) enum CrossCrateTest { + Yes, + No, + } + + pub(crate) fn split_debuginfo( + cross_crate_test: CrossCrateTest, + unstable_options: UnstableOptions, + split_kind: SplitDebuginfo, + level: DebuginfoLevel, + split_dwarf_kind: SplitDwarfKind, + lto: LinkerPluginLto, + remap_path_prefix: RemapPathPrefix, + remap_path_scope: RemapPathScope, + ) { + run_in_tmpdir(|| { + println!( + "checking: unstable_options={:?} + split_kind={:?} + level={:?} + split_dwarf_kind={:?} + lto={:?} + remap_path_prefix={:?} + remap_path_scope={:?}", + unstable_options, + split_kind, + level, + split_dwarf_kind, + lto, + remap_path_prefix, + remap_path_scope + ); + + match cross_crate_test { + CrossCrateTest::Yes => cross_crate_split_debuginfo( + unstable_options, + split_kind, + level, + split_dwarf_kind, + lto, + remap_path_prefix, + remap_path_scope, + ), + CrossCrateTest::No => simple_split_debuginfo( + unstable_options, + split_kind, + level, + split_dwarf_kind, + lto, + remap_path_prefix, + remap_path_scope, + ), + } + }); + } + + fn cross_crate_split_debuginfo( + unstable_options: UnstableOptions, + split_kind: SplitDebuginfo, + level: DebuginfoLevel, + split_dwarf_kind: SplitDwarfKind, + lto: LinkerPluginLto, + remap_path_prefix: RemapPathPrefix, + remap_path_scope: RemapPathScope, + ) { + match (split_kind, level, split_dwarf_kind, lto, remap_path_prefix, remap_path_scope) { + // packed-crosscrate-split + // - Debuginfo in `.dwo` files + // - (bar) `.rlib` file created, contains `.dwo` + // - (bar) `.o` deleted + // - (bar) `.dwo` deleted + // - (bar) `.dwp` never created + // - (main) `.o` deleted + // - (main) `.dwo` deleted + // - (main) `.dwp` present + ( + SplitDebuginfo::Packed, + DebuginfoLevel::Full, + SplitDwarfKind::Split, + LinkerPluginLto::Unspecified, + RemapPathPrefix::Unspecified, + RemapPathScope::Unspecified, + ) => { + rustc(unstable_options) + .input("bar.rs") + .crate_type("lib") + .split_debuginfo(split_kind.cli_value()) + .debuginfo(level.cli_value()) + .arg(format!("-Zsplit-dwarf-kind={}", split_dwarf_kind.cli_value())) + .run(); + + let found_files = cwd_filenames(); + FileAssertions { expected_files: BTreeSet::from(["libbar.rlib"]) } + .assert_on(&found_files); + + rustc(unstable_options) + .extern_("bar", "libbar.rlib") + .input("main.rs") + .split_debuginfo(split_kind.cli_value()) + .debuginfo(level.cli_value()) + .arg(format!("-Zsplit-dwarf-kind={}", split_dwarf_kind.cli_value())) + .run(); + + let found_files = cwd_filenames(); + FileAssertions { + expected_files: BTreeSet::from(["libbar.rlib", "main", "main.dwp"]), + } + .assert_on(&found_files); + } + + // packed-crosscrate-single + // - Debuginfo in `.o` files + // - (bar) `.rlib` file created, contains `.o` + // - (bar) `.o` deleted + // - (bar) `.dwo` never created + // - (bar) `.dwp` never created + // - (main) `.o` deleted + // - (main) `.dwo` never created + // - (main) `.dwp` present + ( + SplitDebuginfo::Packed, + DebuginfoLevel::Full, + SplitDwarfKind::Single, + LinkerPluginLto::Unspecified, + RemapPathPrefix::Unspecified, + RemapPathScope::Unspecified, + ) => { + rustc(unstable_options) + .input("bar.rs") + .crate_type("lib") + .split_debuginfo(split_kind.cli_value()) + .debuginfo(level.cli_value()) + .arg(format!("-Zsplit-dwarf-kind={}", split_dwarf_kind.cli_value())) + .run(); + + let found_files = cwd_filenames(); + FileAssertions { expected_files: BTreeSet::from(["libbar.rlib"]) } + .assert_on(&found_files); + + rustc(unstable_options) + .extern_("bar", "libbar.rlib") + .input("main.rs") + .split_debuginfo(split_kind.cli_value()) + .debuginfo(level.cli_value()) + .arg(format!("-Zsplit-dwarf-kind={}", split_dwarf_kind.cli_value())) + .run(); + + let found_files = cwd_filenames(); + FileAssertions { + expected_files: BTreeSet::from(["libbar.rlib", "main", "main.dwp"]), + } + .assert_on(&found_files); + } + + // unpacked-crosscrate-split + // - Debuginfo in `.dwo` files + // - (bar) `.rlib` file created, contains `.dwo` + // - (bar) `.o` deleted + // - (bar) `.dwo` present + // - (bar) `.dwp` never created + // - (main) `.o` deleted + // - (main) `.dwo` present + // - (main) `.dwp` never created + ( + SplitDebuginfo::Unpacked, + DebuginfoLevel::Full, + SplitDwarfKind::Split, + LinkerPluginLto::Unspecified, + RemapPathPrefix::Unspecified, + RemapPathScope::Unspecified, + ) => { + rustc(unstable_options) + .input("bar.rs") + .crate_type("lib") + .split_debuginfo(split_kind.cli_value()) + .debuginfo(level.cli_value()) + .arg(format!("-Zsplit-dwarf-kind={}", split_dwarf_kind.cli_value())) + .run(); + + let bar_found_files = cwd_filenames(); + + let bar_dwo_files = cwd_dwo_filenames(); + assert_eq!(bar_dwo_files.len(), 1); + + let mut bar_expected_files = BTreeSet::new(); + bar_expected_files.extend(bar_dwo_files); + bar_expected_files.insert("libbar.rlib".to_string()); + + FileAssertions { + expected_files: bar_expected_files.iter().map(String::as_ref).collect(), + } + .assert_on(&bar_found_files); + + rustc(unstable_options) + .extern_("bar", "libbar.rlib") + .input("main.rs") + .split_debuginfo(split_kind.cli_value()) + .debuginfo(level.cli_value()) + .arg(format!("-Zsplit-dwarf-kind={}", split_dwarf_kind.cli_value())) + .run(); + + let overall_found_files = cwd_filenames(); + + let overall_dwo_files = cwd_dwo_filenames(); + assert_eq!(overall_dwo_files.len(), 2); + + let mut overall_expected_files = BTreeSet::new(); + overall_expected_files.extend(overall_dwo_files); + overall_expected_files.insert("main".to_string()); + overall_expected_files.insert("libbar.rlib".to_string()); + + FileAssertions { + expected_files: overall_expected_files.iter().map(String::as_ref).collect(), + } + .assert_on(&overall_found_files); + } + + // unpacked-crosscrate-single + // - Debuginfo in `.o` files + // - (bar) `.rlib` file created, contains `.o` + // - (bar) `.o` present + // - (bar) `.dwo` never created + // - (bar) `.dwp` never created + // - (main) `.o` present + // - (main) `.dwo` never created + // - (main) `.dwp` never created + ( + SplitDebuginfo::Unpacked, + DebuginfoLevel::Full, + SplitDwarfKind::Single, + LinkerPluginLto::Unspecified, + RemapPathPrefix::Unspecified, + RemapPathScope::Unspecified, + ) => { + rustc(unstable_options) + .input("bar.rs") + .crate_type("lib") + .split_debuginfo(split_kind.cli_value()) + .debuginfo(level.cli_value()) + .arg(format!("-Zsplit-dwarf-kind={}", split_dwarf_kind.cli_value())) + .run(); + + let bar_found_files = cwd_filenames(); + + let bar_object_files = cwd_object_filenames(); + assert_eq!(bar_object_files.len(), 1); + + let mut bar_expected_files = BTreeSet::new(); + bar_expected_files.extend(bar_object_files); + bar_expected_files.insert("libbar.rlib".to_string()); + + FileAssertions { + expected_files: bar_expected_files.iter().map(String::as_ref).collect(), + } + .assert_on(&bar_found_files); + + rustc(unstable_options) + .extern_("bar", "libbar.rlib") + .input("main.rs") + .split_debuginfo(split_kind.cli_value()) + .debuginfo(level.cli_value()) + .arg(format!("-Zsplit-dwarf-kind={}", split_dwarf_kind.cli_value())) + .run(); + + let overall_found_files = cwd_filenames(); + + let overall_object_files = cwd_object_filenames(); + assert_eq!(overall_object_files.len(), 2); + + let mut overall_expected_files = BTreeSet::new(); + overall_expected_files.extend(overall_object_files); + overall_expected_files.insert("main".to_string()); + overall_expected_files.insert("libbar.rlib".to_string()); + + FileAssertions { + expected_files: overall_expected_files.iter().map(String::as_ref).collect(), + } + .assert_on(&overall_found_files); + } + + _ => {} + } + } + + fn simple_split_debuginfo( + unstable_options: UnstableOptions, + split_kind: SplitDebuginfo, + level: DebuginfoLevel, + split_dwarf_kind: SplitDwarfKind, + lto: LinkerPluginLto, + remap_path_prefix: RemapPathPrefix, + remap_path_scope: RemapPathScope, + ) { + match (split_kind, level, split_dwarf_kind, lto, remap_path_prefix, remap_path_scope) { + // off (unspecified): + // - Debuginfo in `.o` files + // - `.o` deleted + // - `.dwo` never created + // - `.dwp` never created + ( + SplitDebuginfo::Unspecified, + DebuginfoLevel::Full, + SplitDwarfKind::Unspecified, + LinkerPluginLto::Unspecified, + RemapPathPrefix::Unspecified, + RemapPathScope::Unspecified, + ) => { + rustc(unstable_options).input("foo.rs").debuginfo(level.cli_value()).run(); + let found_files = cwd_filenames(); + FileAssertions { expected_files: BTreeSet::from(["foo"]) }.assert_on(&found_files); + } + + // off: + // - Debuginfo in `.o` files + // - `.o` deleted + // - `.dwo` never created + // - `.dwp` never created + ( + SplitDebuginfo::Off, + DebuginfoLevel::Full, + SplitDwarfKind::Unspecified, + LinkerPluginLto::Unspecified, + RemapPathPrefix::Unspecified, + RemapPathScope::Unspecified, + ) => { + rustc(unstable_options) + .input("foo.rs") + .split_debuginfo(split_kind.cli_value()) + .debuginfo(level.cli_value()) + .run(); + let found_files = cwd_filenames(); + FileAssertions { expected_files: BTreeSet::from(["foo"]) }.assert_on(&found_files); + } + + // packed-split: + // - Debuginfo in `.dwo` files + // - `.o` deleted + // - `.dwo` deleted + // - `.dwp` present + ( + SplitDebuginfo::Packed, + DebuginfoLevel::Full, + SplitDwarfKind::Split, + LinkerPluginLto::Unspecified, + RemapPathPrefix::Unspecified, + RemapPathScope::Unspecified, + ) => { + rustc(unstable_options) + .input("foo.rs") + .split_debuginfo(split_kind.cli_value()) + .debuginfo(level.cli_value()) + .arg(format!("-Zsplit-dwarf-kind={}", split_dwarf_kind.cli_value())) + .run(); + let found_files = cwd_filenames(); + FileAssertions { expected_files: BTreeSet::from(["foo", "foo.dwp"]) } + .assert_on(&found_files); + } + + // packed-single: + // - Debuginfo in `.o` files + // - `.o` deleted + // - `.dwo` never created + // - `.dwp` present + ( + SplitDebuginfo::Packed, + DebuginfoLevel::Full, + SplitDwarfKind::Single, + LinkerPluginLto::Unspecified, + RemapPathPrefix::Unspecified, + RemapPathScope::Unspecified, + ) => { + rustc(unstable_options) + .input("foo.rs") + .split_debuginfo(split_kind.cli_value()) + .debuginfo(level.cli_value()) + .arg(format!("-Zsplit-dwarf-kind={}", split_dwarf_kind.cli_value())) + .run(); + let found_files = cwd_filenames(); + FileAssertions { expected_files: BTreeSet::from(["foo", "foo.dwp"]) } + .assert_on(&found_files); + } + + // packed-lto-split:: + // - `rmeta` file added to `rlib`, no object files are generated and thus no + // debuginfo is generated. + // - `.o` never created + // - `.dwo` never created + // - `.dwp` never created + ( + SplitDebuginfo::Packed, + DebuginfoLevel::Full, + SplitDwarfKind::Split, + LinkerPluginLto::Yes, + RemapPathPrefix::Unspecified, + RemapPathScope::Unspecified, + ) => { + rustc(unstable_options) + .input("baz.rs") + .crate_type("rlib") + .split_debuginfo(split_kind.cli_value()) + .debuginfo(level.cli_value()) + .arg(format!("-Zsplit-dwarf-kind={}", split_dwarf_kind.cli_value())) + .arg("-Clinker-plugin-lto") + .run(); + let found_files = cwd_filenames(); + FileAssertions { expected_files: BTreeSet::from(["libbaz.rlib"]) } + .assert_on(&found_files); + } + + // packed-lto-single: + // - `rmeta` file added to `rlib`, no object files are generated and thus no + // debuginfo is generated + // - `.o` never created + // - `.dwo` never created + // - `.dwp` never created + ( + SplitDebuginfo::Packed, + DebuginfoLevel::Full, + SplitDwarfKind::Single, + LinkerPluginLto::Yes, + RemapPathPrefix::Unspecified, + RemapPathScope::Unspecified, + ) => { + rustc(unstable_options) + .input("baz.rs") + .crate_type("rlib") + .split_debuginfo(split_kind.cli_value()) + .debuginfo(level.cli_value()) + .arg(format!("-Zsplit-dwarf-kind={}", split_dwarf_kind.cli_value())) + .arg("-Clinker-plugin-lto") + .run(); + let found_files = cwd_filenames(); + FileAssertions { expected_files: BTreeSet::from(["libbaz.rlib"]) } + .assert_on(&found_files); + } + + // packed-remapped-split: + // - Debuginfo in `.dwo` files + // - `.o` and binary refer to remapped `.dwo` paths which do not exist + // - `.o` deleted + // - `.dwo` deleted + // - `.dwp` present + ( + SplitDebuginfo::Packed, + DebuginfoLevel::Full, + SplitDwarfKind::Split, + LinkerPluginLto::Unspecified, + RemapPathPrefix::Yes { remapped_prefix }, + RemapPathScope::Unspecified, + ) => { + rustc(unstable_options) + .input("foo.rs") + .split_debuginfo(split_kind.cli_value()) + .debuginfo(level.cli_value()) + .arg(format!("-Zsplit-dwarf-kind={}", split_dwarf_kind.cli_value())) + .remap_path_prefix(cwd(), remapped_prefix) + .run(); + let found_files = cwd_filenames(); + FileAssertions { expected_files: BTreeSet::from(["foo", "foo.dwp"]) } + .assert_on(&found_files); + + check_path_remap(cwd(), RemapExpectation::Remapped); + } + + // packed-remapped-single: + // - `.o` and binary refer to remapped `.o` paths which do not exist + // - `.o` deleted + // - `.dwo` never created + // - `.dwp` present + ( + SplitDebuginfo::Packed, + DebuginfoLevel::Full, + SplitDwarfKind::Single, + LinkerPluginLto::Unspecified, + RemapPathPrefix::Yes { remapped_prefix }, + RemapPathScope::Unspecified, + ) => { + rustc(unstable_options) + .input("foo.rs") + .split_debuginfo(split_kind.cli_value()) + .debuginfo(level.cli_value()) + .arg(format!("-Zsplit-dwarf-kind={}", split_dwarf_kind.cli_value())) + .remap_path_prefix(cwd(), remapped_prefix) + .run(); + let found_files = cwd_filenames(); + FileAssertions { expected_files: BTreeSet::from(["foo", "foo.dwp"]) } + .assert_on(&found_files); + + check_path_remap(cwd(), RemapExpectation::Remapped); + } + + // packed-remapped-scope: + // - Debuginfo in `.o` files + // - `.o` and binary refer to remapped `.o` paths which do not exist + // - `.o` deleted + // - `.dwo` never created + // - `.dwp` present + ( + SplitDebuginfo::Packed, + DebuginfoLevel::Full, + SplitDwarfKind::Single, + LinkerPluginLto::Unspecified, + RemapPathPrefix::Yes { remapped_prefix }, + RemapPathScope::Yes(scope @ "debuginfo"), + ) => { + rustc(unstable_options) + .input("foo.rs") + .split_debuginfo(split_kind.cli_value()) + .debuginfo(level.cli_value()) + .arg(format!("-Zsplit-dwarf-kind={}", split_dwarf_kind.cli_value())) + .remap_path_prefix(cwd(), remapped_prefix) + .arg(format!("-Zremap-path-scope={scope}")) + .run(); + let found_files = cwd_filenames(); + FileAssertions { expected_files: BTreeSet::from(["foo", "foo.dwp"]) } + .assert_on(&found_files); + + check_path_remap(cwd(), RemapExpectation::Remapped); + } + + // packed-remapped-wrong-scope: + // - `.o` and binary refer to un-remapped `.o` paths because remap path scope is + // macro. + // - `.o` deleted + // - `.dwo` never created + // - `.dwp` present + ( + SplitDebuginfo::Packed, + DebuginfoLevel::Full, + SplitDwarfKind::Single, + LinkerPluginLto::Unspecified, + RemapPathPrefix::Yes { remapped_prefix }, + RemapPathScope::Yes(scope @ "macro"), + ) => { + rustc(unstable_options) + .input("foo.rs") + .split_debuginfo(split_kind.cli_value()) + .debuginfo(level.cli_value()) + .arg(format!("-Zsplit-dwarf-kind={}", split_dwarf_kind.cli_value())) + .remap_path_prefix(cwd(), remapped_prefix) + .arg(format!("-Zremap-path-scope={scope}")) + .run(); + let found_files = cwd_filenames(); + FileAssertions { expected_files: BTreeSet::from(["foo", "foo.dwp"]) } + .assert_on(&found_files); + + check_path_remap(cwd(), RemapExpectation::NoRemap); + } + + // unpacked-split + // - Debuginfo in `.dwo` files + // - `.o` deleted + // - `.dwo` present + // - `.dwp` never created + ( + SplitDebuginfo::Unpacked, + DebuginfoLevel::Full, + SplitDwarfKind::Split, + LinkerPluginLto::Unspecified, + RemapPathPrefix::Unspecified, + RemapPathScope::Unspecified, + ) => { + rustc(unstable_options) + .input("foo.rs") + .split_debuginfo(split_kind.cli_value()) + .debuginfo(level.cli_value()) + .arg(format!("-Zsplit-dwarf-kind={}", split_dwarf_kind.cli_value())) + .run(); + let found_files = cwd_filenames(); + + let dwo_files = cwd_dwo_filenames(); + assert_eq!(dwo_files.len(), 1); + + let mut expected_files = BTreeSet::new(); + expected_files.extend(dwo_files); + expected_files.insert("foo".to_string()); + + FileAssertions { + expected_files: expected_files.iter().map(String::as_str).collect(), + } + .assert_on(&found_files); + } + + // unpacked-single + // - Debuginfo in `.o` files + // - `.o` present + // - `.dwo` never created + // - `.dwp` never created + ( + SplitDebuginfo::Unpacked, + DebuginfoLevel::Full, + SplitDwarfKind::Single, + LinkerPluginLto::Unspecified, + RemapPathPrefix::Unspecified, + RemapPathScope::Unspecified, + ) => { + rustc(unstable_options) + .input("foo.rs") + .split_debuginfo(split_kind.cli_value()) + .debuginfo(level.cli_value()) + .arg(format!("-Zsplit-dwarf-kind={}", split_dwarf_kind.cli_value())) + .run(); + let found_files = cwd_filenames(); + + let object_files = cwd_object_filenames(); + assert_eq!(object_files.len(), 1); + + let mut expected_files = BTreeSet::new(); + expected_files.extend(object_files); + expected_files.insert("foo".to_string()); + + FileAssertions { + expected_files: expected_files.iter().map(String::as_str).collect(), + } + .assert_on(&found_files); + } + + // unpacked-lto-split + // - `rmeta` file added to `rlib`, no object files are generated and thus no debuginfo + // is generated + // - `.o` not present + // - `.dwo` never created + // - `.dwp` never created + ( + SplitDebuginfo::Unpacked, + DebuginfoLevel::Full, + SplitDwarfKind::Split, + LinkerPluginLto::Yes, + RemapPathPrefix::Unspecified, + RemapPathScope::Unspecified, + ) => { + rustc(unstable_options) + .input("baz.rs") + .crate_type("rlib") + .split_debuginfo(split_kind.cli_value()) + .debuginfo(level.cli_value()) + .arg(format!("-Zsplit-dwarf-kind={}", split_dwarf_kind.cli_value())) + .arg("-Clinker-plugin-lto") + .run(); + + let found_files = cwd_filenames(); + + FileAssertions { expected_files: BTreeSet::from(["libbaz.rlib"]) } + .assert_on(&found_files); + } + + // unpacked-lto-single + // - rmeta file added to rlib, no object files are generated and thus no debuginfo is generated + // - `.o` present (bitcode) + // - `.dwo` never created + // - `.dwp` never created + ( + SplitDebuginfo::Unpacked, + DebuginfoLevel::Full, + SplitDwarfKind::Single, + LinkerPluginLto::Yes, + RemapPathPrefix::Unspecified, + RemapPathScope::Unspecified, + ) => { + rustc(unstable_options) + .input("baz.rs") + .crate_type("rlib") + .split_debuginfo(split_kind.cli_value()) + .debuginfo(level.cli_value()) + .arg(format!("-Zsplit-dwarf-kind={}", split_dwarf_kind.cli_value())) + .arg("-Clinker-plugin-lto") + .run(); + + let found_files = cwd_filenames(); + + let object_files = cwd_object_filenames(); + assert_eq!(object_files.len(), 1); + + let mut expected_files = BTreeSet::new(); + expected_files.extend(object_files); + expected_files.insert("libbaz.rlib".to_string()); + + FileAssertions { + expected_files: expected_files.iter().map(String::as_ref).collect(), + } + .assert_on(&found_files); + } + + // unpacked-remapped-split + // - Debuginfo in `.dwo` files + // - `.o` and binary refer to remapped `.dwo` paths which do not exist + // - `.o` deleted + // - `.dwo` present + // - `.dwp` never created + ( + SplitDebuginfo::Unpacked, + DebuginfoLevel::Full, + SplitDwarfKind::Split, + LinkerPluginLto::Unspecified, + RemapPathPrefix::Yes { remapped_prefix }, + RemapPathScope::Unspecified, + ) => { + rustc(unstable_options) + .input("foo.rs") + .split_debuginfo(split_kind.cli_value()) + .debuginfo(level.cli_value()) + .arg(format!("-Zsplit-dwarf-kind={}", split_dwarf_kind.cli_value())) + .remap_path_prefix(cwd(), remapped_prefix) + .run(); + + let found_files = cwd_filenames(); + + let dwo_files = cwd_dwo_filenames(); + assert_eq!(dwo_files.len(), 1); + + let mut expected_files = BTreeSet::new(); + expected_files.extend(dwo_files); + expected_files.insert("foo".to_string()); + + FileAssertions { + expected_files: expected_files.iter().map(String::as_ref).collect(), + } + .assert_on(&found_files); + + check_path_remap(cwd(), RemapExpectation::Remapped); + } + + // unpacked-remapped-single + // - Debuginfo in `.o` files + // - `.o` and binary refer to remapped `.o` paths which do not exist + // - `.o` present + // - `.dwo` never created + // - `.dwp` never created + ( + SplitDebuginfo::Unpacked, + DebuginfoLevel::Full, + SplitDwarfKind::Single, + LinkerPluginLto::Unspecified, + RemapPathPrefix::Yes { remapped_prefix }, + RemapPathScope::Unspecified, + ) => { + rustc(unstable_options) + .input("foo.rs") + .split_debuginfo(split_kind.cli_value()) + .debuginfo(level.cli_value()) + .arg(format!("-Zsplit-dwarf-kind={}", split_dwarf_kind.cli_value())) + .remap_path_prefix(cwd(), remapped_prefix) + .run(); + + let found_files = cwd_filenames(); + + let object_files = cwd_object_filenames(); + assert_eq!(object_files.len(), 1); + + let mut expected_files = BTreeSet::new(); + expected_files.extend(object_files); + expected_files.insert("foo".to_string()); + + FileAssertions { + expected_files: expected_files.iter().map(String::as_ref).collect(), + } + .assert_on(&found_files); + + check_path_remap(cwd(), RemapExpectation::Remapped); + } + + // unpacked-remapped-scope + // - Debuginfo in `.o` files + // - `.o` and binary refer to remapped `.o` paths which do not exist + // - `.o` present + // - `.dwo` never created + // - `.dwp` never created + ( + SplitDebuginfo::Unpacked, + DebuginfoLevel::Full, + SplitDwarfKind::Single, + LinkerPluginLto::Unspecified, + RemapPathPrefix::Yes { remapped_prefix }, + RemapPathScope::Yes(scope @ "debuginfo"), + ) => { + rustc(unstable_options) + .input("foo.rs") + .split_debuginfo(split_kind.cli_value()) + .debuginfo(level.cli_value()) + .arg(format!("-Zsplit-dwarf-kind={}", split_dwarf_kind.cli_value())) + .remap_path_prefix(cwd(), remapped_prefix) + .arg(format!("-Zremap-path-scope={scope}")) + .run(); + + let found_files = cwd_filenames(); + + let object_files = cwd_object_filenames(); + assert_eq!(object_files.len(), 1); + + let mut expected_files = BTreeSet::new(); + expected_files.extend(object_files); + expected_files.insert("foo".to_string()); + + FileAssertions { + expected_files: expected_files.iter().map(String::as_ref).collect(), + } + .assert_on(&found_files); + + check_path_remap(cwd(), RemapExpectation::Remapped); + } + + // unpacked-remapped-wrong-scope + // - Debuginfo in `.o` files + // - `.o` and binary refer to un-remapped `.o` paths because remap path scope is macro + // - `.o` present + // - `.dwo` never created + // - `.dwp` never created + ( + SplitDebuginfo::Unpacked, + DebuginfoLevel::Full, + SplitDwarfKind::Single, + LinkerPluginLto::Unspecified, + RemapPathPrefix::Yes { remapped_prefix }, + RemapPathScope::Yes(scope @ "macro"), + ) => { + rustc(unstable_options) + .input("foo.rs") + .split_debuginfo(split_kind.cli_value()) + .debuginfo(level.cli_value()) + .arg(format!("-Zsplit-dwarf-kind={}", split_dwarf_kind.cli_value())) + .remap_path_prefix(cwd(), remapped_prefix) + .arg(format!("-Zremap-path-scope={scope}")) + .run(); + + let found_files = cwd_filenames(); + + let object_files = cwd_object_filenames(); + assert_eq!(object_files.len(), 1); + + let mut expected_files = BTreeSet::new(); + expected_files.extend(object_files); + expected_files.insert("foo".to_string()); + + FileAssertions { + expected_files: expected_files.iter().map(String::as_ref).collect(), + } + .assert_on(&found_files); + + check_path_remap(cwd(), RemapExpectation::NoRemap); + } + + (split_kind, level, split_dwarf_kind, lto, remap_path_prefix, remap_path_scope) => { + panic!( + "split_kind={:?} + level={:?} + split_dwarf_kind={:?} + lto={:?} + remap_path_prefix={:?} + remap_path_scope={:?} is not handled on linux/other", + split_kind, level, split_dwarf_kind, lto, remap_path_prefix, remap_path_scope + ) + } + } + } + + #[derive(PartialEq)] + enum RemapExpectation { + Remapped, + NoRemap, + } + + #[track_caller] + fn check_path_remap(cwd_path: PathBuf, remap_expectation: RemapExpectation) { + let cwd_path = cwd_path.to_str().unwrap(); + let output = llvm_dwarfdump().input("foo").arg("--debug-info").run().stdout_utf8(); + let output_lines: Vec<_> = output.lines().collect(); + + // Look for `DW_AT_comp_dir` and `DW_AT_GNU_dwo_name` via `llvm-dwarfdump`. Note: space + // between uses tabs. + // + // ```text + // 0x0000000b: DW_TAG_compile_unit + // DW_AT_stmt_list (0x00000000) + // DW_AT_comp_dir ("/__MY_REMAPPED_PATH") # this could be e.g. /home/repos/rust/ if not remapped + // DW_AT_GNU_dwo_name ("foo.foo.fc848df41df7a00d-cgu.0.rcgu.dwo") + // ``` + // + // FIXME: this is very fragile because the output format can be load-bearing, but doing this + // via `object` + `gimli` is rather difficult. + let mut window = output_lines.windows(2); + while let Some([first_ln, second_ln]) = window.next() { + let first_ln = first_ln.trim(); + let second_ln = second_ln.trim(); + + if !second_ln.starts_with("DW_AT_GNU_dwo_name") { + continue; + } + + let Some((comp_dir_attr_name, comp_dir_attr_val)) = first_ln.split_once("\t") else { + continue; + }; + + println!("comp_dir_attr_name: `{}`", comp_dir_attr_name); + println!("cwd_path_string: `{}`", cwd_path); + + if comp_dir_attr_name != "DW_AT_comp_dir" { + continue; + } + + println!("comp_dir_attr_val: `{}`", comp_dir_attr_val); + + // Possibly `("/__MY_REMAPPED_PATH")` or `($cwd_path_string)`. + // + // FIXME: this check is insufficiently precise, it should probably also match on suffix + // (`.o` vs `.dwo` reference). But also, string matching is just very fragile. + let comp_dir_attr_val = comp_dir_attr_val.trim(); + + match remap_expectation { + RemapExpectation::Remapped => { + assert!( + !comp_dir_attr_val.contains(&cwd_path), + "unexpected non-remapped path found in `DW_AT_comp_dir`: {}", + comp_dir_attr_val + ); + } + RemapExpectation::NoRemap => { + assert!( + comp_dir_attr_val.contains(&cwd_path), + "failed to find un-remapped path in `DW_AT_comp_dir`: {}", + comp_dir_attr_val + ); + } + } + } + } +} + +fn main() { + // ENHANCEMENT: we are only checking that split-debuginfo is splitting is some way, shape or + // form, we do not sanity check the actual debuginfo artifacts on non-Linux! It may be possible + // to also sanity check the debuginfo artifacts, but I did not want to do that during the port + // to rmake.rs initially. + + // ENHANCEMENT: the Linux checks have significantly more coverage for interaction between `-C + // split-debuginfo` and other flags compared to windows-msvc or windows-gnu or darwin or some + // other non-linux targets. It would be cool if their test coverage could be improved. + + // NOTE: these combinations are not exhaustive, because while porting to rmake.rs initially I + // tried to preserve the existing test behavior closely. Notably, no attempt was made to + // exhaustively cover all cases in the 6-fold Cartesian product of `{,-Csplit=debuginfo=...}` x + // `{,-Cdebuginfo=...}` x `{,--remap-path-prefix}` x `{,-Zremap-path-scope=...}` x + // `{,-Zsplit-dwarf-kind=...}` x `{,-Clinker-plugin-lto}`. If you really want to, you can + // identify which combination isn't exercised with a 6-layers nested for loop iterating through + // each of the cli flag enum variants. + + if is_msvc() { + // FIXME: the windows-msvc test coverage is sparse at best. + + windows_msvc_tests::split_debuginfo(SplitDebuginfo::Off, DebuginfoLevel::Unspecified); + windows_msvc_tests::split_debuginfo(SplitDebuginfo::Unpacked, DebuginfoLevel::Unspecified); + windows_msvc_tests::split_debuginfo(SplitDebuginfo::Packed, DebuginfoLevel::Unspecified); + + windows_msvc_tests::split_debuginfo(SplitDebuginfo::Off, DebuginfoLevel::None); + windows_msvc_tests::split_debuginfo(SplitDebuginfo::Unpacked, DebuginfoLevel::None); + windows_msvc_tests::split_debuginfo(SplitDebuginfo::Packed, DebuginfoLevel::None); + + windows_msvc_tests::split_debuginfo(SplitDebuginfo::Off, DebuginfoLevel::Full); + windows_msvc_tests::split_debuginfo(SplitDebuginfo::Unpacked, DebuginfoLevel::Full); + windows_msvc_tests::split_debuginfo(SplitDebuginfo::Packed, DebuginfoLevel::Full); + } else if is_windows() { + // FIXME(#135531): the `Makefile` version didn't test windows at all. I don't know about the + // intended behavior on windows-gnu to expand test coverage while porting this to rmake.rs, + // but the test coverage here really should be expanded since some windows-gnu targets are + // Tier 1. + } else if is_darwin() { + // FIXME: the darwin test coverage is sparse at best. + + // Expect no `.dSYM` generation if debuginfo is not requested (special case). + darwin_tests::split_debuginfo(SplitDebuginfo::Unspecified, DebuginfoLevel::Unspecified); + + darwin_tests::split_debuginfo(SplitDebuginfo::Off, DebuginfoLevel::Unspecified); + darwin_tests::split_debuginfo(SplitDebuginfo::Unpacked, DebuginfoLevel::Unspecified); + darwin_tests::split_debuginfo(SplitDebuginfo::Packed, DebuginfoLevel::Unspecified); + + darwin_tests::split_debuginfo(SplitDebuginfo::Off, DebuginfoLevel::None); + darwin_tests::split_debuginfo(SplitDebuginfo::Unpacked, DebuginfoLevel::None); + darwin_tests::split_debuginfo(SplitDebuginfo::Packed, DebuginfoLevel::None); + + darwin_tests::split_debuginfo(SplitDebuginfo::Off, DebuginfoLevel::Full); + darwin_tests::split_debuginfo(SplitDebuginfo::Unpacked, DebuginfoLevel::Full); + darwin_tests::split_debuginfo(SplitDebuginfo::Packed, DebuginfoLevel::Full); + } else { + // Unix as well as the non-linux + non-windows + non-darwin targets. + + // FIXME: this `uname` check is very funny, it really should be refined (e.g. llvm bug + // for riscv64 targets). + + // NOTE: some options are not stable on non-linux + non-windows + non-darwin targets... + let unstable_options = + if uname() == "Linux" { UnstableOptions::Unspecified } else { UnstableOptions::Yes }; + + // FIXME: we should add a test with scope `split-debuginfo,split-debuginfo-path` that greps + // the entire `.dwp` file for remapped paths (i.e. without going through objdump or + // readelf). See . + + use shared_linux_other_tests::CrossCrateTest; + + // unspecified `-Csplit-debuginfo` + shared_linux_other_tests::split_debuginfo( + CrossCrateTest::No, + unstable_options, + SplitDebuginfo::Unspecified, + DebuginfoLevel::Full, + SplitDwarfKind::Unspecified, + LinkerPluginLto::Unspecified, + RemapPathPrefix::Unspecified, + RemapPathScope::Unspecified, + ); + + // off + shared_linux_other_tests::split_debuginfo( + CrossCrateTest::No, + unstable_options, + SplitDebuginfo::Off, + DebuginfoLevel::Full, + SplitDwarfKind::Unspecified, + LinkerPluginLto::Unspecified, + RemapPathPrefix::Unspecified, + RemapPathScope::Unspecified, + ); + + // packed-split + shared_linux_other_tests::split_debuginfo( + CrossCrateTest::No, + unstable_options, + SplitDebuginfo::Packed, + DebuginfoLevel::Full, + SplitDwarfKind::Split, + LinkerPluginLto::Unspecified, + RemapPathPrefix::Unspecified, + RemapPathScope::Unspecified, + ); + + // packed-single + shared_linux_other_tests::split_debuginfo( + CrossCrateTest::No, + unstable_options, + SplitDebuginfo::Packed, + DebuginfoLevel::Full, + SplitDwarfKind::Single, + LinkerPluginLto::Unspecified, + RemapPathPrefix::Unspecified, + RemapPathScope::Unspecified, + ); + + // packed-lto-split + shared_linux_other_tests::split_debuginfo( + CrossCrateTest::No, + unstable_options, + SplitDebuginfo::Packed, + DebuginfoLevel::Full, + SplitDwarfKind::Split, + LinkerPluginLto::Yes, + RemapPathPrefix::Unspecified, + RemapPathScope::Unspecified, + ); + + // packed-lto-single + shared_linux_other_tests::split_debuginfo( + CrossCrateTest::No, + unstable_options, + SplitDebuginfo::Packed, + DebuginfoLevel::Full, + SplitDwarfKind::Single, + LinkerPluginLto::Yes, + RemapPathPrefix::Unspecified, + RemapPathScope::Unspecified, + ); + + // FIXME: the remapping tests probably need to be reworked, see + // . + + // packed-remapped-split + shared_linux_other_tests::split_debuginfo( + CrossCrateTest::No, + unstable_options, + SplitDebuginfo::Packed, + DebuginfoLevel::Full, + SplitDwarfKind::Split, + LinkerPluginLto::Unspecified, + RemapPathPrefix::Yes { remapped_prefix: "/__MY_REMAPPED_PATH__" }, + RemapPathScope::Unspecified, + ); + + // packed-remapped-single + shared_linux_other_tests::split_debuginfo( + CrossCrateTest::No, + unstable_options, + SplitDebuginfo::Packed, + DebuginfoLevel::Full, + SplitDwarfKind::Single, + LinkerPluginLto::Unspecified, + RemapPathPrefix::Yes { remapped_prefix: "/__MY_REMAPPED_PATH__" }, + RemapPathScope::Unspecified, + ); + + // packed-remapped-scope + shared_linux_other_tests::split_debuginfo( + CrossCrateTest::No, + unstable_options, + SplitDebuginfo::Packed, + DebuginfoLevel::Full, + SplitDwarfKind::Single, + LinkerPluginLto::Unspecified, + RemapPathPrefix::Yes { remapped_prefix: "/__MY_REMAPPED_PATH__" }, + RemapPathScope::Yes("debuginfo"), + ); + + // packed-remapped-wrong-scope + shared_linux_other_tests::split_debuginfo( + CrossCrateTest::No, + unstable_options, + SplitDebuginfo::Packed, + DebuginfoLevel::Full, + SplitDwarfKind::Single, + LinkerPluginLto::Unspecified, + RemapPathPrefix::Yes { remapped_prefix: "/__MY_REMAPPED_PATH__" }, + RemapPathScope::Yes("macro"), + ); + + // packed-crosscrate-split + shared_linux_other_tests::split_debuginfo( + CrossCrateTest::Yes, + unstable_options, + SplitDebuginfo::Packed, + DebuginfoLevel::Full, + SplitDwarfKind::Split, + LinkerPluginLto::Unspecified, + RemapPathPrefix::Unspecified, + RemapPathScope::Unspecified, + ); + + // packed-crosscrate-single + shared_linux_other_tests::split_debuginfo( + CrossCrateTest::Yes, + unstable_options, + SplitDebuginfo::Packed, + DebuginfoLevel::Full, + SplitDwarfKind::Single, + LinkerPluginLto::Unspecified, + RemapPathPrefix::Unspecified, + RemapPathScope::Unspecified, + ); + + // unpacked-split + shared_linux_other_tests::split_debuginfo( + CrossCrateTest::No, + unstable_options, + SplitDebuginfo::Unpacked, + DebuginfoLevel::Full, + SplitDwarfKind::Split, + LinkerPluginLto::Unspecified, + RemapPathPrefix::Unspecified, + RemapPathScope::Unspecified, + ); + + // unpacked-single + shared_linux_other_tests::split_debuginfo( + CrossCrateTest::No, + unstable_options, + SplitDebuginfo::Unpacked, + DebuginfoLevel::Full, + SplitDwarfKind::Single, + LinkerPluginLto::Unspecified, + RemapPathPrefix::Unspecified, + RemapPathScope::Unspecified, + ); + + // unpacked-lto-split + shared_linux_other_tests::split_debuginfo( + CrossCrateTest::No, + unstable_options, + SplitDebuginfo::Unpacked, + DebuginfoLevel::Full, + SplitDwarfKind::Split, + LinkerPluginLto::Yes, + RemapPathPrefix::Unspecified, + RemapPathScope::Unspecified, + ); + + // unpacked-lto-single + shared_linux_other_tests::split_debuginfo( + CrossCrateTest::No, + unstable_options, + SplitDebuginfo::Unpacked, + DebuginfoLevel::Full, + SplitDwarfKind::Single, + LinkerPluginLto::Yes, + RemapPathPrefix::Unspecified, + RemapPathScope::Unspecified, + ); + + // unpacked-remapped-split + shared_linux_other_tests::split_debuginfo( + CrossCrateTest::No, + unstable_options, + SplitDebuginfo::Unpacked, + DebuginfoLevel::Full, + SplitDwarfKind::Split, + LinkerPluginLto::Unspecified, + RemapPathPrefix::Yes { remapped_prefix: "/__MY_REMAPPED_PATH__" }, + RemapPathScope::Unspecified, + ); + + // unpacked-remapped-single + shared_linux_other_tests::split_debuginfo( + CrossCrateTest::No, + unstable_options, + SplitDebuginfo::Unpacked, + DebuginfoLevel::Full, + SplitDwarfKind::Single, + LinkerPluginLto::Unspecified, + RemapPathPrefix::Yes { remapped_prefix: "/__MY_REMAPPED_PATH__" }, + RemapPathScope::Unspecified, + ); + + // unpacked-remapped-scope + shared_linux_other_tests::split_debuginfo( + CrossCrateTest::No, + unstable_options, + SplitDebuginfo::Unpacked, + DebuginfoLevel::Full, + SplitDwarfKind::Single, + LinkerPluginLto::Unspecified, + RemapPathPrefix::Yes { remapped_prefix: "/__MY_REMAPPED_PATH__" }, + RemapPathScope::Yes("debuginfo"), + ); + + // unpacked-remapped-wrong-scope + shared_linux_other_tests::split_debuginfo( + CrossCrateTest::No, + unstable_options, + SplitDebuginfo::Unpacked, + DebuginfoLevel::Full, + SplitDwarfKind::Single, + LinkerPluginLto::Unspecified, + RemapPathPrefix::Yes { remapped_prefix: "/__MY_REMAPPED_PATH__" }, + RemapPathScope::Yes("macro"), + ); + + // unpacked-crosscrate-split + shared_linux_other_tests::split_debuginfo( + CrossCrateTest::Yes, + unstable_options, + SplitDebuginfo::Unpacked, + DebuginfoLevel::Full, + SplitDwarfKind::Split, + LinkerPluginLto::Unspecified, + RemapPathPrefix::Unspecified, + RemapPathScope::Unspecified, + ); + + // unpacked-crosscrate-single + shared_linux_other_tests::split_debuginfo( + CrossCrateTest::Yes, + unstable_options, + SplitDebuginfo::Unpacked, + DebuginfoLevel::Full, + SplitDwarfKind::Single, + LinkerPluginLto::Unspecified, + RemapPathPrefix::Unspecified, + RemapPathScope::Unspecified, + ); + } +}