@@ -314,7 +314,20 @@ pub fn create_bcx<'a, 'cfg>(
314
314
}
315
315
config. validate_term_config ( ) ?;
316
316
317
- let target_data = RustcTargetData :: new ( ws, & build_config. requested_kinds ) ?;
317
+ let mut target_data_kinds = HashSet :: new ( ) ;
318
+ for requested_kind in build_config. requested_kinds . iter ( ) {
319
+ target_data_kinds. insert ( * requested_kind) ;
320
+ }
321
+ if config. cli_unstable ( ) . member_configs {
322
+ for ( _, member_config) in config. member_cfgs ( ) ?. iter ( ) {
323
+ if let Some ( target) = & member_config. target {
324
+ let kind = CompileKind :: Target ( CompileTarget :: new ( target. raw_value ( ) ) ?) ;
325
+ target_data_kinds. insert ( kind) ;
326
+ }
327
+ }
328
+ }
329
+ let target_data_kinds: Vec < _ > = target_data_kinds. into_iter ( ) . collect ( ) ;
330
+ let target_data = RustcTargetData :: new ( ws, & target_data_kinds) ?;
318
331
319
332
let specs = spec. to_package_id_specs ( ws) ?;
320
333
let dev_deps = ws. require_optional_deps ( ) || filter. need_dev_deps ( build_config. mode ) ;
@@ -414,24 +427,13 @@ pub fn create_bcx<'a, 'cfg>(
414
427
workspace_resolve. as_ref ( ) . unwrap_or ( & resolve) ,
415
428
) ?;
416
429
417
- // If `--target` has not been specified, then the unit graph is built
418
- // assuming `--target $HOST` was specified. See
419
- // `rebuild_unit_graph_shared` for more on why this is done.
420
430
let explicit_host_kind = CompileKind :: Target ( CompileTarget :: new ( & target_data. rustc . host ) ?) ;
421
- let explicit_host_kinds: Vec < _ > = build_config
422
- . requested_kinds
423
- . iter ( )
424
- . map ( |kind| match kind {
425
- CompileKind :: Host => explicit_host_kind,
426
- CompileKind :: Target ( t) => CompileKind :: Target ( * t) ,
427
- } )
428
- . collect ( ) ;
429
-
430
431
let mut units = generate_targets (
431
432
ws,
432
433
& to_builds,
433
434
filter,
434
- & explicit_host_kinds,
435
+ & build_config. requested_kinds ,
436
+ explicit_host_kind,
435
437
build_config. mode ,
436
438
& resolve,
437
439
& workspace_resolve,
@@ -441,6 +443,12 @@ pub fn create_bcx<'a, 'cfg>(
441
443
interner,
442
444
) ?;
443
445
446
+ let mut explicit_kinds = HashSet :: new ( ) ;
447
+ for unit in units. iter ( ) {
448
+ explicit_kinds. insert ( unit. kind ( ) ) ;
449
+ }
450
+ let explicit_kinds: Vec < _ > = explicit_kinds. into_iter ( ) . collect ( ) ;
451
+
444
452
let std_roots = if let Some ( crates) = & config. cli_unstable ( ) . build_std {
445
453
// Only build libtest if it looks like it is needed.
446
454
let mut crates = crates. clone ( ) ;
@@ -459,7 +467,7 @@ pub fn create_bcx<'a, 'cfg>(
459
467
& crates,
460
468
std_resolve,
461
469
std_features,
462
- & explicit_host_kinds ,
470
+ & explicit_kinds ,
463
471
& pkg_set,
464
472
interner,
465
473
& profiles,
@@ -731,6 +739,7 @@ fn generate_targets(
731
739
packages : & [ & Package ] ,
732
740
filter : & CompileFilter ,
733
741
requested_kinds : & [ CompileKind ] ,
742
+ explicit_host_kind : CompileKind ,
734
743
mode : CompileMode ,
735
744
resolve : & Resolve ,
736
745
workspace_resolve : & Option < Resolve > ,
@@ -741,91 +750,112 @@ fn generate_targets(
741
750
) -> CargoResult < Vec < Unit > > {
742
751
let config = ws. config ( ) ;
743
752
// Helper for creating a list of `Unit` structures
744
- let new_unit =
745
- |units : & mut HashSet < Unit > , pkg : & Package , target : & Target , target_mode : CompileMode | {
746
- let unit_for = if target_mode. is_any_test ( ) {
747
- // NOTE: the `UnitFor` here is subtle. If you have a profile
748
- // with `panic` set, the `panic` flag is cleared for
749
- // tests/benchmarks and their dependencies. If this
750
- // was `normal`, then the lib would get compiled three
751
- // times (once with panic, once without, and once with
752
- // `--test`).
753
- //
754
- // This would cause a problem for doc tests, which would fail
755
- // because `rustdoc` would attempt to link with both libraries
756
- // at the same time. Also, it's probably not important (or
757
- // even desirable?) for rustdoc to link with a lib with
758
- // `panic` set.
759
- //
760
- // As a consequence, Examples and Binaries get compiled
761
- // without `panic` set. This probably isn't a bad deal.
762
- //
763
- // Forcing the lib to be compiled three times during `cargo
764
- // test` is probably also not desirable.
765
- UnitFor :: new_test ( config)
766
- } else if target. for_host ( ) {
767
- // Proc macro / plugin should not have `panic` set.
768
- UnitFor :: new_compiler ( )
769
- } else {
770
- UnitFor :: new_normal ( )
771
- } ;
772
- // Custom build units are added in `build_unit_dependencies`.
773
- assert ! ( !target. is_custom_build( ) ) ;
774
- let target_mode = match target_mode {
775
- CompileMode :: Test => {
776
- if target. is_example ( ) && !filter. is_specific ( ) && !target. tested ( ) {
777
- // Examples are included as regular binaries to verify
778
- // that they compile.
779
- CompileMode :: Build
780
- } else {
781
- CompileMode :: Test
782
- }
753
+ let new_unit = |units : & mut HashSet < Unit > ,
754
+ pkg : & Package ,
755
+ target : & Target ,
756
+ target_mode : CompileMode ,
757
+ force_kind : Option < CompileKind > | {
758
+ let unit_for = if target_mode. is_any_test ( ) {
759
+ // NOTE: the `UnitFor` here is subtle. If you have a profile
760
+ // with `panic` set, the `panic` flag is cleared for
761
+ // tests/benchmarks and their dependencies. If this
762
+ // was `normal`, then the lib would get compiled three
763
+ // times (once with panic, once without, and once with
764
+ // `--test`).
765
+ //
766
+ // This would cause a problem for doc tests, which would fail
767
+ // because `rustdoc` would attempt to link with both libraries
768
+ // at the same time. Also, it's probably not important (or
769
+ // even desirable?) for rustdoc to link with a lib with
770
+ // `panic` set.
771
+ //
772
+ // As a consequence, Examples and Binaries get compiled
773
+ // without `panic` set. This probably isn't a bad deal.
774
+ //
775
+ // Forcing the lib to be compiled three times during `cargo
776
+ // test` is probably also not desirable.
777
+ UnitFor :: new_test ( config)
778
+ } else if target. for_host ( ) {
779
+ // Proc macro / plugin should not have `panic` set.
780
+ UnitFor :: new_compiler ( )
781
+ } else {
782
+ UnitFor :: new_normal ( )
783
+ } ;
784
+ // Custom build units are added in `build_unit_dependencies`.
785
+ assert ! ( !target. is_custom_build( ) ) ;
786
+ let target_mode = match target_mode {
787
+ CompileMode :: Test => {
788
+ if target. is_example ( ) && !filter. is_specific ( ) && !target. tested ( ) {
789
+ // Examples are included as regular binaries to verify
790
+ // that they compile.
791
+ CompileMode :: Build
792
+ } else {
793
+ CompileMode :: Test
783
794
}
784
- CompileMode :: Build => match * target. kind ( ) {
785
- TargetKind :: Test => CompileMode :: Test ,
786
- TargetKind :: Bench => CompileMode :: Bench ,
787
- _ => CompileMode :: Build ,
788
- } ,
789
- // `CompileMode::Bench` is only used to inform `filter_default_targets`
790
- // which command is being used (`cargo bench`). Afterwards, tests
791
- // and benches are treated identically. Switching the mode allows
792
- // de-duplication of units that are essentially identical. For
793
- // example, `cargo build --all-targets --release` creates the units
794
- // (lib profile:bench, mode:test) and (lib profile:bench, mode:bench)
795
- // and since these are the same, we want them to be de-duplicated in
796
- // `unit_dependencies`.
797
- CompileMode :: Bench => CompileMode :: Test ,
798
- _ => target_mode,
799
- } ;
795
+ }
796
+ CompileMode :: Build => match * target. kind ( ) {
797
+ TargetKind :: Test => CompileMode :: Test ,
798
+ TargetKind :: Bench => CompileMode :: Bench ,
799
+ _ => CompileMode :: Build ,
800
+ } ,
801
+ // `CompileMode::Bench` is only used to inform `filter_default_targets`
802
+ // which command is being used (`cargo bench`). Afterwards, tests
803
+ // and benches are treated identically. Switching the mode allows
804
+ // de-duplication of units that are essentially identical. For
805
+ // example, `cargo build --all-targets --release` creates the units
806
+ // (lib profile:bench, mode:test) and (lib profile:bench, mode:bench)
807
+ // and since these are the same, we want them to be de-duplicated in
808
+ // `unit_dependencies`.
809
+ CompileMode :: Bench => CompileMode :: Test ,
810
+ _ => target_mode,
811
+ } ;
800
812
801
- let is_local = pkg. package_id ( ) . source_id ( ) . is_path ( ) ;
802
- let profile = profiles. get_profile (
803
- pkg. package_id ( ) ,
804
- ws. is_member ( pkg) ,
805
- is_local,
806
- unit_for,
807
- target_mode,
808
- ) ;
813
+ let is_local = pkg. package_id ( ) . source_id ( ) . is_path ( ) ;
814
+ let profile = profiles. get_profile (
815
+ pkg. package_id ( ) ,
816
+ ws. is_member ( pkg) ,
817
+ is_local,
818
+ unit_for,
819
+ target_mode,
820
+ ) ;
809
821
810
- // No need to worry about build-dependencies, roots are never build dependencies.
811
- let features_for = FeaturesFor :: from_for_host ( target. proc_macro ( ) ) ;
812
- let features = resolved_features. activated_features ( pkg. package_id ( ) , features_for) ;
822
+ // No need to worry about build-dependencies, roots are never build dependencies.
823
+ let features_for = FeaturesFor :: from_for_host ( target. proc_macro ( ) ) ;
824
+ let features = resolved_features. activated_features ( pkg. package_id ( ) , features_for) ;
813
825
814
- for kind in requested_kinds {
815
- let unit = interner. intern (
816
- pkg,
817
- target,
818
- profile,
819
- kind. for_target ( target) ,
820
- target_mode,
821
- features. clone ( ) ,
822
- /*is_std*/ false ,
823
- /*dep_hash*/ 0 ,
824
- ) ;
825
- units. insert ( unit) ;
826
- }
826
+ // If `force_kind` is given we build only that kind
827
+ let requested_kinds = if let Some ( force_kind) = force_kind {
828
+ vec ! [ force_kind]
829
+ } else {
830
+ requested_kinds. to_vec ( )
827
831
} ;
828
832
833
+ // If `--target` has not been specified, then the unit graph is built
834
+ // assuming `--target $HOST` was specified. See
835
+ // `rebuild_unit_graph_shared` for more on why this is done.
836
+ let explicit_kinds: Vec < _ > = requested_kinds
837
+ . iter ( )
838
+ . map ( |kind| match kind {
839
+ CompileKind :: Host => explicit_host_kind,
840
+ CompileKind :: Target ( t) => CompileKind :: Target ( * t) ,
841
+ } )
842
+ . collect ( ) ;
843
+
844
+ for kind in explicit_kinds {
845
+ let unit = interner. intern (
846
+ pkg,
847
+ target,
848
+ profile,
849
+ kind. for_target ( target) ,
850
+ target_mode,
851
+ features. clone ( ) ,
852
+ /*is_std*/ false ,
853
+ /*dep_hash*/ 0 ,
854
+ ) ;
855
+ units. insert ( unit) ;
856
+ }
857
+ } ;
858
+
829
859
// Create a list of proposed targets.
830
860
let mut proposals: Vec < Proposal < ' _ > > = Vec :: new ( ) ;
831
861
@@ -978,7 +1008,23 @@ fn generate_targets(
978
1008
None => Vec :: new ( ) ,
979
1009
} ;
980
1010
if target. is_lib ( ) || unavailable_features. is_empty ( ) {
981
- new_unit ( & mut units, pkg, target, mode) ;
1011
+ let force_kind =
1012
+ if let Some ( member_config) = config. member_config ( pkg. name ( ) . as_str ( ) ) ? {
1013
+ if !config. cli_unstable ( ) . member_configs {
1014
+ anyhow:: bail!(
1015
+ "member configurations are unstable. Add -Zmember-configs to enable them."
1016
+ ) ;
1017
+ }
1018
+ if let Some ( ref target) = member_config. target {
1019
+ let target = target. raw_value ( ) . to_string ( ) ;
1020
+ Some ( CompileKind :: from_requested_targets ( config, & [ target] ) ?[ 0 ] )
1021
+ } else {
1022
+ None
1023
+ }
1024
+ } else {
1025
+ None
1026
+ } ;
1027
+ new_unit ( & mut units, pkg, target, mode, force_kind) ;
982
1028
} else if requires_features {
983
1029
let required_features = target. required_features ( ) . unwrap ( ) ;
984
1030
let quoted_required_features: Vec < String > = required_features
0 commit comments