@@ -520,6 +520,92 @@ impl ToJson for LinkerFlavorCli {
520
520
}
521
521
}
522
522
523
+ /// The different `-Clink-self-contained` options that can be specified in a target spec:
524
+ /// - enabling or disabling in bulk
525
+ /// - some target-specific pieces of inference to determine whether to use self-contained linking
526
+ /// if `-Clink-self-contained` is not specified explicitly (e.g. on musl/mingw)
527
+ /// - explicitly enabling some of the self-contained linking components, e.g. the linker component
528
+ /// to use `rust-lld`
529
+ #[ derive( Clone , Copy , PartialEq , Debug ) ]
530
+ pub enum LinkSelfContained {
531
+ /// The target spec explicitly enables self-contained linking.
532
+ True ,
533
+
534
+ /// The target spec explicitly disables self-contained linking.
535
+ False ,
536
+
537
+ /// The target spec requests that the self-contained mode is inferred, in the context of musl.
538
+ InferredForMusl ,
539
+
540
+ /// The target spec requests that the self-contained mode is inferred, in the context of mingw.
541
+ InferredForMingw ,
542
+
543
+ /// The target spec explicitly enables a list of self-contained linking components: e.g. for
544
+ /// targets opting into a subset of components like the CLI's `-C link-self-contained=+linker`.
545
+ WithComponents ( LinkSelfContainedComponents ) ,
546
+ }
547
+
548
+ impl ToJson for LinkSelfContained {
549
+ fn to_json ( & self ) -> Json {
550
+ match * self {
551
+ LinkSelfContained :: WithComponents ( components) => {
552
+ // Serialize the components in a json object's `components` field, to prepare for a
553
+ // future where `crt-objects-fallback` is removed from the json specs and
554
+ // incorporated as a field here.
555
+ let mut map = BTreeMap :: new ( ) ;
556
+ map. insert ( "components" , components) ;
557
+ map. to_json ( )
558
+ }
559
+
560
+ // Stable values backwards-compatible with `LinkSelfContainedDefault`
561
+ LinkSelfContained :: True => "true" . to_json ( ) ,
562
+ LinkSelfContained :: False => "false" . to_json ( ) ,
563
+ LinkSelfContained :: InferredForMusl => "musl" . to_json ( ) ,
564
+ LinkSelfContained :: InferredForMingw => "mingw" . to_json ( ) ,
565
+ }
566
+ }
567
+ }
568
+
569
+ impl LinkSelfContained {
570
+ /// Returns whether the target spec has self-contained linking explicitly disabled. Used to emit
571
+ /// errors if the user then enables it on the CLI.
572
+ pub fn is_disabled ( self ) -> bool {
573
+ self == Self :: False
574
+ }
575
+
576
+ /// Returns whether the target spec explictly requests self-contained linking, i.e. not via
577
+ /// inference.
578
+ pub fn is_linker_enabled ( self ) -> bool {
579
+ match self {
580
+ LinkSelfContained :: True => true ,
581
+ LinkSelfContained :: False => false ,
582
+ LinkSelfContained :: WithComponents ( c) => c. contains ( LinkSelfContainedComponents :: LINKER ) ,
583
+ _ => false ,
584
+ }
585
+ }
586
+
587
+ /// Returns the key to use when serializing the setting to json:
588
+ /// - individual components in a `link-self-contained` object value
589
+ /// - the other variants as a backwards-compatible `crt-objects-fallback` string
590
+ fn json_key ( self ) -> & ' static str {
591
+ match self {
592
+ LinkSelfContained :: WithComponents ( _) => "link-self-contained" ,
593
+ _ => "crt-objects-fallback" ,
594
+ }
595
+ }
596
+ }
597
+
598
+ impl From < LinkSelfContainedDefault > for LinkSelfContained {
599
+ fn from ( value : LinkSelfContainedDefault ) -> Self {
600
+ match value {
601
+ LinkSelfContainedDefault :: True => LinkSelfContained :: True ,
602
+ LinkSelfContainedDefault :: False => LinkSelfContained :: False ,
603
+ LinkSelfContainedDefault :: Musl => LinkSelfContained :: InferredForMusl ,
604
+ LinkSelfContainedDefault :: Mingw => LinkSelfContained :: InferredForMingw ,
605
+ }
606
+ }
607
+ }
608
+
523
609
bitflags:: bitflags! {
524
610
#[ derive( Default ) ]
525
611
/// The `-C link-self-contained` components that can individually be enabled or disabled.
@@ -594,6 +680,22 @@ impl IntoIterator for LinkSelfContainedComponents {
594
680
}
595
681
}
596
682
683
+ impl ToJson for LinkSelfContainedComponents {
684
+ fn to_json ( & self ) -> Json {
685
+ let components: Vec < _ > = Self :: all_components ( )
686
+ . into_iter ( )
687
+ . filter ( |c| self . contains ( * c) )
688
+ . map ( |c| {
689
+ // We can unwrap because we're iterating over all the known singular components,
690
+ // not an actual set of flags where `as_str` can fail.
691
+ c. as_str ( ) . unwrap ( ) . to_owned ( )
692
+ } )
693
+ . collect ( ) ;
694
+
695
+ components. to_json ( )
696
+ }
697
+ }
698
+
597
699
#[ derive( Clone , Copy , Debug , PartialEq , Hash , Encodable , Decodable , HashStable_Generic ) ]
598
700
pub enum PanicStrategy {
599
701
Unwind ,
@@ -1769,7 +1871,9 @@ pub struct TargetOptions {
1769
1871
/// Same as `(pre|post)_link_objects`, but when self-contained linking mode is enabled.
1770
1872
pub pre_link_objects_self_contained : CrtObjects ,
1771
1873
pub post_link_objects_self_contained : CrtObjects ,
1772
- pub link_self_contained : LinkSelfContainedDefault ,
1874
+ /// Behavior for the self-contained linking mode: inferred for some targets, or explicitly
1875
+ /// enabled (in bulk, or with individual components).
1876
+ pub link_self_contained : LinkSelfContained ,
1773
1877
1774
1878
/// Linker arguments that are passed *before* any user-defined libraries.
1775
1879
pub pre_link_args : LinkArgs ,
@@ -2242,7 +2346,7 @@ impl Default for TargetOptions {
2242
2346
post_link_objects : Default :: default ( ) ,
2243
2347
pre_link_objects_self_contained : Default :: default ( ) ,
2244
2348
post_link_objects_self_contained : Default :: default ( ) ,
2245
- link_self_contained : LinkSelfContainedDefault :: False ,
2349
+ link_self_contained : LinkSelfContained :: False ,
2246
2350
pre_link_args : LinkArgs :: new ( ) ,
2247
2351
pre_link_args_json : LinkArgsCli :: new ( ) ,
2248
2352
late_link_args : LinkArgs :: new ( ) ,
@@ -2723,12 +2827,47 @@ impl Target {
2723
2827
}
2724
2828
Ok :: <( ) , String >( ( ) )
2725
2829
} ) ;
2726
-
2727
- ( $key_name: ident = $json_name: expr, link_self_contained) => ( {
2830
+ ( $key_name: ident, LinkSelfContained ) => ( {
2831
+ // Skeleton of what needs to be parsed:
2832
+ //
2833
+ // ```
2834
+ // $name: {
2835
+ // "components": [
2836
+ // <array of strings>
2837
+ // ]
2838
+ // }
2839
+ // ```
2840
+ let name = ( stringify!( $key_name) ) . replace( "_" , "-" ) ;
2841
+ if let Some ( o) = obj. remove( & name) {
2842
+ if let Some ( o) = o. as_object( ) {
2843
+ let component_array = o. get( "components" )
2844
+ . ok_or_else( || format!( "{name}: expected a \
2845
+ JSON object with a `components` field.") ) ?;
2846
+ let component_array = component_array. as_array( )
2847
+ . ok_or_else( || format!( "{name}.components: expected a JSON array" ) ) ?;
2848
+ let mut components = LinkSelfContainedComponents :: empty( ) ;
2849
+ for s in component_array {
2850
+ components |= match s. as_str( ) {
2851
+ Some ( s) => {
2852
+ LinkSelfContainedComponents :: from_str( s)
2853
+ . ok_or_else( || format!( "unknown \
2854
+ `-Clink-self-contained` component: {s}") ) ?
2855
+ } ,
2856
+ _ => return Err ( format!( "not a string: {:?}" , s) ) ,
2857
+ } ;
2858
+ }
2859
+ base. $key_name = LinkSelfContained :: WithComponents ( components) ;
2860
+ } else {
2861
+ incorrect_type. push( name)
2862
+ }
2863
+ }
2864
+ Ok :: <( ) , String >( ( ) )
2865
+ } ) ;
2866
+ ( $key_name: ident = $json_name: expr, LinkSelfContainedDefault ) => ( {
2728
2867
let name = $json_name;
2729
2868
obj. remove( name) . and_then( |o| o. as_str( ) . and_then( |s| {
2730
2869
match s. parse:: <LinkSelfContainedDefault >( ) {
2731
- Ok ( lsc_default) => base. $key_name = lsc_default,
2870
+ Ok ( lsc_default) => base. $key_name = lsc_default. into ( ) ,
2732
2871
_ => return Some ( Err ( format!( "'{}' is not a valid `-Clink-self-contained` default. \
2733
2872
Use 'false', 'true', 'musl' or 'mingw'", s) ) ) ,
2734
2873
}
@@ -2877,7 +3016,10 @@ impl Target {
2877
3016
key ! ( post_link_objects = "post-link-objects" , link_objects) ;
2878
3017
key ! ( pre_link_objects_self_contained = "pre-link-objects-fallback" , link_objects) ;
2879
3018
key ! ( post_link_objects_self_contained = "post-link-objects-fallback" , link_objects) ;
2880
- key ! ( link_self_contained = "crt-objects-fallback" , link_self_contained) ?;
3019
+ // Deserializes the backwards-compatible variants of `-Clink-self-contained`
3020
+ key ! ( link_self_contained = "crt-objects-fallback" , LinkSelfContainedDefault ) ?;
3021
+ // Deserializes the components variant of `-Clink-self-contained`
3022
+ key ! ( link_self_contained, LinkSelfContained ) ?;
2881
3023
key ! ( pre_link_args_json = "pre-link-args" , link_args) ;
2882
3024
key ! ( late_link_args_json = "late-link-args" , link_args) ;
2883
3025
key ! ( late_link_args_dynamic_json = "late-link-args-dynamic" , link_args) ;
@@ -3133,7 +3275,6 @@ impl ToJson for Target {
3133
3275
target_option_val ! ( post_link_objects) ;
3134
3276
target_option_val ! ( pre_link_objects_self_contained, "pre-link-objects-fallback" ) ;
3135
3277
target_option_val ! ( post_link_objects_self_contained, "post-link-objects-fallback" ) ;
3136
- target_option_val ! ( link_self_contained, "crt-objects-fallback" ) ;
3137
3278
target_option_val ! ( link_args - pre_link_args_json, "pre-link-args" ) ;
3138
3279
target_option_val ! ( link_args - late_link_args_json, "late-link-args" ) ;
3139
3280
target_option_val ! ( link_args - late_link_args_dynamic_json, "late-link-args-dynamic" ) ;
@@ -3230,6 +3371,10 @@ impl ToJson for Target {
3230
3371
d. insert ( "default-adjusted-cabi" . into ( ) , Abi :: name ( abi) . to_json ( ) ) ;
3231
3372
}
3232
3373
3374
+ // Serializing `-Clink-self-contained` needs a dynamic key to support the
3375
+ // backwards-compatible variants.
3376
+ d. insert ( self . link_self_contained . json_key ( ) . into ( ) , self . link_self_contained . to_json ( ) ) ;
3377
+
3233
3378
Json :: Object ( d)
3234
3379
}
3235
3380
}
0 commit comments