From 3adfc229951f6510a3dfa94979d6be5c7dbc7690 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Rakic?= Date: Wed, 20 Sep 2023 17:38:22 +0000 Subject: [PATCH] wip --- Cargo.lock | 1 - compiler/rustc_codegen_ssa/src/back/link.rs | 43 +++- compiler/rustc_session/Cargo.toml | 1 - compiler/rustc_session/src/config.rs | 84 +++---- compiler/rustc_session/src/options.rs | 2 +- compiler/rustc_target/src/spec/crt_objects.rs | 13 - .../rustc_target/src/spec/linux_musl_base.rs | 5 +- compiler/rustc_target/src/spec/mod.rs | 232 +++++++++++++++++- .../rustc_target/src/spec/tests/tests_impl.rs | 2 +- compiler/rustc_target/src/spec/wasm32_wasi.rs | 5 +- .../src/spec/wasm32_wasi_preview1_threads.rs | 5 +- compiler/rustc_target/src/spec/wasm_base.rs | 4 +- .../rustc_target/src/spec/windows_gnu_base.rs | 5 +- .../src/spec/x86_64_unknown_linux_gnu.rs | 7 + 14 files changed, 314 insertions(+), 95 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d9aaedb85443f..dbc8deef4d91c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4391,7 +4391,6 @@ dependencies = [ name = "rustc_session" version = "0.0.0" dependencies = [ - "bitflags 1.3.2", "getopts", "libc", "rustc_ast", diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index a7ac728c59b02..12f742aa3d608 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -22,7 +22,8 @@ use rustc_session::utils::NativeLibKind; /// need out of the shared crate context before we get rid of it. use rustc_session::{filesearch, Session}; use rustc_span::symbol::Symbol; -use rustc_target::spec::crt_objects::{CrtObjects, LinkSelfContainedDefault}; +use rustc_target::spec::crt_objects::CrtObjects; +use rustc_target::spec::LinkSelfContained; use rustc_target::spec::{Cc, LinkOutputKind, LinkerFlavor, Lld, PanicStrategy}; use rustc_target::spec::{RelocModel, RelroLevel, SanitizerSet, SplitDebuginfo}; @@ -1709,21 +1710,37 @@ fn detect_self_contained_mingw(sess: &Session) -> bool { /// instead of being found somewhere on the host system. /// We only provide such support for a very limited number of targets. fn self_contained(sess: &Session, crate_type: CrateType) -> bool { + // Emit an error if the user requested self-contained mode on the CLI but the target explicitly + // refuses it. if let Some(self_contained) = sess.opts.cg.link_self_contained.explicitly_set { - if sess.target.link_self_contained == LinkSelfContainedDefault::False { + if sess.target.link_self_contained.is_disabled() { sess.emit_err(errors::UnsupportedLinkSelfContained); } return self_contained; } match sess.target.link_self_contained { - LinkSelfContainedDefault::False => false, - LinkSelfContainedDefault::True => true, + LinkSelfContained::True => true, + LinkSelfContained::False => false, + LinkSelfContained::WithComponents(components) => { + if components.is_all() { + true + } else if components.is_empty() { + false + } else { + // FIXME: Currently no target makes use of individual components to mean + // self-contained linking is fully enabled, in the sense of what the code downstream + // from here expects. Until components are handled a bit more deeply, we can + // consider that it's disabled and remain backwards compatible. + false + } + } + // FIXME: Find a better heuristic for "native musl toolchain is available", // based on host and linker path, for example. // (https://github.com/rust-lang/rust/pull/71769#issuecomment-626330237). - LinkSelfContainedDefault::Musl => sess.crt_static(Some(crate_type)), - LinkSelfContainedDefault::Mingw => { + LinkSelfContained::InferredForMusl => sess.crt_static(Some(crate_type)), + LinkSelfContained::InferredForMingw => { sess.host == sess.target && sess.target.vendor != "uwp" && detect_self_contained_mingw(&sess) @@ -2992,9 +3009,15 @@ fn add_lld_args(cmd: &mut dyn Linker, sess: &Session, flavor: LinkerFlavor) { } // 1. Implement the "self-contained" part of this feature by adding rustc distribution - // directories to the tool's search path. - let self_contained_linker = sess.opts.cg.link_self_contained.linker() || unstable_use_lld; - if self_contained_linker { + // directories to the tool's search path, depending on a mix between what users can specify on + // the CLI, and what the target spec enables (as it can't disable components): + // - if the self-contained linker is enabled on the CLI or by the target spec (or by the + // unstable CLI flag that will be removed eventually), + // - and if the self-contained linker is not disabled on the CLI. + let self_contained_linker = sess.target.options.link_self_contained.is_linker_enabled() + || sess.opts.cg.link_self_contained.is_linker_enabled() + || unstable_use_lld; + if self_contained_linker && !sess.opts.cg.link_self_contained.is_linker_disabled() { for path in sess.get_tools_search_paths(false) { cmd.arg({ let mut arg = OsString::from("-B"); @@ -3005,7 +3028,7 @@ fn add_lld_args(cmd: &mut dyn Linker, sess: &Session, flavor: LinkerFlavor) { } // 2. Implement the "linker flavor" part of this feature by asking `cc` to use some kind of - // `lld` as the linker. + // `lld` as the linker. cmd.arg("-fuse-ld=lld"); if !flavor.is_gnu() { diff --git a/compiler/rustc_session/Cargo.toml b/compiler/rustc_session/Cargo.toml index e26d25d9a4123..3af83aaaaa8a2 100644 --- a/compiler/rustc_session/Cargo.toml +++ b/compiler/rustc_session/Cargo.toml @@ -4,7 +4,6 @@ version = "0.0.0" edition = "2021" [dependencies] -bitflags = "1.2.1" getopts = "0.2" rustc_macros = { path = "../rustc_macros" } tracing = "0.1" diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index e8f3fe6a9f270..21274df592274 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -12,6 +12,7 @@ use crate::{EarlyErrorHandler, Session}; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::stable_hasher::{StableOrd, ToStableHashKey}; use rustc_target::abi::Align; +use rustc_target::spec::LinkSelfContainedComponents; use rustc_target::spec::{PanicStrategy, RelocModel, SanitizerSet, SplitDebuginfo}; use rustc_target::spec::{Target, TargetTriple, TargetWarnings, TARGETS}; @@ -232,63 +233,35 @@ pub struct LinkSelfContained { /// Used for compatibility with the existing opt-in and target inference. pub explicitly_set: Option, - /// The components that are enabled. - components: LinkSelfContainedComponents, -} + /// The components that are enabled on the CLI, using the `+component` syntax or one of the + /// `true` shorcuts. + enabled_components: LinkSelfContainedComponents, -bitflags::bitflags! { - #[derive(Default)] - /// The `-C link-self-contained` components that can individually be enabled or disabled. - pub struct LinkSelfContainedComponents: u8 { - /// CRT objects (e.g. on `windows-gnu`, `musl`, `wasi` targets) - const CRT_OBJECTS = 1 << 0; - /// libc static library (e.g. on `musl`, `wasi` targets) - const LIBC = 1 << 1; - /// libgcc/libunwind (e.g. on `windows-gnu`, `fuchsia`, `fortanix`, `gnullvm` targets) - const UNWIND = 1 << 2; - /// Linker, dlltool, and their necessary libraries (e.g. on `windows-gnu` and for `rust-lld`) - const LINKER = 1 << 3; - /// Sanitizer runtime libraries - const SANITIZERS = 1 << 4; - /// Other MinGW libs and Windows import libs - const MINGW = 1 << 5; - } -} - -impl FromStr for LinkSelfContainedComponents { - type Err = (); - - fn from_str(s: &str) -> Result { - Ok(match s { - "crto" => LinkSelfContainedComponents::CRT_OBJECTS, - "libc" => LinkSelfContainedComponents::LIBC, - "unwind" => LinkSelfContainedComponents::UNWIND, - "linker" => LinkSelfContainedComponents::LINKER, - "sanitizers" => LinkSelfContainedComponents::SANITIZERS, - "mingw" => LinkSelfContainedComponents::MINGW, - _ => return Err(()), - }) - } + /// The components that are disabled on the CLI, using the `-component` syntax or one of the + /// `false` shortcuts. + disabled_components: LinkSelfContainedComponents, } impl LinkSelfContained { /// Incorporates an enabled or disabled component as specified on the CLI, if possible. /// For example: `+linker`, and `-crto`. - pub(crate) fn handle_cli_component(&mut self, component: &str) -> Result<(), ()> { + pub(crate) fn handle_cli_component(&mut self, component: &str) -> Option<()> { // Note that for example `-Cself-contained=y -Cself-contained=-linker` is not an explicit // set of all values like `y` or `n` used to be. Therefore, if this flag had previously been // set in bulk with its historical values, then manually setting a component clears that // `explicitly_set` state. if let Some(component_to_enable) = component.strip_prefix('+') { self.explicitly_set = None; - self.components.insert(component_to_enable.parse()?); - Ok(()) + self.enabled_components + .insert(LinkSelfContainedComponents::from_str(component_to_enable)?); + Some(()) } else if let Some(component_to_disable) = component.strip_prefix('-') { self.explicitly_set = None; - self.components.remove(component_to_disable.parse()?); - Ok(()) + self.disabled_components + .insert(LinkSelfContainedComponents::from_str(component_to_disable)?); + Some(()) } else { - Err(()) + None } } @@ -296,11 +269,14 @@ impl LinkSelfContained { /// purposes. pub(crate) fn set_all_explicitly(&mut self, enabled: bool) { self.explicitly_set = Some(enabled); - self.components = if enabled { - LinkSelfContainedComponents::all() + + if enabled { + self.enabled_components = LinkSelfContainedComponents::all(); + self.disabled_components = LinkSelfContainedComponents::empty(); } else { - LinkSelfContainedComponents::empty() - }; + self.enabled_components = LinkSelfContainedComponents::empty(); + self.disabled_components = LinkSelfContainedComponents::all(); + } } /// Helper creating a fully enabled `LinkSelfContained` instance. Used in tests. @@ -314,13 +290,21 @@ impl LinkSelfContained { /// components was set individually. This would also require the `-Zunstable-options` flag, to /// be allowed. fn are_unstable_variants_set(&self) -> bool { - let any_component_set = !self.components.is_empty(); + let any_component_set = + !self.enabled_components.is_empty() || !self.disabled_components.is_empty(); self.explicitly_set.is_none() && any_component_set } - /// Returns whether the self-contained linker component is enabled. - pub fn linker(&self) -> bool { - self.components.contains(LinkSelfContainedComponents::LINKER) + /// Returns whether the self-contained linker component was enabled on the CLI, using the + /// `-C link-self-contained=+linker` syntax, or one of the `true` shorcuts. + pub fn is_linker_enabled(&self) -> bool { + self.enabled_components.contains(LinkSelfContainedComponents::LINKER) + } + + /// Returns whether the self-contained linker component was disabled on the CLI, using the + /// `-C link-self-contained=-linker` syntax, or one of the `false` shorcuts. + pub fn is_linker_disabled(&self) -> bool { + self.disabled_components.contains(LinkSelfContainedComponents::LINKER) } } diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index f2c8f0bc19894..8936fd5e39c1e 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -1160,7 +1160,7 @@ mod parse { // 2. Parse a list of enabled and disabled components. for comp in s.split(',') { - if slot.handle_cli_component(comp).is_err() { + if slot.handle_cli_component(comp).is_none() { return false; } } diff --git a/compiler/rustc_target/src/spec/crt_objects.rs b/compiler/rustc_target/src/spec/crt_objects.rs index c126390f5a908..a31727f5f9b4b 100644 --- a/compiler/rustc_target/src/spec/crt_objects.rs +++ b/compiler/rustc_target/src/spec/crt_objects.rs @@ -40,7 +40,6 @@ //! but not gcc's. As a result rustc cannot link with C++ static libraries (#36710) //! when linking in self-contained mode. -use crate::json::{Json, ToJson}; use crate::spec::LinkOutputKind; use std::borrow::Cow; use std::collections::BTreeMap; @@ -147,15 +146,3 @@ impl FromStr for LinkSelfContainedDefault { }) } } - -impl ToJson for LinkSelfContainedDefault { - fn to_json(&self) -> Json { - match *self { - LinkSelfContainedDefault::False => "false", - LinkSelfContainedDefault::True => "true", - LinkSelfContainedDefault::Musl => "musl", - LinkSelfContainedDefault::Mingw => "mingw", - } - .to_json() - } -} diff --git a/compiler/rustc_target/src/spec/linux_musl_base.rs b/compiler/rustc_target/src/spec/linux_musl_base.rs index 61553e71b4500..318d06e9889dd 100644 --- a/compiler/rustc_target/src/spec/linux_musl_base.rs +++ b/compiler/rustc_target/src/spec/linux_musl_base.rs @@ -1,4 +1,5 @@ -use crate::spec::crt_objects::{self, LinkSelfContainedDefault}; +use crate::spec::crt_objects; +use crate::spec::LinkSelfContained; use crate::spec::TargetOptions; pub fn opts() -> TargetOptions { @@ -7,7 +8,7 @@ pub fn opts() -> TargetOptions { base.env = "musl".into(); base.pre_link_objects_self_contained = crt_objects::pre_musl_self_contained(); base.post_link_objects_self_contained = crt_objects::post_musl_self_contained(); - base.link_self_contained = LinkSelfContainedDefault::Musl; + base.link_self_contained = LinkSelfContained::InferredForMusl; // These targets statically link libc by default base.crt_static_default = true; diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs index 89494e3647f07..859a49b0b2a66 100644 --- a/compiler/rustc_target/src/spec/mod.rs +++ b/compiler/rustc_target/src/spec/mod.rs @@ -532,6 +532,169 @@ impl ToJson for LinkerFlavorCli { } } +/// The different `-Clink-self-contained` options that can be specified in a target spec: +/// - enabling or disabling in bulk +/// - some target-specific pieces of inference to determine whether to use self-contained linking +/// if `-Clink-self-contained` is not specified explicitly (e.g. on musl/mingw) +/// - explicitly enabling some of the self-contained linking components, e.g. the linker component +/// to use `rust-lld` +#[derive(Clone, Copy, PartialEq, Debug)] +pub enum LinkSelfContained { + /// The target spec explicitly enables self-contained linking. + True, + + /// The target spec explicitly disables self-contained linking. + False, + + /// The target spec requests that the self-contained mode is inferred, in the context of musl. + InferredForMusl, + + /// The target spec requests that the self-contained mode is inferred, in the context of mingw. + InferredForMingw, + + /// The target spec explicitly enables a list of self-contained linking components: e.g. for + /// targets opting into a subset of components like the CLI's `-C link-self-contained=+linker`. + WithComponents(LinkSelfContainedComponents), +} + +impl ToJson for LinkSelfContained { + fn to_json(&self) -> Json { + match *self { + LinkSelfContained::WithComponents(components) => { + // Serialize the components in a json object's `components` field, to prepare for a + // future where `crt-objects-fallback` is removed from the json specs and + // incorporated as a field here. + let mut map = BTreeMap::new(); + map.insert("components", components); + map.to_json() + } + + // Stable values backwards-compatible with `LinkSelfContainedDefault` + LinkSelfContained::True => "true".to_json(), + LinkSelfContained::False => "false".to_json(), + LinkSelfContained::InferredForMusl => "musl".to_json(), + LinkSelfContained::InferredForMingw => "mingw".to_json(), + } + } +} + +impl LinkSelfContained { + /// Returns whether the target spec has self-contained linking explicitly disabled. Used to emit + /// errors if the user then enables it on the CLI. + pub fn is_disabled(self) -> bool { + self == Self::False + } + + /// Returns whether the target spec explictly requests self-contained linking, i.e. not via + /// inference. + pub fn is_linker_enabled(self) -> bool { + match self { + LinkSelfContained::True => true, + LinkSelfContained::False => false, + LinkSelfContained::WithComponents(c) => c.contains(LinkSelfContainedComponents::LINKER), + _ => false, + } + } + + /// Returns the key to use when serializing the setting to json: + /// - individual components in a `link-self-contained` object value + /// - the other variants as a backwards-compatible `crt-objects-fallback` string + fn json_key(self) -> &'static str { + match self { + LinkSelfContained::WithComponents(_) => "link-self-contained", + _ => "crt-objects-fallback", + } + } +} + +impl From for LinkSelfContained { + fn from(value: LinkSelfContainedDefault) -> Self { + match value { + LinkSelfContainedDefault::True => LinkSelfContained::True, + LinkSelfContainedDefault::False => LinkSelfContained::False, + LinkSelfContainedDefault::Musl => LinkSelfContained::InferredForMusl, + LinkSelfContainedDefault::Mingw => LinkSelfContained::InferredForMingw, + } + } +} + +bitflags::bitflags! { + #[derive(Default)] + /// The `-C link-self-contained` components that can individually be enabled or disabled. + pub struct LinkSelfContainedComponents: u8 { + /// CRT objects (e.g. on `windows-gnu`, `musl`, `wasi` targets) + const CRT_OBJECTS = 1 << 0; + /// libc static library (e.g. on `musl`, `wasi` targets) + const LIBC = 1 << 1; + /// libgcc/libunwind (e.g. on `windows-gnu`, `fuchsia`, `fortanix`, `gnullvm` targets) + const UNWIND = 1 << 2; + /// Linker, dlltool, and their necessary libraries (e.g. on `windows-gnu` and for `rust-lld`) + const LINKER = 1 << 3; + /// Sanitizer runtime libraries + const SANITIZERS = 1 << 4; + /// Other MinGW libs and Windows import libs + const MINGW = 1 << 5; + } +} + +impl LinkSelfContainedComponents { + /// Parses a single `-Clink-self-contained` well-known component, not a set of flags. + pub fn from_str(s: &str) -> Option { + Some(match s { + "crto" => LinkSelfContainedComponents::CRT_OBJECTS, + "libc" => LinkSelfContainedComponents::LIBC, + "unwind" => LinkSelfContainedComponents::UNWIND, + "linker" => LinkSelfContainedComponents::LINKER, + "sanitizers" => LinkSelfContainedComponents::SANITIZERS, + "mingw" => LinkSelfContainedComponents::MINGW, + _ => return None, + }) + } + + /// Return the component's name. + /// + /// Returns `None` if the bitflags aren't a singular component (but a mix of multiple flags). + fn as_str(self) -> Option<&'static str> { + Some(match self { + LinkSelfContainedComponents::CRT_OBJECTS => "crto", + LinkSelfContainedComponents::LIBC => "libc", + LinkSelfContainedComponents::UNWIND => "unwind", + LinkSelfContainedComponents::LINKER => "linker", + LinkSelfContainedComponents::SANITIZERS => "sanitizers", + LinkSelfContainedComponents::MINGW => "mingw", + _ => return None, + }) + } + + /// Returns an array of all the components. + fn all_components() -> [LinkSelfContainedComponents; 6] { + [ + LinkSelfContainedComponents::CRT_OBJECTS, + LinkSelfContainedComponents::LIBC, + LinkSelfContainedComponents::UNWIND, + LinkSelfContainedComponents::LINKER, + LinkSelfContainedComponents::SANITIZERS, + LinkSelfContainedComponents::MINGW, + ] + } +} + +impl ToJson for LinkSelfContainedComponents { + fn to_json(&self) -> Json { + let components: Vec<_> = Self::all_components() + .into_iter() + .filter(|c| self.contains(*c)) + .map(|c| { + // We can unwrap because we're iterating over all the known singular components, + // not an actual set of flags where `as_str` can fail. + c.as_str().unwrap().to_owned() + }) + .collect(); + + components.to_json() + } +} + #[derive(Clone, Copy, Debug, PartialEq, Hash, Encodable, Decodable, HashStable_Generic)] pub enum PanicStrategy { Unwind, @@ -1706,7 +1869,9 @@ pub struct TargetOptions { /// Same as `(pre|post)_link_objects`, but when self-contained linking mode is enabled. pub pre_link_objects_self_contained: CrtObjects, pub post_link_objects_self_contained: CrtObjects, - pub link_self_contained: LinkSelfContainedDefault, + /// Behavior for the self-contained linking mode: inferred for some targets, or explicitly + /// enabled (in bulk, or with individual components). + pub link_self_contained: LinkSelfContained, /// Linker arguments that are passed *before* any user-defined libraries. pub pre_link_args: LinkArgs, @@ -2106,7 +2271,17 @@ impl TargetOptions { } fn update_to_cli(&mut self) { - self.linker_flavor_json = self.linker_flavor.to_cli(); + // self.linker_flavor_json = self.linker_flavor.to_cli(); + self.linker_flavor_json = match self.linker_flavor { + LinkerFlavor::Gnu(cc, lld) => LinkerFlavorCli::Gnu(cc, lld), + LinkerFlavor::Darwin(cc, lld) => LinkerFlavorCli::Darwin(cc, lld), + LinkerFlavor::WasmLld(cc) => LinkerFlavorCli::WasmLld(cc), + LinkerFlavor::Unix(cc) => LinkerFlavorCli::Unix(cc), + LinkerFlavor::Msvc(lld) => LinkerFlavorCli::Msvc(lld), + LinkerFlavor::EmCc => LinkerFlavorCli::EmCc, + LinkerFlavor::Bpf => LinkerFlavorCli::Bpf, + LinkerFlavor::Ptx => LinkerFlavorCli::Ptx, + }; self.lld_flavor_json = self.linker_flavor.lld_flavor(); self.linker_is_gnu_json = self.linker_flavor.is_gnu(); for (args, args_json) in [ @@ -2179,7 +2354,7 @@ impl Default for TargetOptions { post_link_objects: Default::default(), pre_link_objects_self_contained: Default::default(), post_link_objects_self_contained: Default::default(), - link_self_contained: LinkSelfContainedDefault::False, + link_self_contained: LinkSelfContained::False, pre_link_args: LinkArgs::new(), pre_link_args_json: LinkArgsCli::new(), late_link_args: LinkArgs::new(), @@ -2660,12 +2835,47 @@ impl Target { } Ok::<(), String>(()) } ); - - ($key_name:ident = $json_name:expr, link_self_contained) => ( { + ($key_name:ident, LinkSelfContained) => ( { + // Skeleton of what needs to be parsed: + // + // ``` + // $name: { + // "components": [ + // + // ] + // } + // ``` + let name = (stringify!($key_name)).replace("_", "-"); + if let Some(o) = obj.remove(&name) { + if let Some(o) = o.as_object() { + let component_array = o.get("components") + .ok_or_else(|| format!("{name}: expected a \ + JSON object with a `components` field."))?; + let component_array = component_array.as_array() + .ok_or_else(|| format!("{name}.components: expected a JSON array"))?; + let mut components = LinkSelfContainedComponents::empty(); + for s in component_array { + components |= match s.as_str() { + Some(s) => { + LinkSelfContainedComponents::from_str(s) + .ok_or_else(|| format!("unknown \ + `-Clink-self-contained` component: {s}"))? + }, + _ => return Err(format!("not a string: {:?}", s)), + }; + } + base.$key_name = LinkSelfContained::WithComponents(components); + } else { + incorrect_type.push(name) + } + } + Ok::<(), String>(()) + } ); + ($key_name:ident = $json_name:expr, LinkSelfContainedDefault) => ( { let name = $json_name; obj.remove(name).and_then(|o| o.as_str().and_then(|s| { match s.parse::() { - Ok(lsc_default) => base.$key_name = lsc_default, + Ok(lsc_default) => base.$key_name = lsc_default.into(), _ => return Some(Err(format!("'{}' is not a valid `-Clink-self-contained` default. \ Use 'false', 'true', 'musl' or 'mingw'", s))), } @@ -2814,7 +3024,10 @@ impl Target { key!(post_link_objects = "post-link-objects", link_objects); key!(pre_link_objects_self_contained = "pre-link-objects-fallback", link_objects); key!(post_link_objects_self_contained = "post-link-objects-fallback", link_objects); - key!(link_self_contained = "crt-objects-fallback", link_self_contained)?; + // Deserializes the backwards-compatible variants of `-Clink-self-contained` + key!(link_self_contained = "crt-objects-fallback", LinkSelfContainedDefault)?; + // Deserializes the components variant of `-Clink-self-contained` + key!(link_self_contained, LinkSelfContained)?; key!(pre_link_args_json = "pre-link-args", link_args); key!(late_link_args_json = "late-link-args", link_args); key!(late_link_args_dynamic_json = "late-link-args-dynamic", link_args); @@ -3070,7 +3283,6 @@ impl ToJson for Target { target_option_val!(post_link_objects); target_option_val!(pre_link_objects_self_contained, "pre-link-objects-fallback"); target_option_val!(post_link_objects_self_contained, "post-link-objects-fallback"); - target_option_val!(link_self_contained, "crt-objects-fallback"); target_option_val!(link_args - pre_link_args_json, "pre-link-args"); target_option_val!(link_args - late_link_args_json, "late-link-args"); target_option_val!(link_args - late_link_args_dynamic_json, "late-link-args-dynamic"); @@ -3167,6 +3379,10 @@ impl ToJson for Target { d.insert("default-adjusted-cabi".into(), Abi::name(abi).to_json()); } + // Serializing `-Clink-self-contained` needs a dynamic key to support the + // backwards-compatible variants. + d.insert(self.link_self_contained.json_key().into(), self.link_self_contained.to_json()); + Json::Object(d) } } diff --git a/compiler/rustc_target/src/spec/tests/tests_impl.rs b/compiler/rustc_target/src/spec/tests/tests_impl.rs index e0ecf8037c3e5..257867b1b807b 100644 --- a/compiler/rustc_target/src/spec/tests/tests_impl.rs +++ b/compiler/rustc_target/src/spec/tests/tests_impl.rs @@ -97,7 +97,7 @@ impl Target { ); } - if self.link_self_contained == LinkSelfContainedDefault::False { + if self.link_self_contained.is_disabled() { assert!( self.pre_link_objects_self_contained.is_empty() && self.post_link_objects_self_contained.is_empty() diff --git a/compiler/rustc_target/src/spec/wasm32_wasi.rs b/compiler/rustc_target/src/spec/wasm32_wasi.rs index a0476d542e642..2c00c601b394e 100644 --- a/compiler/rustc_target/src/spec/wasm32_wasi.rs +++ b/compiler/rustc_target/src/spec/wasm32_wasi.rs @@ -72,7 +72,8 @@ //! best we can with this target. Don't start relying on too much here unless //! you know what you're getting in to! -use super::crt_objects::{self, LinkSelfContainedDefault}; +use super::crt_objects; +use super::LinkSelfContained; use super::{wasm_base, Cc, LinkerFlavor, Target}; pub fn target() -> Target { @@ -85,7 +86,7 @@ pub fn target() -> Target { options.post_link_objects_self_contained = crt_objects::post_wasi_self_contained(); // FIXME: Figure out cases in which WASM needs to link with a native toolchain. - options.link_self_contained = LinkSelfContainedDefault::True; + options.link_self_contained = LinkSelfContained::True; // Right now this is a bit of a workaround but we're currently saying that // the target by default has a static crt which we're taking as a signal diff --git a/compiler/rustc_target/src/spec/wasm32_wasi_preview1_threads.rs b/compiler/rustc_target/src/spec/wasm32_wasi_preview1_threads.rs index c567155fee653..93a49acb15180 100644 --- a/compiler/rustc_target/src/spec/wasm32_wasi_preview1_threads.rs +++ b/compiler/rustc_target/src/spec/wasm32_wasi_preview1_threads.rs @@ -72,7 +72,8 @@ //! best we can with this target. Don't start relying on too much here unless //! you know what you're getting in to! -use super::crt_objects::{self, LinkSelfContainedDefault}; +use super::crt_objects; +use super::LinkSelfContained; use super::{wasm_base, Cc, LinkerFlavor, Target}; pub fn target() -> Target { @@ -98,7 +99,7 @@ pub fn target() -> Target { options.post_link_objects_self_contained = crt_objects::post_wasi_self_contained(); // FIXME: Figure out cases in which WASM needs to link with a native toolchain. - options.link_self_contained = LinkSelfContainedDefault::True; + options.link_self_contained = LinkSelfContained::True; // Right now this is a bit of a workaround but we're currently saying that // the target by default has a static crt which we're taking as a signal diff --git a/compiler/rustc_target/src/spec/wasm_base.rs b/compiler/rustc_target/src/spec/wasm_base.rs index 341763aadbaf1..a29bddd849b43 100644 --- a/compiler/rustc_target/src/spec/wasm_base.rs +++ b/compiler/rustc_target/src/spec/wasm_base.rs @@ -1,5 +1,5 @@ -use super::crt_objects::LinkSelfContainedDefault; use super::{cvs, Cc, LinkerFlavor, PanicStrategy, RelocModel, TargetOptions, TlsModel}; +use crate::spec::LinkSelfContained; pub fn options() -> TargetOptions { macro_rules! args { @@ -100,7 +100,7 @@ pub fn options() -> TargetOptions { // rust-lang/rust#104137: cannot blindly remove this without putting in // some other way to compensate for lack of `-nostartfiles` in linker // invocation. - link_self_contained: LinkSelfContainedDefault::True, + link_self_contained: LinkSelfContained::True, // This has no effect in LLVM 8 or prior, but in LLVM 9 and later when // PIC code is implemented this has quite a drastic effect if it stays diff --git a/compiler/rustc_target/src/spec/windows_gnu_base.rs b/compiler/rustc_target/src/spec/windows_gnu_base.rs index 2231983f07126..d99a95a77e145 100644 --- a/compiler/rustc_target/src/spec/windows_gnu_base.rs +++ b/compiler/rustc_target/src/spec/windows_gnu_base.rs @@ -1,4 +1,5 @@ -use crate::spec::crt_objects::{self, LinkSelfContainedDefault}; +use crate::spec::crt_objects; +use crate::spec::LinkSelfContained; use crate::spec::{cvs, Cc, DebuginfoKind, LinkerFlavor, Lld, SplitDebuginfo, TargetOptions}; use std::borrow::Cow; @@ -90,7 +91,7 @@ pub fn opts() -> TargetOptions { post_link_objects: crt_objects::post_mingw(), pre_link_objects_self_contained: crt_objects::pre_mingw_self_contained(), post_link_objects_self_contained: crt_objects::post_mingw_self_contained(), - link_self_contained: LinkSelfContainedDefault::Mingw, + link_self_contained: LinkSelfContained::InferredForMingw, late_link_args, late_link_args_dynamic, late_link_args_static, diff --git a/compiler/rustc_target/src/spec/x86_64_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/x86_64_unknown_linux_gnu.rs index 2f970f87cc642..4ac78221d1d5a 100644 --- a/compiler/rustc_target/src/spec/x86_64_unknown_linux_gnu.rs +++ b/compiler/rustc_target/src/spec/x86_64_unknown_linux_gnu.rs @@ -1,4 +1,5 @@ use crate::spec::{Cc, LinkerFlavor, Lld, SanitizerSet, StackProbeType, Target}; +use crate::spec::{LinkSelfContained, LinkSelfContainedComponents}; pub fn target() -> Target { let mut base = super::linux_gnu_base::opts(); @@ -6,6 +7,12 @@ pub fn target() -> Target { base.plt_by_default = false; base.max_atomic_width = Some(64); base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m64"]); + // #[cfg(not(bootstrap))] + { + base.linker_flavor = LinkerFlavor::Gnu(Cc::Yes, Lld::Yes); + base.link_self_contained = + LinkSelfContained::WithComponents(LinkSelfContainedComponents::LINKER); + } base.stack_probes = StackProbeType::X86; base.static_position_independent_executables = true; base.supported_sanitizers = SanitizerSet::ADDRESS