Introduce LldMode
and generalize parsing of use-lld
This commit is contained in:
parent
d9f9e67bc1
commit
48c1607bc6
@ -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");
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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));
|
||||
}
|
||||
|
@ -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) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user