Skip to content

Commit 40d804b

Browse files
committed
Auto merge of #14752 - RalfJung:rustc-root-path, r=epage
add unstable -Zroot-dir flag to configure the path from which rustc should be invoked This implements the proposal described [here](#9887 (comment)): we add a new flag, for now called `-Zroot-dir`, that configures the directory relative to which rustc is given the crate root filenames to build. (Files outside this directory are passed absolutely.) This is necessary to be able to fix (no github don't close that issue yet) rust-lang/rust#128726: in multi-workspace repositories that use scripts to manage a whole bunch of cargo invocations, currently the output cargo+rustc produce is often hard or even impossible to interpret for both human and machine consumption. This is because directories in the output are always relative to the workspace root, but when cargo is invoked many times for different workspaces, it is quite unclear what the workspace root is for the invocation that failed. So I suggest we should have a new flag that the build script in such a repo can set to the consistent "root dir" that the user would recognize as such (e.g., the root of the rustc source tree), and all paths emitted by cargo and rustc should be relative to that directory. I don't know all the places that cargo itself emits paths (if any), but this PR changes the way we invoke rustc to honor the new flag, so all paths emitted by rustc will be relative to the `-Zroot-dir`. See rust-lang/rust#132390 for the changes needed in rustc bootstrap to wire this up; together, that suffices to finally properly show errors in RA for all parts of the rustc src tree. :)
2 parents 497c228 + 0f80faf commit 40d804b

File tree

5 files changed

+114
-15
lines changed

5 files changed

+114
-15
lines changed

src/cargo/core/features.rs

+3
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,7 @@ 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| v.into()),
12901293
"rustdoc-map" => self.rustdoc_map = parse_empty(k, v)?,
12911294
"rustdoc-scrape-examples" => self.rustdoc_scrape_examples = parse_empty(k, v)?,
12921295
"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())

src/doc/src/reference/unstable.md

+8
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ Each new feature described below should explain how to use it.
7878
* Output behavior
7979
* [artifact-dir](#artifact-dir) --- Adds a directory where artifacts are copied to.
8080
* [Different binary name](#different-binary-name) --- Assign a name to the built binary that is separate from the crate name.
81+
* [root-dir](#root-dir) --- Controls the root directory relative to which paths are printed
8182
* Compile behavior
8283
* [mtime-on-use](#mtime-on-use) --- Updates the last-modified timestamp on every dependency every time it is used, to provide a mechanism to delete unused artifacts.
8384
* [doctest-xcompile](#doctest-xcompile) --- Supports running doctests with the `--target` flag.
@@ -236,6 +237,13 @@ This can also be specified in `.cargo/config.toml` files.
236237
artifact-dir = "out"
237238
```
238239

240+
## root-dir
241+
* Original Issue: [#9887](https://github.com/rust-lang/cargo/issues/9887)
242+
* Tracking Issue: None (not currently slated for stabilization)
243+
244+
The `-Zroot-dir` flag sets the root directory relative to which paths are printed.
245+
This affects both diagnostics and paths emitted by the `file!()` macro.
246+
239247
## doctest-xcompile
240248
* Tracking Issue: [#7040](https://github.com/rust-lang/cargo/issues/7040)
241249
* Tracking Rustc Issue: [#64245](https://github.com/rust-lang/rust/issues/64245)

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

+14-12
Loading

tests/testsuite/directory.rs

+80
Original file line numberDiff line numberDiff line change
@@ -784,3 +784,83 @@ Caused by:
784784
.with_status(101)
785785
.run();
786786
}
787+
788+
#[cargo_test]
789+
fn root_dir_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-dir=.")
809+
.arg("--manifest-path=ws_root/Cargo.toml")
810+
.masquerade_as_nightly_cargo(&["-Zroot-dir"])
811+
.with_status(101)
812+
.with_stderr_data(str![[r#"
813+
[CHECKING] foo v0.1.0 ([ROOT]/ws_root)
814+
[ERROR] [..]
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_dir_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 path is relative to our fake home, not to the workspace root.
847+
p.cargo("run")
848+
.arg("-Zroot-dir=.")
849+
.arg("--manifest-path=ws_root/Cargo.toml")
850+
.masquerade_as_nightly_cargo(&["-Zroot-dir"])
851+
.with_stdout_data(str![[r#"
852+
ws_root/src/main.rs
853+
854+
"#]])
855+
.run();
856+
// Try again with an absolute path for `root-dir`.
857+
p.cargo("run")
858+
.arg(format!("-Zroot-dir={}", p.root().display()))
859+
.arg("--manifest-path=ws_root/Cargo.toml")
860+
.masquerade_as_nightly_cargo(&["-Zroot-dir"])
861+
.with_stdout_data(str![[r#"
862+
ws_root/src/main.rs
863+
864+
"#]])
865+
.run();
866+
}

0 commit comments

Comments
 (0)