Skip to content

Commit 40b674c

Browse files
committed
Auto merge of #9566 - ehuss:relative-rustc-path, r=alexcrichton
Fix rustc/rustdoc config values to be config-relative. The `rustc`, `rustdoc`, `rustc_wrapper`, and `rustc_workspace_wrapper` config values (in the `[build]` table) were being interpreted literally. This caused a problem if you used a relative path like `foo/rustc`. This would be interpreted as a relative path from whatever cwd cargo launches rustc from, which changes for different scenarios, making it essentially unusuable (since crates.io dependencies wouldn't be buildable). Additionally, due to rust-lang/rust#37868, it is a bad idea to use relative paths. This changes it so that those paths are config-relative. Bare names (like "my-rustc-program") still use PATH as before. This also includes a commit to centralize the rustc-wrapper program used by several tests so that it isn't built multiple times (and to allow several tests to work on windows). Fixes #8202
2 parents b3475e6 + 47a0291 commit 40b674c

File tree

9 files changed

+121
-105
lines changed

9 files changed

+121
-105
lines changed

crates/cargo-test-support/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ pub mod git;
3939
pub mod paths;
4040
pub mod publish;
4141
pub mod registry;
42+
pub mod tools;
4243

4344
/*
4445
*

crates/cargo-test-support/src/paths.rs

Lines changed: 0 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
use crate::{basic_manifest, project};
21
use filetime::{self, FileTime};
32
use lazy_static::lazy_static;
43
use std::cell::RefCell;
@@ -296,24 +295,3 @@ pub fn sysroot() -> String {
296295
let sysroot = String::from_utf8(output.stdout).unwrap();
297296
sysroot.trim().to_string()
298297
}
299-
300-
pub fn echo_wrapper() -> std::path::PathBuf {
301-
let p = project()
302-
.at("rustc-echo-wrapper")
303-
.file("Cargo.toml", &basic_manifest("rustc-echo-wrapper", "1.0.0"))
304-
.file(
305-
"src/main.rs",
306-
r#"
307-
fn main() {
308-
let args = std::env::args().collect::<Vec<_>>();
309-
eprintln!("WRAPPER CALLED: {}", args[1..].join(" "));
310-
let status = std::process::Command::new(&args[1])
311-
.args(&args[2..]).status().unwrap();
312-
std::process::exit(status.code().unwrap_or(1));
313-
}
314-
"#,
315-
)
316-
.build();
317-
p.cargo("build").run();
318-
p.bin("rustc-echo-wrapper")
319-
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
//! Common executables that can be reused by various tests.
2+
3+
use crate::{basic_manifest, paths, project};
4+
use lazy_static::lazy_static;
5+
use std::path::PathBuf;
6+
use std::sync::Mutex;
7+
8+
lazy_static! {
9+
static ref ECHO_WRAPPER: Mutex<Option<PathBuf>> = Mutex::new(None);
10+
}
11+
12+
/// Returns the path to an executable that works as a wrapper around rustc.
13+
///
14+
/// The wrapper will echo the command line it was called with to stderr.
15+
pub fn echo_wrapper() -> PathBuf {
16+
let mut lock = ECHO_WRAPPER.lock().unwrap();
17+
if let Some(path) = &*lock {
18+
return path.clone();
19+
}
20+
let p = project()
21+
.at(paths::global_root().join("rustc-echo-wrapper"))
22+
.file("Cargo.toml", &basic_manifest("rustc-echo-wrapper", "1.0.0"))
23+
.file(
24+
"src/main.rs",
25+
r#"
26+
fn main() {
27+
let args = std::env::args().collect::<Vec<_>>();
28+
eprintln!("WRAPPER CALLED: {}", args[1..].join(" "));
29+
let status = std::process::Command::new(&args[1])
30+
.args(&args[2..]).status().unwrap();
31+
std::process::exit(status.code().unwrap_or(1));
32+
}
33+
"#,
34+
)
35+
.build();
36+
p.cargo("build").run();
37+
let path = p.bin("rustc-echo-wrapper");
38+
*lock = Some(path.clone());
39+
path
40+
}

src/cargo/util/config/mod.rs

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -732,7 +732,7 @@ impl Config {
732732
})
733733
}
734734

735-
fn string_to_path(&self, value: String, definition: &Definition) -> PathBuf {
735+
fn string_to_path(&self, value: &str, definition: &Definition) -> PathBuf {
736736
let is_path = value.contains('/') || (cfg!(windows) && value.contains('\\'));
737737
if is_path {
738738
definition.root(self).join(value)
@@ -1391,7 +1391,11 @@ impl Config {
13911391

13921392
/// Looks for a path for `tool` in an environment variable or the given config, and returns
13931393
/// `None` if it's not present.
1394-
fn maybe_get_tool(&self, tool: &str, from_config: &Option<PathBuf>) -> Option<PathBuf> {
1394+
fn maybe_get_tool(
1395+
&self,
1396+
tool: &str,
1397+
from_config: &Option<ConfigRelativePath>,
1398+
) -> Option<PathBuf> {
13951399
let var = tool.to_uppercase();
13961400

13971401
match env::var_os(&var) {
@@ -1408,13 +1412,13 @@ impl Config {
14081412
Some(path)
14091413
}
14101414

1411-
None => from_config.clone(),
1415+
None => from_config.as_ref().map(|p| p.resolve_program(self)),
14121416
}
14131417
}
14141418

14151419
/// Looks for a path for `tool` in an environment variable or config path, defaulting to `tool`
14161420
/// as a path.
1417-
fn get_tool(&self, tool: &str, from_config: &Option<PathBuf>) -> PathBuf {
1421+
fn get_tool(&self, tool: &str, from_config: &Option<ConfigRelativePath>) -> PathBuf {
14181422
self.maybe_get_tool(tool, from_config)
14191423
.unwrap_or_else(|| PathBuf::from(tool))
14201424
}
@@ -2084,10 +2088,10 @@ pub struct CargoBuildConfig {
20842088
pub jobs: Option<u32>,
20852089
pub rustflags: Option<StringList>,
20862090
pub rustdocflags: Option<StringList>,
2087-
pub rustc_wrapper: Option<PathBuf>,
2088-
pub rustc_workspace_wrapper: Option<PathBuf>,
2089-
pub rustc: Option<PathBuf>,
2090-
pub rustdoc: Option<PathBuf>,
2091+
pub rustc_wrapper: Option<ConfigRelativePath>,
2092+
pub rustc_workspace_wrapper: Option<ConfigRelativePath>,
2093+
pub rustc: Option<ConfigRelativePath>,
2094+
pub rustdoc: Option<ConfigRelativePath>,
20912095
pub out_dir: Option<ConfigRelativePath>,
20922096
}
20932097

src/cargo/util/config/path.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,8 @@ impl ConfigRelativePath {
3434
/// Values which don't look like a filesystem path (don't contain `/` or
3535
/// `\`) will be returned as-is, and everything else will fall through to an
3636
/// absolute path.
37-
pub fn resolve_program(self, config: &Config) -> PathBuf {
38-
config.string_to_path(self.0.val, &self.0.definition)
37+
pub fn resolve_program(&self, config: &Config) -> PathBuf {
38+
config.string_to_path(&self.0.val, &self.0.definition)
3939
}
4040
}
4141

tests/testsuite/build.rs

Lines changed: 52 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ use cargo::{
88
};
99
use cargo_test_support::paths::{root, CargoPathExt};
1010
use cargo_test_support::registry::Package;
11+
use cargo_test_support::tools;
1112
use cargo_test_support::{
1213
basic_bin_manifest, basic_lib_manifest, basic_manifest, cargo_exe, git, is_nightly,
1314
lines_match_unordered, main_file, paths, process, project, rustc_host, sleep_ms,
@@ -4054,64 +4055,77 @@ fn run_proper_binary_main_rs_as_foo() {
40544055
}
40554056

40564057
#[cargo_test]
4057-
// NOTE: we don't have `/usr/bin/env` on Windows.
4058-
#[cfg(not(windows))]
40594058
fn rustc_wrapper() {
40604059
let p = project().file("src/lib.rs", "").build();
4060+
let wrapper = tools::echo_wrapper();
4061+
let running = format!(
4062+
"[RUNNING] `{} rustc --crate-name foo [..]",
4063+
wrapper.display()
4064+
);
40614065
p.cargo("build -v")
4062-
.env("RUSTC_WRAPPER", "/usr/bin/env")
4063-
.with_stderr_contains("[RUNNING] `/usr/bin/env rustc --crate-name foo [..]")
4066+
.env("RUSTC_WRAPPER", &wrapper)
4067+
.with_stderr_contains(&running)
40644068
.run();
4065-
}
4066-
4067-
#[cargo_test]
4068-
#[cfg(not(windows))]
4069-
fn rustc_wrapper_relative() {
4070-
let p = project().file("src/lib.rs", "").build();
4069+
p.build_dir().rm_rf();
40714070
p.cargo("build -v")
4072-
.env("RUSTC_WRAPPER", "./sccache")
4073-
.with_status(101)
4074-
.with_stderr_contains("[..]/foo/./sccache rustc[..]")
4071+
.env("RUSTC_WORKSPACE_WRAPPER", &wrapper)
4072+
.with_stderr_contains(&running)
40754073
.run();
40764074
}
40774075

40784076
#[cargo_test]
4079-
#[cfg(not(windows))]
4080-
fn rustc_wrapper_from_path() {
4081-
let p = project().file("src/lib.rs", "").build();
4077+
fn rustc_wrapper_relative() {
4078+
Package::new("bar", "1.0.0").publish();
4079+
let p = project()
4080+
.file(
4081+
"Cargo.toml",
4082+
r#"
4083+
[package]
4084+
name = "foo"
4085+
version = "0.1.0"
4086+
4087+
[dependencies]
4088+
bar = "1.0"
4089+
"#,
4090+
)
4091+
.file("src/lib.rs", "")
4092+
.build();
4093+
let wrapper = tools::echo_wrapper();
4094+
let exe_name = wrapper.file_name().unwrap().to_str().unwrap();
4095+
let relative_path = format!("./{}", exe_name);
4096+
fs::hard_link(&wrapper, p.root().join(exe_name)).unwrap();
4097+
let running = format!("[RUNNING] `[ROOT]/foo/./{} rustc[..]", exe_name);
40824098
p.cargo("build -v")
4083-
.env("RUSTC_WRAPPER", "wannabe_sccache")
4084-
.with_status(101)
4085-
.with_stderr_contains("[..]`wannabe_sccache rustc [..]")
4099+
.env("RUSTC_WRAPPER", &relative_path)
4100+
.with_stderr_contains(&running)
40864101
.run();
4087-
}
4088-
4089-
#[cargo_test]
4090-
// NOTE: we don't have `/usr/bin/env` on Windows.
4091-
#[cfg(not(windows))]
4092-
fn rustc_workspace_wrapper() {
4093-
let p = project().file("src/lib.rs", "").build();
4102+
p.build_dir().rm_rf();
40944103
p.cargo("build -v")
4095-
.env("RUSTC_WORKSPACE_WRAPPER", "/usr/bin/env")
4096-
.with_stderr_contains("[RUNNING] `/usr/bin/env rustc --crate-name foo [..]")
4104+
.env("RUSTC_WORKSPACE_WRAPPER", &relative_path)
4105+
.with_stderr_contains(&running)
40974106
.run();
4107+
p.build_dir().rm_rf();
4108+
p.change_file(
4109+
".cargo/config.toml",
4110+
&format!(
4111+
r#"
4112+
build.rustc-wrapper = "./{}"
4113+
"#,
4114+
exe_name
4115+
),
4116+
);
4117+
p.cargo("build -v").with_stderr_contains(&running).run();
40984118
}
40994119

41004120
#[cargo_test]
4101-
#[cfg(not(windows))]
4102-
fn rustc_workspace_wrapper_relative() {
4121+
fn rustc_wrapper_from_path() {
41034122
let p = project().file("src/lib.rs", "").build();
41044123
p.cargo("build -v")
4105-
.env("RUSTC_WORKSPACE_WRAPPER", "./sccache")
4124+
.env("RUSTC_WRAPPER", "wannabe_sccache")
41064125
.with_status(101)
4107-
.with_stderr_contains("[..]/foo/./sccache rustc[..]")
4126+
.with_stderr_contains("[..]`wannabe_sccache rustc [..]")
41084127
.run();
4109-
}
4110-
4111-
#[cargo_test]
4112-
#[cfg(not(windows))]
4113-
fn rustc_workspace_wrapper_from_path() {
4114-
let p = project().file("src/lib.rs", "").build();
4128+
p.build_dir().rm_rf();
41154129
p.cargo("build -v")
41164130
.env("RUSTC_WORKSPACE_WRAPPER", "wannabe_sccache")
41174131
.with_status(101)

tests/testsuite/cache_messages.rs

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
//! Tests for caching compiler diagnostics.
22
3+
use cargo_test_support::tools;
34
use cargo_test_support::{
45
basic_manifest, is_coarse_mtime, process, project, registry::Package, sleep_ms,
56
};
@@ -459,8 +460,6 @@ fn caching_large_output() {
459460

460461
#[cargo_test]
461462
fn rustc_workspace_wrapper() {
462-
use cargo_test_support::paths;
463-
464463
let p = project()
465464
.file(
466465
"src/lib.rs",
@@ -470,7 +469,7 @@ fn rustc_workspace_wrapper() {
470469
.build();
471470

472471
p.cargo("check -v")
473-
.env("RUSTC_WORKSPACE_WRAPPER", paths::echo_wrapper())
472+
.env("RUSTC_WORKSPACE_WRAPPER", tools::echo_wrapper())
474473
.with_stderr_contains("WRAPPER CALLED: rustc --crate-name foo src/lib.rs [..]")
475474
.run();
476475

@@ -488,7 +487,7 @@ fn rustc_workspace_wrapper() {
488487

489488
// Again, reading from the cache.
490489
p.cargo("check -v")
491-
.env("RUSTC_WORKSPACE_WRAPPER", paths::echo_wrapper())
490+
.env("RUSTC_WORKSPACE_WRAPPER", tools::echo_wrapper())
492491
.with_stderr_contains("[FRESH] foo [..]")
493492
.with_stdout_does_not_contain("WRAPPER CALLED: rustc --crate-name foo src/lib.rs [..]")
494493
.run();

tests/testsuite/check.rs

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ use std::fmt::{self, Write};
55
use cargo_test_support::install::exe;
66
use cargo_test_support::paths::CargoPathExt;
77
use cargo_test_support::registry::Package;
8+
use cargo_test_support::tools;
89
use cargo_test_support::{basic_manifest, project};
910

1011
#[cargo_test]
@@ -887,7 +888,6 @@ fn error_from_deep_recursion() -> Result<(), fmt::Error> {
887888

888889
#[cargo_test]
889890
fn rustc_workspace_wrapper_affects_all_workspace_members() {
890-
use cargo_test_support::paths;
891891
let p = project()
892892
.file(
893893
"Cargo.toml",
@@ -903,15 +903,14 @@ fn rustc_workspace_wrapper_affects_all_workspace_members() {
903903
.build();
904904

905905
p.cargo("check")
906-
.env("RUSTC_WORKSPACE_WRAPPER", paths::echo_wrapper())
906+
.env("RUSTC_WORKSPACE_WRAPPER", tools::echo_wrapper())
907907
.with_stderr_contains("WRAPPER CALLED: rustc --crate-name bar [..]")
908908
.with_stderr_contains("WRAPPER CALLED: rustc --crate-name baz [..]")
909909
.run();
910910
}
911911

912912
#[cargo_test]
913913
fn rustc_workspace_wrapper_includes_path_deps() {
914-
use cargo_test_support::paths;
915914
let p = project()
916915
.file(
917916
"Cargo.toml",
@@ -936,7 +935,7 @@ fn rustc_workspace_wrapper_includes_path_deps() {
936935
.build();
937936

938937
p.cargo("check --workspace")
939-
.env("RUSTC_WORKSPACE_WRAPPER", paths::echo_wrapper())
938+
.env("RUSTC_WORKSPACE_WRAPPER", tools::echo_wrapper())
940939
.with_stderr_contains("WRAPPER CALLED: rustc --crate-name foo [..]")
941940
.with_stderr_contains("WRAPPER CALLED: rustc --crate-name bar [..]")
942941
.with_stderr_contains("WRAPPER CALLED: rustc --crate-name baz [..]")
@@ -945,7 +944,6 @@ fn rustc_workspace_wrapper_includes_path_deps() {
945944

946945
#[cargo_test]
947946
fn rustc_workspace_wrapper_respects_primary_units() {
948-
use cargo_test_support::paths;
949947
let p = project()
950948
.file(
951949
"Cargo.toml",
@@ -961,15 +959,14 @@ fn rustc_workspace_wrapper_respects_primary_units() {
961959
.build();
962960

963961
p.cargo("check -p bar")
964-
.env("RUSTC_WORKSPACE_WRAPPER", paths::echo_wrapper())
962+
.env("RUSTC_WORKSPACE_WRAPPER", tools::echo_wrapper())
965963
.with_stderr_contains("WRAPPER CALLED: rustc --crate-name bar [..]")
966964
.with_stdout_does_not_contain("WRAPPER CALLED: rustc --crate-name baz [..]")
967965
.run();
968966
}
969967

970968
#[cargo_test]
971969
fn rustc_workspace_wrapper_excludes_published_deps() {
972-
use cargo_test_support::paths;
973970
let p = project()
974971
.file(
975972
"Cargo.toml",
@@ -994,7 +991,7 @@ fn rustc_workspace_wrapper_excludes_published_deps() {
994991
Package::new("baz", "1.0.0").publish();
995992

996993
p.cargo("check --workspace -v")
997-
.env("RUSTC_WORKSPACE_WRAPPER", paths::echo_wrapper())
994+
.env("RUSTC_WORKSPACE_WRAPPER", tools::echo_wrapper())
998995
.with_stderr_contains("WRAPPER CALLED: rustc --crate-name foo [..]")
999996
.with_stderr_contains("WRAPPER CALLED: rustc --crate-name bar [..]")
1000997
.with_stderr_contains("[CHECKING] baz [..]")

0 commit comments

Comments
 (0)