@@ -531,6 +531,92 @@ impl ToJson for LinkerFlavorCli {
531
531
}
532
532
}
533
533
534
+ /// The different `-Clink-self-contained` options that can be specified in a target spec:
535
+ /// - enabling or disabling in bulk
536
+ /// - some target-specific pieces of inference to determine whether to use self-contained linking
537
+ /// if `-Clink-self-contained` is not specified explicitly (e.g. on musl/mingw)
538
+ /// - explicitly enabling some of the self-contained linking components, e.g. the linker component
539
+ /// to use `rust-lld`
540
+ #[ derive( Clone , Copy , PartialEq , Debug ) ]
541
+ pub enum LinkSelfContained {
542
+ /// The target spec explicitly enables self-contained linking.
543
+ True ,
544
+
545
+ /// The target spec explicitly disables self-contained linking.
546
+ False ,
547
+
548
+ /// The target spec requests that the self-contained mode is inferred, in the context of musl.
549
+ InferredForMusl ,
550
+
551
+ /// The target spec requests that the self-contained mode is inferred, in the context of mingw.
552
+ InferredForMingw ,
553
+
554
+ /// The target spec explicitly enables a list of self-contained linking components: e.g. for
555
+ /// targets opting into a subset of components like the CLI's `-C link-self-contained=+linker`.
556
+ WithComponents ( LinkSelfContainedComponents ) ,
557
+ }
558
+
559
+ impl ToJson for LinkSelfContained {
560
+ fn to_json ( & self ) -> Json {
561
+ match * self {
562
+ LinkSelfContained :: WithComponents ( components) => {
563
+ // Serialize the components in a json object's `components` field, to prepare for a
564
+ // future where `crt-objects-fallback` is removed from the json specs and
565
+ // incorporated as a field here.
566
+ let mut map = BTreeMap :: new ( ) ;
567
+ map. insert ( "components" , components) ;
568
+ map. to_json ( )
569
+ }
570
+
571
+ // Stable values backwards-compatible with `LinkSelfContainedDefault`
572
+ LinkSelfContained :: True => "true" . to_json ( ) ,
573
+ LinkSelfContained :: False => "false" . to_json ( ) ,
574
+ LinkSelfContained :: InferredForMusl => "musl" . to_json ( ) ,
575
+ LinkSelfContained :: InferredForMingw => "mingw" . to_json ( ) ,
576
+ }
577
+ }
578
+ }
579
+
580
+ impl LinkSelfContained {
581
+ /// Returns whether the target spec has self-contained linking explicitly disabled. Used to emit
582
+ /// errors if the user then enables it on the CLI.
583
+ pub fn is_disabled ( self ) -> bool {
584
+ self == Self :: False
585
+ }
586
+
587
+ /// Returns whether the target spec explictly requests self-contained linking, i.e. not via
588
+ /// inference.
589
+ pub fn is_linker_enabled ( self ) -> bool {
590
+ match self {
591
+ LinkSelfContained :: True => true ,
592
+ LinkSelfContained :: False => false ,
593
+ LinkSelfContained :: WithComponents ( c) => c. contains ( LinkSelfContainedComponents :: LINKER ) ,
594
+ _ => false ,
595
+ }
596
+ }
597
+
598
+ /// Returns the key to use when serializing the setting to json:
599
+ /// - individual components in a `link-self-contained` object value
600
+ /// - the other variants as a backwards-compatible `crt-objects-fallback` string
601
+ fn json_key ( self ) -> & ' static str {
602
+ match self {
603
+ LinkSelfContained :: WithComponents ( _) => "link-self-contained" ,
604
+ _ => "crt-objects-fallback" ,
605
+ }
606
+ }
607
+ }
608
+
609
+ impl From < LinkSelfContainedDefault > for LinkSelfContained {
610
+ fn from ( value : LinkSelfContainedDefault ) -> Self {
611
+ match value {
612
+ LinkSelfContainedDefault :: True => LinkSelfContained :: True ,
613
+ LinkSelfContainedDefault :: False => LinkSelfContained :: False ,
614
+ LinkSelfContainedDefault :: Musl => LinkSelfContained :: InferredForMusl ,
615
+ LinkSelfContainedDefault :: Mingw => LinkSelfContained :: InferredForMingw ,
616
+ }
617
+ }
618
+ }
619
+
534
620
bitflags:: bitflags! {
535
621
#[ derive( Default ) ]
536
622
/// The `-C link-self-contained` components that can individually be enabled or disabled.
@@ -563,6 +649,49 @@ impl LinkSelfContainedComponents {
563
649
_ => return None ,
564
650
} )
565
651
}
652
+
653
+ /// Return the component's name.
654
+ ///
655
+ /// Returns `None` if the bitflags aren't a singular component (but a mix of multiple flags).
656
+ fn as_str ( self ) -> Option < & ' static str > {
657
+ Some ( match self {
658
+ LinkSelfContainedComponents :: CRT_OBJECTS => "crto" ,
659
+ LinkSelfContainedComponents :: LIBC => "libc" ,
660
+ LinkSelfContainedComponents :: UNWIND => "unwind" ,
661
+ LinkSelfContainedComponents :: LINKER => "linker" ,
662
+ LinkSelfContainedComponents :: SANITIZERS => "sanitizers" ,
663
+ LinkSelfContainedComponents :: MINGW => "mingw" ,
664
+ _ => return None ,
665
+ } )
666
+ }
667
+
668
+ /// Returns an array of all the components.
669
+ fn all_components ( ) -> [ LinkSelfContainedComponents ; 6 ] {
670
+ [
671
+ LinkSelfContainedComponents :: CRT_OBJECTS ,
672
+ LinkSelfContainedComponents :: LIBC ,
673
+ LinkSelfContainedComponents :: UNWIND ,
674
+ LinkSelfContainedComponents :: LINKER ,
675
+ LinkSelfContainedComponents :: SANITIZERS ,
676
+ LinkSelfContainedComponents :: MINGW ,
677
+ ]
678
+ }
679
+ }
680
+
681
+ impl ToJson for LinkSelfContainedComponents {
682
+ fn to_json ( & self ) -> Json {
683
+ let components: Vec < _ > = Self :: all_components ( )
684
+ . into_iter ( )
685
+ . filter ( |c| self . contains ( * c) )
686
+ . map ( |c| {
687
+ // We can unwrap because we're iterating over all the known singular components,
688
+ // not an actual set of flags where `as_str` can fail.
689
+ c. as_str ( ) . unwrap ( ) . to_owned ( )
690
+ } )
691
+ . collect ( ) ;
692
+
693
+ components. to_json ( )
694
+ }
566
695
}
567
696
568
697
#[ derive( Clone , Copy , Debug , PartialEq , Hash , Encodable , Decodable , HashStable_Generic ) ]
@@ -1739,7 +1868,9 @@ pub struct TargetOptions {
1739
1868
/// Same as `(pre|post)_link_objects`, but when self-contained linking mode is enabled.
1740
1869
pub pre_link_objects_self_contained : CrtObjects ,
1741
1870
pub post_link_objects_self_contained : CrtObjects ,
1742
- pub link_self_contained : LinkSelfContainedDefault ,
1871
+ /// Behavior for the self-contained linking mode: inferred for some targets, or explicitly
1872
+ /// enabled (in bulk, or with individual components).
1873
+ pub link_self_contained : LinkSelfContained ,
1743
1874
1744
1875
/// Linker arguments that are passed *before* any user-defined libraries.
1745
1876
pub pre_link_args : LinkArgs ,
@@ -2212,7 +2343,7 @@ impl Default for TargetOptions {
2212
2343
post_link_objects : Default :: default ( ) ,
2213
2344
pre_link_objects_self_contained : Default :: default ( ) ,
2214
2345
post_link_objects_self_contained : Default :: default ( ) ,
2215
- link_self_contained : LinkSelfContainedDefault :: False ,
2346
+ link_self_contained : LinkSelfContained :: False ,
2216
2347
pre_link_args : LinkArgs :: new ( ) ,
2217
2348
pre_link_args_json : LinkArgsCli :: new ( ) ,
2218
2349
late_link_args : LinkArgs :: new ( ) ,
@@ -2693,12 +2824,47 @@ impl Target {
2693
2824
}
2694
2825
Ok :: <( ) , String >( ( ) )
2695
2826
} ) ;
2696
-
2697
- ( $key_name: ident = $json_name: expr, link_self_contained) => ( {
2827
+ ( $key_name: ident, LinkSelfContained ) => ( {
2828
+ // Skeleton of what needs to be parsed:
2829
+ //
2830
+ // ```
2831
+ // $name: {
2832
+ // "components": [
2833
+ // <array of strings>
2834
+ // ]
2835
+ // }
2836
+ // ```
2837
+ let name = ( stringify!( $key_name) ) . replace( "_" , "-" ) ;
2838
+ if let Some ( o) = obj. remove( & name) {
2839
+ if let Some ( o) = o. as_object( ) {
2840
+ let component_array = o. get( "components" )
2841
+ . ok_or_else( || format!( "{name}: expected a \
2842
+ JSON object with a `components` field.") ) ?;
2843
+ let component_array = component_array. as_array( )
2844
+ . ok_or_else( || format!( "{name}.components: expected a JSON array" ) ) ?;
2845
+ let mut components = LinkSelfContainedComponents :: empty( ) ;
2846
+ for s in component_array {
2847
+ components |= match s. as_str( ) {
2848
+ Some ( s) => {
2849
+ LinkSelfContainedComponents :: from_str( s)
2850
+ . ok_or_else( || format!( "unknown \
2851
+ `-Clink-self-contained` component: {s}") ) ?
2852
+ } ,
2853
+ _ => return Err ( format!( "not a string: {:?}" , s) ) ,
2854
+ } ;
2855
+ }
2856
+ base. $key_name = LinkSelfContained :: WithComponents ( components) ;
2857
+ } else {
2858
+ incorrect_type. push( name)
2859
+ }
2860
+ }
2861
+ Ok :: <( ) , String >( ( ) )
2862
+ } ) ;
2863
+ ( $key_name: ident = $json_name: expr, LinkSelfContainedDefault ) => ( {
2698
2864
let name = $json_name;
2699
2865
obj. remove( name) . and_then( |o| o. as_str( ) . and_then( |s| {
2700
2866
match s. parse:: <LinkSelfContainedDefault >( ) {
2701
- Ok ( lsc_default) => base. $key_name = lsc_default,
2867
+ Ok ( lsc_default) => base. $key_name = lsc_default. into ( ) ,
2702
2868
_ => return Some ( Err ( format!( "'{}' is not a valid `-Clink-self-contained` default. \
2703
2869
Use 'false', 'true', 'musl' or 'mingw'", s) ) ) ,
2704
2870
}
@@ -2847,7 +3013,10 @@ impl Target {
2847
3013
key ! ( post_link_objects = "post-link-objects" , link_objects) ;
2848
3014
key ! ( pre_link_objects_self_contained = "pre-link-objects-fallback" , link_objects) ;
2849
3015
key ! ( post_link_objects_self_contained = "post-link-objects-fallback" , link_objects) ;
2850
- key ! ( link_self_contained = "crt-objects-fallback" , link_self_contained) ?;
3016
+ // Deserializes the backwards-compatible variants of `-Clink-self-contained`
3017
+ key ! ( link_self_contained = "crt-objects-fallback" , LinkSelfContainedDefault ) ?;
3018
+ // Deserializes the components variant of `-Clink-self-contained`
3019
+ key ! ( link_self_contained, LinkSelfContained ) ?;
2851
3020
key ! ( pre_link_args_json = "pre-link-args" , link_args) ;
2852
3021
key ! ( late_link_args_json = "late-link-args" , link_args) ;
2853
3022
key ! ( late_link_args_dynamic_json = "late-link-args-dynamic" , link_args) ;
@@ -3103,7 +3272,6 @@ impl ToJson for Target {
3103
3272
target_option_val ! ( post_link_objects) ;
3104
3273
target_option_val ! ( pre_link_objects_self_contained, "pre-link-objects-fallback" ) ;
3105
3274
target_option_val ! ( post_link_objects_self_contained, "post-link-objects-fallback" ) ;
3106
- target_option_val ! ( link_self_contained, "crt-objects-fallback" ) ;
3107
3275
target_option_val ! ( link_args - pre_link_args_json, "pre-link-args" ) ;
3108
3276
target_option_val ! ( link_args - late_link_args_json, "late-link-args" ) ;
3109
3277
target_option_val ! ( link_args - late_link_args_dynamic_json, "late-link-args-dynamic" ) ;
@@ -3200,6 +3368,10 @@ impl ToJson for Target {
3200
3368
d. insert ( "default-adjusted-cabi" . into ( ) , Abi :: name ( abi) . to_json ( ) ) ;
3201
3369
}
3202
3370
3371
+ // Serializing `-Clink-self-contained` needs a dynamic key to support the
3372
+ // backwards-compatible variants.
3373
+ d. insert ( self . link_self_contained . json_key ( ) . into ( ) , self . link_self_contained . to_json ( ) ) ;
3374
+
3203
3375
Json :: Object ( d)
3204
3376
}
3205
3377
}
0 commit comments