Skip to content

Commit adde602

Browse files
committed
Auto merge of #9601 - jonhoo:fix-9600, r=ehuss
Inform build scripts of rustc compiler context Fixes #9600.
2 parents fe15457 + 1cbce47 commit adde602

File tree

4 files changed

+224
-5
lines changed

4 files changed

+224
-5
lines changed

src/cargo/core/compiler/build_context/target_info.rs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -548,6 +548,7 @@ fn output_err_info(cmd: &ProcessBuilder, stdout: &str, stderr: &str) -> String {
548548
///
549549
/// The locations are:
550550
///
551+
/// - the `CARGO_ENCODED_RUSTFLAGS` environment variable
551552
/// - the `RUSTFLAGS` environment variable
552553
///
553554
/// then if this was not found
@@ -595,7 +596,16 @@ fn env_args(
595596
return Ok(Vec::new());
596597
}
597598

598-
// First try RUSTFLAGS from the environment
599+
// First try CARGO_ENCODED_RUSTFLAGS from the environment.
600+
// Prefer this over RUSTFLAGS since it's less prone to encoding errors.
601+
if let Ok(a) = env::var(format!("CARGO_ENCODED_{}", name)) {
602+
if a.is_empty() {
603+
return Ok(Vec::new());
604+
}
605+
return Ok(a.split('\x1f').map(str::to_string).collect());
606+
}
607+
608+
// Then try RUSTFLAGS from the environment
599609
if let Ok(a) = env::var(name) {
600610
let args = a
601611
.split(' ')

src/cargo/core/compiler/custom_build.rs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -252,6 +252,24 @@ fn build_work(cx: &mut Context<'_, '_>, unit: &Unit) -> CargoResult<Job> {
252252
}
253253
}
254254

255+
// Also inform the build script of the rustc compiler context.
256+
if let Some(wrapper) = bcx.rustc().wrapper.as_ref() {
257+
cmd.env("RUSTC_WRAPPER", wrapper);
258+
} else {
259+
cmd.env_remove("RUSTC_WRAPPER");
260+
}
261+
cmd.env_remove("RUSTC_WORKSPACE_WRAPPER");
262+
if cx.bcx.ws.is_member(&unit.pkg) {
263+
if let Some(wrapper) = bcx.rustc().workspace_wrapper.as_ref() {
264+
cmd.env("RUSTC_WORKSPACE_WRAPPER", wrapper);
265+
}
266+
}
267+
cmd.env(
268+
"CARGO_ENCODED_RUSTFLAGS",
269+
bcx.rustflags_args(unit).join("\x1f"),
270+
);
271+
cmd.env_remove("RUSTFLAGS");
272+
255273
// Gather the set of native dependencies that this package has along with
256274
// some other variables to close over.
257275
//

src/doc/src/reference/environment-variables.md

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,11 +35,17 @@ system:
3535
* `RUSTDOCFLAGS` — A space-separated list of custom flags to pass to all `rustdoc`
3636
invocations that Cargo performs. In contrast with [`cargo rustdoc`], this is
3737
useful for passing a flag to *all* `rustdoc` instances. See
38-
[`build.rustdocflags`] for some more ways to set flags.
38+
[`build.rustdocflags`] for some more ways to set flags. This string is
39+
split by whitespace; for a more robust encoding of multiple arguments,
40+
set `CARGO_ENCODED_RUSTDOCFLAGS` instead with arguments separated by
41+
`0x1f` (ASCII Unit Separator).
3942
* `RUSTFLAGS` — A space-separated list of custom flags to pass to all compiler
4043
invocations that Cargo performs. In contrast with [`cargo rustc`], this is
4144
useful for passing a flag to *all* compiler instances. See
42-
[`build.rustflags`] for some more ways to set flags.
45+
[`build.rustflags`] for some more ways to set flags. This string is
46+
split by whitespace; for a more robust encoding of multiple arguments,
47+
set `CARGO_ENCODED_RUSTFLAGS` instead with arguments separated by
48+
`0x1f` (ASCII Unit Separator).
4349
* `CARGO_INCREMENTAL` — If this is set to 1 then Cargo will force [incremental
4450
compilation] to be enabled for the current compilation, and when set to 0 it
4551
will force disabling it. If this env var isn't present then cargo's defaults
@@ -334,11 +340,20 @@ let out_dir = env::var("OUT_DIR").unwrap();
334340
* `RUSTC`, `RUSTDOC` — the compiler and documentation generator that Cargo has
335341
resolved to use, passed to the build script so it might
336342
use it as well.
343+
* `RUSTC_WRAPPER` — the `rustc` wrapper, if any, that Cargo is using.
344+
See [`build.rustc-wrapper`].
345+
* `RUSTC_WORKSPACE_WRAPPER` — the `rustc` wrapper, if any, that Cargo is
346+
using for workspace members. See
347+
[`build.rustc-workspace-wrapper`].
337348
* `RUSTC_LINKER` — The path to the linker binary that Cargo has resolved to use
338349
for the current target, if specified. The linker can be
339350
changed by editing `.cargo/config.toml`; see the documentation
340351
about [cargo configuration][cargo-config] for more
341352
information.
353+
* `CARGO_ENCODED_RUSTFLAGS` — extra flags that Cargo invokes `rustc`
354+
with, separated by a `0x1f` character
355+
(ASCII Unit Separator). See
356+
[`build.rustflags`].
342357
* `CARGO_PKG_<var>` - The package information variables, with the same names and values as are [provided during crate building][variables set for crates].
343358

344359
[unix-like platforms]: ../../reference/conditional-compilation.html#unix-and-windows

tests/testsuite/build_script.rs

Lines changed: 178 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
use cargo_test_support::compare::assert_match_exact;
44
use cargo_test_support::paths::CargoPathExt;
55
use cargo_test_support::registry::Package;
6+
use cargo_test_support::tools;
67
use cargo_test_support::{basic_manifest, cross_compile, is_coarse_mtime, project};
78
use cargo_test_support::{rustc_host, sleep_ms, slow_cpu_multiplier, symlink_supported};
89
use cargo_util::paths::remove_dir_all;
@@ -82,7 +83,6 @@ fn custom_build_env_vars() {
8283
let file_content = format!(
8384
r#"
8485
use std::env;
85-
use std::io::prelude::*;
8686
use std::path::Path;
8787
8888
fn main() {{
@@ -115,21 +115,197 @@ fn custom_build_env_vars() {
115115
let rustdoc = env::var("RUSTDOC").unwrap();
116116
assert_eq!(rustdoc, "rustdoc");
117117
118+
assert!(env::var("RUSTC_WRAPPER").is_err());
119+
assert!(env::var("RUSTC_WORKSPACE_WRAPPER").is_err());
120+
118121
assert!(env::var("RUSTC_LINKER").is_err());
122+
123+
assert!(env::var("RUSTFLAGS").is_err());
124+
let rustflags = env::var("CARGO_ENCODED_RUSTFLAGS").unwrap();
125+
assert_eq!(rustflags, "");
119126
}}
120127
"#,
121128
p.root()
122129
.join("target")
123130
.join("debug")
124131
.join("build")
125-
.display()
132+
.display(),
126133
);
127134

128135
let p = p.file("bar/build.rs", &file_content).build();
129136

130137
p.cargo("build --features bar_feat").run();
131138
}
132139

140+
#[cargo_test]
141+
fn custom_build_env_var_rustflags() {
142+
let rustflags = "--cfg=special";
143+
let rustflags_alt = "--cfg=notspecial";
144+
let p = project()
145+
.file(
146+
".cargo/config",
147+
&format!(
148+
r#"
149+
[build]
150+
rustflags = ["{}"]
151+
"#,
152+
rustflags
153+
),
154+
)
155+
.file(
156+
"build.rs",
157+
&format!(
158+
r#"
159+
use std::env;
160+
161+
fn main() {{
162+
// Static assertion that exactly one of the cfg paths is always taken.
163+
assert!(env::var("RUSTFLAGS").is_err());
164+
let x;
165+
#[cfg(special)]
166+
{{ assert_eq!(env::var("CARGO_ENCODED_RUSTFLAGS").unwrap(), "{}"); x = String::new(); }}
167+
#[cfg(notspecial)]
168+
{{ assert_eq!(env::var("CARGO_ENCODED_RUSTFLAGS").unwrap(), "{}"); x = String::new(); }}
169+
let _ = x;
170+
}}
171+
"#,
172+
rustflags, rustflags_alt,
173+
),
174+
)
175+
.file("src/lib.rs", "")
176+
.build();
177+
178+
p.cargo("check").run();
179+
180+
// RUSTFLAGS overrides build.rustflags, so --cfg=special shouldn't be passed
181+
p.cargo("check").env("RUSTFLAGS", rustflags_alt).run();
182+
}
183+
184+
#[cargo_test]
185+
fn custom_build_env_var_encoded_rustflags() {
186+
// NOTE: We use "-Clink-arg=-B nope" here rather than, say, "-A missing_docs", since for the
187+
// latter it won't matter if the whitespace accidentally gets split, as rustc will do the right
188+
// thing either way.
189+
let p = project()
190+
.file(
191+
".cargo/config",
192+
r#"
193+
[build]
194+
rustflags = ["-Clink-arg=-B nope", "--cfg=foo"]
195+
"#,
196+
)
197+
.file(
198+
"build.rs",
199+
r#"
200+
use std::env;
201+
202+
fn main() {{
203+
assert_eq!(env::var("CARGO_ENCODED_RUSTFLAGS").unwrap(), "-Clink-arg=-B nope\x1f--cfg=foo");
204+
}}
205+
"#,
206+
)
207+
.file("src/lib.rs", "")
208+
.build();
209+
210+
p.cargo("check").run();
211+
}
212+
213+
#[cargo_test]
214+
fn custom_build_env_var_rustc_wrapper() {
215+
let wrapper = tools::echo_wrapper();
216+
let p = project()
217+
.file(
218+
"build.rs",
219+
r#"
220+
use std::env;
221+
222+
fn main() {{
223+
assert_eq!(
224+
env::var("RUSTC_WRAPPER").unwrap(),
225+
env::var("CARGO_RUSTC_WRAPPER_CHECK").unwrap()
226+
);
227+
}}
228+
"#,
229+
)
230+
.file("src/lib.rs", "")
231+
.build();
232+
233+
p.cargo("check")
234+
.env("CARGO_BUILD_RUSTC_WRAPPER", &wrapper)
235+
.env("CARGO_RUSTC_WRAPPER_CHECK", &wrapper)
236+
.run();
237+
}
238+
239+
#[cargo_test]
240+
fn custom_build_env_var_rustc_workspace_wrapper() {
241+
let wrapper = tools::echo_wrapper();
242+
243+
// Workspace wrapper should be set for any crate we're operating directly on.
244+
let p = project()
245+
.file(
246+
"build.rs",
247+
r#"
248+
use std::env;
249+
250+
fn main() {{
251+
assert_eq!(
252+
env::var("RUSTC_WORKSPACE_WRAPPER").unwrap(),
253+
env::var("CARGO_RUSTC_WORKSPACE_WRAPPER_CHECK").unwrap()
254+
);
255+
}}
256+
"#,
257+
)
258+
.file("src/lib.rs", "")
259+
.build();
260+
261+
p.cargo("check")
262+
.env("CARGO_BUILD_RUSTC_WORKSPACE_WRAPPER", &wrapper)
263+
.env("CARGO_RUSTC_WORKSPACE_WRAPPER_CHECK", &wrapper)
264+
.run();
265+
266+
// But should not be set for a crate from the registry, as then it's not in a workspace.
267+
Package::new("bar", "0.1.0")
268+
.file(
269+
"Cargo.toml",
270+
r#"
271+
[package]
272+
name = "bar"
273+
version = "0.1.0"
274+
links = "a"
275+
"#,
276+
)
277+
.file(
278+
"build.rs",
279+
r#"
280+
use std::env;
281+
282+
fn main() {{
283+
assert!(env::var("RUSTC_WORKSPACE_WRAPPER").is_err());
284+
}}
285+
"#,
286+
)
287+
.file("src/lib.rs", "")
288+
.publish();
289+
let p = project()
290+
.file(
291+
"Cargo.toml",
292+
r#"
293+
[package]
294+
name = "foo"
295+
version = "0.1.0"
296+
297+
[dependencies]
298+
bar = "0.1"
299+
"#,
300+
)
301+
.file("src/lib.rs", "")
302+
.build();
303+
304+
p.cargo("check")
305+
.env("CARGO_BUILD_RUSTC_WORKSPACE_WRAPPER", &wrapper)
306+
.run();
307+
}
308+
133309
#[cargo_test]
134310
fn custom_build_env_var_rustc_linker() {
135311
if cross_compile::disabled() {

0 commit comments

Comments
 (0)