@@ -12,6 +12,7 @@ use crate::{EarlyErrorHandler, Session};
1212use rustc_data_structures:: fx:: { FxHashMap , FxHashSet } ;
1313use rustc_data_structures:: stable_hasher:: { StableOrd , ToStableHashKey } ;
1414use rustc_target:: abi:: Align ;
15+ use rustc_target:: spec:: LinkSelfContainedComponents ;
1516use rustc_target:: spec:: { PanicStrategy , RelocModel , SanitizerSet , SplitDebuginfo } ;
1617use rustc_target:: spec:: { Target , TargetTriple , TargetWarnings , TARGETS } ;
1718
@@ -232,75 +233,50 @@ pub struct LinkSelfContained {
232233 /// Used for compatibility with the existing opt-in and target inference.
233234 pub explicitly_set : Option < bool > ,
234235
235- /// The components that are enabled.
236- components : LinkSelfContainedComponents ,
237- }
238-
239- bitflags:: bitflags! {
240- #[ derive( Default ) ]
241- /// The `-C link-self-contained` components that can individually be enabled or disabled.
242- pub struct LinkSelfContainedComponents : u8 {
243- /// CRT objects (e.g. on `windows-gnu`, `musl`, `wasi` targets)
244- const CRT_OBJECTS = 1 << 0 ;
245- /// libc static library (e.g. on `musl`, `wasi` targets)
246- const LIBC = 1 << 1 ;
247- /// libgcc/libunwind (e.g. on `windows-gnu`, `fuchsia`, `fortanix`, `gnullvm` targets)
248- const UNWIND = 1 << 2 ;
249- /// Linker, dlltool, and their necessary libraries (e.g. on `windows-gnu` and for `rust-lld`)
250- const LINKER = 1 << 3 ;
251- /// Sanitizer runtime libraries
252- const SANITIZERS = 1 << 4 ;
253- /// Other MinGW libs and Windows import libs
254- const MINGW = 1 << 5 ;
255- }
256- }
257-
258- impl FromStr for LinkSelfContainedComponents {
259- type Err = ( ) ;
236+ /// The components that are enabled on the CLI, using the `+component` syntax or one of the
237+ /// `true` shorcuts.
238+ enabled_components : LinkSelfContainedComponents ,
260239
261- fn from_str ( s : & str ) -> Result < Self , Self :: Err > {
262- Ok ( match s {
263- "crto" => LinkSelfContainedComponents :: CRT_OBJECTS ,
264- "libc" => LinkSelfContainedComponents :: LIBC ,
265- "unwind" => LinkSelfContainedComponents :: UNWIND ,
266- "linker" => LinkSelfContainedComponents :: LINKER ,
267- "sanitizers" => LinkSelfContainedComponents :: SANITIZERS ,
268- "mingw" => LinkSelfContainedComponents :: MINGW ,
269- _ => return Err ( ( ) ) ,
270- } )
271- }
240+ /// The components that are disabled on the CLI, using the `-component` syntax or one of the
241+ /// `false` shortcuts.
242+ disabled_components : LinkSelfContainedComponents ,
272243}
273244
274245impl LinkSelfContained {
275246 /// Incorporates an enabled or disabled component as specified on the CLI, if possible.
276247 /// For example: `+linker`, and `-crto`.
277- pub ( crate ) fn handle_cli_component ( & mut self , component : & str ) -> Result < ( ) , ( ) > {
248+ pub ( crate ) fn handle_cli_component ( & mut self , component : & str ) -> Option < ( ) > {
278249 // Note that for example `-Cself-contained=y -Cself-contained=-linker` is not an explicit
279250 // set of all values like `y` or `n` used to be. Therefore, if this flag had previously been
280251 // set in bulk with its historical values, then manually setting a component clears that
281252 // `explicitly_set` state.
282253 if let Some ( component_to_enable) = component. strip_prefix ( '+' ) {
283254 self . explicitly_set = None ;
284- self . components . insert ( component_to_enable. parse ( ) ?) ;
285- Ok ( ( ) )
255+ self . enabled_components
256+ . insert ( LinkSelfContainedComponents :: from_str ( component_to_enable) ?) ;
257+ Some ( ( ) )
286258 } else if let Some ( component_to_disable) = component. strip_prefix ( '-' ) {
287259 self . explicitly_set = None ;
288- self . components . remove ( component_to_disable. parse ( ) ?) ;
289- Ok ( ( ) )
260+ self . disabled_components
261+ . insert ( LinkSelfContainedComponents :: from_str ( component_to_disable) ?) ;
262+ Some ( ( ) )
290263 } else {
291- Err ( ( ) )
264+ None
292265 }
293266 }
294267
295268 /// Turns all components on or off and records that this was done explicitly for compatibility
296269 /// purposes.
297270 pub ( crate ) fn set_all_explicitly ( & mut self , enabled : bool ) {
298271 self . explicitly_set = Some ( enabled) ;
299- self . components = if enabled {
300- LinkSelfContainedComponents :: all ( )
272+
273+ if enabled {
274+ self . enabled_components = LinkSelfContainedComponents :: all ( ) ;
275+ self . disabled_components = LinkSelfContainedComponents :: empty ( ) ;
301276 } else {
302- LinkSelfContainedComponents :: empty ( )
303- } ;
277+ self . enabled_components = LinkSelfContainedComponents :: empty ( ) ;
278+ self . disabled_components = LinkSelfContainedComponents :: all ( ) ;
279+ }
304280 }
305281
306282 /// Helper creating a fully enabled `LinkSelfContained` instance. Used in tests.
@@ -314,13 +290,32 @@ impl LinkSelfContained {
314290 /// components was set individually. This would also require the `-Zunstable-options` flag, to
315291 /// be allowed.
316292 fn are_unstable_variants_set ( & self ) -> bool {
317- let any_component_set = !self . components . is_empty ( ) ;
293+ let any_component_set =
294+ !self . enabled_components . is_empty ( ) || !self . disabled_components . is_empty ( ) ;
318295 self . explicitly_set . is_none ( ) && any_component_set
319296 }
320297
321- /// Returns whether the self-contained linker component is enabled.
322- pub fn linker ( & self ) -> bool {
323- self . components . contains ( LinkSelfContainedComponents :: LINKER )
298+ /// Returns whether the self-contained linker component was enabled on the CLI, using the
299+ /// `-C link-self-contained=+linker` syntax, or one of the `true` shorcuts.
300+ pub fn is_linker_enabled ( & self ) -> bool {
301+ self . enabled_components . contains ( LinkSelfContainedComponents :: LINKER )
302+ }
303+
304+ /// Returns whether the self-contained linker component was disabled on the CLI, using the
305+ /// `-C link-self-contained=-linker` syntax, or one of the `false` shorcuts.
306+ pub fn is_linker_disabled ( & self ) -> bool {
307+ self . disabled_components . contains ( LinkSelfContainedComponents :: LINKER )
308+ }
309+
310+ /// Returns CLI inconsistencies to emit errors: individual components were both enabled and
311+ /// disabled.
312+ fn check_consistency ( & self ) -> Option < LinkSelfContainedComponents > {
313+ if self . explicitly_set . is_some ( ) {
314+ None
315+ } else {
316+ let common = self . enabled_components . intersection ( self . disabled_components ) ;
317+ if common. is_empty ( ) { None } else { Some ( common) }
318+ }
324319 }
325320}
326321
@@ -2758,9 +2753,8 @@ pub fn build_session_options(
27582753 }
27592754
27602755 // For testing purposes, until we have more feedback about these options: ensure `-Z
2761- // unstable-options` is required when using the unstable `-C link-self-contained` options, like
2762- // `-C link-self-contained=+linker`, and when using the unstable `-C linker-flavor` options, like
2763- // `-C linker-flavor=gnu-lld-cc`.
2756+ // unstable-options` is required when using the unstable `-C link-self-contained` and `-C
2757+ // linker-flavor` options.
27642758 if !nightly_options:: is_unstable_enabled ( matches) {
27652759 let uses_unstable_self_contained_option =
27662760 cg. link_self_contained . are_unstable_variants_set ( ) ;
@@ -2782,6 +2776,19 @@ pub fn build_session_options(
27822776 }
27832777 }
27842778
2779+ // Check `-C link-self-contained` for consistency: individual components cannot be both enabled
2780+ // and disabled at the same time.
2781+ if let Some ( erroneous_components) = cg. link_self_contained . check_consistency ( ) {
2782+ let names: String = erroneous_components
2783+ . into_iter ( )
2784+ . map ( |c| c. as_str ( ) . unwrap ( ) )
2785+ . intersperse ( ", " )
2786+ . collect ( ) ;
2787+ handler. early_error ( format ! (
2788+ "some `-C link-self-contained` components were both enabled and disabled: {names}"
2789+ ) ) ;
2790+ }
2791+
27852792 let prints = collect_print_requests ( handler, & mut cg, & mut unstable_opts, matches) ;
27862793
27872794 let cg = cg;
0 commit comments