diff --git a/src/tools/run-make-support/src/external_deps/llvm.rs b/src/tools/run-make-support/src/external_deps/llvm.rs index dc651fdd8205a..7af79443affd6 100644 --- a/src/tools/run-make-support/src/external_deps/llvm.rs +++ b/src/tools/run-make-support/src/external_deps/llvm.rs @@ -48,6 +48,12 @@ pub fn llvm_bcanalyzer() -> LlvmBcanalyzer { LlvmBcanalyzer::new() } +/// Construct a new `llvm-dwarfdump` invocation. This assumes that `llvm-dwarfdump` is available +/// at `$LLVM_BIN_DIR/llvm-dwarfdump`. +pub fn llvm_dwarfdump() -> LlvmDwarfdump { + LlvmDwarfdump::new() +} + /// A `llvm-readobj` invocation builder. #[derive(Debug)] #[must_use] @@ -97,6 +103,13 @@ pub struct LlvmBcanalyzer { cmd: Command, } +/// A `llvm-dwarfdump` invocation builder. +#[derive(Debug)] +#[must_use] +pub struct LlvmDwarfdump { + cmd: Command, +} + crate::macros::impl_common_helpers!(LlvmReadobj); crate::macros::impl_common_helpers!(LlvmProfdata); crate::macros::impl_common_helpers!(LlvmFilecheck); @@ -104,6 +117,7 @@ crate::macros::impl_common_helpers!(LlvmObjdump); crate::macros::impl_common_helpers!(LlvmAr); crate::macros::impl_common_helpers!(LlvmNm); crate::macros::impl_common_helpers!(LlvmBcanalyzer); +crate::macros::impl_common_helpers!(LlvmDwarfdump); /// Generate the path to the bin directory of LLVM. #[must_use] @@ -317,3 +331,19 @@ impl LlvmBcanalyzer { self } } + +impl LlvmDwarfdump { + /// Construct a new `llvm-dwarfdump` invocation. This assumes that `llvm-dwarfdump` is available + /// at `$LLVM_BIN_DIR/llvm-dwarfdump`. + pub fn new() -> Self { + let llvm_dwarfdump = llvm_bin_dir().join("llvm-dwarfdump"); + let cmd = Command::new(llvm_dwarfdump); + Self { cmd } + } + + /// Provide an input file. + pub fn input>(&mut self, path: P) -> &mut Self { + self.cmd.arg(path.as_ref()); + self + } +} diff --git a/src/tools/run-make-support/src/lib.rs b/src/tools/run-make-support/src/lib.rs index a44dd00ad7986..4d0c1b0930ced 100644 --- a/src/tools/run-make-support/src/lib.rs +++ b/src/tools/run-make-support/src/lib.rs @@ -49,8 +49,9 @@ pub use c_build::{build_native_dynamic_lib, build_native_static_lib, build_nativ pub use clang::{clang, Clang}; pub use htmldocck::htmldocck; pub use llvm::{ - llvm_ar, llvm_bcanalyzer, llvm_filecheck, llvm_nm, llvm_objdump, llvm_profdata, llvm_readobj, - LlvmAr, LlvmBcanalyzer, LlvmFilecheck, LlvmNm, LlvmObjdump, LlvmProfdata, LlvmReadobj, + llvm_ar, llvm_bcanalyzer, llvm_dwarfdump, llvm_filecheck, llvm_nm, llvm_objdump, llvm_profdata, + llvm_readobj, LlvmAr, LlvmBcanalyzer, LlvmDwarfdump, LlvmFilecheck, LlvmNm, LlvmObjdump, + LlvmProfdata, LlvmReadobj, }; pub use python::python_command; pub use rustc::{aux_build, bare_rustc, rustc, Rustc}; diff --git a/src/tools/tidy/src/allowed_run_make_makefiles.txt b/src/tools/tidy/src/allowed_run_make_makefiles.txt index 5c1d9a2d47e20..fd519b23526e0 100644 --- a/src/tools/tidy/src/allowed_run_make_makefiles.txt +++ b/src/tools/tidy/src/allowed_run_make_makefiles.txt @@ -21,7 +21,6 @@ run-make/pgo-indirect-call-promotion/Makefile run-make/remap-path-prefix-dwarf/Makefile run-make/reproducible-build/Makefile run-make/rlib-format-packed-bundled-libs/Makefile -run-make/split-debuginfo/Makefile run-make/staticlib-dylib-linkage/Makefile run-make/symbol-mangling-hashed/Makefile run-make/sysroot-crates-are-unstable/Makefile diff --git a/tests/run-make/split-debuginfo/Makefile b/tests/run-make/split-debuginfo/Makefile deleted file mode 100644 index 5f463ffe8cde6..0000000000000 --- a/tests/run-make/split-debuginfo/Makefile +++ /dev/null @@ -1,371 +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 -C $(UNSTABLEOPTS) 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 -C debuginfo=2 \ - -Z split-dwarf-kind=split --remap-path-prefix $(TMPDIR)=/a foo.rs -g - 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 -C debuginfo=2 \ - -Z split-dwarf-kind=single --remap-path-prefix $(TMPDIR)=/a foo.rs -g - 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 -C debuginfo=2 \ - -Z split-dwarf-kind=single --remap-path-prefix $(TMPDIR)=/a \ - -Z remap-path-scope=debuginfo foo.rs -g - 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-wrong-scope: - $(RUSTC) $(UNSTABLEOPTS) -C split-debuginfo=packed -C debuginfo=2 \ - -Z split-dwarf-kind=single --remap-path-prefix $(TMPDIR)=/a \ - -Z remap-path-scope=macro foo.rs -g - 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 -C debuginfo=2 -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 -C debuginfo=2 -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 -C debuginfo=2 -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 -C debuginfo=2 -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` present (bitcode) -# - `.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 -C debuginfo=2 \ - -Z split-dwarf-kind=split --remap-path-prefix $(TMPDIR)=/a foo.rs -g - 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 -C debuginfo=2 \ - -Z split-dwarf-kind=single --remap-path-prefix $(TMPDIR)=/a foo.rs -g - 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 -C debuginfo=2 \ - -Z split-dwarf-kind=single --remap-path-prefix $(TMPDIR)=/a \ - -Z remap-path-scope=debuginfo foo.rs -g - 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 -C debuginfo=2 \ - -Z split-dwarf-kind=single --remap-path-prefix $(TMPDIR)=/a \ - -Z remap-path-scope=macro foo.rs -g - 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 -C debuginfo=2 -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 -C debuginfo=2 -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 -C debuginfo=2 -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 -C debuginfo=2 -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 -endif diff --git a/tests/run-make/split-debuginfo/baz.rs b/tests/run-make/split-debuginfo/lto.rs similarity index 100% rename from tests/run-make/split-debuginfo/baz.rs rename to tests/run-make/split-debuginfo/lto.rs diff --git a/tests/run-make/split-debuginfo/rmake.rs b/tests/run-make/split-debuginfo/rmake.rs new file mode 100644 index 0000000000000..c1c4efe576fe0 --- /dev/null +++ b/tests/run-make/split-debuginfo/rmake.rs @@ -0,0 +1,428 @@ +// This test checks that the `-C split-debuginfo` feature behaves in certain expected +// ways. It comes in 3 different flavours: +// * `off` - This indicates that split-debuginfo from the final artifact is +// not desired. This is not supported on Windows and is the default on +// Unix platforms except macOS. On macOS this means that `dsymutil` is +// not executed. + +// * `packed` - This means that debuginfo is desired in one location +// separate from the main executable. This is the default on Windows +// (`*.pdb`) and macOS (`*.dSYM`). On other Unix platforms this subsumes +// `-Zsplit-dwarf=single` and produces a `*.dwp` file. + +// * `unpacked` - This means that debuginfo will be roughly equivalent to +// object files, meaning that it's throughout the build directory +// rather than in one location (often the fastest for local development). +// This is not the default on any platform and is not supported on Windows. +// For each test, compilation should be successful, output artifacts should be +// exactly what is expected, no more, no less, and in some cases, the dwarf dump +// of debuginfo should reveal a certain symbol and the current working directory, +// depending on if the scope passed was wrong or not. +// See https://github.com/rust-lang/rust/pull/81493 + +//@ ignore-windows +// Reason: Windows only supports packed debuginfo - nothing to test. +//@ ignore-riscv64 +// Reason: on this platform only `-Csplit-debuginfo=off` is supported, see #120518 + +//FIXME(Oneirical): try it with ignore-cross-compile + +use run_make_support::{ + bin_name, cwd, has_extension, is_darwin, llvm_dwarfdump, rfs, rust_lib_name, rustc, + shallow_find_files, target, Rustc, +}; + +fn main() { + if is_darwin() { + // If disabled, don't run `dsymutil`. + for dsym in shallow_find_files(cwd(), |path| has_extension(path, "dSYM")) { + rfs::remove_file(dsym); + } + rustc().input("foo.rs").arg("-g").arg("-Csplit-debuginfo=off").run(); + check_extension_not_exists("dSYM"); + + // Packed by default, but only if debuginfo is requested + for dsym in shallow_find_files(cwd(), |path| has_extension(path, "dSYM")) { + rfs::remove_file(dsym); + } + rustc().input("foo.rs").run(); + check_extension_not_exists("dSYM"); + rustc().input("foo.rs").arg("-g").run(); + check_extension_exists("dSYM"); + for dsym in shallow_find_files(cwd(), |path| has_extension(path, "dSYM")) { + rfs::remove_file(dsym); + } + rustc().input("foo.rs").arg("-g").arg("-Csplit-debuginfo=packed").run(); + check_extension_exists("dSYM"); + + // Object files are preserved with unpacked and `dsymutil` isn't run + for dsym in shallow_find_files(cwd(), |path| has_extension(path, "dSYM")) { + rfs::remove_file(dsym); + } + rustc().input("foo.rs").arg("-g").arg("-Csplit-debuginfo=unpacked").run(); + check_extension_exists("o"); + check_extension_not_exists("dSYM"); + } else { + // PACKED + + unstable_rustc().input("foo.rs").arg("-g").arg("-Csplit-debuginfo=off").run(); + check_extension_not_exists("dwp"); + check_extension_not_exists("dwo"); + rustc().input("foo.rs").arg("-g").run(); + check_extension_not_exists("dwp"); + check_extension_not_exists("dwo"); + + let split_dwarf_types = [SplitDwarf::Split, SplitDwarf::Single]; + + for dwarf_type in split_dwarf_types { + run_test(DebugInfoTest { + input: "foo.rs", + crate_type: None, + debug_info: DebugInfo::Packed, + split_dwarf: dwarf_type, + has_o: false, + has_dwo: false, + dwp: Some("foo"), + output: Some(bin_name("foo")), + remap_scope: None, + }); + } + + for dwarf_type in split_dwarf_types { + run_test(DebugInfoTest { + input: "lto.rs", + crate_type: Some(CrateType::Rlib), + debug_info: DebugInfo::Packed, + split_dwarf: dwarf_type, + has_o: false, + has_dwo: false, + dwp: None, + output: Some(rust_lib_name("lto")), + remap_scope: None, + }); + } + + for dwarf_type in split_dwarf_types { + run_test(DebugInfoTest { + input: "foo.rs", + crate_type: None, + debug_info: DebugInfo::Packed, + split_dwarf: dwarf_type, + has_o: false, + has_dwo: false, + dwp: Some("foo"), + output: Some(bin_name("foo")), + remap_scope: Some(None), + }); + } + + run_test(DebugInfoTest { + input: "foo.rs", + crate_type: None, + debug_info: DebugInfo::Packed, + split_dwarf: SplitDwarf::Single, + has_o: false, + has_dwo: false, + dwp: Some("foo"), + output: Some(bin_name("foo")), + remap_scope: Some(Some(Scope::Debug)), + }); + run_test(DebugInfoTest { + input: "foo.rs", + crate_type: None, + debug_info: DebugInfo::Packed, + split_dwarf: SplitDwarf::Single, + has_o: false, + has_dwo: false, + dwp: Some("foo"), + output: Some(bin_name("foo")), + remap_scope: Some(Some(Scope::Macro)), + }); + + for dwarf_type in split_dwarf_types { + run_test(DebugInfoTest { + input: "bar.rs", + crate_type: Some(CrateType::Lib), + debug_info: DebugInfo::Packed, + split_dwarf: dwarf_type, + has_o: false, + has_dwo: false, + dwp: None, + output: None, + remap_scope: None, + }); + run_test(DebugInfoTest { + input: "main.rs", + crate_type: None, + debug_info: DebugInfo::Packed, + split_dwarf: dwarf_type, + has_o: false, + has_dwo: false, + dwp: Some("main"), + output: Some(bin_name("main")), + remap_scope: None, + }); + } + + // UNPACKED + + run_test(DebugInfoTest { + input: "foo.rs", + crate_type: None, + debug_info: DebugInfo::Unpacked, + split_dwarf: SplitDwarf::Split, + has_o: false, + has_dwo: true, + dwp: None, + output: Some(bin_name("foo")), + remap_scope: None, + }); + run_test(DebugInfoTest { + input: "foo.rs", + crate_type: None, + debug_info: DebugInfo::Unpacked, + split_dwarf: SplitDwarf::Single, + has_o: true, + has_dwo: false, + dwp: None, + output: Some(bin_name("foo")), + remap_scope: None, + }); + + for dwarf_type in split_dwarf_types { + run_test(DebugInfoTest { + input: "lto.rs", + crate_type: Some(CrateType::Rlib), + debug_info: DebugInfo::Unpacked, + split_dwarf: dwarf_type, + has_o: true, + has_dwo: false, + dwp: None, + output: Some(rust_lib_name("lto")), + remap_scope: None, + }); + } + + run_test(DebugInfoTest { + input: "foo.rs", + crate_type: None, + debug_info: DebugInfo::Unpacked, + split_dwarf: SplitDwarf::Split, + has_o: false, + has_dwo: true, + dwp: None, + output: Some(bin_name("foo")), + remap_scope: Some(None), + }); + run_test(DebugInfoTest { + input: "foo.rs", + crate_type: None, + debug_info: DebugInfo::Unpacked, + split_dwarf: SplitDwarf::Single, + has_o: true, + has_dwo: false, + dwp: None, + output: Some(bin_name("foo")), + remap_scope: Some(None), + }); + + run_test(DebugInfoTest { + input: "foo.rs", + crate_type: None, + debug_info: DebugInfo::Unpacked, + split_dwarf: SplitDwarf::Single, + has_o: true, + has_dwo: false, + dwp: None, + output: Some(bin_name("foo")), + remap_scope: Some(Some(Scope::Debug)), + }); + run_test(DebugInfoTest { + input: "foo.rs", + crate_type: None, + debug_info: DebugInfo::Unpacked, + split_dwarf: SplitDwarf::Single, + has_o: true, + has_dwo: false, + dwp: None, + output: Some(bin_name("foo")), + remap_scope: Some(Some(Scope::Macro)), + }); + + run_test(DebugInfoTest { + input: "bar.rs", + crate_type: Some(CrateType::Lib), + debug_info: DebugInfo::Unpacked, + split_dwarf: SplitDwarf::Split, + has_o: false, + has_dwo: true, + dwp: None, + output: None, + remap_scope: None, + }); + run_test(DebugInfoTest { + input: "main.rs", + crate_type: None, + debug_info: DebugInfo::Unpacked, + split_dwarf: SplitDwarf::Split, + has_o: false, + has_dwo: true, + dwp: None, + output: Some(bin_name("main")), + remap_scope: None, + }); + + run_test(DebugInfoTest { + input: "bar.rs", + crate_type: Some(CrateType::Lib), + debug_info: DebugInfo::Unpacked, + split_dwarf: SplitDwarf::Single, + has_o: true, + has_dwo: false, + dwp: None, + output: None, + remap_scope: None, + }); + run_test(DebugInfoTest { + input: "main.rs", + crate_type: None, + debug_info: DebugInfo::Unpacked, + split_dwarf: SplitDwarf::Single, + has_o: true, + has_dwo: false, + dwp: None, + output: Some(bin_name("main")), + remap_scope: None, + }); + } +} + +#[track_caller] +fn run_test(params: DebugInfoTest) { + let mut compiler = unstable_rustc(); + compiler.input(params.input).arg("-g"); + match params.debug_info { + DebugInfo::Packed => compiler.arg("-Csplit-debuginfo=packed"), + DebugInfo::Unpacked => compiler.arg("-Csplit-debuginfo=unpacked"), + }; + match params.split_dwarf { + SplitDwarf::Split => compiler.arg("-Zsplit-dwarf-kind=split"), + SplitDwarf::Single => compiler.arg("-Zsplit-dwarf-kind=single"), + }; + if let Some(crate_type) = params.crate_type { + match crate_type { + CrateType::Rlib => compiler.crate_type("rlib"), + CrateType::Lib => compiler.crate_type("lib"), + }; + }; + if params.input == "lto.rs" { + compiler.arg("-Clinker-plugin-lto"); + } + if params.input == "main.rs" { + compiler.extern_("bar", rust_lib_name("bar")); + } + if let Some(remap) = params.remap_scope { + compiler.remap_path_prefix(cwd(), "/a"); + if let Some(scope) = remap { + match scope { + Scope::Debug => compiler.arg("-Zremap-path-scope=debuginfo"), + Scope::Macro => compiler.arg("-Zremap-path-scope=macro"), + }; + }; + } + compiler.run(); + if let Some(remap) = params.remap_scope { + let mut objdump = llvm_dwarfdump(); + let out = objdump.arg("--debug-info").input("foo").run(); + out.assert_stdout_contains("DW_AT_GNU_dwo_name"); + if let Some(scope) = remap { + match scope { + Scope::Debug => out.assert_stdout_not_contains(cwd().display().to_string()), + Scope::Macro => out.assert_stdout_contains(cwd().display().to_string()), + }; + } else { + out.assert_stdout_not_contains(cwd().display().to_string()); + }; + } + if params.has_o { + for object in shallow_find_files(cwd(), |path| has_extension(path, "o")) { + rfs::remove_file(object); + } + } else { + check_extension_not_exists("o"); + } + if params.has_dwo { + for dwo in shallow_find_files(cwd(), |path| has_extension(path, "dwo")) { + rfs::remove_file(dwo); + } + } else { + check_extension_not_exists("dwo"); + } + if let Some(name) = params.dwp { + rfs::remove_file(&format!("{name}.dwp")); + } else { + check_extension_not_exists("dwp"); + } + if let Some(output) = params.output { + rfs::remove_file(output); + } +} + +struct DebugInfoTest { + input: &'static str, + crate_type: Option, + debug_info: DebugInfo, + split_dwarf: SplitDwarf, + has_o: bool, + has_dwo: bool, + dwp: Option<&'static str>, + output: Option, + remap_scope: Option>, +} + +enum CrateType { + Lib, + Rlib, +} + +#[derive(Clone, Copy)] +enum Scope { + Debug, + Macro, +} + +enum DebugInfo { + Packed, + Unpacked, +} + +#[derive(Clone, Copy)] +enum SplitDwarf { + Split, + Single, +} + +// Some non-Windows, non-Darwin platforms are not stable, and some are. +fn unstable_rustc() -> Rustc { + let mut compiler = rustc(); + if !target().contains("linux") { + compiler.arg("-Zunstable-options"); + } + compiler +} + +#[track_caller] +fn check_extension_exists(ext: &str) { + if shallow_find_files(cwd(), |path| has_extension(path, ext)).len() == 0 { + eprintln!("{:#?}", rfs::shallow_find_dir_entries(cwd())); + panic!("a file with the requested extension {ext} was not found"); + } +} + +#[track_caller] +fn check_extension_not_exists(ext: &str) { + if shallow_find_files(cwd(), |path| has_extension(path, ext)).len() > 0 { + eprintln!("{:#?}", rfs::shallow_find_dir_entries(cwd())); + panic!("a file with the requested extension {ext} was unexpectedly found"); + } +}