about summary refs log tree commit diff
diff options
context:
space:
mode:
authorJakub Beránek <berykubik@gmail.com>2023-09-29 18:08:07 +0200
committerJakub Beránek <berykubik@gmail.com>2023-12-10 11:21:35 +0100
commit48c1607bc6742f964d291cd1fb6c3284f0d5a61d (patch)
treeaf2ea71bbf85a16c097b4d637e8ab76a468e23fb
parentd9f9e67bc19002d553bc3ca294c24c000d29f4e9 (diff)
Introduce `LldMode` and generalize parsing of `use-lld`
-rw-r--r--src/bootstrap/src/core/build_steps/compile.rs2
-rw-r--r--src/bootstrap/src/core/config/config.rs77
-rw-r--r--src/bootstrap/src/lib.rs19
-rw-r--r--src/bootstrap/src/tests/config.rs11
-rw-r--r--src/bootstrap/src/utils/helpers.rs2
5 files changed, 99 insertions, 12 deletions
diff --git a/src/bootstrap/src/core/build_steps/compile.rs b/src/bootstrap/src/core/build_steps/compile.rs
index 89abf976776..11e789a996a 100644
--- a/src/bootstrap/src/core/build_steps/compile.rs
+++ b/src/bootstrap/src/core/build_steps/compile.rs
@@ -870,7 +870,7 @@ impl Step for Rustc {
         // is already on by default in MSVC optimized builds, which is interpreted as --icf=all:
         // https://github.com/llvm/llvm-project/blob/3329cec2f79185bafd678f310fafadba2a8c76d2/lld/COFF/Driver.cpp#L1746
         // https://github.com/rust-lang/rust/blob/f22819bcce4abaff7d1246a56eec493418f9f4ee/compiler/rustc_codegen_ssa/src/back/linker.rs#L827
-        if builder.config.use_lld && !compiler.host.is_msvc() {
+        if builder.config.lld_mode.is_used() && !compiler.host.is_msvc() {
             cargo.rustflag("-Clink-args=-Wl,--icf=all");
         }
 
diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs
index 23a9b6a2f11..ade7d83f8b2 100644
--- a/src/bootstrap/src/core/config/config.rs
+++ b/src/bootstrap/src/core/config/config.rs
@@ -105,6 +105,39 @@ impl Display for DebuginfoLevel {
     }
 }
 
+/// LLD in bootstrap works like this:
+/// - Self-contained lld: use `rust-lld` from the compiler's sysroot
+/// - External: use an external `lld` binary
+///
+/// It is configured depending on the target:
+/// 1) Everything except MSVC
+/// - Self-contained: -Clinker-flavor=gnu-lld-cc -Clink-self-contained=+linker
+/// - External: -Clinker-flavor=gnu-lld-cc
+/// 2) MSVC
+/// - Self-contained: -Clinker=<path to rust-lld>
+/// - External: -Clinker=lld
+#[derive(Default, Clone)]
+pub enum LldMode {
+    /// Do not use LLD
+    #[default]
+    Unused,
+    /// Use `rust-lld` from the compiler's sysroot
+    SelfContained,
+    /// Use an externally provided `lld` binary.
+    /// Note that the linker name cannot be overridden, the binary has to be named `lld` and it has
+    /// to be in $PATH.
+    External,
+}
+
+impl LldMode {
+    pub fn is_used(&self) -> bool {
+        match self {
+            LldMode::SelfContained | LldMode::External => true,
+            LldMode::Unused => false,
+        }
+    }
+}
+
 /// Global configuration for the entire build and/or bootstrap.
 ///
 /// This structure is parsed from `config.toml`, and some of the fields are inferred from `git` or build-time parameters.
@@ -199,7 +232,7 @@ pub struct Config {
     pub llvm_from_ci: bool,
     pub llvm_build_config: HashMap<String, String>,
 
-    pub use_lld: bool,
+    pub lld_mode: LldMode,
     pub lld_enabled: bool,
     pub llvm_tools_enabled: bool,
 
@@ -981,6 +1014,44 @@ enum StringOrInt<'a> {
     String(&'a str),
     Int(i64),
 }
+
+impl<'de> Deserialize<'de> for LldMode {
+    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
+    where
+        D: Deserializer<'de>,
+    {
+        struct LldModeVisitor;
+
+        impl<'de> serde::de::Visitor<'de> for LldModeVisitor {
+            type Value = LldMode;
+
+            fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
+                formatter.write_str("one of true, 'self-contained' or 'external'")
+            }
+
+            fn visit_bool<E>(self, v: bool) -> Result<Self::Value, E>
+            where
+                E: serde::de::Error,
+            {
+                Ok(if v { LldMode::External } else { LldMode::Unused })
+            }
+
+            fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
+            where
+                E: serde::de::Error,
+            {
+                match v {
+                    "external" => Ok(LldMode::External),
+                    "self-contained" => Ok(LldMode::SelfContained),
+                    _ => Err(E::custom("unknown mode {v}")),
+                }
+            }
+        }
+
+        deserializer.deserialize_any(LldModeVisitor)
+    }
+}
+
 define_config! {
     /// TOML representation of how the Rust build is configured.
     struct Rust {
@@ -1018,7 +1089,7 @@ define_config! {
         save_toolstates: Option<String> = "save-toolstates",
         codegen_backends: Option<Vec<String>> = "codegen-backends",
         lld: Option<bool> = "lld",
-        use_lld: Option<bool> = "use-lld",
+        lld_mode: Option<LldMode> = "use-lld",
         llvm_tools: Option<bool> = "llvm-tools",
         deny_warnings: Option<bool> = "deny-warnings",
         backtrace_on_ice: Option<bool> = "backtrace-on-ice",
@@ -1446,7 +1517,7 @@ impl Config {
             if let Some(true) = rust.incremental {
                 config.incremental = true;
             }
-            set(&mut config.use_lld, rust.use_lld);
+            set(&mut config.lld_mode, rust.lld_mode);
             set(&mut config.lld_enabled, rust.lld);
             set(&mut config.llvm_tools_enabled, rust.llvm_tools);
             config.rustc_parallel = rust
diff --git a/src/bootstrap/src/lib.rs b/src/bootstrap/src/lib.rs
index 5442ce97a8d..fd0b61eae8d 100644
--- a/src/bootstrap/src/lib.rs
+++ b/src/bootstrap/src/lib.rs
@@ -37,7 +37,7 @@ use utils::channel::GitInfo;
 
 use crate::core::builder;
 use crate::core::builder::Kind;
-use crate::core::config::flags;
+use crate::core::config::{flags, LldMode};
 use crate::core::config::{DryRun, Target};
 use crate::core::config::{LlvmLibunwind, TargetSelection};
 use crate::utils::cache::{Interned, INTERNER};
@@ -1258,17 +1258,24 @@ impl Build {
             && !target.is_msvc()
         {
             Some(self.cc(target))
-        } else if self.config.use_lld && !self.is_fuse_ld_lld(target) && self.build == target {
-            Some(self.initial_lld.clone())
+        } else if self.config.lld_mode.is_used()
+            && self.is_lld_direct_linker(target)
+            && self.build == target
+        {
+            match self.config.lld_mode {
+                LldMode::SelfContained => Some(self.initial_lld.clone()),
+                LldMode::External => Some("lld".into()),
+                LldMode::Unused => None,
+            }
         } else {
             None
         }
     }
 
-    // LLD is used through `-fuse-ld=lld` rather than directly.
+    // Is LLD configured directly through `-Clinker`?
     // Only MSVC targets use LLD directly at the moment.
-    fn is_fuse_ld_lld(&self, target: TargetSelection) -> bool {
-        self.config.use_lld && !target.is_msvc()
+    fn is_lld_direct_linker(&self, target: TargetSelection) -> bool {
+        target.is_msvc()
     }
 
     /// Returns if this target should statically link the C runtime, if specified
diff --git a/src/bootstrap/src/tests/config.rs b/src/bootstrap/src/tests/config.rs
index a8106ca8ff9..c24d57fb8f8 100644
--- a/src/bootstrap/src/tests/config.rs
+++ b/src/bootstrap/src/tests/config.rs
@@ -1,5 +1,5 @@
-use crate::core::config::TomlConfig;
 use super::{Config, Flags};
+use crate::core::config::{LldMode, TomlConfig};
 
 use clap::CommandFactory;
 use serde::Deserialize;
@@ -217,3 +217,12 @@ fn verify_file_integrity() {
 
     remove_file(tempfile).unwrap();
 }
+
+#[test]
+fn rust_lld() {
+    assert!(matches!(parse("").lld_mode, LldMode::Unused));
+    assert!(matches!(parse("rust.use-lld = \"self-contained\"").lld_mode, LldMode::SelfContained));
+    assert!(matches!(parse("rust.use-lld = \"external\"").lld_mode, LldMode::External));
+    assert!(matches!(parse("rust.use-lld = true").lld_mode, LldMode::External));
+    assert!(matches!(parse("rust.use-lld = false").lld_mode, LldMode::Unused));
+}
diff --git a/src/bootstrap/src/utils/helpers.rs b/src/bootstrap/src/utils/helpers.rs
index eeed9c87438..2da556f0a2d 100644
--- a/src/bootstrap/src/utils/helpers.rs
+++ b/src/bootstrap/src/utils/helpers.rs
@@ -499,7 +499,7 @@ pub fn linker_flags(
     lld_threads: LldThreads,
 ) -> Vec<String> {
     let mut args = vec![];
-    if builder.is_fuse_ld_lld(target) {
+    if !builder.is_lld_direct_linker(target) && builder.config.lld_mode.is_used() {
         args.push(String::from("-Clink-arg=-fuse-ld=lld"));
 
         if matches!(lld_threads, LldThreads::No) {