Skip to content

Commit 5ab58e3

Browse files
committed
feat: reduce build binary size (#4228)
1 parent 7595a1c commit 5ab58e3

6 files changed

Lines changed: 91 additions & 8 deletions

File tree

.cargo/release.toml

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,18 @@
22
trim-paths = "all"
33

44
[target.'cfg(all())']
5-
rustflags = [ "-Cpasses=mergefunc" ]
5+
rustflags = [
6+
"-Cpasses=mergefunc",
7+
"-Zshare-generics=true",
8+
]
9+
10+
# LLD lacks the SPARC GOTDATA_OP relocations emitted by GCC.
11+
[target.'cfg(all(target_os = "linux", not(target_arch = "sparc64")))']
12+
rustflags = [
13+
"-Clink-arg=-fuse-ld=lld",
14+
"-Clink-arg=-Wl,--icf=safe",
15+
"-Clink-arg=-Wl,-z,pack-relative-relocs",
16+
]
17+
18+
[target.'cfg(target_os = "macos")']
19+
rustflags = [ "-Clink-arg=-Wl,-O1" ]

.github/workflows/draft.yml

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,8 @@ jobs:
1919
include:
2020
- os: ubuntu-latest
2121
target: x86_64-unknown-linux-gnu
22-
- os: ubuntu-latest
22+
- os: ubuntu-24.04-arm
2323
target: aarch64-unknown-linux-gnu
24-
gcc: gcc-aarch64-linux-gnu
2524
- os: ubuntu-latest
2625
target: i686-unknown-linux-gnu
2726
gcc: gcc-i686-linux-gnu
@@ -37,7 +36,6 @@ jobs:
3736
target: aarch64-apple-darwin
3837
runs-on: ${{ matrix.os }}
3938
env:
40-
CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER: aarch64-linux-gnu-gcc
4139
CARGO_TARGET_I686_UNKNOWN_LINUX_GNU_LINKER: i686-linux-gnu-gcc
4240
CARGO_TARGET_RISCV64GC_UNKNOWN_LINUX_GNU_LINKER: riscv64-linux-gnu-gcc
4341
CARGO_TARGET_SPARC64_UNKNOWN_LINUX_GNU_LINKER: sparc64-linux-gnu-gcc

nix/yazi-unwrapped.nix

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
rev ? "unknown",
55
date ? "19700101",
66
lib,
7+
stdenv,
78

89
installShellFiles,
910
fetchFromGitHub,
@@ -15,6 +16,7 @@ let
1516
src = lib.fileset.toSource {
1617
root = ../.;
1718
fileset = lib.fileset.unions [
19+
../.cargo
1820
../assets
1921
../Cargo.toml
2022
../Cargo.lock
@@ -34,6 +36,7 @@ rustPlatform.buildRustPackage (finalAttrs: {
3436
YAZI_GEN_COMPLETIONS = true;
3537
VERGEN_GIT_SHA = rev;
3638
VERGEN_BUILD_DATE = builtins.concatStringsSep "-" (builtins.match "(.{4})(.{2})(.{2}).*" date);
39+
CARGO_NET_OFFLINE = "true";
3740
};
3841

3942
nativeBuildInputs = [
@@ -45,6 +48,12 @@ rustPlatform.buildRustPackage (finalAttrs: {
4548
rust-jemalloc-sys
4649
];
4750

51+
buildPhase = ''
52+
runHook preBuild
53+
cargo xtask build --target ${stdenv.hostPlatform.rust.rustcTarget}
54+
runHook postBuild
55+
'';
56+
4857
postInstall = ''
4958
installShellCompletion --cmd yazi \
5059
--bash ./yazi-boot/completions/yazi.bash \

snap/snapcraft.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ parts:
4343
- xclip
4444
- zoxide
4545
override-build: |
46-
craftctl default
46+
cargo xtask install --bin-dir "$CRAFT_PART_INSTALL"
4747
craftctl set version=$(git describe --tags --abbrev=0)
4848
build-attributes:
4949
- enable-patchelf

yazi-build/src/build.rs

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

3-
use anyhow::{Context, Result};
3+
use anyhow::{Context, Result, ensure};
4+
use yazi_macro::ok_or_not_found;
45

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

78
pub(super) struct Build {
89
pub(super) target: String,
@@ -33,11 +34,64 @@ impl Build {
3334
if self.completions {
3435
cmd.env("YAZI_GEN_COMPLETIONS", "1");
3536
}
37+
if is_linux_target(&self.target) && !is_sparc64_target(&self.target) {
38+
self.expose_lld(&mut cmd)?;
39+
}
3640

3741
run(&mut cmd).context("failed to build Yazi")
3842
}
3943

4044
pub(super) fn profile(&self) -> &'static str {
4145
if is_windows_target(&self.target) { "release-windows" } else { "release" }
4246
}
47+
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> {
72+
let output = Command::new(env::var_os("RUSTC").unwrap_or_else(|| "rustc".into()))
73+
.args(["--print", "target-libdir"])
74+
.output()
75+
.context("failed to locate the Rust target libdir")?;
76+
77+
ensure!(output.status.success(), "`rustc --print target-libdir` failed");
78+
Ok(String::from_utf8(output.stdout)?.trim().into())
79+
}
80+
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");
94+
95+
Some(format!("{prefix}ld.lld"))
96+
}
4397
}

yazi-build/src/common.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,10 +29,18 @@ pub(super) fn workspace_root() -> Result<PathBuf> {
2929
.context("yazi-build must be inside the Yazi workspace")
3030
}
3131

32+
pub(super) fn is_linux_target(target: &str) -> bool {
33+
target.contains("-linux-") || (target.is_empty() && cfg!(target_os = "linux"))
34+
}
35+
3236
pub(super) fn is_windows_target(target: &str) -> bool {
3337
target.contains("-windows-") || (target.is_empty() && cfg!(windows))
3438
}
3539

40+
pub(super) fn is_sparc64_target(target: &str) -> bool {
41+
target.starts_with("sparc64-") || (target.is_empty() && cfg!(target_arch = "sparc64"))
42+
}
43+
3644
pub(super) fn copy_bins(target: &str, profile: &str, to: &Path) -> Result<()> {
3745
let mut from = workspace_root()?.join("target");
3846
if !target.is_empty() {

0 commit comments

Comments
 (0)