// This test makes sure that --remap-path-prefix has the expected effects on paths in debuginfo. // We explicitly switch to a directory that *is* a prefix of the directory our // source code is contained in. // It tests several cases, each of them has a detailed description attached to it. // See https://github.com/rust-lang/rust/pull/96867 //@ ignore-windows // Reason: the remap path prefix is not printed in the dwarf dump. use run_make_support::{cwd, is_darwin, llvm_dwarfdump, rust_lib_name, rustc}; fn main() { // The compiler is called with an *ABSOLUTE PATH* as input, and that absolute path *is* within // the working directory of the compiler. We are remapping the path that contains `src`. check_dwarf(DwarfTest { lib_name: "abs_input_inside_working_dir", input_path: PathType::Absolute, scope: None, remap_path_prefix: PrefixType::Regular(format!("{}=REMAPPED", cwd().display())), dwarf_test: DwarfDump::ContainsSrcPath, }); check_dwarf(DwarfTest { lib_name: "abs_input_inside_working_dir_scope", input_path: PathType::Absolute, scope: Some(ScopeType::Object), remap_path_prefix: PrefixType::Regular(format!("{}=REMAPPED", cwd().display())), dwarf_test: DwarfDump::ContainsSrcPath, }); // The compiler is called with an *ABSOLUTE PATH* as input, and that absolute path is *not* // within the working directory of the compiler. We are remapping both the path that contains // `src` and the working directory to the same thing. This setup corresponds to a workaround // that is needed when trying to remap everything to something that looks like a local // path. Relative paths are interpreted as relative to the compiler's working directory (e.g. // in debuginfo). If we also remap the working directory, the compiler strip it from other // paths so that the final outcome is the desired one again. check_dwarf(DwarfTest { lib_name: "abs_input_outside_working_dir", input_path: PathType::Absolute, scope: None, remap_path_prefix: PrefixType::Dual(( format!("{}=REMAPPED", cwd().display()), "rmake_out=REMAPPED".to_owned(), )), dwarf_test: DwarfDump::ContainsSrcPath, }); // The compiler is called with a *RELATIVE PATH* as input. We are remapping the working // directory of the compiler, which naturally is an implicit prefix of our relative input path. // Debuginfo will expand the relative path to an absolute path and we expect the working // directory to be remapped in that expansion. check_dwarf(DwarfTest { lib_name: "rel_input_remap_working_dir", input_path: PathType::Relative, scope: None, remap_path_prefix: PrefixType::Regular(format!("{}=REMAPPED", cwd().display())), dwarf_test: DwarfDump::ContainsSrcPath, }); check_dwarf(DwarfTest { lib_name: "rel_input_remap_working_dir_scope", input_path: PathType::Relative, scope: Some(ScopeType::Object), remap_path_prefix: PrefixType::Regular(format!("{}=REMAPPED", cwd().display())), dwarf_test: DwarfDump::ContainsSrcPath, }); check_dwarf(DwarfTest { lib_name: "rel_input_remap_working_dir_scope", input_path: PathType::Relative, scope: Some(ScopeType::Diagnostics), remap_path_prefix: PrefixType::Regular(format!("{}=REMAPPED", cwd().display())), dwarf_test: DwarfDump::AvoidSrcPath, }); // The compiler is called with a *RELATIVE PATH* as input. We are remapping a *SUB-DIRECTORY* // of the compiler's working directory. This test makes sure that that directory is remapped // even though it won't actually show up in this form in the compiler's SourceMap and instead // is only constructed on demand during debuginfo generation. check_dwarf(DwarfTest { lib_name: "rel_input_remap_working_dir_child", input_path: PathType::Relative, scope: None, remap_path_prefix: PrefixType::Regular(format!("{}=REMAPPED", cwd().join("src").display())), dwarf_test: DwarfDump::ChildTest, }); // The compiler is called with a *RELATIVE PATH* as input. We are remapping a // *PARENT DIRECTORY* of the compiler's working directory. check_dwarf(DwarfTest { lib_name: "rel_input_remap_working_dir_parent", input_path: PathType::Relative, scope: None, remap_path_prefix: PrefixType::Regular(format!( "{}=REMAPPED", cwd().parent().unwrap().display() )), dwarf_test: DwarfDump::ParentTest, }); } #[track_caller] fn check_dwarf(test: DwarfTest) { let mut rustc = rustc(); match test.input_path { PathType::Absolute => rustc.input(cwd().join("src/quux.rs")), PathType::Relative => rustc.input("src/quux.rs"), }; rustc.output(rust_lib_name(test.lib_name)); rustc.arg("-Cdebuginfo=2"); if let Some(scope) = test.scope { match scope { ScopeType::Object => rustc.arg("-Zremap-path-scope=object"), ScopeType::Diagnostics => rustc.arg("-Zremap-path-scope=diagnostics"), }; if is_darwin() { rustc.arg("-Csplit-debuginfo=off"); } } match test.remap_path_prefix { PrefixType::Regular(prefix) => { // We explicitly switch to a directory that *is* a prefix of the directory our // source code is contained in. rustc.arg("--remap-path-prefix"); rustc.arg(prefix); } PrefixType::Dual((prefix1, prefix2)) => { // We explicitly switch to a directory that is *not* a prefix of the directory our // source code is contained in. rustc.arg("--remap-path-prefix"); rustc.arg(prefix1); rustc.arg("--remap-path-prefix"); rustc.arg(prefix2); } } rustc.run(); match test.dwarf_test { DwarfDump::ContainsSrcPath => { llvm_dwarfdump() .input(rust_lib_name(test.lib_name)) .run() // We expect the path to the main source file to be remapped. .assert_stdout_contains("REMAPPED/src/quux.rs") // No weird duplication of remapped components (see #78479) .assert_stdout_not_contains("REMAPPED/REMAPPED"); } DwarfDump::AvoidSrcPath => { llvm_dwarfdump() .input(rust_lib_name(test.lib_name)) .run() .assert_stdout_not_contains("REMAPPED/src/quux.rs") .assert_stdout_not_contains("REMAPPED/REMAPPED"); } DwarfDump::ChildTest => { llvm_dwarfdump() .input(rust_lib_name(test.lib_name)) .run() // We expect `src/quux.rs` to have been remapped to `REMAPPED/quux.rs`. .assert_stdout_contains("REMAPPED/quux.rs") // We don't want to find the path that we just remapped anywhere in the DWARF .assert_stdout_not_contains(cwd().join("src").to_str().unwrap()) // No weird duplication of remapped components (see #78479) .assert_stdout_not_contains("REMAPPED/REMAPPED"); } DwarfDump::ParentTest => { llvm_dwarfdump() .input(rust_lib_name(test.lib_name)) .run() // We expect `src/quux.rs` to have been remapped to // `REMAPPED/remap-path-prefix-dwarf/src/quux.rs`. .assert_stdout_contains("REMAPPED/rmake_out/src/quux.rs") // We don't want to find the path that we just remapped anywhere in the DWARF .assert_stdout_not_contains(cwd().parent().unwrap().to_str().unwrap()) // No weird duplication of remapped components (see #78479) .assert_stdout_not_contains("REMAPPED/REMAPPED"); } }; } struct DwarfTest { lib_name: &'static str, input_path: PathType, scope: Option, remap_path_prefix: PrefixType, dwarf_test: DwarfDump, } enum PathType { Absolute, Relative, } enum ScopeType { Object, Diagnostics, } enum DwarfDump { ContainsSrcPath, AvoidSrcPath, ChildTest, ParentTest, } enum PrefixType { Regular(String), Dual((String, String)), }