@@ -144,7 +144,7 @@ impl TargetInfo {
144144 & rustc. host ,
145145 None ,
146146 kind,
147- "RUSTFLAGS" ,
147+ Flags :: Rust ,
148148 ) ?;
149149 let extra_fingerprint = kind. fingerprint_hash ( ) ;
150150 let mut process = rustc. workspace_process ( ) ;
@@ -241,15 +241,15 @@ impl TargetInfo {
241241 & rustc. host ,
242242 Some ( & cfg) ,
243243 kind,
244- "RUSTFLAGS" ,
244+ Flags :: Rust ,
245245 ) ?,
246246 rustdocflags : env_args (
247247 config,
248248 requested_kinds,
249249 & rustc. host ,
250250 Some ( & cfg) ,
251251 kind,
252- "RUSTDOCFLAGS" ,
252+ Flags :: Rustdoc ,
253253 ) ?,
254254 cfg,
255255 supports_split_debuginfo,
@@ -554,89 +554,134 @@ fn output_err_info(cmd: &ProcessBuilder, stdout: &str, stderr: &str) -> String {
554554 result
555555}
556556
557+ #[ derive( Debug , Copy , Clone ) ]
558+ enum Flags {
559+ Rust ,
560+ Rustdoc ,
561+ }
562+
563+ impl Flags {
564+ fn as_key ( self ) -> & ' static str {
565+ match self {
566+ Flags :: Rust => "rustflags" ,
567+ Flags :: Rustdoc => "rustdocflags" ,
568+ }
569+ }
570+
571+ fn as_env ( self ) -> & ' static str {
572+ match self {
573+ Flags :: Rust => "RUSTFLAGS" ,
574+ Flags :: Rustdoc => "RUSTDOCFLAGS" ,
575+ }
576+ }
577+ }
578+
557579/// Acquire extra flags to pass to the compiler from various locations.
558580///
559581/// The locations are:
560582///
561583/// - the `CARGO_ENCODED_RUSTFLAGS` environment variable
562584/// - the `RUSTFLAGS` environment variable
563585///
564- /// then if this was not found
586+ /// then if none of those were found
565587///
566588/// - `target.*.rustflags` from the config (.cargo/config)
567589/// - `target.cfg(..).rustflags` from the config
590+ /// - `host.*.rustflags` from the config if compiling a host artifact or without `--target`
568591///
569- /// then if neither of these were found
592+ /// then if none of those were found
570593///
571594/// - `build.rustflags` from the config
572595///
573- /// Note that if a `target` is specified, no args will be passed to host code (plugins, build
574- /// scripts, ...), even if it is the same as the target.
596+ /// The behavior differs slightly when cross-compiling (or, specifically, when `--target` is
597+ /// provided) for artifacts that are always built for the host (plugins, build scripts, ...).
598+ /// For those artifacts, _only_ `host.*.rustflags` is respected, and no other configuration
599+ /// sources, _regardless of the value of `target-applies-to-host`_. This is counterintuitive, but
600+ /// necessary to retain bacwkards compatibility with older versions of Cargo.
575601fn env_args (
576602 config : & Config ,
577603 requested_kinds : & [ CompileKind ] ,
578604 host_triple : & str ,
579605 target_cfg : Option < & [ Cfg ] > ,
580606 kind : CompileKind ,
581- name : & str ,
607+ flags : Flags ,
582608) -> CargoResult < Vec < String > > {
583- // We *want* to apply RUSTFLAGS only to builds for the
584- // requested target architecture, and not to things like build
585- // scripts and plugins, which may be for an entirely different
586- // architecture. Cargo's present architecture makes it quite
587- // hard to only apply flags to things that are not build
588- // scripts and plugins though, so we do something more hacky
589- // instead to avoid applying the same RUSTFLAGS to multiple targets
590- // arches:
591- //
592- // 1) If --target is not specified we just apply RUSTFLAGS to
593- // all builds; they are all going to have the same target.
594- //
595- // 2) If --target *is* specified then we only apply RUSTFLAGS
596- // to compilation units with the Target kind, which indicates
597- // it was chosen by the --target flag.
609+ let target_applies_to_host = config. target_applies_to_host ( ) ?;
610+
611+ // Host artifacts should not generally pick up rustflags from anywhere except [host].
598612 //
599- // This means that, e.g., even if the specified --target is the
600- // same as the host, build scripts in plugins won't get
601- // RUSTFLAGS.
602- if requested_kinds != [ CompileKind :: Host ] && kind. is_host ( ) {
603- // This is probably a build script or plugin and we're
604- // compiling with --target. In this scenario there are
605- // no rustflags we can apply.
606- return Ok ( Vec :: new ( ) ) ;
613+ // The one exception to this is if `target-applies-to-host = true`, which opts into a
614+ // particular (inconsistent) past Cargo behavior where host artifacts _do_ pick up rustflags
615+ // set elsewhere when `--target` isn't passed.
616+ if kind. is_host ( ) {
617+ if target_applies_to_host && requested_kinds == [ CompileKind :: Host ] {
618+ // This is the past Cargo behavior where we fall back to the same logic as for other
619+ // artifacts without --target.
620+ } else {
621+ // In all other cases, host artifacts just get flags from [host], regardless of
622+ // --target. Or, phrased differently, no `--target` behaves the same as `--target
623+ // <host>`, and host artifacts are always "special" (they don't pick up `RUSTFLAGS` for
624+ // example).
625+ return Ok ( rustflags_from_host ( config, flags, host_triple) ?. unwrap_or_else ( Vec :: new) ) ;
626+ }
607627 }
608628
629+ // All other artifacts pick up the RUSTFLAGS, [target.*], and [build], in that order.
630+ // NOTE: It is impossible to have a [host] section and reach this logic with kind.is_host(),
631+ // since [host] implies `target-applies-to-host = false`, which always early-returns above.
632+
633+ if let Some ( rustflags) = rustflags_from_env ( flags) {
634+ Ok ( rustflags)
635+ } else if let Some ( rustflags) =
636+ rustflags_from_target ( config, host_triple, target_cfg, kind, flags) ?
637+ {
638+ Ok ( rustflags)
639+ } else if let Some ( rustflags) = rustflags_from_build ( config, flags) ? {
640+ Ok ( rustflags)
641+ } else {
642+ Ok ( Vec :: new ( ) )
643+ }
644+ }
645+
646+ fn rustflags_from_env ( flags : Flags ) -> Option < Vec < String > > {
609647 // First try CARGO_ENCODED_RUSTFLAGS from the environment.
610648 // Prefer this over RUSTFLAGS since it's less prone to encoding errors.
611- if let Ok ( a) = env:: var ( format ! ( "CARGO_ENCODED_{}" , name ) ) {
649+ if let Ok ( a) = env:: var ( format ! ( "CARGO_ENCODED_{}" , flags . as_env ( ) ) ) {
612650 if a. is_empty ( ) {
613- return Ok ( Vec :: new ( ) ) ;
651+ return Some ( Vec :: new ( ) ) ;
614652 }
615- return Ok ( a. split ( '\x1f' ) . map ( str:: to_string) . collect ( ) ) ;
653+ return Some ( a. split ( '\x1f' ) . map ( str:: to_string) . collect ( ) ) ;
616654 }
617655
618656 // Then try RUSTFLAGS from the environment
619- if let Ok ( a) = env:: var ( name ) {
657+ if let Ok ( a) = env:: var ( flags . as_env ( ) ) {
620658 let args = a
621659 . split ( ' ' )
622660 . map ( str:: trim)
623661 . filter ( |s| !s. is_empty ( ) )
624662 . map ( str:: to_string) ;
625- return Ok ( args. collect ( ) ) ;
663+ return Some ( args. collect ( ) ) ;
626664 }
627665
666+ // No rustflags to be collected from the environment
667+ None
668+ }
669+
670+ fn rustflags_from_target (
671+ config : & Config ,
672+ host_triple : & str ,
673+ target_cfg : Option < & [ Cfg ] > ,
674+ kind : CompileKind ,
675+ flag : Flags ,
676+ ) -> CargoResult < Option < Vec < String > > > {
628677 let mut rustflags = Vec :: new ( ) ;
629678
630- let name = name
631- . chars ( )
632- . flat_map ( |c| c. to_lowercase ( ) )
633- . collect :: < String > ( ) ;
634679 // Then the target.*.rustflags value...
635680 let target = match & kind {
636681 CompileKind :: Host => host_triple,
637682 CompileKind :: Target ( target) => target. short_name ( ) ,
638683 } ;
639- let key = format ! ( "target.{}.{}" , target, name ) ;
684+ let key = format ! ( "target.{}.{}" , target, flag . as_key ( ) ) ;
640685 if let Some ( args) = config. get :: < Option < StringList > > ( & key) ? {
641686 rustflags. extend ( args. as_slice ( ) . iter ( ) . cloned ( ) ) ;
642687 }
@@ -656,22 +701,37 @@ fn env_args(
656701 } ) ;
657702 }
658703
659- if !rustflags. is_empty ( ) {
660- return Ok ( rustflags) ;
704+ if rustflags. is_empty ( ) {
705+ Ok ( None )
706+ } else {
707+ Ok ( Some ( rustflags) )
661708 }
709+ }
662710
711+ fn rustflags_from_host (
712+ config : & Config ,
713+ flag : Flags ,
714+ host_triple : & str ,
715+ ) -> CargoResult < Option < Vec < String > > > {
716+ let target_cfg = config. host_cfg_triple ( host_triple) ?;
717+ let list = match flag {
718+ Flags :: Rust => & target_cfg. rustflags ,
719+ Flags :: Rustdoc => {
720+ // host.rustdocflags is not a thing, since it does not make sense
721+ return Ok ( None ) ;
722+ }
723+ } ;
724+ Ok ( list. as_ref ( ) . map ( |l| l. val . as_slice ( ) . to_vec ( ) ) )
725+ }
726+
727+ fn rustflags_from_build ( config : & Config , flag : Flags ) -> CargoResult < Option < Vec < String > > > {
663728 // Then the `build.rustflags` value.
664729 let build = config. build_config ( ) ?;
665- let list = if name == "rustflags" {
666- & build. rustflags
667- } else {
668- & build. rustdocflags
730+ let list = match flag {
731+ Flags :: Rust => & build. rustflags ,
732+ Flags :: Rustdoc => & build. rustdocflags ,
669733 } ;
670- if let Some ( list) = list {
671- return Ok ( list. as_slice ( ) . to_vec ( ) ) ;
672- }
673-
674- Ok ( Vec :: new ( ) )
734+ Ok ( list. as_ref ( ) . map ( |l| l. as_slice ( ) . to_vec ( ) ) )
675735}
676736
677737/// Collection of information about `rustc` and the host and target.
0 commit comments