Skip to content

Commit ad2636d

Browse files
committed
add unstable -Zroot-path flag to configure the path from which rustc should be invoked
1 parent 06e0ef4 commit ad2636d

File tree

4 files changed

+105
-15
lines changed

4 files changed

+105
-15
lines changed

src/cargo/core/features.rs

+11
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,7 @@
121121
use std::collections::BTreeSet;
122122
use std::env;
123123
use std::fmt::{self, Write};
124+
use std::path::PathBuf;
124125
use std::str::FromStr;
125126

126127
use anyhow::{bail, Error};
@@ -783,6 +784,7 @@ unstable_cli_options!(
783784
profile_rustflags: bool = ("Enable the `rustflags` option in profiles in .cargo/config.toml file"),
784785
public_dependency: bool = ("Respect a dependency's `public` field in Cargo.toml to control public/private dependencies"),
785786
publish_timeout: bool = ("Enable the `publish.timeout` key in .cargo/config.toml file"),
787+
root_dir: Option<PathBuf> = ("Set the root directory relative to which paths are printed (defaults to workspace root)"),
786788
rustdoc_map: bool = ("Allow passing external documentation mappings to rustdoc"),
787789
rustdoc_scrape_examples: bool = ("Allows Rustdoc to scrape code examples from reverse-dependencies"),
788790
script: bool = ("Enable support for single-file, `.rs` packages"),
@@ -1287,6 +1289,15 @@ impl CliUnstable {
12871289
"profile-rustflags" => self.profile_rustflags = parse_empty(k, v)?,
12881290
"trim-paths" => self.trim_paths = parse_empty(k, v)?,
12891291
"publish-timeout" => self.publish_timeout = parse_empty(k, v)?,
1292+
"root-dir" => self.root_dir = v.map(|v| {
1293+
// Make the path absolute, if we can.
1294+
let v = PathBuf::from(v);
1295+
if v.is_absolute() {
1296+
v
1297+
} else {
1298+
v.canonicalize().unwrap_or(v)
1299+
}
1300+
}),
12901301
"rustdoc-map" => self.rustdoc_map = parse_empty(k, v)?,
12911302
"rustdoc-scrape-examples" => self.rustdoc_scrape_examples = parse_empty(k, v)?,
12921303
"separate-nightlies" => self.separate_nightlies = parse_empty(k, v)?,

src/cargo/util/workspace.rs

+9-3
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ use crate::core::{Target, Workspace};
44
use crate::ops::CompileOptions;
55
use crate::util::CargoResult;
66
use anyhow::bail;
7+
use cargo_util::paths::normalize_path;
78
use cargo_util::ProcessBuilder;
89
use std::fmt::Write;
910
use std::path::PathBuf;
@@ -109,15 +110,20 @@ pub fn print_available_tests(ws: &Workspace<'_>, options: &CompileOptions) -> Ca
109110
/// The first returned value here is the argument to pass to rustc, and the
110111
/// second is the cwd that rustc should operate in.
111112
pub fn path_args(ws: &Workspace<'_>, unit: &Unit) -> (PathBuf, PathBuf) {
112-
let ws_root = ws.root();
113113
let src = match unit.target.src_path() {
114114
TargetSourcePath::Path(path) => path.to_path_buf(),
115115
TargetSourcePath::Metabuild => unit.pkg.manifest().metabuild_path(ws.target_dir()),
116116
};
117117
assert!(src.is_absolute());
118118
if unit.pkg.package_id().source_id().is_path() {
119-
if let Ok(path) = src.strip_prefix(ws_root) {
120-
return (path.to_path_buf(), ws_root.to_path_buf());
119+
// Determine which path we make this relative to: usually it's the workspace root,
120+
// but this can be overwritten with a `-Z` flag.
121+
let root = match &ws.gctx().cli_unstable().root_dir {
122+
None => ws.root().to_owned(),
123+
Some(root_dir) => normalize_path(&ws.gctx().cwd().join(root_dir)),
124+
};
125+
if let Ok(path) = src.strip_prefix(&root) {
126+
return (path.to_path_buf(), root);
121127
}
122128
}
123129
(src, unit.pkg.root().to_path_buf())

tests/testsuite/cargo/z_help/stdout.term.svg

+14-12
Loading

tests/testsuite/directory.rs

+71
Original file line numberDiff line numberDiff line change
@@ -784,3 +784,74 @@ Caused by:
784784
.with_status(101)
785785
.run();
786786
}
787+
788+
#[cargo_test]
789+
fn root_path_diagnostics() {
790+
let p = ProjectBuilder::new(paths::root())
791+
.no_manifest() // we are placing it in a different dir
792+
.file(
793+
"ws_root/Cargo.toml",
794+
r#"
795+
[package]
796+
name = "foo"
797+
version = "0.1.0"
798+
edition = "2015"
799+
authors = []
800+
"#,
801+
)
802+
.file("ws_root/src/lib.rs", "invalid;")
803+
.build();
804+
805+
// Crucially, the rustc error message below says `ws_root/...`, i.e.
806+
// it is relative to our fake home, not to the workspace root.
807+
p.cargo("check")
808+
.arg("-Zroot-path=.")
809+
.arg("--manifest-path=ws_root/Cargo.toml")
810+
.masquerade_as_nightly_cargo(&["-Zroot-path"])
811+
.with_status(101)
812+
.with_stderr_data(str![[r#"
813+
[CHECKING] foo v0.1.0 ([ROOT]/ws_root)
814+
[ERROR] expected one of `!` or `::`, found `;`
815+
--> ws_root/src/lib.rs:1:8
816+
|
817+
1 | invalid;
818+
| [..]
819+
820+
[ERROR] could not compile `foo` (lib) due to 1 previous error
821+
822+
"#]])
823+
.run();
824+
}
825+
826+
#[cargo_test]
827+
fn root_path_file_macro() {
828+
let p = ProjectBuilder::new(paths::root())
829+
.no_manifest() // we are placing it in a different dir
830+
.file(
831+
"ws_root/Cargo.toml",
832+
r#"
833+
[package]
834+
name = "foo"
835+
version = "0.1.0"
836+
edition = "2015"
837+
authors = []
838+
"#,
839+
)
840+
.file(
841+
"ws_root/src/main.rs",
842+
r#"fn main() { println!("{}", file!()); }"#,
843+
)
844+
.build();
845+
846+
// Crucially, the rustc error message below says `ws_root/...`, i.e.
847+
// it is relative to our fake home, not to the workspace root.
848+
p.cargo("run")
849+
.arg("-Zroot-path=.")
850+
.arg("--manifest-path=ws_root/Cargo.toml")
851+
.masquerade_as_nightly_cargo(&["-Zroot-path"])
852+
.with_stdout_data(str![[r#"
853+
ws_root/src/main.rs
854+
855+
"#]])
856+
.run();
857+
}

0 commit comments

Comments
 (0)