Skip to content

Commit 00651b2

Browse files
committed
fix: delegate lld discovery to rustc (#4269)
1 parent 25d6bd1 commit 00651b2

3 files changed

Lines changed: 27 additions & 51 deletions

File tree

.cargo/release.toml

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,20 @@
1+
[unstable]
2+
trim-paths = true
3+
14
[profile.release]
25
trim-paths = "all"
36

47
[target.'cfg(all())']
58
rustflags = [
69
"-Cpasses=mergefunc",
10+
"-Zunstable-options",
711
"-Zshare-generics=true",
812
]
913

1014
# LLD lacks the SPARC GOTDATA_OP relocations emitted by GCC.
1115
[target.'cfg(all(target_os = "linux", not(target_arch = "sparc64")))']
1216
rustflags = [
13-
"-Clink-arg=-fuse-ld=lld",
17+
"-Clinker-features=+lld",
1418
"-Clink-arg=-Wl,--icf=safe",
1519
"-Clink-arg=-Wl,-z,pack-relative-relocs",
1620
]

yazi-build/src/build.rs

Lines changed: 20 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
1-
use std::{env, fs, iter, path::{Path, PathBuf}, process::Command};
1+
use std::{env::{self, consts::EXE_SUFFIX}, path::PathBuf, process::Command};
22

33
use anyhow::{Context, Result, ensure};
4-
use yazi_macro::ok_or_not_found;
54

6-
use super::{cargo, is_linux_target, is_sparc64_target, is_windows_target, run, workspace_root};
5+
use super::{cargo, is_linux_target, is_sparc64_target, is_windows_target, run};
76

87
pub(super) struct Build {
98
pub(super) target: String,
@@ -25,18 +24,21 @@ impl Build {
2524
cmd
2625
.env("RUSTC_BOOTSTRAP", "1")
2726
.env("CARGO_TARGET_DIR", "target")
28-
.args(["-Z", "trim-paths", "--config", ".cargo/release.toml", "build", "--locked"])
27+
.args(["--config", ".cargo/release.toml", "build", "--locked"])
2928
.args(["--profile", self.profile()]);
3029

3130
if !self.target.is_empty() {
3231
cmd.arg("--target").arg(&self.target);
3332
}
33+
if is_linux_target(&self.target) && !is_sparc64_target(&self.target) && Self::has_rust_lld()? {
34+
cmd.args([
35+
"--config",
36+
r#"target.'cfg(target_os = "linux")'.rustflags=["-Clink-self-contained=+linker"]"#,
37+
]);
38+
}
3439
if self.completions {
3540
cmd.env("YAZI_GEN_COMPLETIONS", "1");
3641
}
37-
if is_linux_target(&self.target) && !is_sparc64_target(&self.target) {
38-
self.expose_lld(&mut cmd)?;
39-
}
4042

4143
run(&mut cmd).context("failed to build Yazi")
4244
}
@@ -45,53 +47,23 @@ impl Build {
4547
if is_windows_target(&self.target) { "release-windows" } else { "release" }
4648
}
4749

48-
fn expose_lld(&self, cmd: &mut Command) -> Result<()> {
49-
let rust_lld = Self::rustc_libdir()?
50-
.parent()
51-
.context("Rust target libdir has no parent")?
52-
.join("bin/rust-lld");
53-
ensure!(rust_lld.is_file(), "{} does not exist", rust_lld.display());
54-
55-
let temp_dir = workspace_root()?.join("target/.rust-lld");
56-
fs::create_dir_all(&temp_dir).context("failed to create `target/.rust-lld` directory")?;
57-
for name in ["ld.lld".to_owned()].into_iter().chain(self.lld_alias()) {
58-
let link = temp_dir.join(name);
59-
ok_or_not_found!(fs::remove_file(&link));
60-
#[cfg(unix)]
61-
std::os::unix::fs::symlink(&rust_lld, link)?;
62-
#[cfg(not(unix))]
63-
anyhow::bail!("bundled rust-lld setup requires a Unix host");
64-
}
65-
66-
let path = env::var_os("PATH").unwrap_or_default();
67-
cmd.env("PATH", env::join_paths(iter::once(temp_dir).chain(env::split_paths(&path)))?);
68-
Ok(())
69-
}
70-
71-
fn rustc_libdir() -> Result<PathBuf> {
50+
fn has_rust_lld() -> Result<bool> {
7251
let output = Command::new(env::var_os("RUSTC").unwrap_or_else(|| "rustc".into()))
7352
.args(["--print", "target-libdir"])
7453
.output()
7554
.context("failed to locate the Rust target libdir")?;
76-
7755
ensure!(output.status.success(), "`rustc --print target-libdir` failed");
78-
Ok(String::from_utf8(output.stdout)?.trim().into())
79-
}
8056

81-
// Cross GCC resolves `-fuse-ld=lld` as `<toolchain-prefix>ld.lld`.
82-
// For example:
83-
// `aarch64-linux-musl-gcc.sh` => `aarch64-linux-musl-ld.lld`
84-
// if Cargo has no configured linker:
85-
// `CROSS_TOOLCHAIN_PREFIX=x86_64-linux-musl-` => `x86_64-linux-musl-ld.lld`
86-
fn lld_alias(&self) -> Option<String> {
87-
let var = env::var_os(format!(
88-
"CARGO_TARGET_{}_LINKER",
89-
self.target.replace('-', "_").to_ascii_uppercase()
90-
))
91-
.or_else(|| env::var_os("CROSS_TOOLCHAIN_PREFIX"))?;
92-
93-
let prefix = Path::new(&var).file_stem()?.to_str()?.trim_end_matches("gcc");
57+
let libdir: PathBuf = String::from_utf8(output.stdout)
58+
.context("rustc returned an invalid target libdir")?
59+
.trim()
60+
.into();
61+
let rust_lld = libdir
62+
.parent()
63+
.context("Rust target libdir has no parent")?
64+
.join("bin")
65+
.join(format!("rust-lld{EXE_SUFFIX}"));
9466

95-
Some(format!("{prefix}ld.lld"))
67+
Ok(rust_lld.is_file())
9668
}
9769
}

yazi-config/src/keymap/key.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ impl FromStr for Key {
5454
let mut key = Self::default();
5555
if !s.starts_with('<') || !s.ends_with('>') {
5656
key.code = KeyCode::Char(s.chars().next().unwrap());
57-
key.shift = matches!(key.code, KeyCode::Char(c) if c.is_ascii_uppercase());
57+
key.shift = matches!(key.code, KeyCode::Char(c) if c.is_uppercase());
5858
return Ok(key);
5959
}
6060

@@ -104,7 +104,7 @@ impl FromStr for Key {
104104
_ => match next {
105105
s if it.peek().is_none() => {
106106
let c = s.chars().next().unwrap();
107-
key.shift |= c.is_ascii_uppercase();
107+
key.shift |= c.is_uppercase();
108108
key.code = KeyCode::Char(if key.shift { c.to_ascii_uppercase() } else { c });
109109
}
110110
s => bail!("unknown key: {s}"),

0 commit comments

Comments
 (0)