Skip to content

Commit

Permalink
Auto merge of #14752 - RalfJung:rustc-root-path, r=epage
Browse files Browse the repository at this point in the history
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. :)
  • Loading branch information
bors committed Oct 31, 2024
2 parents 497c228 + 0f80faf commit 40d804b
Show file tree
Hide file tree
Showing 5 changed files with 114 additions and 15 deletions.
3 changes: 3 additions & 0 deletions src/cargo/core/features.rs
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,7 @@
use std::collections::BTreeSet;
use std::env;
use std::fmt::{self, Write};
use std::path::PathBuf;
use std::str::FromStr;

use anyhow::{bail, Error};
Expand Down Expand Up @@ -783,6 +784,7 @@ unstable_cli_options!(
profile_rustflags: bool = ("Enable the `rustflags` option in profiles in .cargo/config.toml file"),
public_dependency: bool = ("Respect a dependency's `public` field in Cargo.toml to control public/private dependencies"),
publish_timeout: bool = ("Enable the `publish.timeout` key in .cargo/config.toml file"),
root_dir: Option<PathBuf> = ("Set the root directory relative to which paths are printed (defaults to workspace root)"),
rustdoc_map: bool = ("Allow passing external documentation mappings to rustdoc"),
rustdoc_scrape_examples: bool = ("Allows Rustdoc to scrape code examples from reverse-dependencies"),
script: bool = ("Enable support for single-file, `.rs` packages"),
Expand Down Expand Up @@ -1287,6 +1289,7 @@ impl CliUnstable {
"profile-rustflags" => self.profile_rustflags = parse_empty(k, v)?,
"trim-paths" => self.trim_paths = parse_empty(k, v)?,
"publish-timeout" => self.publish_timeout = parse_empty(k, v)?,
"root-dir" => self.root_dir = v.map(|v| v.into()),
"rustdoc-map" => self.rustdoc_map = parse_empty(k, v)?,
"rustdoc-scrape-examples" => self.rustdoc_scrape_examples = parse_empty(k, v)?,
"separate-nightlies" => self.separate_nightlies = parse_empty(k, v)?,
Expand Down
12 changes: 9 additions & 3 deletions src/cargo/util/workspace.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use crate::core::{Target, Workspace};
use crate::ops::CompileOptions;
use crate::util::CargoResult;
use anyhow::bail;
use cargo_util::paths::normalize_path;
use cargo_util::ProcessBuilder;
use std::fmt::Write;
use std::path::PathBuf;
Expand Down Expand Up @@ -109,15 +110,20 @@ pub fn print_available_tests(ws: &Workspace<'_>, options: &CompileOptions) -> Ca
/// The first returned value here is the argument to pass to rustc, and the
/// second is the cwd that rustc should operate in.
pub fn path_args(ws: &Workspace<'_>, unit: &Unit) -> (PathBuf, PathBuf) {
let ws_root = ws.root();
let src = match unit.target.src_path() {
TargetSourcePath::Path(path) => path.to_path_buf(),
TargetSourcePath::Metabuild => unit.pkg.manifest().metabuild_path(ws.target_dir()),
};
assert!(src.is_absolute());
if unit.pkg.package_id().source_id().is_path() {
if let Ok(path) = src.strip_prefix(ws_root) {
return (path.to_path_buf(), ws_root.to_path_buf());
// Determine which path we make this relative to: usually it's the workspace root,
// but this can be overwritten with a `-Z` flag.
let root = match &ws.gctx().cli_unstable().root_dir {
None => ws.root().to_owned(),
Some(root_dir) => normalize_path(&ws.gctx().cwd().join(root_dir)),
};
if let Ok(path) = src.strip_prefix(&root) {
return (path.to_path_buf(), root);
}
}
(src, unit.pkg.root().to_path_buf())
Expand Down
8 changes: 8 additions & 0 deletions src/doc/src/reference/unstable.md
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ Each new feature described below should explain how to use it.
* Output behavior
* [artifact-dir](#artifact-dir) --- Adds a directory where artifacts are copied to.
* [Different binary name](#different-binary-name) --- Assign a name to the built binary that is separate from the crate name.
* [root-dir](#root-dir) --- Controls the root directory relative to which paths are printed
* Compile behavior
* [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.
* [doctest-xcompile](#doctest-xcompile) --- Supports running doctests with the `--target` flag.
Expand Down Expand Up @@ -236,6 +237,13 @@ This can also be specified in `.cargo/config.toml` files.
artifact-dir = "out"
```

## root-dir
* Original Issue: [#9887](https://github.com/rust-lang/cargo/issues/9887)
* Tracking Issue: None (not currently slated for stabilization)

The `-Zroot-dir` flag sets the root directory relative to which paths are printed.
This affects both diagnostics and paths emitted by the `file!()` macro.

## doctest-xcompile
* Tracking Issue: [#7040](https://github.com/rust-lang/cargo/issues/7040)
* Tracking Rustc Issue: [#64245](https://github.com/rust-lang/rust/issues/64245)
Expand Down
26 changes: 14 additions & 12 deletions tests/testsuite/cargo/z_help/stdout.term.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
80 changes: 80 additions & 0 deletions tests/testsuite/directory.rs
Original file line number Diff line number Diff line change
Expand Up @@ -784,3 +784,83 @@ Caused by:
.with_status(101)
.run();
}

#[cargo_test]
fn root_dir_diagnostics() {
let p = ProjectBuilder::new(paths::root())
.no_manifest() // we are placing it in a different dir
.file(
"ws_root/Cargo.toml",
r#"
[package]
name = "foo"
version = "0.1.0"
edition = "2015"
authors = []
"#,
)
.file("ws_root/src/lib.rs", "invalid;")
.build();

// Crucially, the rustc error message below says `ws_root/...`, i.e.
// it is relative to our fake home, not to the workspace root.
p.cargo("check")
.arg("-Zroot-dir=.")
.arg("--manifest-path=ws_root/Cargo.toml")
.masquerade_as_nightly_cargo(&["-Zroot-dir"])
.with_status(101)
.with_stderr_data(str![[r#"
[CHECKING] foo v0.1.0 ([ROOT]/ws_root)
[ERROR] [..]
--> ws_root/src/lib.rs:1:8
|
1 | invalid;
| [..]
[ERROR] could not compile `foo` (lib) due to 1 previous error
"#]])
.run();
}

#[cargo_test]
fn root_dir_file_macro() {
let p = ProjectBuilder::new(paths::root())
.no_manifest() // we are placing it in a different dir
.file(
"ws_root/Cargo.toml",
r#"
[package]
name = "foo"
version = "0.1.0"
edition = "2015"
authors = []
"#,
)
.file(
"ws_root/src/main.rs",
r#"fn main() { println!("{}", file!()); }"#,
)
.build();

// Crucially, the path is relative to our fake home, not to the workspace root.
p.cargo("run")
.arg("-Zroot-dir=.")
.arg("--manifest-path=ws_root/Cargo.toml")
.masquerade_as_nightly_cargo(&["-Zroot-dir"])
.with_stdout_data(str![[r#"
ws_root/src/main.rs
"#]])
.run();
// Try again with an absolute path for `root-dir`.
p.cargo("run")
.arg(format!("-Zroot-dir={}", p.root().display()))
.arg("--manifest-path=ws_root/Cargo.toml")
.masquerade_as_nightly_cargo(&["-Zroot-dir"])
.with_stdout_data(str![[r#"
ws_root/src/main.rs
"#]])
.run();
}

0 comments on commit 40d804b

Please sign in to comment.