@@ -144,7 +144,7 @@ impl TargetInfo {
144
144
& rustc. host ,
145
145
None ,
146
146
kind,
147
- "RUSTFLAGS" ,
147
+ Flags :: Rust ,
148
148
) ?;
149
149
let extra_fingerprint = kind. fingerprint_hash ( ) ;
150
150
let mut process = rustc. workspace_process ( ) ;
@@ -241,15 +241,15 @@ impl TargetInfo {
241
241
& rustc. host ,
242
242
Some ( & cfg) ,
243
243
kind,
244
- "RUSTFLAGS" ,
244
+ Flags :: Rust ,
245
245
) ?,
246
246
rustdocflags : env_args (
247
247
config,
248
248
requested_kinds,
249
249
& rustc. host ,
250
250
Some ( & cfg) ,
251
251
kind,
252
- "RUSTDOCFLAGS" ,
252
+ Flags :: Rustdoc ,
253
253
) ?,
254
254
cfg,
255
255
supports_split_debuginfo,
@@ -554,89 +554,134 @@ fn output_err_info(cmd: &ProcessBuilder, stdout: &str, stderr: &str) -> String {
554
554
result
555
555
}
556
556
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
+
557
579
/// Acquire extra flags to pass to the compiler from various locations.
558
580
///
559
581
/// The locations are:
560
582
///
561
583
/// - the `CARGO_ENCODED_RUSTFLAGS` environment variable
562
584
/// - the `RUSTFLAGS` environment variable
563
585
///
564
- /// then if this was not found
586
+ /// then if none of those were found
565
587
///
566
588
/// - `target.*.rustflags` from the config (.cargo/config)
567
589
/// - `target.cfg(..).rustflags` from the config
590
+ /// - `host.*.rustflags` from the config if compiling a host artifact or without `--target`
568
591
///
569
- /// then if neither of these were found
592
+ /// then if none of those were found
570
593
///
571
594
/// - `build.rustflags` from the config
572
595
///
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.
575
601
fn env_args (
576
602
config : & Config ,
577
603
requested_kinds : & [ CompileKind ] ,
578
604
host_triple : & str ,
579
605
target_cfg : Option < & [ Cfg ] > ,
580
606
kind : CompileKind ,
581
- name : & str ,
607
+ flags : Flags ,
582
608
) -> 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].
598
612
//
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
+ }
607
627
}
608
628
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 > > {
609
647
// First try CARGO_ENCODED_RUSTFLAGS from the environment.
610
648
// 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 ( ) ) ) {
612
650
if a. is_empty ( ) {
613
- return Ok ( Vec :: new ( ) ) ;
651
+ return Some ( Vec :: new ( ) ) ;
614
652
}
615
- return Ok ( a. split ( '\x1f' ) . map ( str:: to_string) . collect ( ) ) ;
653
+ return Some ( a. split ( '\x1f' ) . map ( str:: to_string) . collect ( ) ) ;
616
654
}
617
655
618
656
// Then try RUSTFLAGS from the environment
619
- if let Ok ( a) = env:: var ( name ) {
657
+ if let Ok ( a) = env:: var ( flags . as_env ( ) ) {
620
658
let args = a
621
659
. split ( ' ' )
622
660
. map ( str:: trim)
623
661
. filter ( |s| !s. is_empty ( ) )
624
662
. map ( str:: to_string) ;
625
- return Ok ( args. collect ( ) ) ;
663
+ return Some ( args. collect ( ) ) ;
626
664
}
627
665
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 > > > {
628
677
let mut rustflags = Vec :: new ( ) ;
629
678
630
- let name = name
631
- . chars ( )
632
- . flat_map ( |c| c. to_lowercase ( ) )
633
- . collect :: < String > ( ) ;
634
679
// Then the target.*.rustflags value...
635
680
let target = match & kind {
636
681
CompileKind :: Host => host_triple,
637
682
CompileKind :: Target ( target) => target. short_name ( ) ,
638
683
} ;
639
- let key = format ! ( "target.{}.{}" , target, name ) ;
684
+ let key = format ! ( "target.{}.{}" , target, flag . as_key ( ) ) ;
640
685
if let Some ( args) = config. get :: < Option < StringList > > ( & key) ? {
641
686
rustflags. extend ( args. as_slice ( ) . iter ( ) . cloned ( ) ) ;
642
687
}
@@ -656,22 +701,37 @@ fn env_args(
656
701
} ) ;
657
702
}
658
703
659
- if !rustflags. is_empty ( ) {
660
- return Ok ( rustflags) ;
704
+ if rustflags. is_empty ( ) {
705
+ Ok ( None )
706
+ } else {
707
+ Ok ( Some ( rustflags) )
661
708
}
709
+ }
662
710
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 > > > {
663
728
// Then the `build.rustflags` value.
664
729
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 ,
669
733
} ;
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 ( ) ) )
675
735
}
676
736
677
737
/// Collection of information about `rustc` and the host and target.
0 commit comments