From 0d71dc0b47497430801662c19c707c8007046521 Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Sun, 21 Jun 2026 05:42:14 -0400 Subject: [PATCH 1/9] test: Set version-dependent skips based on header defines When there are additions or updates that are only available with newer platform versions, we don't have a great way to handle testing. The only thing we can really do is unconditionally skip anything that doesn't pass on the oldest versions we have on CI. Improve this by adding a preprocess-only compiler invocation that collects versions from the headers we are building against. These are then used to skip This initial patch only uses the versions for skips on Linux and replacing the NetBSD `uname` invocation. --- libc-test/build.rs | 242 ++++++++++++++++++++++++++++++++------------- 1 file changed, 176 insertions(+), 66 deletions(-) diff --git a/libc-test/build.rs b/libc-test/build.rs index 18d020363e13..a544eaf1f24f 100644 --- a/libc-test/build.rs +++ b/libc-test/build.rs @@ -11,11 +11,18 @@ use std::path::{ Path, PathBuf, }; +use std::process::{ + Command, + Stdio, +}; +use std::sync::LazyLock; use std::{ env, io, }; +use regex::Regex; + fn do_cc() { let target = env::var("TARGET").unwrap(); if cfg!(unix) || target.contains("cygwin") { @@ -176,6 +183,8 @@ fn process_semver_file>(output: &mut W, path: &mut Path fn main() { // Avoid unnecessary re-building. println!("cargo:rerun-if-changed=build.rs"); + // Ensure version checking works, even if we don't use it. + LazyLock::force(&VERSIONS); do_cc(); do_ctest(); @@ -1227,10 +1236,7 @@ fn test_netbsd(target: &str) { let mut cfg = ctest_cfg(); // Assume netbsd10 but check for netbsd9 for test config. - let netbsd9 = match try_command_output("uname", &["-sr"]) { - Some(s) if s.starts_with("NetBSD 9.") => true, - _ => false, - }; + let netbsd9 = matches!(VERSIONS.netbsd, Some((9, _))); cfg.flag("-Wno-deprecated-declarations"); cfg.define("_NETBSD_SOURCE", Some("1")); @@ -3816,6 +3822,8 @@ fn test_linux(target: &str) { let mips = target.contains("mips"); let mips64 = target.contains("mips64"); let mips32 = mips && !mips64; + let versions = &*VERSIONS; + let kernel = versions.linux.unwrap_or((0, 0)); let musl_v1_2_3 = env::var("CARGO_CFG_LIBC_UNSTABLE_MUSL_V1_2_3").is_ok(); if musl_v1_2_3 { @@ -4169,11 +4177,6 @@ fn test_linux(target: &str) { cfg.skip_struct(move |struct_| { let ty = struct_.ident(); - // FIXME(linux): Requires >= 6.12 kernel headers. CI has old headers - if ty == "ptp_sys_offset_extended" { - return true; - } - // LFS64 types have been removed in musl 1.2.4+ if musl && (ty.ends_with("64") || ty.ends_with("64_t")) { return true; @@ -4267,15 +4270,15 @@ fn test_linux(target: &str) { // kernel so we can drop this and test the type once this new version is used in CI. "sched_attr" => true, - // FIXME(linux): Requires >= 6.9 kernel headers. - "epoll_params" => true, + // Recent additions + "ptp_sys_offset_extended" if kernel < (6, 12) => true, + "epoll_params" => kernel < (6, 9), + "mnt_ns_info" => kernel < (6, 12), - // FIXME(linux): Requires >= 6.12 kernel headers. + // FIXME(linux): Only requires >= 6.12 kernel headers, but including `uio.h` creates + // a conflict with the `iovec` definition. "dmabuf_cmsg" | "dmabuf_token" => true, - // FIXME(linux): Requires >= 6.12 kernel headers. - "mnt_ns_info" => true, - // FIXME(musl): Struct has changed for new musl versions "tcp_info" if musl => true, @@ -4666,8 +4669,8 @@ fn test_linux(target: &str) { // FIXME(linux): Not yet implemented on sparc64 "SYS_clone3" if sparc64 => true, - // FIXME(linux): Requires >= 6.9 kernel headers. - n if (arm || ppc32) && n.starts_with("FUTEX2_") => true, + // Requires >= 6.9 kernel headers. + n if (arm || ppc32) && n.starts_with("FUTEX2_") => kernel < (6, 9), // FIXME(linux): Not defined on ARM, gnueabihf, mips, musl, PowerPC, riscv64, s390x, and sparc64. "SYS_memfd_secret" @@ -4679,7 +4682,8 @@ fn test_linux(target: &str) { // Skip as this signal codes and trap reasons need newer headers "TRAP_PERF" => true, - // headers conflicts with linux/pidfd.h + // FIXME(linux): linux/pidfd.h includes linux/flock.h which conflicts with flock.h, + // so pidfd isn't currently tested. "PIDFD_NONBLOCK" => true, // Linux >= 6.9 "PIDFD_THREAD" @@ -4723,14 +4727,10 @@ fn test_linux(target: &str) { // so opt out of tests for constants which are different in later kernels. "NF_NETDEV_NUMHOOKS" | "RLIM_NLIMITS" | "NFT_MSG_MAX" if uclibc => true, - // kernel 6.9 minimum - "RWF_NOAPPEND" => true, - - // kernel 6.11 minimum - "RWF_ATOMIC" => true, - - // kernel 6.14 minimum - "RWF_DONTCACHE" => true, + // Recent additions + "RWF_NOAPPEND" => kernel < (6, 9), + "RWF_ATOMIC" => kernel < (6, 11), + "RWF_DONTCACHE" => kernel < (6, 14), // musl doesn't use in "FAN_REPORT_PIDFD" @@ -4748,7 +4748,7 @@ fn test_linux(target: &str) { } // FIXME(linux32): Requires >= 6.6 kernel headers. - "XDP_USE_SG" | "XDP_PKT_CONTD" if pointer_width == 32 => true, + "XDP_USE_SG" | "XDP_PKT_CONTD" if pointer_width == 32 => kernel < (6, 6), // FIXME(linux): Missing only on this platform for some reason "PR_MDWE_NO_INHERIT" if gnueabihf => true, @@ -4761,25 +4761,19 @@ fn test_linux(target: &str) { | "XDP_TX_METADATA" if musl || pointer_width == 32 => { - true + musl || kernel < (6, 8) } - // FIXME(linux): Requires >= 6.11 kernel headers. - "XDP_UMEM_TX_METADATA_LEN" => true, - - // FIXME(linux): Requires >= 6.11 kernel headers. + "XDP_UMEM_TX_METADATA_LEN" => kernel < (6, 11), "NS_GET_MNTNS_ID" | "NS_GET_PID_FROM_PIDNS" | "NS_GET_TGID_FROM_PIDNS" | "NS_GET_PID_IN_PIDNS" - | "NS_GET_TGID_IN_PIDNS" => true, - // FIXME(linux): Requires >= 6.12 kernel headers. + | "NS_GET_TGID_IN_PIDNS" => kernel < (6, 11), "MNT_NS_INFO_SIZE_VER0" | "NS_MNT_GET_INFO" | "NS_MNT_GET_NEXT" | "NS_MNT_GET_PREV" => { - true + kernel < (6, 12) } - - // FIXME(linux): Requires >= 6.10 kernel headers. - "SYS_mseal" => true, + "SYS_mseal" => kernel < (6, 10), // FIXME(linux): seems to not be available all the time (from : "PF_VCPU" | "PF_IDLE" | "PF_EXITING" | "PF_POSTCOREDUMP" | "PF_IO_WORKER" @@ -4790,43 +4784,35 @@ fn test_linux(target: &str) { | "PF_RANDOMIZE" | "PF_NO_SETAFFINITY" | "PF_MCE_EARLY" | "PF_MEMALLOC_PIN" | "PF_BLOCK_TS" | "PF_SUSPEND_TASK" => true, - // FIXME(linux): Requires >= 6.9 kernel headers. - "EPIOCSPARAMS" | "EPIOCGPARAMS" => true, - - // FIXME(linux): Requires >= 6.11 kernel headers. - "MAP_DROPPABLE" => true, - - // FIXME(linux): Requires >= 6.12 kernel headers. - "SOF_TIMESTAMPING_OPT_RX_FILTER" => true, + "EPIOCSPARAMS" | "EPIOCGPARAMS" => kernel < (6, 9), + "MAP_DROPPABLE" => kernel < (6, 11), + "SOF_TIMESTAMPING_OPT_RX_FILTER" => kernel < (6, 12), - // FIXME(linux): Requires >= 6.12 kernel headers. "SO_DEVMEM_LINEAR" | "SO_DEVMEM_DMABUF" | "SO_DEVMEM_DONTNEED" - | "SCM_DEVMEM_LINEAR" | "SCM_DEVMEM_DMABUF" => true, + | "SCM_DEVMEM_LINEAR" | "SCM_DEVMEM_DMABUF" => kernel < (6, 12), - // FIXME(linux): Requires >= 6.14 kernel headers. "SECBIT_EXEC_DENY_INTERACTIVE" | "SECBIT_EXEC_DENY_INTERACTIVE_LOCKED" | "SECBIT_EXEC_RESTRICT_FILE" | "SECBIT_EXEC_RESTRICT_FILE_LOCKED" - | "SECURE_ALL_UNPRIVILEGED" => true, - - // FIXME(linux): Value changed in 6.14 - "SECURE_ALL_BITS" | "SECURE_ALL_LOCKS" => true, - - // FIXME(linux): Requires >= 6.9 kernel headers. - "AT_HWCAP3" | "AT_HWCAP4" => true, - - // Linux 6.14 - "AT_EXECVE_CHECK" => true, + | "SECURE_ALL_UNPRIVILEGED" => kernel < (6, 14), - // FIXME(linux): Requires >= 6.16 kernel headers. - "PTRACE_SET_SYSCALL_INFO" => true, + // Value changed in 6.14 + "SECURE_ALL_BITS" | "SECURE_ALL_LOCKS" => kernel < (6, 14), - // FIXME(linux): Requires >= 6.13 kernel headers. - "AT_HANDLE_CONNECTABLE" => true, + // Recent additions + "AT_HWCAP3" | "AT_HWCAP4" => kernel < (6, 9), + "PTRACE_SET_SYSCALL_INFO" => kernel < (6, 16), - // FIXME(linux): Requires >= 6.12 kernel headers. - "AT_HANDLE_MNT_ID_UNIQUE" => true, + // Added in kernel versions 6.12..6.14 but we can't include `linux/fcntl.h` + // (conflicts), so these need to wait on glibc's redefinition in 2.44-2.43. + "AT_HANDLE_CONNECTABLE" | "AT_HANDLE_MNT_ID_UNIQUE" | "AT_EXECVE_CHECK" => { + if gnu { + versions.glibc.unwrap() < (2, 43) + } else { + true + } + } // FIXME(musl): This value is not yet in musl. // eabihf targets are tested using an older version of glibc @@ -6183,10 +6169,134 @@ fn test_qurt(target: &str) { ctest::generate_test(&mut cfg, "../src/lib.rs", "ctest_output.rs").unwrap(); } +/// Platform versions for checking expected support. These are extracted from headers so should be +/// accurate for the target we are building, rather than the host (which `uname` would provide). +static VERSIONS: LazyLock = LazyLock::new(Versions::init_from_cc); + +#[derive(Clone, Copy, Debug, Default)] +struct Versions { + linux: Option<(u32, u32)>, + glibc: Option<(u32, u32)>, + freebsd: Option<(u32, u32)>, + openbsd: Option<(u32, u32)>, + netbsd: Option<(u32, u32)>, + macos: Option<(u32, u32)>, +} + +impl Versions { + fn init_from_cc() -> Self { + let src = r#" + #ifdef __linux__ + /* Defines LINUX_VERSION_MAJOR, LINUX_VERSION_PATCHLEVEL (integers) */ + #include "linux/version.h" + #endif + + /* Including a libc header will define __GLIBC__ */ + #include + + #ifdef __GLIBC__ + /* Provides __GLIBC__, __GLIBC_MINOR__ (integers) */ + #include "gnu/libc-version.h" + #endif + + #if defined(__FreeBSD__) \ + || defined(__NetBSD__) \ + || defined(__OpenBSD__) \ + || defined(__APPLE__) + /* FreeBSD: __FreeBSD_version (MMmmRxx string, e.g. 1600018) + * NetBSD: __NetBSD_Version__ (MMmmrrpp00 string, e.g. 1001000000) + * OpenBSD: OpenBSD (release date, e.g. 202510) and OpenBSDM_m (e.g. OpenBSD7_8) + * Apple: __MAC_OS_X_VERSION_MAX_ALLOWED __MAC_M_m (e.g. __MAC_26_5) + */ + #include "sys/param.h" + #endif + "#; + + let mut ret = Versions::default(); + + let compiler = cc::Build::new().get_compiler(); + + if !(compiler.is_like_gnu() || compiler.is_like_clang()) { + println!("cargo:warning=unsupported compiler for version detection, skipping"); + return ret; + } + + // `-dM -E` invokes the preprocessor and prints all `#define`s. `cc` automatically + // sets target-specific flags. + let mut cmd = compiler.to_command(); + cmd.stdin(Stdio::piped()) + .stdout(Stdio::piped()) + .args(["-dM", "-E", "-"]); + let mut child = cmd.spawn().expect("failed to spawn compiler"); + child + .stdin + .take() + .unwrap() + .write_all(src.as_bytes()) + .expect("failed to send stdin"); + let out = child.wait_with_output().expect("failed to wait on child"); + let out = String::from_utf8_lossy(&out.stdout); + + // Allow spaces everywhere so we match things like `\n # define foo bar \n`. + let re = Regex::new(r"^\s*#\s*define\s+(\w+)\s+(.*?)\s*$").unwrap(); + let obsd_re = Regex::new(r"^OpenBSD(\d+)_(\d+)$").unwrap(); + let mac_re = Regex::new(r"^__MAC_(\d+)_(\d+)").unwrap(); + + for line in out.lines() { + let Some(caps) = re.captures(line) else { + continue; + }; + let name = &caps[1]; + let value = &caps[2]; + + match name { + "LINUX_VERSION_MAJOR" => { + ret.linux.get_or_insert_default().0 = value.parse().unwrap() + } + "LINUX_VERSION_PATCHLEVEL" => { + ret.linux.get_or_insert_default().1 = value.parse().unwrap() + } + "__GLIBC__" => ret.glibc.get_or_insert_default().0 = value.parse().unwrap(), + "__GLIBC_MINOR__" => ret.glibc.get_or_insert_default().1 = value.parse().unwrap(), + "__MAC_OS_X_VERSION_MAX_ALLOWED" => { + let caps = mac_re.captures(value).unwrap(); + let major: u32 = caps[1].parse().unwrap(); + let minor: u32 = caps[2].parse().unwrap(); + ret.macos = Some((major, minor)); + } + "__FreeBSD_version" => { + // Format: MmmRxx where M is major (possibly multi-digit), mm is minor, R + // indicates release status, xx is some sequence. + let major: u32 = value[..(value.len() - 5)].parse().unwrap(); + let minor: u32 = value[(value.len() - 5)..(value.len() - 3)].parse().unwrap(); + ret.freebsd = Some((major, minor)); + } + "__NetBSD_Version__" => { + // Format: MMmmrrpp00 where M is major (possibly multi-digit), mm is minor, r + // and p are patch level. + let major: u32 = value[..(value.len() - 8)].parse().unwrap(); + let minor: u32 = value[(value.len() - 8)..(value.len() - 6)].parse().unwrap(); + ret.netbsd = Some((major, minor)); + } + x if obsd_re.is_match(x) => { + let caps = obsd_re.captures(name).expect("is_match checked"); + let major: u32 = caps[1].parse().unwrap(); + let minor: u32 = caps[2].parse().unwrap(); + ret.openbsd = Some((major, minor)); + } + _ => (), + } + } + + println!("cargo:warning=detected versions: {ret:?}"); + ret + } +} + /// Attempt to execute a command and collect its output, If the command fails for whatever /// reason, return `None`. fn try_command_output(cmd: &str, args: &[&str]) -> Option { - let output = std::process::Command::new(cmd).args(args).output().ok()?; + let output = Command::new(cmd).args(args).output().ok()?; if !output.status.success() { return None; From 19cf615a55831a4fef3d9fe39031fd1ff859f47a Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Tue, 23 Jun 2026 03:19:57 -0400 Subject: [PATCH 2/9] linux: Correct the value of `EPIOC[GS]PARAMS` with nonstandard _IOC PowerPC, Sparc, and MIPS (32- and 64-bit for all) have different `_IOC` numbers, meaning the constants were inaccurate. Example error on PowerPC64: bad `EPIOCSPARAMS` value at byte 4: rust: 64 (0x40) != c 128 (0x80) rust bytes: 00 00 00 00 40 08 8a 01 c bytes: 00 00 00 00 80 08 8a 01 bad `EPIOCGPARAMS` value at byte 4: rust: 128 (0x80) != c 64 (0x40) rust bytes: 00 00 00 00 80 08 8a 02 c bytes: 00 00 00 00 40 08 8a 02 Resolve this by using `_IOW` and `_IOR`. Source: https://github.com/torvalds/linux/blob/502d801f0ab03e4f32f9a33d203154ce84887921/include/uapi/linux/eventpoll.h#L97-L99 Fixes: fb58c011af41 ("epoll: add busy polling parameters") --- src/unix/linux_like/linux/mod.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/unix/linux_like/linux/mod.rs b/src/unix/linux_like/linux/mod.rs index 66d2bf70a3ee..ecba148ad9af 100644 --- a/src/unix/linux_like/linux/mod.rs +++ b/src/unix/linux_like/linux/mod.rs @@ -3641,8 +3641,9 @@ pub const SCHED_FLAG_ALL: c_int = SCHED_FLAG_RESET_ON_FORK | SCHED_FLAG_UTIL_CLAMP; // ioctl_eventpoll: added in Linux 6.9 -pub const EPIOCSPARAMS: Ioctl = 0x40088a01; -pub const EPIOCGPARAMS: Ioctl = u32_cast_ioctl(0x80088a02); +const EPOLL_IOC_TYPE: u32 = 0x8A; +pub const EPIOCSPARAMS: Ioctl = _IOW::(EPOLL_IOC_TYPE, 0x01); +pub const EPIOCGPARAMS: Ioctl = _IOR::(EPOLL_IOC_TYPE, 0x02); // siginfo.h pub const SI_DETHREAD: c_int = -7; From 9e233f5b45f7e974098f811df3f839ae9e534097 Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Wed, 17 Jun 2026 19:57:41 -0400 Subject: [PATCH 3/9] ci: Switch to ubuntu:26.04 images Where possible, change to the latest Ubuntu release. The 32-bit images still aren't bumped because of the time64 mismatch. --- ci/docker/aarch64-linux-android/Dockerfile | 2 +- ci/docker/aarch64-unknown-linux-gnu/Dockerfile | 2 +- ci/docker/aarch64-unknown-linux-musl/Dockerfile | 2 +- ci/docker/arm-linux-androideabi/Dockerfile | 2 +- ci/docker/asmjs-unknown-emscripten/Dockerfile | 2 +- ci/docker/i686-linux-android/Dockerfile | 2 +- ci/docker/i686-unknown-linux-gnu/Dockerfile | 2 +- ci/docker/i686-unknown-linux-musl/Dockerfile | 2 +- ci/docker/loongarch64-unknown-linux-gnu/Dockerfile | 2 +- ci/docker/loongarch64-unknown-linux-musl/Dockerfile | 2 +- ci/docker/powerpc64-unknown-linux-gnu/Dockerfile | 2 +- ci/docker/powerpc64le-unknown-linux-gnu/Dockerfile | 2 +- ci/docker/powerpc64le-unknown-linux-musl/Dockerfile | 2 +- ci/docker/riscv64gc-unknown-linux-gnu/Dockerfile | 4 ++-- ci/docker/s390x-unknown-linux-gnu/Dockerfile | 2 +- ci/docker/s390x-unknown-linux-musl/Dockerfile | 2 +- ci/docker/sparc64-unknown-linux-gnu/Dockerfile | 4 ++-- ci/docker/wasm32-unknown-emscripten/Dockerfile | 3 +-- ci/docker/wasm32-wasip1/Dockerfile | 2 +- ci/docker/wasm32-wasip2/Dockerfile | 2 +- ci/docker/x86_64-linux-android/Dockerfile | 2 +- ci/docker/x86_64-unknown-linux-gnu/Dockerfile | 2 +- ci/docker/x86_64-unknown-linux-gnux32/Dockerfile | 2 +- ci/docker/x86_64-unknown-linux-musl/Dockerfile | 2 +- 24 files changed, 26 insertions(+), 27 deletions(-) diff --git a/ci/docker/aarch64-linux-android/Dockerfile b/ci/docker/aarch64-linux-android/Dockerfile index 0e5baf085423..91c074150f94 100644 --- a/ci/docker/aarch64-linux-android/Dockerfile +++ b/ci/docker/aarch64-linux-android/Dockerfile @@ -1,4 +1,4 @@ -FROM ubuntu:25.04 +FROM ubuntu:26.04 RUN dpkg --add-architecture i386 RUN apt-get update && apt-get install -y --no-install-recommends \ diff --git a/ci/docker/aarch64-unknown-linux-gnu/Dockerfile b/ci/docker/aarch64-unknown-linux-gnu/Dockerfile index e6b1798b1cfb..e734c9c127b6 100644 --- a/ci/docker/aarch64-unknown-linux-gnu/Dockerfile +++ b/ci/docker/aarch64-unknown-linux-gnu/Dockerfile @@ -1,4 +1,4 @@ -FROM ubuntu:25.04 +FROM ubuntu:26.04 RUN apt-get update && apt-get install -y --no-install-recommends \ ca-certificates \ diff --git a/ci/docker/aarch64-unknown-linux-musl/Dockerfile b/ci/docker/aarch64-unknown-linux-musl/Dockerfile index 15c38af65ce9..4173a97435e5 100644 --- a/ci/docker/aarch64-unknown-linux-musl/Dockerfile +++ b/ci/docker/aarch64-unknown-linux-musl/Dockerfile @@ -1,4 +1,4 @@ -FROM ubuntu:25.04 +FROM ubuntu:26.04 RUN apt-get update && apt-get install -y --no-install-recommends \ ca-certificates \ diff --git a/ci/docker/arm-linux-androideabi/Dockerfile b/ci/docker/arm-linux-androideabi/Dockerfile index 23afe49970e7..657ff81097c7 100644 --- a/ci/docker/arm-linux-androideabi/Dockerfile +++ b/ci/docker/arm-linux-androideabi/Dockerfile @@ -1,4 +1,4 @@ -FROM ubuntu:25.04 +FROM ubuntu:26.04 RUN dpkg --add-architecture i386 RUN apt-get update && apt-get install -y --no-install-recommends \ diff --git a/ci/docker/asmjs-unknown-emscripten/Dockerfile b/ci/docker/asmjs-unknown-emscripten/Dockerfile index 312eca1146db..5663e29df51f 100644 --- a/ci/docker/asmjs-unknown-emscripten/Dockerfile +++ b/ci/docker/asmjs-unknown-emscripten/Dockerfile @@ -1,4 +1,4 @@ -FROM ubuntu:25.04 +FROM ubuntu:26.04 # This is a workaround to avoid the interaction with tzdata. ENV DEBIAN_FRONTEND=noninteractive diff --git a/ci/docker/i686-linux-android/Dockerfile b/ci/docker/i686-linux-android/Dockerfile index 96507d7fc227..450df8b3c810 100644 --- a/ci/docker/i686-linux-android/Dockerfile +++ b/ci/docker/i686-linux-android/Dockerfile @@ -1,4 +1,4 @@ -FROM ubuntu:25.04 +FROM ubuntu:26.04 RUN dpkg --add-architecture i386 RUN apt-get update && apt-get install -y --no-install-recommends \ diff --git a/ci/docker/i686-unknown-linux-gnu/Dockerfile b/ci/docker/i686-unknown-linux-gnu/Dockerfile index b1596071b8f6..cb2d4e7d42e1 100644 --- a/ci/docker/i686-unknown-linux-gnu/Dockerfile +++ b/ci/docker/i686-unknown-linux-gnu/Dockerfile @@ -1,4 +1,4 @@ -FROM ubuntu:25.04 +FROM ubuntu:26.04 RUN apt-get update && apt-get install -y --no-install-recommends \ ca-certificates \ diff --git a/ci/docker/i686-unknown-linux-musl/Dockerfile b/ci/docker/i686-unknown-linux-musl/Dockerfile index 225823d6143c..b1926457a150 100644 --- a/ci/docker/i686-unknown-linux-musl/Dockerfile +++ b/ci/docker/i686-unknown-linux-musl/Dockerfile @@ -1,4 +1,4 @@ -FROM ubuntu:25.04 +FROM ubuntu:26.04 RUN dpkg --add-architecture i386 && \ apt-get update && apt-get install -y --no-install-recommends \ diff --git a/ci/docker/loongarch64-unknown-linux-gnu/Dockerfile b/ci/docker/loongarch64-unknown-linux-gnu/Dockerfile index ab13f33f1187..10d706bcb1c1 100644 --- a/ci/docker/loongarch64-unknown-linux-gnu/Dockerfile +++ b/ci/docker/loongarch64-unknown-linux-gnu/Dockerfile @@ -1,4 +1,4 @@ -FROM ubuntu:25.04 +FROM ubuntu:26.04 RUN apt-get update && apt-get install -y --no-install-recommends \ ca-certificates \ diff --git a/ci/docker/loongarch64-unknown-linux-musl/Dockerfile b/ci/docker/loongarch64-unknown-linux-musl/Dockerfile index c3066e027a40..7944dd0c8d73 100644 --- a/ci/docker/loongarch64-unknown-linux-musl/Dockerfile +++ b/ci/docker/loongarch64-unknown-linux-musl/Dockerfile @@ -1,4 +1,4 @@ -FROM ubuntu:25.04 +FROM ubuntu:26.04 RUN apt-get update && apt-get install -y --no-install-recommends \ ca-certificates \ diff --git a/ci/docker/powerpc64-unknown-linux-gnu/Dockerfile b/ci/docker/powerpc64-unknown-linux-gnu/Dockerfile index f7907a32347a..369916bb6771 100644 --- a/ci/docker/powerpc64-unknown-linux-gnu/Dockerfile +++ b/ci/docker/powerpc64-unknown-linux-gnu/Dockerfile @@ -1,4 +1,4 @@ -FROM ubuntu:25.04 +FROM ubuntu:26.04 RUN apt-get update && apt-get install -y --no-install-recommends \ ca-certificates \ diff --git a/ci/docker/powerpc64le-unknown-linux-gnu/Dockerfile b/ci/docker/powerpc64le-unknown-linux-gnu/Dockerfile index f2f0a6e20c7b..98dc2c44df03 100644 --- a/ci/docker/powerpc64le-unknown-linux-gnu/Dockerfile +++ b/ci/docker/powerpc64le-unknown-linux-gnu/Dockerfile @@ -1,4 +1,4 @@ -FROM ubuntu:25.04 +FROM ubuntu:26.04 RUN apt-get update && apt-get install -y --no-install-recommends \ ca-certificates \ diff --git a/ci/docker/powerpc64le-unknown-linux-musl/Dockerfile b/ci/docker/powerpc64le-unknown-linux-musl/Dockerfile index 10cd93981a18..574cdd90bbef 100644 --- a/ci/docker/powerpc64le-unknown-linux-musl/Dockerfile +++ b/ci/docker/powerpc64le-unknown-linux-musl/Dockerfile @@ -1,4 +1,4 @@ -FROM ubuntu:25.04 +FROM ubuntu:26.04 RUN apt-get update && apt-get install -y --no-install-recommends \ ca-certificates \ diff --git a/ci/docker/riscv64gc-unknown-linux-gnu/Dockerfile b/ci/docker/riscv64gc-unknown-linux-gnu/Dockerfile index 10395b72406b..798737e350eb 100644 --- a/ci/docker/riscv64gc-unknown-linux-gnu/Dockerfile +++ b/ci/docker/riscv64gc-unknown-linux-gnu/Dockerfile @@ -1,4 +1,4 @@ -FROM ubuntu:25.04 +FROM ubuntu:26.04 RUN apt-get update && apt-get install -y --no-install-recommends \ ca-certificates \ @@ -6,7 +6,7 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ gcc-riscv64-linux-gnu \ libc6-dev \ libc6-dev-riscv64-cross \ - qemu-system-riscv64 \ + qemu-system-riscv \ qemu-user ENV CARGO_TARGET_RISCV64GC_UNKNOWN_LINUX_GNU_LINKER=riscv64-linux-gnu-gcc \ diff --git a/ci/docker/s390x-unknown-linux-gnu/Dockerfile b/ci/docker/s390x-unknown-linux-gnu/Dockerfile index bda125a83186..a44b7e9f6bc1 100644 --- a/ci/docker/s390x-unknown-linux-gnu/Dockerfile +++ b/ci/docker/s390x-unknown-linux-gnu/Dockerfile @@ -1,4 +1,4 @@ -FROM ubuntu:25.04 +FROM ubuntu:26.04 RUN apt-get update && apt-get install -y --no-install-recommends \ ca-certificates \ diff --git a/ci/docker/s390x-unknown-linux-musl/Dockerfile b/ci/docker/s390x-unknown-linux-musl/Dockerfile index 385f71e5b9dd..d8ede27faaa1 100644 --- a/ci/docker/s390x-unknown-linux-musl/Dockerfile +++ b/ci/docker/s390x-unknown-linux-musl/Dockerfile @@ -1,4 +1,4 @@ -FROM ubuntu:25.04 +FROM ubuntu:26.04 RUN apt-get update && apt-get install -y --no-install-recommends \ curl \ diff --git a/ci/docker/sparc64-unknown-linux-gnu/Dockerfile b/ci/docker/sparc64-unknown-linux-gnu/Dockerfile index 728586f11954..4bd1a3cc8bd3 100644 --- a/ci/docker/sparc64-unknown-linux-gnu/Dockerfile +++ b/ci/docker/sparc64-unknown-linux-gnu/Dockerfile @@ -1,4 +1,4 @@ -FROM ubuntu:25.04 +FROM ubuntu:26.04 RUN apt-get update && apt-get install -y --no-install-recommends \ ca-certificates \ @@ -6,7 +6,7 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ gcc-sparc64-linux-gnu \ libc6-dev \ libc6-dev-sparc64-cross \ - qemu-system-sparc64 \ + qemu-system-sparc \ qemu-user ENV CARGO_TARGET_SPARC64_UNKNOWN_LINUX_GNU_LINKER=sparc64-linux-gnu-gcc \ diff --git a/ci/docker/wasm32-unknown-emscripten/Dockerfile b/ci/docker/wasm32-unknown-emscripten/Dockerfile index e068ad59f94c..8999ca2d52e9 100644 --- a/ci/docker/wasm32-unknown-emscripten/Dockerfile +++ b/ci/docker/wasm32-unknown-emscripten/Dockerfile @@ -1,4 +1,4 @@ -FROM ubuntu:25.04 +FROM ubuntu:26.04 # This is a workaround to avoid the interaction with tzdata. ENV DEBIAN_FRONTEND=noninteractive @@ -15,7 +15,6 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ gdb \ git \ libc6-dev \ - libxml2 \ make \ python3 \ tzdata \ diff --git a/ci/docker/wasm32-wasip1/Dockerfile b/ci/docker/wasm32-wasip1/Dockerfile index 4da0e17554f8..26ec34ce5917 100644 --- a/ci/docker/wasm32-wasip1/Dockerfile +++ b/ci/docker/wasm32-wasip1/Dockerfile @@ -1,4 +1,4 @@ -FROM ubuntu:25.04 +FROM ubuntu:26.04 COPY wasi.sh / RUN /wasi.sh diff --git a/ci/docker/wasm32-wasip2/Dockerfile b/ci/docker/wasm32-wasip2/Dockerfile index a240928fa1ae..6db3d139f0cc 100644 --- a/ci/docker/wasm32-wasip2/Dockerfile +++ b/ci/docker/wasm32-wasip2/Dockerfile @@ -1,4 +1,4 @@ -FROM ubuntu:25.04 +FROM ubuntu:26.04 COPY wasi.sh / RUN /wasi.sh diff --git a/ci/docker/x86_64-linux-android/Dockerfile b/ci/docker/x86_64-linux-android/Dockerfile index 76b80a894b2b..bc9580e6e1c0 100644 --- a/ci/docker/x86_64-linux-android/Dockerfile +++ b/ci/docker/x86_64-linux-android/Dockerfile @@ -1,4 +1,4 @@ -FROM ubuntu:25.04 +FROM ubuntu:26.04 RUN apt-get update && apt-get install -y --no-install-recommends \ ca-certificates \ diff --git a/ci/docker/x86_64-unknown-linux-gnu/Dockerfile b/ci/docker/x86_64-unknown-linux-gnu/Dockerfile index ed9734ca2b6f..5b5c86ffad8d 100644 --- a/ci/docker/x86_64-unknown-linux-gnu/Dockerfile +++ b/ci/docker/x86_64-unknown-linux-gnu/Dockerfile @@ -1,4 +1,4 @@ -FROM ubuntu:25.04 +FROM ubuntu:26.04 RUN apt-get update && apt-get install -y --no-install-recommends \ ca-certificates \ diff --git a/ci/docker/x86_64-unknown-linux-gnux32/Dockerfile b/ci/docker/x86_64-unknown-linux-gnux32/Dockerfile index 0d5cdd7daafb..88a9ccfa0296 100644 --- a/ci/docker/x86_64-unknown-linux-gnux32/Dockerfile +++ b/ci/docker/x86_64-unknown-linux-gnux32/Dockerfile @@ -1,4 +1,4 @@ -FROM ubuntu:25.04 +FROM ubuntu:26.04 RUN apt-get update && apt-get install -y --no-install-recommends \ ca-certificates \ diff --git a/ci/docker/x86_64-unknown-linux-musl/Dockerfile b/ci/docker/x86_64-unknown-linux-musl/Dockerfile index ec993efd8e65..efc193cefaa1 100644 --- a/ci/docker/x86_64-unknown-linux-musl/Dockerfile +++ b/ci/docker/x86_64-unknown-linux-musl/Dockerfile @@ -1,4 +1,4 @@ -FROM ubuntu:25.04 +FROM ubuntu:26.04 RUN apt-get update && apt-get install -y --no-install-recommends \ ca-certificates \ From f187bd15d9b0c9b11600a3d333b6cc434b16f7df Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Tue, 23 Jun 2026 03:42:39 -0400 Subject: [PATCH 4/9] linux: Update the value of `SW_MAX` and `SW_CNT` Source: https://github.com/torvalds/linux/commit/67890d579402804b1d32b3280d9860073542528e --- libc-test/build.rs | 3 +++ src/unix/linux_like/linux/mod.rs | 13 +------------ 2 files changed, 4 insertions(+), 12 deletions(-) diff --git a/libc-test/build.rs b/libc-test/build.rs index a544eaf1f24f..df44391997d6 100644 --- a/libc-test/build.rs +++ b/libc-test/build.rs @@ -4804,6 +4804,9 @@ fn test_linux(target: &str) { "AT_HWCAP3" | "AT_HWCAP4" => kernel < (6, 9), "PTRACE_SET_SYSCALL_INFO" => kernel < (6, 16), + // Changed value recently + "SW_MAX" | "SW_CNT" => kernel < (6, 16), + // Added in kernel versions 6.12..6.14 but we can't include `linux/fcntl.h` // (conflicts), so these need to wait on glibc's redefinition in 2.44-2.43. "AT_HANDLE_CONNECTABLE" | "AT_HANDLE_MNT_ID_UNIQUE" | "AT_EXECVE_CHECK" => { diff --git a/src/unix/linux_like/linux/mod.rs b/src/unix/linux_like/linux/mod.rs index ecba148ad9af..acddec247d71 100644 --- a/src/unix/linux_like/linux/mod.rs +++ b/src/unix/linux_like/linux/mod.rs @@ -3059,7 +3059,6 @@ pub const NFT_NG_RANDOM: c_int = 1; /// This symbol is prone to change across releases upstream. /// See the [usage guidelines](crate#usage-guidelines) for details. pub const FF_MAX: __u16 = 0x7f; - pub const FF_CNT: usize = FF_MAX as usize + 1; // linux/input-event-codes.h @@ -3080,61 +3079,51 @@ pub const INPUT_PROP_CNT: usize = INPUT_PROP_MAX as usize + 1; /// This symbol is prone to change across releases upstream. /// See the [usage guidelines](crate#usage-guidelines) for details. pub const EV_MAX: __u16 = 0x1f; - pub const EV_CNT: usize = EV_MAX as usize + 1; /// This symbol is prone to change across releases upstream. /// See the [usage guidelines](crate#usage-guidelines) for details. pub const SYN_MAX: __u16 = 0xf; - pub const SYN_CNT: usize = SYN_MAX as usize + 1; /// This symbol is prone to change across releases upstream. /// See the [usage guidelines](crate#usage-guidelines) for details. pub const KEY_MAX: __u16 = 0x2ff; - pub const KEY_CNT: usize = KEY_MAX as usize + 1; /// This symbol is prone to change across releases upstream. /// See the [usage guidelines](crate#usage-guidelines) for details. pub const REL_MAX: __u16 = 0x0f; - pub const REL_CNT: usize = REL_MAX as usize + 1; /// This symbol is prone to change across releases upstream. /// See the [usage guidelines](crate#usage-guidelines) for details. pub const ABS_MAX: __u16 = 0x3f; - pub const ABS_CNT: usize = ABS_MAX as usize + 1; /// This symbol is prone to change across releases upstream. /// See the [usage guidelines](crate#usage-guidelines) for details. -pub const SW_MAX: __u16 = 0x10; - +pub const SW_MAX: __u16 = 0x11; pub const SW_CNT: usize = SW_MAX as usize + 1; /// This symbol is prone to change across releases upstream. /// See the [usage guidelines](crate#usage-guidelines) for details. pub const MSC_MAX: __u16 = 0x07; - pub const MSC_CNT: usize = MSC_MAX as usize + 1; /// This symbol is prone to change across releases upstream. /// See the [usage guidelines](crate#usage-guidelines) for details. pub const LED_MAX: __u16 = 0x0f; - pub const LED_CNT: usize = LED_MAX as usize + 1; /// This symbol is prone to change across releases upstream. /// See the [usage guidelines](crate#usage-guidelines) for details. pub const REP_MAX: __u16 = 0x01; - pub const REP_CNT: usize = REP_MAX as usize + 1; /// This symbol is prone to change across releases upstream. /// See the [usage guidelines](crate#usage-guidelines) for details. pub const SND_MAX: __u16 = 0x07; - pub const SND_CNT: usize = SND_MAX as usize + 1; // linux/uinput.h From 40eeb97952f6c25c0050af4aff90d39822e378d1 Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Tue, 23 Jun 2026 03:49:21 -0400 Subject: [PATCH 5/9] glibc: Update the value of `MS_NOUSER` Glibc 2.42 updated this definition to an unsigned integer so it no longer overflows. Source: https://sourceware.org/git/?p=glibc.git;a=commit;h=3263675250cbcbbcc76ede4f7c660418bd345a11 --- src/unix/linux_like/linux_l4re_shared.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/unix/linux_like/linux_l4re_shared.rs b/src/unix/linux_like/linux_l4re_shared.rs index 6ff42c4b765b..1c3f0eeb6d99 100644 --- a/src/unix/linux_like/linux_l4re_shared.rs +++ b/src/unix/linux_like/linux_l4re_shared.rs @@ -1438,8 +1438,8 @@ pub const NT_LWPSTATUS: c_int = 16; pub const NT_LWPSINFO: c_int = 17; pub const NT_PRFPXREG: c_int = 20; -#[allow(overflowing_literals)] // fixed in a future kernel version -pub const MS_NOUSER: c_ulong = 0xffffffff80000000; +// FIXME(1.0): C uses an unsigned int here. +pub const MS_NOUSER: c_ulong = 1 << 31; f! { pub fn CMSG_NXTHDR( From 11446206c301b9ed057037f02d26a482e380352f Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Tue, 23 Jun 2026 03:57:00 -0400 Subject: [PATCH 6/9] glibc: Add new fields to `struct tcp_info` Glibc 2.43 adds the additional fields from Linux 6.17 to `struct tcp_info`. Source: https://sourceware.org/git/?p=glibc.git;a=commit;h=7e46c2aae47d3284d4eb0845ddcc3951e987d681 --- libc-test/build.rs | 3 ++ src/unix/linux_like/linux/gnu/mod.rs | 50 ++++++++++++++++++++++++++++ 2 files changed, 53 insertions(+) diff --git a/libc-test/build.rs b/libc-test/build.rs index df44391997d6..068f35198950 100644 --- a/libc-test/build.rs +++ b/libc-test/build.rs @@ -4308,6 +4308,9 @@ fn test_linux(target: &str) { // Extern types "DIR" | "FILE" | "fpos_t" | "timezone" => true, + // Many more fields added in the glibc update to go with 6.17 + "tcp_info" if gnu && versions.glibc.unwrap() < (2, 43) => true, + _ => false, } }); diff --git a/src/unix/linux_like/linux/gnu/mod.rs b/src/unix/linux_like/linux/gnu/mod.rs index cf5d70e19909..eafd5476c195 100644 --- a/src/unix/linux_like/linux/gnu/mod.rs +++ b/src/unix/linux_like/linux/gnu/mod.rs @@ -233,19 +233,23 @@ s! { /// This contains the bitfields `tcpi_snd_wscale` and `tcpi_rcv_wscale`. /// Each is 4 bits. pub tcpi_snd_rcv_wscale: u8, + pub tcpi_rto: u32, pub tcpi_ato: u32, pub tcpi_snd_mss: u32, pub tcpi_rcv_mss: u32, + pub tcpi_unacked: u32, pub tcpi_sacked: u32, pub tcpi_lost: u32, pub tcpi_retrans: u32, pub tcpi_fackets: u32, + pub tcpi_last_data_sent: u32, pub tcpi_last_ack_sent: u32, pub tcpi_last_data_recv: u32, pub tcpi_last_ack_recv: u32, + pub tcpi_pmtu: u32, pub tcpi_rcv_ssthresh: u32, pub tcpi_rtt: u32, @@ -254,9 +258,55 @@ s! { pub tcpi_snd_cwnd: u32, pub tcpi_advmss: u32, pub tcpi_reordering: u32, + pub tcpi_rcv_rtt: u32, pub tcpi_rcv_space: u32, + pub tcpi_total_retrans: u32, + + pub tcpi_pacing_rate: u64, + pub tcpi_max_pacing_rate: u64, + pub tcpi_bytes_acked: u64, + pub tcpi_bytes_received: u64, + pub tcpi_segs_out: u32, + pub tcpi_segs_in: u32, + + pub tcpi_notsent_bytes: u32, + pub tcpi_min_rtt: u32, + pub tcpi_data_segs_in: u32, + pub tcpi_data_segs_out: u32, + + pub tcpi_delivery_rate: u64, + + pub tcpi_busy_time: u64, + pub tcpi_rwnd_limited: u64, + pub tcpi_sndbuf_limited: u64, + + pub tcpi_delivered: u32, + pub tcpi_delivered_ce: u32, + + pub tcpi_bytes_sent: u64, + pub tcpi_bytes_retrans: u64, + pub tcpi_dsack_dups: u32, + pub tcpi_reord_seen: u32, + + pub tcpi_rcv_ooopack: u32, + pub tcpi_snd_wnd: u32, + pub tcpi_rcv_wnd: u32, + + pub tcpi_rehash: u32, + pub tcpi_total_rto: u16, + pub tcpi_total_rto_recoveries: u16, + pub tcpi_total_rto_time: u32, + pub tcpi_received_ce: u32, + pub tcpi_delivered_e1_bytes: u32, + pub tcpi_delivered_e0_bytes: u32, + pub tcpi_delivered_ce_bytes: u32, + pub tcpi_received_e1_bytes: u32, + pub tcpi_received_e0_bytes: u32, + pub tcpi_received_ce_bytes: u32, + pub tcpi_accecn_fail_mode: u16, + pub tcpi_accecn_opt_seen: u16, } pub struct fanotify_event_info_pidfd { From e0aec8a5b80d136580cf4afda98cda1746789a2f Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Tue, 23 Jun 2026 04:17:46 -0400 Subject: [PATCH 7/9] musl: Add a patch for `basename` to the 1.1.x build In Ubuntu 26.04, the musl build hits: In file included from /checkout/target/aarch64-unknown-linux-musl/debug/build/libc-test-1eed7f417ef9e9ac/out/ctest_output.c:51: /musl-aarch64/include/string.h:97:7: error: conflicting types for 'basename'; have 'char *(void)' 97 | char *basename(); | ^~~~~~~~ In file included from /checkout/target/aarch64-unknown-linux-musl/debug/build/libc-test-1eed7f417ef9e9ac/out/ctest_output.c:19: /musl-aarch64/include/libgen.h:9:7: note: previous declaration of 'basename' with type 'char *(char *)' 9 | char *basename(char *); | ^~~~~~~~ cc1: note: unrecognized command-line option '-Wno-unknown-warning-option' may have been intended to silence earlier diagnostics I believe this may be due to a new error in recent versions of GCC, though I have not actually gone through the effort to verify this. In any case, musl received a patch in 1.2.5 that resolves the issue; apply it to our 1.1.x build to keep it working. Link: https://github.com/kraj/musl/commit/725e17ed6dff4d0cd22487bb64470881e86a92e7 --- .../aarch64-unknown-linux-musl/Dockerfile | 6 +- .../arm-unknown-linux-musleabihf/Dockerfile | 6 +- ci/docker/i686-unknown-linux-musl/Dockerfile | 5 +- .../loongarch64-unknown-linux-musl/Dockerfile | 6 +- .../powerpc64le-unknown-linux-musl/Dockerfile | 6 +- ci/docker/s390x-unknown-linux-musl/Dockerfile | 15 +++-- .../x86_64-unknown-linux-musl/Dockerfile | 4 +- ci/install-musl.sh | 11 +++- .../0001-remove-non-prototype-basename.patch | 59 +++++++++++++++++++ 9 files changed, 94 insertions(+), 24 deletions(-) create mode 100644 ci/musl-patches-1.1.x/0001-remove-non-prototype-basename.patch diff --git a/ci/docker/aarch64-unknown-linux-musl/Dockerfile b/ci/docker/aarch64-unknown-linux-musl/Dockerfile index 4173a97435e5..281dc66c86f1 100644 --- a/ci/docker/aarch64-unknown-linux-musl/Dockerfile +++ b/ci/docker/aarch64-unknown-linux-musl/Dockerfile @@ -9,13 +9,13 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ libc6-dev \ make \ patch \ - qemu-user \ rsync \ + qemu-user \ xz-utils ARG MUSL_VERSION -COPY install-musl.sh / -RUN /install-musl.sh aarch64 "$MUSL_VERSION" +COPY . /ci +RUN ci/install-musl.sh aarch64 "$MUSL_VERSION" # FIXME: shouldn't need the `-lgcc` here, shouldn't that be in std? ENV PATH=$PATH:/musl-aarch64/bin:/rust/bin \ diff --git a/ci/docker/arm-unknown-linux-musleabihf/Dockerfile b/ci/docker/arm-unknown-linux-musleabihf/Dockerfile index 5d3d0aed50a1..dbb4da647d26 100644 --- a/ci/docker/arm-unknown-linux-musleabihf/Dockerfile +++ b/ci/docker/arm-unknown-linux-musleabihf/Dockerfile @@ -12,13 +12,13 @@ RUN sed -i -E 's/(archive|security)\.ubuntu\.com/old-releases.ubuntu.com/g' \ libc6-dev \ make \ patch \ - qemu-user \ rsync \ + qemu-user \ xz-utils ARG MUSL_VERSION -COPY install-musl.sh / -RUN /install-musl.sh arm "$MUSL_VERSION" +COPY . /ci +RUN ci/install-musl.sh arm "$MUSL_VERSION" ENV PATH=$PATH:/musl-arm/bin:/rust/bin \ CC_arm_unknown_linux_musleabihf=musl-gcc \ diff --git a/ci/docker/i686-unknown-linux-musl/Dockerfile b/ci/docker/i686-unknown-linux-musl/Dockerfile index b1926457a150..f32d3155b85b 100644 --- a/ci/docker/i686-unknown-linux-musl/Dockerfile +++ b/ci/docker/i686-unknown-linux-musl/Dockerfile @@ -7,15 +7,14 @@ RUN dpkg --add-architecture i386 && \ gcc-multilib \ git \ libc6-dev \ - libc6-i386 \ make \ patch \ rsync \ xz-utils ARG MUSL_VERSION -COPY install-musl.sh / -RUN /install-musl.sh i686 "$MUSL_VERSION" +COPY . /ci +RUN ci/install-musl.sh i686 "$MUSL_VERSION" ENV PATH=$PATH:/musl-i686/bin:/rust/bin \ CC_i686_unknown_linux_musl=musl-gcc \ diff --git a/ci/docker/loongarch64-unknown-linux-musl/Dockerfile b/ci/docker/loongarch64-unknown-linux-musl/Dockerfile index 7944dd0c8d73..eb7e090643b0 100644 --- a/ci/docker/loongarch64-unknown-linux-musl/Dockerfile +++ b/ci/docker/loongarch64-unknown-linux-musl/Dockerfile @@ -9,13 +9,13 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ libc6-dev \ make \ patch \ - qemu-user \ rsync \ + qemu-user \ xz-utils ARG MUSL_VERSION -COPY install-musl.sh / -RUN /install-musl.sh loongarch64 "$MUSL_VERSION" +COPY . /ci +RUN ci/install-musl.sh loongarch64 "$MUSL_VERSION" ENV CC_loongarch64_unknown_linux_musl=musl-gcc \ CFLAGS_loongarch64_unknown_linux_musl="-mabi=lp64d -fPIC" \ diff --git a/ci/docker/powerpc64le-unknown-linux-musl/Dockerfile b/ci/docker/powerpc64le-unknown-linux-musl/Dockerfile index 574cdd90bbef..7f913d32ac17 100644 --- a/ci/docker/powerpc64le-unknown-linux-musl/Dockerfile +++ b/ci/docker/powerpc64le-unknown-linux-musl/Dockerfile @@ -9,13 +9,13 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ libc6-dev \ make \ patch \ - qemu-user \ rsync \ + qemu-user \ xz-utils ARG MUSL_VERSION -COPY install-musl.sh / -RUN /install-musl.sh powerpc64le "$MUSL_VERSION" +COPY . /ci +RUN ci/install-musl.sh powerpc64le "$MUSL_VERSION" # FIXME: shouldn't need the `-lgcc` here, shouldn't that be in std? ENV PATH=$PATH:/musl-powerpc64/bin:/rust/bin \ diff --git a/ci/docker/s390x-unknown-linux-musl/Dockerfile b/ci/docker/s390x-unknown-linux-musl/Dockerfile index d8ede27faaa1..b67b0f652578 100644 --- a/ci/docker/s390x-unknown-linux-musl/Dockerfile +++ b/ci/docker/s390x-unknown-linux-musl/Dockerfile @@ -1,18 +1,21 @@ FROM ubuntu:26.04 RUN apt-get update && apt-get install -y --no-install-recommends \ - curl \ ca-certificates \ + curl \ gcc \ gcc-s390x-linux-gnu \ - qemu-user \ - xz-utils \ + git \ + libc6-dev \ + make \ patch \ - rsync + rsync \ + qemu-user \ + xz-utils ARG MUSL_VERSION -COPY install-musl.sh / -RUN /install-musl.sh s390x "$MUSL_VERSION" +COPY . /ci +RUN ci/install-musl.sh s390x "$MUSL_VERSION" # FIXME: shouldn't need the `-lgcc` here, shouldn't that be in std? ENV CC_s390x_unknown_linux_gnu=musl-gcc \ diff --git a/ci/docker/x86_64-unknown-linux-musl/Dockerfile b/ci/docker/x86_64-unknown-linux-musl/Dockerfile index efc193cefaa1..78cfa532ee85 100644 --- a/ci/docker/x86_64-unknown-linux-musl/Dockerfile +++ b/ci/docker/x86_64-unknown-linux-musl/Dockerfile @@ -12,8 +12,8 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ xz-utils ARG MUSL_VERSION -COPY install-musl.sh / -RUN /install-musl.sh x86_64 "$MUSL_VERSION" +COPY . /ci +RUN ci/install-musl.sh x86_64 "$MUSL_VERSION" ENV PATH=$PATH:/musl-x86_64/bin:/rust/bin \ EXTRA_RUSTFLAGS="-L /musl-x86_64/lib" diff --git a/ci/install-musl.sh b/ci/install-musl.sh index a4e4dea71606..5eb416a3c148 100755 --- a/ci/install-musl.sh +++ b/ci/install-musl.sh @@ -30,8 +30,17 @@ musl="musl-${musl_version}" # first. See https://github.com/rust-lang/ci-mirrors/blob/main/files/libc.toml. curl --retry 5 "https://ci-mirrors.rust-lang.org/libc/${musl}.tar.gz" | tar xzf - -# Configure, build, and install musl: cd "$musl" + +# Apply patches +if [ "$musl_version" = "$old_musl" ]; then + patch_dir="$(realpath ../ci/musl-patches-1.1.x)" + for patchfile in "$patch_dir"/*; do + cat "$patchfile" | patch -p1 + done +fi + +# Configure, build, and install musl: case ${1} in aarch64) musl_arch=aarch64 diff --git a/ci/musl-patches-1.1.x/0001-remove-non-prototype-basename.patch b/ci/musl-patches-1.1.x/0001-remove-non-prototype-basename.patch new file mode 100644 index 000000000000..f913e593975f --- /dev/null +++ b/ci/musl-patches-1.1.x/0001-remove-non-prototype-basename.patch @@ -0,0 +1,59 @@ +From 725e17ed6dff4d0cd22487bb64470881e86a92e7 Mon Sep 17 00:00:00 2001 +From: Rich Felker +Date: Mon, 6 Nov 2023 08:26:19 -0500 +Subject: [PATCH] remove non-prototype declaration of basename from string.h + +commit 37bb3cce4598c19288628e675eaf1cda6e96958f suppressed the +declaration for C++, where it is wrongly interpreted as declaring the +function as taking no arguments. with C23 removing non-prototype +declarations, that problem is now also relevant to C. + +the non-prototype declaration for basename originates with commit +06aec8d7152dfb8360cb7ed9b3d7215ca0b0b500, where it was designed to +avoid conflicts with programs which declare basename with the GNU +signature taking const char *. that change was probably misguided, as +it represents not only misaligned expectations with the caller, but +also undefined behavior (calling a function that's been declared with +the wrong type). + +we could opt to fix the declaration, but since glibc, with the +gratuitously incompatible GNU-basename function, seems to be the only +implementation that declares it in string.h, it seems better to just +remove the declaration. this provides some warning if applications are +being built expecting the GNU behavior but not getting it. if we +declared it here, it would only produce a warning if the caller also +declares it themselves (rare) or if the caller attempts to pass a +const-qualified pointer. +--- + +rust-libc note: this patch is applied to musl 1.1.x builds because +without it, recent compilers emit errors like: + + In file included from /checkout/target/aarch64-unknown-linux-musl/debug/build/libc-test-1eed7f417ef9e9ac/out/ctest_output.c:51: + /musl-aarch64/include/string.h:97:7: error: conflicting types for 'basename'; have 'char *(void)' + 97 | char *basename(); + | ^~~~~~~~ + In file included from /checkout/target/aarch64-unknown-linux-musl/debug/build/libc-test-1eed7f417ef9e9ac/out/ctest_output.c:19: + /musl-aarch64/include/libgen.h:9:7: note: previous declaration of 'basename' with type 'char *(char *)' + 9 | char *basename(char *); + | ^~~~~~~~ + cc1: note: unrecognized command-line option '-Wno-unknown-warning-option' may have been intended to silence earlier diagnostics + + + include/string.h | 3 --- + 1 file changed, 3 deletions(-) + +diff --git a/include/string.h b/include/string.h +index db73d2a92..83e2b9464 100644 +--- a/include/string.h ++++ b/include/string.h +@@ -95,9 +95,6 @@ char *strchrnul(const char *, int); + char *strcasestr(const char *, const char *); + void *memrchr(const void *, int, size_t); + void *mempcpy(void *, const void *, size_t); +-#ifndef __cplusplus +-char *basename(); +-#endif + #endif + + #ifdef __cplusplus From e9220612968f84da9cb78b13c3aebf1cf28379b4 Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Wed, 24 Jun 2026 06:52:18 -0400 Subject: [PATCH 8/9] ppc64le-linux-gnu: Skip testing `*printf` functions Ubuntu 26.04 transitioned PowerPC64LE from the IBM long double format to IEEE binary128 [1], which mean a handful of variadic functions needed to switch to a binary128-compatible version. These were available starting with glibc 2.32 (2020-08) per the abilist [2], which is quite a bit newer than what we say we support at [3] (2.17, 2012-12). This explains test failures, so skip checking the functions per now. We should migrate to the `__ieee128` functions at some point, which need not be related to our documented minimum, but there is no reason to do it now since Rust doesn't even stably support either IBM `long double` or binary128. Demo on Ubuntu 24.04: $ cat demo.c #include #include void demo() { char buf1[20] = { 0 }; char buf2[20] = { 0 }; printf("Hello, world! %d\n", 1); fprintf(stderr, "Hello, world! %d\n", 2); sprintf(buf1, "Hello, world! %d\n", 3); snprintf(buf2, 20, "Hello, world! %d\n", 4); syslog(0, "Hello, world! %d\n", 5); } $ powerpc64le-linux-gnu-gcc demo.c -c $ powerpc64le-linux-gnu-nm demo.o U .TOC. U __stack_chk_fail 0000000000000000 T demo U fprintf U printf U snprintf U sprintf U stderr U syslog And the same demo on Ubuntu 26.04: $ cat demo.c #include #include void demo() { char buf1[20] = { 0 }; char buf2[20] = { 0 }; printf("Hello, world! %d\n", 1); fprintf(stderr, "Hello, world! %d\n", 2); sprintf(buf1, "Hello, world! %d\n", 3); snprintf(buf2, 20, "Hello, world! %d\n", 4); syslog(0, "Hello, world! %d\n", 5); } $ powerpc64le-linux-gnu-gcc demo.c -c $ powerpc64le-linux-gnu-nm demo.o U .TOC. U __fprintfieee128 U __printfieee128 U __snprintfieee128 U __sprintfieee128 U __stack_chk_fail U __syslogieee128 0000000000000000 T demo U stderr [1]: https://bugs.launchpad.net/ubuntu/+bug/2132257 [2]: https://sourceware.org/git/?p=glibc.git;a=blob;f=sysdeps/unix/sysv/linux/powerpc/powerpc64/le/libc.abilist;h=65d78e50760b5d6b1a9cb39016a7bf8064224794;hb=HEAD#l2519 [3]: https://doc.rust-lang.org/1.96.0/rustc/platform-support.html --- libc-test/build.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/libc-test/build.rs b/libc-test/build.rs index 068f35198950..d72b69a53e7d 100644 --- a/libc-test/build.rs +++ b/libc-test/build.rs @@ -3805,6 +3805,8 @@ fn test_linux(target: &str) { let i686 = target.contains("i686"); let ppc = target.contains("powerpc"); let ppc64 = target.contains("powerpc64"); + let ppc64le = target.contains("powerpc64le"); + let _ppc64be = target.contains("powerpc64-"); let ppc32 = ppc && !ppc64; let s390x = target.contains("s390x"); let sparc = target.contains("sparc"); @@ -4950,6 +4952,10 @@ fn test_linux(target: &str) { // FIXME(linux): function pointers changed since Ubuntu 23.10 "strtol" | "strtoll" | "strtoul" | "strtoull" | "fscanf" | "scanf" | "sscanf" => true, + // FIXME(ppc): function pointers changed in Ubuntu 26.04 to support IEEE binary128 + // `long double`. We should update at some point but there is no hurry. + "printf" | "fprintf" | "sprintf" | "snprintf" | "syslog" if gnu && ppc64le => true, + _ => false, } }); From cf32fda960a71bfedc517dc217739161fcba8b15 Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Wed, 24 Jun 2026 17:07:15 -0400 Subject: [PATCH 9/9] ci: Bump musl 1.2.5->1.2.6 and Alpine headers 3.20->3.24 (kernel 6.6->7.0) --- ci/install-musl.sh | 12 +++++++----- libc-test/build.rs | 3 +++ 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/ci/install-musl.sh b/ci/install-musl.sh index 5eb416a3c148..f4f765e2bfbe 100755 --- a/ci/install-musl.sh +++ b/ci/install-musl.sh @@ -8,7 +8,7 @@ set -eux arch="$1" version="$2" old_musl=1.1.24 -new_musl=1.2.5 +new_musl=1.2.6 case "$arch" in loongarch64) musl_version="$new_musl" ;; @@ -108,18 +108,20 @@ rm -rf "$musl" # Download, configure, build, and install musl-sanitized kernel headers. -# Alpine follows stable kernel releases, 3.20 uses Linux 6.6 headers. -alpine_version=3.20 +# Alpine follows stable kernel releases, 3.24 uses Linux 7.0 headers. +alpine_version=3.24 alpine_git=https://git.alpinelinux.org/aports -# This routine piggybacks on: https://git.alpinelinux.org/aports/tree/main/linux-headers?h=3.20-stable +# This routine piggybacks on: https://git.alpinelinux.org/aports/tree/main/linux-headers?h=3.24-stable git clone -n --depth=1 --filter=tree:0 -b "${alpine_version}-stable" "$alpine_git" ( cd aports git sparse-checkout set --no-cone main/linux-headers git checkout - cd main/linux-headers + + # Create a version of APKBUILD that dumps the variables we're interested + # in. This file doesn't retrieve or build anything on its own. cp APKBUILD APKBUILD.vars cat <<- EOF >> APKBUILD.vars echo "\$source" > alpine-source diff --git a/libc-test/build.rs b/libc-test/build.rs index d72b69a53e7d..82702f3484c1 100644 --- a/libc-test/build.rs +++ b/libc-test/build.rs @@ -4274,6 +4274,7 @@ fn test_linux(target: &str) { // Recent additions "ptp_sys_offset_extended" if kernel < (6, 12) => true, + "epoll_params" if old_musl => true, "epoll_params" => kernel < (6, 9), "mnt_ns_info" => kernel < (6, 12), @@ -4789,6 +4790,7 @@ fn test_linux(target: &str) { | "PF_RANDOMIZE" | "PF_NO_SETAFFINITY" | "PF_MCE_EARLY" | "PF_MEMALLOC_PIN" | "PF_BLOCK_TS" | "PF_SUSPEND_TASK" => true, + "EPIOCSPARAMS" | "EPIOCGPARAMS" if old_musl => true, "EPIOCSPARAMS" | "EPIOCGPARAMS" => kernel < (6, 9), "MAP_DROPPABLE" => kernel < (6, 11), "SOF_TIMESTAMPING_OPT_RX_FILTER" => kernel < (6, 12), @@ -4806,6 +4808,7 @@ fn test_linux(target: &str) { "SECURE_ALL_BITS" | "SECURE_ALL_LOCKS" => kernel < (6, 14), // Recent additions + "AT_HWCAP3" | "AT_HWCAP4" if old_musl => true, "AT_HWCAP3" | "AT_HWCAP4" => kernel < (6, 9), "PTRACE_SET_SYSCALL_INFO" => kernel < (6, 16),