@@ -52,7 +52,8 @@ use std::sync::{Arc, Mutex};
52
52
/// build script has finished running. Read [the doc] for more.
53
53
///
54
54
/// [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=" ;
56
57
57
58
/// Contains the parsed output of a custom build script.
58
59
#[ derive( Clone , Debug , Hash , Default ) ]
@@ -435,7 +436,10 @@ fn build_work(cx: &mut Context<'_, '_>, unit: &Unit) -> CargoResult<Job> {
435
436
let output = cmd
436
437
. exec_with_streaming (
437
438
& 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
+ {
439
443
warnings_in_case_of_panic. push ( warning. to_owned ( ) ) ;
440
444
}
441
445
if extra_verbose {
@@ -638,47 +642,120 @@ impl BuildOutput {
638
642
let mut warnings = Vec :: new ( ) ;
639
643
let whence = format ! ( "build script of `{}`" , pkg_descr) ;
640
644
645
+ // Old syntax:
646
+ // cargo:rustc-flags=VALUE
647
+ // cargo:KEY=VALUE (for other unreserved keys)
648
+ // New syntax:
649
+ // cargo::rustc-flags=VALUE
650
+ // cargo::metadata=KEY=VALUE (for other unreserved keys)
651
+ // Due to backwards compatibility, no new keys can be added to this old format.
652
+ // All new keys must use the new format: `cargo::metadata=KEY=VALUE`.
653
+ const RESERVED_PREFIXES : & [ & str ] = & [
654
+ "rustc-flags=" ,
655
+ "rustc-link-lib=" ,
656
+ "rustc-link-search=" ,
657
+ "rustc-link-arg-cdylib=" ,
658
+ "rustc-link-arg-bins=" ,
659
+ "rustc-link-arg-bin=" ,
660
+ "rustc-link-arg-tests=" ,
661
+ "rustc-link-arg-benches=" ,
662
+ "rustc-link-arg-examples=" ,
663
+ "rustc-link-arg=" ,
664
+ "rustc-cfg=" ,
665
+ "rustc-check-cfg=" ,
666
+ "rustc-env=" ,
667
+ "warning=" ,
668
+ "rerun-if-changed=" ,
669
+ "rerun-if-env-changed=" ,
670
+ ] ;
671
+ const DOCS_LINK_SUGGESTION : & str = "See https://doc.rust-lang.org/cargo/reference/build-scripts.html#outputs-of-the-build-script \
672
+ for more information about build script outputs.";
673
+
674
+ fn parse_directive < ' a > (
675
+ whence : & str ,
676
+ line : & str ,
677
+ data : & ' a str ,
678
+ new_syntax : bool ,
679
+ is_metadata : bool ,
680
+ ) -> CargoResult < ( & ' a str , & ' a str ) > {
681
+ let mut iter = data. splitn ( 2 , "=" ) ;
682
+ let key = iter. next ( ) ;
683
+ let value = iter. next ( ) ;
684
+ match ( key, value) {
685
+ ( Some ( a) , Some ( b) ) => Ok ( ( a, b. trim_end ( ) ) ) ,
686
+ _ => bail ! (
687
+ "invalid output in {}: `{}`\n \
688
+ Expected a line with `{}{}KEY=VALUE` with an `=` character, \
689
+ but none was found.\n \
690
+ {}",
691
+ whence,
692
+ line,
693
+ if new_syntax { "cargo::" } else { "cargo:" } ,
694
+ if is_metadata { "metadata=" } else { "" } ,
695
+ DOCS_LINK_SUGGESTION
696
+ ) ,
697
+ }
698
+ }
699
+
641
700
for line in input. split ( |b| * b == b'\n' ) {
642
701
let line = match str:: from_utf8 ( line) {
643
702
Ok ( line) => line. trim ( ) ,
644
703
Err ( ..) => continue ,
645
704
} ;
646
- let mut iter = line. splitn ( 2 , ':' ) ;
647
- if iter. next ( ) != Some ( "cargo" ) {
648
- // skip this line since it doesn't start with "cargo:"
649
- continue ;
705
+ let mut new_syntax = false ;
706
+ let ( key, value) = if let Some ( data) = line. strip_prefix ( "cargo::" ) {
707
+ new_syntax = true ;
708
+
709
+ // For instance, `cargo::rustc-flags=foo`.
710
+ if RESERVED_PREFIXES
711
+ . iter ( )
712
+ . any ( |prefix| data. starts_with ( prefix) )
713
+ {
714
+ parse_directive ( whence. as_str ( ) , line, data, new_syntax, false ) ?
715
+ }
716
+ // For instance, `cargo::metadata=foo=bar`.
717
+ else if let Some ( data) = data. strip_prefix ( "metadata=" ) {
718
+ // Reserved keys should not be used with the `cargo::metadata=` syntax.
719
+ if let Some ( prefix) = RESERVED_PREFIXES
720
+ . iter ( )
721
+ . find ( |prefix| data. starts_with ( * prefix) )
722
+ {
723
+ bail ! ( "invalid output in {}: `{}`\n \
724
+ The reserved key cannot be used in the `cargo::metadata=` syntax. Please use `cargo::{}VAlUE` instead.\n \
725
+ {}", whence, line, prefix, DOCS_LINK_SUGGESTION
726
+ )
727
+ }
728
+ parse_directive ( whence. as_str ( ) , line, data, new_syntax, true ) ?
729
+ } else {
730
+ bail ! ( "invalid output in {}: `{}`\n \
731
+ Expected a line with `cargo::metadata=KEY=VALUE` but it did not have the `metadata=` part.\n \
732
+ {}", whence, line, DOCS_LINK_SUGGESTION
733
+ )
734
+ }
650
735
}
651
- let data = match iter. next ( ) {
652
- Some ( val) => val,
653
- None => continue ,
654
- } ;
655
-
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) ,
736
+ // For backwards compatibility, we also accept lines that start with "cargo:".
737
+ else if let Some ( data) = line. strip_prefix ( "cargo:" ) {
738
+ // For instance, `cargo:rustc-flags=foo` or `cargo:foo=bar`.
739
+ parse_directive ( whence. as_str ( ) , line, data, false , false ) ?
740
+ }
741
+ // Skip this line since it doesn't start with "cargo:" or "cargo::".
742
+ else {
743
+ continue ;
668
744
} ;
669
745
670
746
// This will rewrite paths if the target directory has been moved.
671
747
let value = value. replace (
672
748
script_out_dir_when_generated. to_str ( ) . unwrap ( ) ,
673
749
script_out_dir. to_str ( ) . unwrap ( ) ,
674
750
) ;
675
-
751
+ let syntax_prefix = if new_syntax { "cargo::" } else { "cargo:" } ;
676
752
macro_rules! check_and_add_target {
677
753
( $target_kind: expr, $is_target_kind: expr, $link_type: expr) => {
678
754
if !targets. iter( ) . any( |target| $is_target_kind( target) ) {
679
755
bail!(
680
- "invalid instruction `cargo: {}` from {}\n \
756
+ "invalid instruction `{} {}` from {}\n \
681
757
The package {} does not have a {} target.",
758
+ syntax_prefix,
682
759
key,
683
760
whence,
684
761
pkg_descr,
@@ -701,14 +778,14 @@ impl BuildOutput {
701
778
"rustc-link-arg-cdylib" | "rustc-cdylib-link-arg" => {
702
779
if !targets. iter ( ) . any ( |target| target. is_cdylib ( ) ) {
703
780
warnings. push ( format ! (
704
- "cargo: {} was specified in the build script of {}, \
781
+ "{} {} was specified in the build script of {}, \
705
782
but that package does not contain a cdylib target\n \
706
783
\n \
707
784
Allowing this was an unintended change in the 1.50 \
708
785
release, and may become an error in the future. \
709
786
For more information, see \
710
787
<https://github.com/rust-lang/cargo/issues/9562>.",
711
- key, pkg_descr
788
+ syntax_prefix , key, pkg_descr
712
789
) ) ;
713
790
}
714
791
linker_args. push ( ( LinkType :: Cdylib , value) )
@@ -721,11 +798,13 @@ impl BuildOutput {
721
798
let bin_name = parts. next ( ) . unwrap ( ) . to_string ( ) ;
722
799
let arg = parts. next ( ) . ok_or_else ( || {
723
800
anyhow:: format_err!(
724
- "invalid instruction `cargo:{}={}` from {}\n \
725
- The instruction should have the form cargo:{}=BIN=ARG",
801
+ "invalid instruction `{}{}={}` from {}\n \
802
+ The instruction should have the form {}{}=BIN=ARG",
803
+ syntax_prefix,
726
804
key,
727
805
value,
728
806
whence,
807
+ syntax_prefix,
729
808
key
730
809
)
731
810
} ) ?;
@@ -734,8 +813,9 @@ impl BuildOutput {
734
813
. any ( |target| target. is_bin ( ) && target. name ( ) == bin_name)
735
814
{
736
815
bail ! (
737
- "invalid instruction `cargo: {}` from {}\n \
816
+ "invalid instruction `{} {}` from {}\n \
738
817
The package {} does not have a bin target with the name `{}`.",
818
+ syntax_prefix,
739
819
key,
740
820
whence,
741
821
pkg_descr,
@@ -761,7 +841,10 @@ impl BuildOutput {
761
841
if extra_check_cfg {
762
842
check_cfgs. push ( value. to_string ( ) ) ;
763
843
} else {
764
- warnings. push ( format ! ( "cargo:{} requires -Zcheck-cfg=output flag" , key) ) ;
844
+ warnings. push ( format ! (
845
+ "{}{} requires -Zcheck-cfg=output flag" ,
846
+ syntax_prefix, key
847
+ ) ) ;
765
848
}
766
849
}
767
850
"rustc-env" => {
@@ -836,9 +919,9 @@ impl BuildOutput {
836
919
} )
837
920
}
838
921
839
- /// Parses [`cargo:rustc-flags`] instruction.
922
+ /// Parses [`cargo:: rustc-flags`] instruction.
840
923
///
841
- /// [`cargo:rustc-flags`]: https://doc.rust-lang.org/nightly/cargo/reference/build-scripts.html#cargorustc-flagsflags
924
+ /// [`cargo:: rustc-flags`]: https://doc.rust-lang.org/nightly/cargo/reference/build-scripts.html#cargorustc-flagsflags
842
925
pub fn parse_rustc_flags (
843
926
value : & str ,
844
927
whence : & str ,
@@ -884,9 +967,9 @@ impl BuildOutput {
884
967
Ok ( ( library_paths, library_links) )
885
968
}
886
969
887
- /// Parses [`cargo:rustc-env`] instruction.
970
+ /// Parses [`cargo:: rustc-env`] instruction.
888
971
///
889
- /// [`cargo:rustc-env`]: https://doc.rust-lang.org/nightly/cargo/reference/build-scripts.html#rustc-env
972
+ /// [`cargo:: rustc-env`]: https://doc.rust-lang.org/nightly/cargo/reference/build-scripts.html#rustc-env
890
973
pub fn parse_rustc_env ( value : & str , whence : & str ) -> CargoResult < ( String , String ) > {
891
974
let mut iter = value. splitn ( 2 , '=' ) ;
892
975
let name = iter. next ( ) ;
0 commit comments