Skip to content

Commit c1ea4a0

Browse files
committed
link musl libc statically
In the context of musl, users are typically expecting statically-linked tools, as this is one of musl's strong suits and one of the biggest reasons to use it instead of glibc (that is not static-link-friendly for reasons). - remove the build-flag which was causing musl libc to be linked dynamically - re-add which feat_os_unix_musl which was removed in 21d5cef - exclude stdbuf from feat_os_unix_musl, since libstdbuf.so can't be built with a statically linked musl libc - add test_musl_no_dynamic_deps so that this does not regress in the future Fixes #8572 Signed-off-by: Etienne Cordonnier <[email protected]>
1 parent 56bbc14 commit c1ea4a0

File tree

4 files changed

+52
-11
lines changed

4 files changed

+52
-11
lines changed

.cargo/config.toml

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,3 @@ linker = "x86_64-unknown-redox-gcc"
88
[env]
99
# See feat_external_libstdbuf in src/uu/stdbuf/Cargo.toml
1010
LIBSTDBUF_DIR = "/usr/local/libexec/coreutils"
11-
12-
# libstdbuf must be a shared library, so musl libc can't be linked statically
13-
# https://github.com/rust-lang/rust/issues/82193
14-
[build]
15-
rustflags = ["-C", "target-feature=-crt-static"]

.github/workflows/CICD.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -531,13 +531,13 @@ jobs:
531531
# - { os , target , cargo-options , default-features, features , use-cross , toolchain, skip-tests, workspace-tests, skip-package, skip-publish }
532532
- { os: ubuntu-latest , target: arm-unknown-linux-gnueabihf , features: feat_os_unix_gnueabihf , use-cross: use-cross , skip-tests: true }
533533
- { os: ubuntu-24.04-arm , target: aarch64-unknown-linux-gnu , features: feat_os_unix_gnueabihf }
534-
- { os: ubuntu-latest , target: aarch64-unknown-linux-musl , features: feat_os_unix , use-cross: use-cross , skip-tests: true }
534+
- { os: ubuntu-latest , target: aarch64-unknown-linux-musl , features: feat_os_unix_musl , use-cross: use-cross , skip-tests: true }
535535
# - { os: ubuntu-latest , target: x86_64-unknown-linux-gnu , features: feat_selinux , use-cross: use-cross }
536536
- { os: ubuntu-latest , target: i686-unknown-linux-gnu , features: "feat_os_unix,test_risky_names", use-cross: use-cross }
537-
- { os: ubuntu-latest , target: i686-unknown-linux-musl , features: feat_os_unix , use-cross: use-cross }
537+
- { os: ubuntu-latest , target: i686-unknown-linux-musl , features: feat_os_unix_musl , use-cross: use-cross }
538538
- { os: ubuntu-latest , target: x86_64-unknown-linux-gnu , features: "feat_os_unix,test_risky_names", use-cross: use-cross }
539539
- { os: ubuntu-latest , target: x86_64-unknown-linux-gnu , features: "feat_os_unix,uudoc" , use-cross: no, workspace-tests: true }
540-
- { os: ubuntu-latest , target: x86_64-unknown-linux-musl , features: feat_os_unix , use-cross: use-cross }
540+
- { os: ubuntu-latest , target: x86_64-unknown-linux-musl , features: feat_os_unix_musl , use-cross: use-cross }
541541
- { os: ubuntu-latest , target: x86_64-unknown-redox , features: feat_os_unix_redox , use-cross: redoxer , skip-tests: true }
542542
- { os: ubuntu-latest , target: wasm32-unknown-unknown , default-features: false, features: uucore/format, skip-tests: true, skip-package: true, skip-publish: true }
543543
- { os: macos-latest , target: aarch64-apple-darwin , features: feat_os_macos, workspace-tests: true } # M1 CPU

Cargo.toml

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -163,14 +163,22 @@ feat_os_macos = [
163163
"feat_require_unix_hostid",
164164
]
165165
# "feat_os_unix" == set of utilities which can be built/run on modern/usual *nix platforms.
166-
# Also used for targets binding to the "musl" library (ref: <https://musl.libc.org/about.html>)
167166
feat_os_unix = [
168167
"feat_Tier1",
169168
#
170169
"feat_require_unix",
171170
"feat_require_unix_hostid",
172171
"feat_require_unix_utmpx",
173172
]
173+
# "feat_os_unix_musl" == set of utilities which can be built/run on targets binding to the "musl" library (ref: <https://musl.libc.org/about.html>)
174+
# It excludes stdbuf due to cdylib limitations (https://github.com/rust-lang/rust/issues/82193)
175+
feat_os_unix_musl = [
176+
"feat_Tier1",
177+
#
178+
"feat_require_unix_musl",
179+
"feat_require_unix_hostid",
180+
"feat_require_unix_utmpx",
181+
]
174182
# "feat_os_windows" == set of utilities which can be built/run on modern/usual windows platforms
175183
feat_os_windows = [
176184
"feat_Tier1", ## == "feat_os_windows_legacy" + "hostname"
@@ -194,7 +202,11 @@ feat_os_unix_android = [
194202
# ** NOTE: these `feat_require_...` sets should be minimized as much as possible to encourage cross-platform availability of utilities
195203
#
196204
# "feat_require_unix" == set of utilities requiring support which is only available on unix platforms
197-
feat_require_unix = [
205+
feat_require_unix = ["feat_require_unix_core", "stdbuf"]
206+
# "feat_require_unix_musl" == set of utilities requiring unix support, excluding stdbuf (cdylib not supported on musl)
207+
feat_require_unix_musl = ["feat_require_unix_core"]
208+
# "feat_require_unix_core" == core unix utilities (shared between regular unix and musl)
209+
feat_require_unix_core = [
198210
"chgrp",
199211
"chmod",
200212
"chown",
@@ -210,7 +222,6 @@ feat_require_unix = [
210222
"nohup",
211223
"pathchk",
212224
"stat",
213-
"stdbuf",
214225
"stty",
215226
"timeout",
216227
"tty",

tests/test_util_name.rs

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -280,3 +280,38 @@ fn util_version() {
280280
assert_eq!(format!("coreutils {ver} (multi-call binary)\n"), output_str);
281281
}
282282
}
283+
284+
#[test]
285+
#[cfg(target_env = "musl")]
286+
fn test_musl_no_dynamic_deps() {
287+
use std::process::Command;
288+
289+
let binary_path = if cfg!(debug_assertions) {
290+
"target/x86_64-unknown-linux-musl/debug/coreutils"
291+
} else {
292+
"target/x86_64-unknown-linux-musl/release/coreutils"
293+
};
294+
295+
let output = Command::new("/lib/ld-musl-x86_64.so.1")
296+
.arg("--list")
297+
.arg(binary_path)
298+
.output()
299+
.expect("Failed to run musl loader");
300+
301+
let stdout = String::from_utf8_lossy(&output.stdout);
302+
let lines: Vec<&str> = stdout.trim().lines().collect();
303+
304+
// Should only show the musl loader itself (statically linked binary)
305+
assert_eq!(
306+
lines.len(),
307+
1,
308+
"Expected only musl loader, but found dynamic dependencies: {:?}",
309+
lines
310+
);
311+
312+
assert!(
313+
lines[0].contains("ld-musl"),
314+
"Expected musl loader path, got: {}",
315+
lines[0]
316+
);
317+
}

0 commit comments

Comments
 (0)