Skip to content

Commit e4c7581

Browse files
committed
Extend the build directive syntax with cargo::metadata=
Signed-off-by: hi-rustin <[email protected]>
1 parent c9b89c6 commit e4c7581

File tree

1 file changed

+86
-17
lines changed

1 file changed

+86
-17
lines changed

src/cargo/core/compiler/custom_build.rs

Lines changed: 86 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,8 @@ use std::sync::{Arc, Mutex};
5252
/// build script has finished running. Read [the doc] for more.
5353
///
5454
/// [the doc]: https://doc.rust-lang.org/nightly/cargo/reference/build-scripts.html#cargo-warning
55-
const CARGO_WARNING: &str = "cargo:warning=";
55+
const OLD_CARGO_WARNING_SYNTAX: &str = "cargo:warning=";
56+
const NEW_CARGO_WARNING_SYNTAX: &str = "cargo::warning=";
5657

5758
/// Contains the parsed output of a custom build script.
5859
#[derive(Clone, Debug, Hash, Default)]
@@ -435,7 +436,10 @@ fn build_work(cx: &mut Context<'_, '_>, unit: &Unit) -> CargoResult<Job> {
435436
let output = cmd
436437
.exec_with_streaming(
437438
&mut |stdout| {
438-
if let Some(warning) = stdout.strip_prefix(CARGO_WARNING) {
439+
if let Some(warning) = stdout
440+
.strip_prefix(OLD_CARGO_WARNING_SYNTAX)
441+
.or(stdout.strip_prefix(NEW_CARGO_WARNING_SYNTAX))
442+
{
439443
warnings_in_case_of_panic.push(warning.to_owned());
440444
}
441445
if extra_verbose {
@@ -643,28 +647,93 @@ impl BuildOutput {
643647
Ok(line) => line.trim(),
644648
Err(..) => continue,
645649
};
646-
let mut iter = line.splitn(2, ':');
650+
let mut new_syntax = true;
651+
let mut iter = line.splitn(2, "::");
647652
if iter.next() != Some("cargo") {
648-
// skip this line since it doesn't start with "cargo:"
649-
continue;
653+
// For backwards compatibility, we also accept lines that start with "cargo:".
654+
new_syntax = false;
655+
iter = line.splitn(2, ":");
656+
if iter.next() != Some("cargo") {
657+
// skip this line since it doesn't start with "cargo:" or "cargo::".
658+
continue;
659+
}
650660
}
651661
let data = match iter.next() {
652662
Some(val) => val,
653663
None => continue,
654664
};
655665

656-
// getting the `key=value` part of the line
657-
let mut iter = data.splitn(2, '=');
658-
let key = iter.next();
659-
let value = iter.next();
660-
let (key, value) = match (key, value) {
661-
(Some(a), Some(b)) => (a, b.trim_end()),
662-
// Line started with `cargo:` but didn't match `key=value`.
663-
_ => bail!("invalid output in {}: `{}`\n\
664-
Expected a line with `cargo:key=value` with an `=` character, \
665-
but none was found.\n\
666-
See https://doc.rust-lang.org/cargo/reference/build-scripts.html#outputs-of-the-build-script \
667-
for more information about build script outputs.", whence, line),
666+
// Old syntax:
667+
// cargo:rustc-flags=VALUE
668+
// cargo:KEY=VALUE (for other unreserved keys)
669+
// New syntax:
670+
// cargo::rustc-flags=VALUE
671+
// cargo::metadata=KEY=VALUE (for other unreserved keys)
672+
const RESERVED_KEYS: &[&str] = &[
673+
"rustc-flags",
674+
"rustc-link-lib",
675+
"rustc-link-search",
676+
"rustc-link-arg-cdylib",
677+
"rustc-link-arg-bins",
678+
"rustc-link-arg-bin",
679+
"rustc-link-arg-tests",
680+
"rustc-link-arg-benches",
681+
"rustc-link-arg-examples",
682+
"rustc-link-arg",
683+
"rustc-cfg",
684+
"rustc-check-cfg",
685+
"rustc-env",
686+
"warning",
687+
"rerun-if-changed",
688+
"rerun-if-env-changed",
689+
];
690+
const DOCS_LINK_SUGGESTION: &str = "See https://doc.rust-lang.org/cargo/reference/build-scripts.html#outputs-of-the-build-script \
691+
for more information about build script outputs.";
692+
let mut iter = data.splitn(3, '=');
693+
let part1 = iter.next();
694+
let part2 = iter.next();
695+
let part3 = iter.next();
696+
let (key, value) = match (part1, part2, part3) {
697+
// For instance, `cargo::metadata=foo=bar`.
698+
(Some("metadata"), Some(a), Some(b)) => {
699+
// `cargo::metadata=` should only be used with the new syntax.
700+
if !new_syntax {
701+
bail!("invalid output in {}: `{}`\n\
702+
Expected a line with `cargo::KEY=VALUE`, but found `cargo:metadata=KEY=VALUE`.\n\
703+
{}", whence, line, DOCS_LINK_SUGGESTION
704+
)
705+
}
706+
// Reserved keys should not be used with the `cargo::metadata` syntax.
707+
if new_syntax && RESERVED_KEYS.contains(&a) {
708+
bail!("invalid output in {}: `{}`\n\
709+
The reserved key `{}` cannot be used in a `cargo::metadata` line. Please use `cargo::{}=VAlUE` instead.\n\
710+
{}", whence, line, a, a, DOCS_LINK_SUGGESTION
711+
)
712+
}
713+
(a, b.trim_end().to_owned())
714+
}
715+
// For instance, `cargo::warning=foo` or `cargo:warning=foo`.
716+
(Some(a), Some(b), None) => {
717+
// Only reserved keys should be used with the `cargo::` syntax.
718+
// Otherwise, it should be `cargo::metadata=KEY=VALUE`.
719+
if new_syntax && !RESERVED_KEYS.contains(&a) {
720+
bail!("invalid output in {}: `{}`\n\
721+
Expected a line with `cargo::metadata=KEY=VALUE` but it did not have the `metadata=` part.\n\
722+
{}", whence, line, DOCS_LINK_SUGGESTION
723+
)
724+
}
725+
(a, b.trim_end().to_owned())
726+
}
727+
// For instance, `cargo:rustc-link-search=[KIND=]PATH` or `cargo::rustc-link-search=[KIND=]PATH`.
728+
(Some(a), Some(b), Some(c)) => (a, format!("{}={}", b, c).trim_end().to_owned()),
729+
// Line started with `cargo:` or `cargo::` but didn't match any of the above.
730+
_ => bail!(
731+
"invalid output in {}: `{}`\n\
732+
{}",
733+
whence,
734+
line,
735+
DOCS_LINK_SUGGESTION
736+
),
668737
};
669738

670739
// This will rewrite paths if the target directory has been moved.

0 commit comments

Comments
 (0)