diff --git a/src/compiler/trim_paths.rs b/src/compiler/trim_paths.rs index 99629cb9c9a..59587425820 100644 --- a/src/compiler/trim_paths.rs +++ b/src/compiler/trim_paths.rs @@ -34,6 +34,9 @@ pub(crate) const UNREMAP_SUFFIX: &str = ".trim-paths.jsonl"; /// See . pub(crate) const WS_REMAP_ENV: &str = "__CARGO_RUSTC_BOOTSTRAP_WS_REMAP"; +/// A single `=` remap rule. +type RemapPair = (PathBuf, String); + /// Like [`trim_paths_args`] but for rustdoc invocations. pub(crate) fn trim_paths_args_rustdoc( cmd: &mut ProcessBuilder, @@ -103,15 +106,19 @@ pub(crate) fn trim_paths_args( /// **†**: path dependencies outside the workspace and other uncategorized dependencies. /// /// [RFC 3127]: https://rust-lang.github.io/rfcs/3127-trim-paths.html -pub(crate) fn trim_paths_remap(build_runner: &BuildRunner<'_, '_>, unit: &Unit) -> [OsString; 3] { - [ - join_remap(package_remap(build_runner, unit)), - join_remap(build_dir_remap(build_runner)), - join_remap(sysroot_remap(build_runner)), - ] +pub(crate) fn trim_paths_remap(build_runner: &BuildRunner<'_, '_>, unit: &Unit) -> Vec { + let package = package_remap(build_runner, unit); + let workspace_relative = custom_workspace_relative_remap(unit, &package); + + let mut remaps = Vec::with_capacity(4); + remaps.push(join_remap(package)); + remaps.extend(workspace_relative.map(join_remap)); + remaps.push(join_remap(build_dir_remap(build_runner))); + remaps.push(join_remap(sysroot_remap(build_runner))); + remaps } -fn join_remap((from, to): (PathBuf, String)) -> OsString { +fn join_remap((from, to): RemapPair) -> OsString { let mut remap = OsString::with_capacity(from.as_os_str().len() + 1 + to.len()); remap.push(from); remap.push("="); @@ -123,7 +130,7 @@ fn join_remap((from, to): (PathBuf, String)) -> OsString { /// /// This remap logic aligns with rustc: /// -fn sysroot_remap(build_runner: &BuildRunner<'_, '_>) -> (PathBuf, String) { +fn sysroot_remap(build_runner: &BuildRunner<'_, '_>) -> RemapPair { // See also `detect_sysroot_src_path()`. let sysroot = build_runner .bcx @@ -142,7 +149,7 @@ fn sysroot_remap(build_runner: &BuildRunner<'_, '_>) -> (PathBuf, String) { } /// Path prefix remap rules for dependencies. -fn package_remap(build_runner: &BuildRunner<'_, '_>, unit: &Unit) -> (PathBuf, String) { +fn package_remap(build_runner: &BuildRunner<'_, '_>, unit: &Unit) -> RemapPair { let pkg_root = unit.pkg.root(); let ws_root = build_runner.bcx.ws.root(); let source_id = unit.pkg.package_id().source_id(); @@ -175,7 +182,7 @@ fn package_remap(build_runner: &BuildRunner<'_, '_>, unit: &Unit) -> (PathBuf, S } /// Path prefix remap rules for dependencies within workspaces. -fn workspace_remap(build_runner: &BuildRunner<'_, '_>, unit: &Unit) -> (PathBuf, String) { +fn workspace_remap(build_runner: &BuildRunner<'_, '_>, unit: &Unit) -> RemapPair { let ws_root = build_runner.bcx.ws.root(); // rustc working directory is usually workspace root. // However, when `-Zroot-dir` is set, it may not be. @@ -199,6 +206,38 @@ fn workspace_remap(build_runner: &BuildRunner<'_, '_>, unit: &Unit) -> (PathBuf, (from, to) } +/// Extra remap rule for relative workspace member paths. +/// +/// Cargo passes member source paths relative to the working directory (see [`path_args`]), +/// so the absolute [`workspace_remap`] rule never covers them. +/// +/// When custom prefix for workspace remap is set via [`WS_REMAP_ENV`], +/// an extra remap rule for relative member paths is required for correctly +/// adding prefix to member paths. +fn custom_workspace_relative_remap(unit: &Unit, (from, to): &RemapPair) -> Option { + // `to` staying as `.` means WS_REMAP_ENV didn't kick in. + if to == "." { + return None; + } + + if !unit.pkg.package_id().source_id().is_path() { + return None; + } + + let rel = unit.pkg.root().strip_prefix(from).ok()?; + if rel.as_os_str().is_empty() { + return None; + } + + let mut rel_to = to.clone(); + for comp in rel.components() { + // e.g., library -> /library + rel_to.push('/'); + rel_to.push_str(&comp.as_os_str().to_string_lossy()); + } + Some((rel.to_path_buf(), rel_to)) +} + /// Finds the checkout root and revision directory name of a git dependency. /// /// This is built under this layout: `$CARGO_HOME/git/checkouts/-[-shallow]/`. @@ -231,7 +270,7 @@ fn git_checkout<'a>( /// [`file!`] macro in-place via the `OUT_DIR` environment. /// * On Linux, `DW_AT_GNU_dwo_name` that contains paths to split debuginfo /// files (dwp and dwo). -fn build_dir_remap(build_runner: &BuildRunner<'_, '_>) -> (PathBuf, String) { +fn build_dir_remap(build_runner: &BuildRunner<'_, '_>) -> RemapPair { let from = build_runner.bcx.ws.build_dir().into_path_unlocked(); let to = "/cargo/build-dir".to_owned(); (from, to) @@ -280,7 +319,7 @@ pub(crate) fn write_unremap_file( ) -> CargoResult<()> { let mut remaps = BTreeMap::new(); - let mut insert = |(from, to): (PathBuf, String)| match remaps.entry(to) { + let mut insert = |(from, to): RemapPair| match remaps.entry(to) { Entry::Vacant(entry) => { entry.insert(from); } diff --git a/tests/testsuite/profile_trim_paths.rs b/tests/testsuite/profile_trim_paths.rs index fe43b4b6545..beec8327076 100644 --- a/tests/testsuite/profile_trim_paths.rs +++ b/tests/testsuite/profile_trim_paths.rs @@ -1640,19 +1640,27 @@ fn workspace_prefix_override_from_env() { version = "0.0.1" edition = "2015" + [dependencies] + member = { path = "member" } + [profile.dev] trim-paths = "object" "#, ) .file("src/main.rs", "fn main() {}") + .file("member/Cargo.toml", &basic_manifest("member", "0.0.1")) + .file("member/src/lib.rs", "") .build(); p.cargo("build --verbose -Ztrim-paths") .env("__CARGO_RUSTC_BOOTSTRAP_WS_REMAP", "/rustc-dev/1111111") .masquerade_as_nightly_cargo(&["-Ztrim-paths"]) .with_stderr_data(str![[r#" +[LOCKING] 1 package to highest compatible version +[COMPILING] member v0.0.1 ([ROOT]/foo/member) +[RUNNING] `rustc [..]--remap-path-prefix=[ROOT]/foo=/rustc-dev/1111111 --remap-path-prefix=member=/rustc-dev/1111111/member --remap-path-prefix=[ROOT]/foo/target=/cargo/build-dir [..]` [COMPILING] foo v0.0.1 ([ROOT]/foo) -[RUNNING] `rustc [..]--remap-path-prefix=[ROOT]/foo=/rustc-dev/1111111 [..]` +[RUNNING] `rustc [..]--remap-path-prefix=[ROOT]/foo=/rustc-dev/1111111 --remap-path-prefix=[ROOT]/foo/target=/cargo/build-dir [..]` [FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s "#]])