Skip to content

Commit bcc217d

Browse files
authored
feat(build-rs): Add the 'error' directive (#14910)
### What does this PR try to resolve? My previous audit mostly focused on env variables and missed that `cargo::error` hadn't been added yet. This also includes other clean up along the way to #14902 and fixing of some env variable handling that I'm working towards. ### How should we test and review this PR? ### Additional information
2 parents 58c2374 + 5fa8a68 commit bcc217d

File tree

4 files changed

+57
-86
lines changed

4 files changed

+57
-86
lines changed

crates/build-rs/src/allow_use.rs

-44
This file was deleted.

crates/build-rs/src/lib.rs

+10-3
Original file line numberDiff line numberDiff line change
@@ -26,13 +26,20 @@ macro_rules! unstable {
2626
};
2727
}
2828

29-
macro_rules! msrv {
29+
macro_rules! respected_msrv {
3030
($ver:literal) => {
31-
concat!("> MSRV: Respected as of ", $ver, ".")
31+
concat!(
32+
r#"<div class="warning">
33+
34+
MSRV: Respected as of "#,
35+
$ver,
36+
r#".
37+
38+
</div>"#
39+
)
3240
};
3341
}
3442

35-
mod allow_use;
3643
mod ident;
3744

3845
pub mod input;

crates/build-rs/src/output.rs

+43-35
Original file line numberDiff line numberDiff line change
@@ -6,18 +6,14 @@
66
//!
77
//! Reference: <https://doc.rust-lang.org/cargo/reference/build-scripts.html#outputs-of-the-build-script>
88
9-
use crate::{
10-
allow_use,
11-
ident::{is_ascii_ident, is_ident},
12-
};
13-
use std::{ffi::OsStr, fmt::Display, fmt::Write, path::Path, str};
9+
use std::ffi::OsStr;
10+
use std::path::Path;
11+
use std::{fmt::Display, fmt::Write as _};
12+
13+
use crate::ident::{is_ascii_ident, is_ident};
1414

1515
fn emit(directive: &str, value: impl Display) {
16-
if allow_use::double_colon_directives() {
17-
println!("cargo::{}={}", directive, value);
18-
} else {
19-
println!("cargo:{}={}", directive, value);
20-
}
16+
println!("cargo::{}={}", directive, value);
2117
}
2218

2319
/// The `rerun-if-changed` instruction tells Cargo to re-run the build script if the
@@ -171,7 +167,7 @@ pub fn rustc_link_arg_benches(flag: &str) {
171167
/// to the symbols from the given lib, and the binary should access them through
172168
/// the library target’s public API.
173169
///
174-
/// The optional `KIND` may be one of dylib, static, or framework. See the
170+
/// The optional `KIND` may be one of `dylib`, `static`, or `framework`. See the
175171
/// [rustc book][-l] for more detail.
176172
///
177173
/// [-l]: https://doc.rust-lang.org/stable/rustc/command-line-arguments.html#option-l-link-lib
@@ -301,7 +297,7 @@ pub fn rustc_cfg_value(key: &str, value: &str) {
301297
/// and other mistakes.
302298
///
303299
/// [`unexpected_cfgs`]: https://doc.rust-lang.org/rustc/lints/listing/warn-by-default.html#unexpected-cfgs
304-
#[doc = msrv!("1.80")]
300+
#[doc = respected_msrv!("1.80")]
305301
#[track_caller]
306302
pub fn rustc_check_cfgs(keys: &[&str]) {
307303
if keys.is_empty() {
@@ -313,13 +309,11 @@ pub fn rustc_check_cfgs(keys: &[&str]) {
313309
}
314310
}
315311

316-
if allow_use::check_cfg() {
317-
let mut directive = keys[0].to_string();
318-
for key in &keys[1..] {
319-
write!(directive, ", {key}").expect("writing to string should be infallible");
320-
}
321-
emit("rustc-check-cfg", format_args!("cfg({directive})"));
312+
let mut directive = keys[0].to_string();
313+
for key in &keys[1..] {
314+
write!(directive, ", {key}").expect("writing to string should be infallible");
322315
}
316+
emit("rustc-check-cfg", format_args!("cfg({directive})"));
323317
}
324318

325319
/// Add to the list of expected config names that is used when checking the
@@ -332,7 +326,7 @@ pub fn rustc_check_cfgs(keys: &[&str]) {
332326
/// and other mistakes.
333327
///
334328
/// [`unexpected_cfgs`]: https://doc.rust-lang.org/rustc/lints/listing/warn-by-default.html#unexpected-cfgs
335-
#[doc = msrv!("1.80")]
329+
#[doc = respected_msrv!("1.80")]
336330
#[track_caller]
337331
pub fn rustc_check_cfg_values(key: &str, values: &[&str]) {
338332
if !is_ident(key) {
@@ -343,17 +337,15 @@ pub fn rustc_check_cfg_values(key: &str, values: &[&str]) {
343337
return;
344338
}
345339

346-
if allow_use::check_cfg() {
347-
let mut directive = format!("\"{}\"", values[0].escape_default());
348-
for value in &values[1..] {
349-
write!(directive, ", \"{}\"", value.escape_default())
350-
.expect("writing to string should be infallible");
351-
}
352-
emit(
353-
"rustc-check-cfg",
354-
format_args!("cfg({key}, values({directive}))"),
355-
);
356-
}
340+
let mut directive = format!("\"{}\"", values[0].escape_default());
341+
for value in &values[1..] {
342+
write!(directive, ", \"{}\"", value.escape_default())
343+
.expect("writing to string should be infallible");
344+
}
345+
emit(
346+
"rustc-check-cfg",
347+
format_args!("cfg({key}, values({directive}))"),
348+
);
357349
}
358350

359351
/// The `rustc-env` instruction tells Cargo to set the given environment variable
@@ -411,6 +403,26 @@ pub fn warning(message: &str) {
411403
emit("warning", message);
412404
}
413405

406+
/// The `error` instruction tells Cargo to display an error after the build script has finished
407+
/// running, and then fail the build.
408+
///
409+
/// <div class="warning">
410+
///
411+
/// Build script libraries should carefully consider if they want to use [`error`] versus
412+
/// returning a `Result`. It may be better to return a `Result`, and allow the caller to decide if the
413+
/// error is fatal or not. The caller can then decide whether or not to display the `Err` variant
414+
/// using [`error`].
415+
///
416+
/// </div>
417+
#[doc = respected_msrv!("1.84")]
418+
#[track_caller]
419+
pub fn error(message: &str) {
420+
if message.contains('\n') {
421+
panic!("cannot emit warning: message contains newline");
422+
}
423+
emit("error", message);
424+
}
425+
414426
/// Metadata, used by `links` scripts.
415427
#[track_caller]
416428
pub fn metadata(key: &str, val: &str) {
@@ -421,9 +433,5 @@ pub fn metadata(key: &str, val: &str) {
421433
panic!("cannot emit metadata: invalid value {val:?}");
422434
}
423435

424-
if allow_use::double_colon_directives() {
425-
emit("metadata", format_args!("{}={}", key, val));
426-
} else {
427-
emit(key, val);
428-
}
436+
emit("metadata", format_args!("{}={}", key, val));
429437
}

src/cargo/core/compiler/custom_build.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -339,11 +339,11 @@ fn build_work(build_runner: &mut BuildRunner<'_, '_>, unit: &Unit) -> CargoResul
339339
for cfg in bcx.target_data.cfg(unit.kind) {
340340
match *cfg {
341341
Cfg::Name(ref n) => {
342-
cfg_map.insert(n.clone(), Vec::new());
342+
cfg_map.insert(n.as_str(), Vec::new());
343343
}
344344
Cfg::KeyPair(ref k, ref v) => {
345-
let values = cfg_map.entry(k.clone()).or_default();
346-
values.push(v.clone());
345+
let values = cfg_map.entry(k.as_str()).or_default();
346+
values.push(v.as_str());
347347
}
348348
}
349349
}
@@ -355,7 +355,7 @@ fn build_work(build_runner: &mut BuildRunner<'_, '_>, unit: &Unit) -> CargoResul
355355
}
356356
// FIXME: We should handle raw-idents somehow instead of predenting they
357357
// don't exist here
358-
let k = format!("CARGO_CFG_{}", super::envify(k.as_str()));
358+
let k = format!("CARGO_CFG_{}", super::envify(k));
359359
cmd.env(&k, v.join(","));
360360
}
361361

0 commit comments

Comments
 (0)