@@ -2,11 +2,11 @@ use super::job::{Freshness, Job, Work};
22use super :: { fingerprint, Context , LinkType , Unit } ;
33use crate :: core:: compiler:: context:: Metadata ;
44use crate :: core:: compiler:: job_queue:: JobState ;
5- use crate :: core:: { profiles:: ProfileRoot , PackageId } ;
5+ use crate :: core:: { profiles:: ProfileRoot , PackageId , Target } ;
66use crate :: util:: errors:: CargoResult ;
77use crate :: util:: machine_message:: { self , Message } ;
88use crate :: util:: { internal, profile} ;
9- use anyhow:: Context as _;
9+ use anyhow:: { bail , Context as _} ;
1010use cargo_platform:: Cfg ;
1111use cargo_util:: paths;
1212use std:: collections:: hash_map:: { Entry , HashMap } ;
@@ -296,6 +296,9 @@ fn build_work(cx: &mut Context<'_, '_>, unit: &Unit) -> CargoResult<Job> {
296296
297297 let extra_link_arg = cx. bcx . config . cli_unstable ( ) . extra_link_arg ;
298298 let nightly_features_allowed = cx. bcx . config . nightly_features_allowed ;
299+ let targets: Vec < Target > = unit. pkg . targets ( ) . iter ( ) . cloned ( ) . collect ( ) ;
300+ // Need a separate copy for the fresh closure.
301+ let targets_fresh = targets. clone ( ) ;
299302
300303 // Prepare the unit of "dirty work" which will actually run the custom build
301304 // command.
@@ -405,6 +408,7 @@ fn build_work(cx: &mut Context<'_, '_>, unit: &Unit) -> CargoResult<Job> {
405408 & script_out_dir,
406409 extra_link_arg,
407410 nightly_features_allowed,
411+ & targets,
408412 ) ?;
409413
410414 if json_messages {
@@ -432,6 +436,7 @@ fn build_work(cx: &mut Context<'_, '_>, unit: &Unit) -> CargoResult<Job> {
432436 & script_out_dir,
433437 extra_link_arg,
434438 nightly_features_allowed,
439+ & targets_fresh,
435440 ) ?,
436441 } ;
437442
@@ -484,6 +489,7 @@ impl BuildOutput {
484489 script_out_dir : & Path ,
485490 extra_link_arg : bool ,
486491 nightly_features_allowed : bool ,
492+ targets : & [ Target ] ,
487493 ) -> CargoResult < BuildOutput > {
488494 let contents = paths:: read_bytes ( path) ?;
489495 BuildOutput :: parse (
@@ -494,6 +500,7 @@ impl BuildOutput {
494500 script_out_dir,
495501 extra_link_arg,
496502 nightly_features_allowed,
503+ targets,
497504 )
498505 }
499506
@@ -509,6 +516,7 @@ impl BuildOutput {
509516 script_out_dir : & Path ,
510517 extra_link_arg : bool ,
511518 nightly_features_allowed : bool ,
519+ targets : & [ Target ] ,
512520 ) -> CargoResult < BuildOutput > {
513521 let mut library_paths = Vec :: new ( ) ;
514522 let mut library_links = Vec :: new ( ) ;
@@ -543,7 +551,7 @@ impl BuildOutput {
543551 let ( key, value) = match ( key, value) {
544552 ( Some ( a) , Some ( b) ) => ( a, b. trim_end ( ) ) ,
545553 // Line started with `cargo:` but didn't match `key=value`.
546- _ => anyhow :: bail!( "Wrong output in {}: `{}`" , whence, line) ,
554+ _ => bail ! ( "Wrong output in {}: `{}`" , whence, line) ,
547555 } ;
548556
549557 // This will rewrite paths if the target directory has been moved.
@@ -552,7 +560,7 @@ impl BuildOutput {
552560 script_out_dir. to_str ( ) . unwrap ( ) ,
553561 ) ;
554562
555- // Keep in sync with TargetConfig::new .
563+ // Keep in sync with TargetConfig::parse_links_overrides .
556564 match key {
557565 "rustc-flags" => {
558566 let ( paths, links) = BuildOutput :: parse_rustc_flags ( & value, & whence) ?;
@@ -562,29 +570,61 @@ impl BuildOutput {
562570 "rustc-link-lib" => library_links. push ( value. to_string ( ) ) ,
563571 "rustc-link-search" => library_paths. push ( PathBuf :: from ( value) ) ,
564572 "rustc-link-arg-cdylib" | "rustc-cdylib-link-arg" => {
573+ if !targets. iter ( ) . any ( |target| target. is_cdylib ( ) ) {
574+ bail ! (
575+ "invalid instruction `cargo:{}` from {}\n \
576+ The package {} does not have a cdylib target.",
577+ key,
578+ whence,
579+ pkg_descr
580+ ) ;
581+ }
565582 linker_args. push ( ( LinkType :: Cdylib , value) )
566583 }
567584 "rustc-link-arg-bins" => {
568585 if extra_link_arg {
586+ if !targets. iter ( ) . any ( |target| target. is_bin ( ) ) {
587+ bail ! (
588+ "invalid instruction `cargo:{}` from {}\n \
589+ The package {} does not have a bin target.",
590+ key,
591+ whence,
592+ pkg_descr
593+ ) ;
594+ }
569595 linker_args. push ( ( LinkType :: Bin , value) ) ;
570596 } else {
571597 warnings. push ( format ! ( "cargo:{} requires -Zextra-link-arg flag" , key) ) ;
572598 }
573599 }
574600 "rustc-link-arg-bin" => {
575601 if extra_link_arg {
576- let parts = value. splitn ( 2 , "=" ) . collect :: < Vec < _ > > ( ) ;
577- if parts. len ( ) == 2 {
578- linker_args. push ( (
579- LinkType :: SingleBin ( parts[ 0 ] . to_string ( ) ) ,
580- parts[ 1 ] . to_string ( ) ,
581- ) ) ;
582- } else {
583- warnings. push ( format ! (
584- "cargo:{} has invalid syntax: expected `cargo:{}=BIN=ARG`" ,
585- key, key
586- ) ) ;
602+ let mut parts = value. splitn ( 2 , '=' ) ;
603+ let bin_name = parts. next ( ) . unwrap ( ) . to_string ( ) ;
604+ let arg = parts. next ( ) . ok_or_else ( || {
605+ anyhow:: format_err!(
606+ "invalid instruction `cargo:{}={}` from {}\n \
607+ The instruction should have the form cargo:{}=BIN=ARG",
608+ key,
609+ value,
610+ whence,
611+ key
612+ )
613+ } ) ?;
614+ if !targets
615+ . iter ( )
616+ . any ( |target| target. is_bin ( ) && target. name ( ) == bin_name)
617+ {
618+ bail ! (
619+ "invalid instruction `cargo:{}` from {}\n \
620+ The package {} does not have a bin target with the name `{}`.",
621+ key,
622+ whence,
623+ pkg_descr,
624+ bin_name
625+ ) ;
587626 }
627+ linker_args. push ( ( LinkType :: SingleBin ( bin_name) , arg. to_string ( ) ) ) ;
588628 } else {
589629 warnings. push ( format ! ( "cargo:{} requires -Zextra-link-arg flag" , key) ) ;
590630 }
@@ -632,7 +672,7 @@ impl BuildOutput {
632672 } else {
633673 // Setting RUSTC_BOOTSTRAP would change the behavior of the crate.
634674 // Abort with an error.
635- anyhow :: bail!( "Cannot set `RUSTC_BOOTSTRAP={}` from {}.\n \
675+ bail ! ( "Cannot set `RUSTC_BOOTSTRAP={}` from {}.\n \
636676 note: Crates cannot set `RUSTC_BOOTSTRAP` themselves, as doing so would subvert the stability guarantees of Rust for your project.\n \
637677 help: If you're sure you want to do this in your project, set the environment variable `RUSTC_BOOTSTRAP={}` before running cargo instead.",
638678 val,
@@ -683,7 +723,7 @@ impl BuildOutput {
683723 if value. is_empty ( ) {
684724 value = match flags_iter. next ( ) {
685725 Some ( v) => v,
686- None => anyhow :: bail! {
726+ None => bail ! {
687727 "Flag in rustc-flags has no value in {}: {}" ,
688728 whence,
689729 value
@@ -699,7 +739,7 @@ impl BuildOutput {
699739 _ => unreachable ! ( ) ,
700740 } ;
701741 } else {
702- anyhow :: bail!(
742+ bail ! (
703743 "Only `-l` and `-L` flags are allowed in {}: `{}`" ,
704744 whence,
705745 value
@@ -715,7 +755,7 @@ impl BuildOutput {
715755 let val = iter. next ( ) ;
716756 match ( name, val) {
717757 ( Some ( n) , Some ( v) ) => Ok ( ( n. to_owned ( ) , v. to_owned ( ) ) ) ,
718- _ => anyhow :: bail!( "Variable rustc-env has no value in {}: {}" , whence, value) ,
758+ _ => bail ! ( "Variable rustc-env has no value in {}: {}" , whence, value) ,
719759 }
720760 }
721761}
@@ -900,6 +940,7 @@ fn prev_build_output(cx: &mut Context<'_, '_>, unit: &Unit) -> (Option<BuildOutp
900940 & script_out_dir,
901941 extra_link_arg,
902942 cx. bcx . config . nightly_features_allowed ,
943+ unit. pkg . targets ( ) ,
903944 )
904945 . ok ( ) ,
905946 prev_script_out_dir,
0 commit comments