Skip to content

Commit 321c530

Browse files
jyn514flip1995
authored andcommitted
Don't pass --sysroot twice if SYSROOT is set
This is useful for rust-lang/rust to allow setting a sysroot that's *only* for build scripts, different from the regular sysroot passed in RUSTFLAGS (since cargo doesn't apply RUSTFLAGS to build scripts or proc-macros). That said, the exact motivation is not particularly important: this fixes a regression from 5907e91#r1060215684. Note that only RUSTFLAGS is tested in the new integration test; passing --sysroot through `clippy-driver` never worked as far as I can tell, and no one is using it, so I didn't fix it here.
1 parent decaba9 commit 321c530

File tree

2 files changed

+77
-25
lines changed

2 files changed

+77
-25
lines changed

src/driver.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -256,11 +256,14 @@ pub fn main() {
256256
LazyLock::force(&ICE_HOOK);
257257
exit(rustc_driver::catch_with_exit_code(move || {
258258
let mut orig_args: Vec<String> = env::args().collect();
259+
let has_sysroot_arg = arg_value(&orig_args, "--sysroot", |_| true).is_some();
259260

260261
let sys_root_env = std::env::var("SYSROOT").ok();
261262
let pass_sysroot_env_if_given = |args: &mut Vec<String>, sys_root_env| {
262263
if let Some(sys_root) = sys_root_env {
263-
args.extend(vec!["--sysroot".into(), sys_root]);
264+
if !has_sysroot_arg {
265+
args.extend(vec!["--sysroot".into(), sys_root]);
266+
}
264267
};
265268
};
266269

tests/integration.rs

+73-24
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,42 @@
1+
//! To run this test, use
2+
//! `env INTEGRATION=rust-lang/log cargo test --test integration --features=integration`
3+
//!
4+
//! You can use a different `INTEGRATION` value to test different repositories.
5+
16
#![cfg(feature = "integration")]
27
#![cfg_attr(feature = "deny-warnings", deny(warnings))]
38
#![warn(rust_2018_idioms, unused_lifetimes)]
49

5-
use std::env;
610
use std::ffi::OsStr;
11+
use std::path::{Path, PathBuf};
712
use std::process::Command;
13+
use std::{env, eprintln};
814

915
#[cfg(not(windows))]
1016
const CARGO_CLIPPY: &str = "cargo-clippy";
1117
#[cfg(windows)]
1218
const CARGO_CLIPPY: &str = "cargo-clippy.exe";
1319

14-
#[cfg_attr(feature = "integration", test)]
15-
fn integration_test() {
16-
let repo_name = env::var("INTEGRATION").expect("`INTEGRATION` var not set");
20+
// NOTE: arguments passed to the returned command will be `clippy-driver` args, not `cargo-clippy`
21+
// args. Use `cargo_args` to pass arguments to cargo-clippy.
22+
fn clippy_command(repo_dir: &Path, cargo_args: &[&str]) -> Command {
23+
let root_dir = std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR"));
24+
let target_dir = option_env!("CARGO_TARGET_DIR").map_or_else(|| root_dir.join("target"), PathBuf::from);
25+
let clippy_binary = target_dir.join(env!("PROFILE")).join(CARGO_CLIPPY);
26+
27+
let mut cargo_clippy = Command::new(clippy_binary);
28+
cargo_clippy
29+
.current_dir(repo_dir)
30+
.env("RUST_BACKTRACE", "full")
31+
.env("CARGO_TARGET_DIR", root_dir.join("target"))
32+
.args(["clippy", "--all-targets", "--all-features"])
33+
.args(cargo_args)
34+
.args(["--", "--cap-lints", "warn", "-Wclippy::pedantic", "-Wclippy::nursery"]);
35+
cargo_clippy
36+
}
37+
38+
/// Return a directory with a checkout of the repository in `INTEGRATION`.
39+
fn repo_dir(repo_name: &str) -> PathBuf {
1740
let repo_url = format!("https://github.com/{repo_name}");
1841
let crate_name = repo_name
1942
.split('/')
@@ -34,28 +57,19 @@ fn integration_test() {
3457
.expect("unable to run git");
3558
assert!(st.success());
3659

37-
let root_dir = std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR"));
38-
let target_dir = std::path::Path::new(&root_dir).join("target");
39-
let clippy_binary = target_dir.join(env!("PROFILE")).join(CARGO_CLIPPY);
40-
41-
let output = Command::new(clippy_binary)
42-
.current_dir(repo_dir)
43-
.env("RUST_BACKTRACE", "full")
44-
.env("CARGO_TARGET_DIR", target_dir)
45-
.args([
46-
"clippy",
47-
"--all-targets",
48-
"--all-features",
49-
"--",
50-
"--cap-lints",
51-
"warn",
52-
"-Wclippy::pedantic",
53-
"-Wclippy::nursery",
54-
])
55-
.output()
56-
.expect("unable to run clippy");
60+
repo_dir
61+
}
5762

63+
#[cfg_attr(feature = "integration", test)]
64+
fn integration_test() {
65+
let repo_name = env::var("INTEGRATION").expect("`INTEGRATION` var not set");
66+
let repo_dir = repo_dir(&repo_name);
67+
let output = clippy_command(&repo_dir, &[]).output().expect("failed to run clippy");
5868
let stderr = String::from_utf8_lossy(&output.stderr);
69+
if !stderr.is_empty() {
70+
eprintln!("{stderr}");
71+
}
72+
5973
if let Some(backtrace_start) = stderr.find("error: internal compiler error") {
6074
static BACKTRACE_END_MSG: &str = "end of query stack";
6175
let backtrace_end = stderr[backtrace_start..]
@@ -90,3 +104,38 @@ fn integration_test() {
90104
None => panic!("Process terminated by signal"),
91105
}
92106
}
107+
108+
#[cfg_attr(feature = "integration", test)]
109+
fn test_sysroot() {
110+
#[track_caller]
111+
fn verify_cmd(cmd: &mut Command) {
112+
// Test that SYSROOT is ignored if `--sysroot` is passed explicitly.
113+
cmd.env("SYSROOT", "/dummy/value/does/not/exist");
114+
// We don't actually care about emitting lints, we only want to verify clippy doesn't give a hard
115+
// error.
116+
cmd.arg("-Awarnings");
117+
let output = cmd.output().expect("failed to run clippy");
118+
let stderr = String::from_utf8_lossy(&output.stderr);
119+
assert!(stderr.is_empty(), "clippy printed an error: {stderr}");
120+
assert!(output.status.success(), "clippy exited with an error");
121+
}
122+
123+
let rustc = std::env::var("RUSTC").unwrap_or("rustc".to_string());
124+
let rustc_output = Command::new(rustc)
125+
.args(["--print", "sysroot"])
126+
.output()
127+
.expect("unable to run rustc");
128+
assert!(rustc_output.status.success());
129+
let sysroot = String::from_utf8(rustc_output.stdout).unwrap();
130+
let sysroot = sysroot.trim_end();
131+
132+
// This is a fairly small repo; we want to avoid checking out anything heavy twice, so just
133+
// hard-code it.
134+
let repo_name = "rust-lang/log";
135+
let repo_dir = repo_dir(repo_name);
136+
// Pass the sysroot through RUSTFLAGS.
137+
verify_cmd(clippy_command(&repo_dir, &["--quiet"]).env("RUSTFLAGS", format!("--sysroot={sysroot}")));
138+
// NOTE: we don't test passing the arguments directly to clippy-driver (with `-- --sysroot`)
139+
// because it breaks for some reason. I (@jyn514) haven't taken time to track down the bug
140+
// because rust-lang/rust uses RUSTFLAGS and nearly no one else uses --sysroot.
141+
}

0 commit comments

Comments
 (0)