diff --git a/ci/buildroot_defconfigs/armv7_unknown_linux_uclibceabihf.config b/ci/buildroot_defconfigs/armv7_unknown_linux_uclibceabihf.config new file mode 100644 index 0000000000000..3fa61c503b323 --- /dev/null +++ b/ci/buildroot_defconfigs/armv7_unknown_linux_uclibceabihf.config @@ -0,0 +1,13 @@ +BR2_arm=y +BR2_cortex_a9=y +BR2_ARM_ENABLE_VFP=y +BR2_TOOLCHAIN_BUILDROOT_UCLIBC=y +BR2_TOOLCHAIN_BUILDROOT_LOCALE=y +BR2_PTHREAD_DEBUG=y +BR2_BINUTILS_VERSION_2_44_X=y +BR2_GCC_VERSION_15_X=y +BR2_INIT_NONE=y +BR2_SYSTEM_BIN_SH_NONE=y +# BR2_PACKAGE_BUSYBOX is not set +BR2_PACKAGE_READLINE=y +# BR2_TARGET_ROOTFS_TAR is not set diff --git a/ci/docker/armv7-unknown-linux-uclibceabihf/Dockerfile b/ci/docker/armv7-unknown-linux-uclibceabihf/Dockerfile index a5e685318ad0a..867f206deb657 100644 --- a/ci/docker/armv7-unknown-linux-uclibceabihf/Dockerfile +++ b/ci/docker/armv7-unknown-linux-uclibceabihf/Dockerfile @@ -1,9 +1,6 @@ -FROM ubuntu:23.10 +FROM ubuntu:25.04 -# FIXME(time): we are using an EOL release because 24.04 changes to 64-bit time -RUN sed -i -E 's/(archive|security)\.ubuntu\.com/old-releases.ubuntu.com/g' \ - /etc/apt/sources.list && \ - apt-get update && apt-get install -y --no-install-recommends \ +RUN apt-get update && apt-get install -y --no-install-recommends \ ca-certificates \ curl \ file \ @@ -12,14 +9,25 @@ RUN sed -i -E 's/(archive|security)\.ubuntu\.com/old-releases.ubuntu.com/g' \ patch \ qemu-system-arm \ qemu-user \ + bzip2 \ + gzip \ + make \ + wget \ + cpio \ + unzip \ + rsync \ + bc \ + g++ \ + perl \ xz-utils ARG TEST_UCLIBC_TIME64 COPY install-uclibc.sh / -RUN /install-uclibc.sh "$TEST_UCLIBC_TIME64" +COPY buildroot_defconfigs/armv7_unknown_linux_uclibceabihf.config / +RUN /install-uclibc.sh /armv7_unknown_linux_uclibceabihf.config "$TEST_UCLIBC_TIME64" -ENV PATH=$PATH:/rust/bin:/toolchain/bin \ - STAGING_DIR=/toolchain/armv7-buildroot-linux-uclibceabihf/sysroot \ +ENV PATH=$PATH:/rust/bin:/buildroot/output/host/bin \ + STAGING_DIR=/buildroot/output/host/armv7-buildroot-linux-uclibceabihf/sysroot \ CC_armv7_unknown_linux_uclibceabihf=arm-buildroot-linux-uclibcgnueabihf-gcc \ CARGO_TARGET_ARMV7_UNKNOWN_LINUX_UCLIBCEABIHF_LINKER=arm-buildroot-linux-uclibcgnueabihf-gcc \ - CARGO_TARGET_ARMV7_UNKNOWN_LINUX_UCLIBCEABIHF_RUNNER="qemu-arm -L /toolchain/arm-buildroot-linux-uclibcgnueabihf/sysroot/" + CARGO_TARGET_ARMV7_UNKNOWN_LINUX_UCLIBCEABIHF_RUNNER="qemu-arm -L /buildroot/output/host/arm-buildroot-linux-uclibcgnueabihf/sysroot/" diff --git a/ci/install-uclibc.sh b/ci/install-uclibc.sh index 131f78f2065d0..c0ea105b8505d 100755 --- a/ci/install-uclibc.sh +++ b/ci/install-uclibc.sh @@ -1,20 +1,19 @@ #!/bin/bash # -# Installs the appropriate uclibc toolchain into /toolchain +# Builds a buildroot uclibc toolchain into /buildroot/output/host/ +# +# usage: install-uclibc.sh BUILDROOT_DEFCONFIG USE_TIME64 set -eux -time64="$1" - -if [ "${time64:-0}" != "0" ]; then - version='bleeding-edge-2025.08-1' -else - version='bleeding-edge-2024.02-1' # last version with 32-bit time_t -fi - -mkdir /toolchain +defconfig="$1" +# shellcheck disable=SC2034 +time64="$2" # TODO: honor this flag, adjusting UCLIBC_USE_TIME64 in config -curl --retry 5 -L "https://toolchains.bootlin.com/downloads/releases/toolchains/armv7-eabihf/tarballs/armv7-eabihf--uclibc--${version}.tar.bz2" | -tar xjf - -C /toolchain --strip-components=1 +mkdir /buildroot +BR_URL=https://buildroot.org/downloads/buildroot-2026.05.tar.xz +curl --retry 5 -L "$BR_URL" | tar xJf - -C /buildroot --strip-components=1 -/toolchain/relocate-sdk.sh +cd /buildroot +make defconfig "BR2_DEFCONFIG=$defconfig" +make diff --git a/ci/run-docker.sh b/ci/run-docker.sh index 37d76f56bf91d..b4afdb65392eb 100755 --- a/ci/run-docker.sh +++ b/ci/run-docker.sh @@ -50,7 +50,7 @@ run() { if [ -n "${TEST_UCLIBC_TIME64:-}" ]; then build_args+=("--build-arg=TEST_UCLIBC_TIME64=1") - export RUSTFLAGS="$RUSTFLAGS --cfg=libc_unstable_uclibc_time64" + export RUSTFLAGS="${RUSTFLAGS:-} --cfg=libc_unstable_uclibc_time64" fi # use -f so we can use ci/ as build context diff --git a/ci/run.sh b/ci/run.sh index 88f5424a8f006..11748b315c4dd 100755 --- a/ci/run.sh +++ b/ci/run.sh @@ -38,6 +38,11 @@ case "$target" in powerpc64le*musl) cmd="$cmd --exclude ctest --exclude ctest-test --exclude ctest-next" ;; esac +if [ "${LIBC_CI_ZBUILD_STD:-}" ]; then + # ctest test infrastructure has no support for -Zbuild-std + cmd="$cmd --exclude ctest --exclude ctest-test" +fi + env="$(rustc --print cfg --target "$target" | sed -n 's/target_env="\(.*\)"/\1/p')" bits="$(rustc --print cfg --target "$target" | sed -n 's/target_pointer_width="\(.*\)"/\1/p')" diff --git a/ctest/Cargo.toml b/ctest/Cargo.toml index 88db9c33d7883..57eb02ec0e101 100644 --- a/ctest/Cargo.toml +++ b/ctest/Cargo.toml @@ -14,6 +14,7 @@ cc = "1.2.43" proc-macro2 = { version = "1.0.103", features = ["span-locations"] } quote = "1.0.41" syn = { version = "2.0.108", features = ["full", "visit", "extra-traits"] } +tempfile = "3.23.0" thiserror = "2.0.17" [lints] @@ -21,4 +22,3 @@ workspace = true [dev-dependencies] pretty_assertions = "1.4.1" -tempfile = "3.23.0" diff --git a/ctest/src/generator.rs b/ctest/src/generator.rs index a622b73fee7bb..5e7df3e0a93ad 100644 --- a/ctest/src/generator.rs +++ b/ctest/src/generator.rs @@ -13,6 +13,7 @@ use syn::visit::Visit; use thiserror::Error; use crate::ffi_items::FfiItems; +use crate::macro_expansion::expand_with_args; use crate::template::{ CTestTemplate, RustTestTemplate, @@ -32,7 +33,6 @@ use crate::{ Type, Union, VolatileItemKind, - expand, get_build_target, }; @@ -78,6 +78,10 @@ pub struct TestGenerator { cfg: Vec<(String, Option)>, /// A list of functions that remaps names used in the tests. mapped_names: Vec, + /// Extra command line args to pass to cargo when generating macro expansions. + macro_expansion_cargo_args: Vec, + /// Crate name to use when performing macro expansion. + crate_name: Option, /// The programming language to generate tests in. pub(crate) language: Language, /// A list of functions that determine what items to skip all tests for. @@ -723,6 +727,22 @@ impl TestGenerator { self } + /// Configures extra arguments to be passed to cargo during macro expansion. + /// This can be used, for example, to pass `-Zbuild-std`` if required. + pub fn macro_expansion_cargo_args_mut(&mut self) -> &mut Vec { + &mut self.macro_expansion_cargo_args + } + + /// Configures the crate name which should be used during macro expansion. + /// + /// If the tested crate uses `#![crate_name = "..."]`, this must be called with the + /// same name. Otherwise, there will be an error about `--crate-name` not + /// matching. + pub fn crate_name(&mut self, name: String) -> &mut Self { + self.crate_name = Some(name); + self + } + /// Configures whether tests for the type of a field is skipped or not. /// /// The closure is given a Rust struct as well as a field within that @@ -1087,7 +1107,14 @@ impl TestGenerator { crate_path: impl AsRef, output_file_path: impl AsRef, ) -> Result { - let expanded = expand(&crate_path, &self.cfg, get_build_target(self)?).map_err(|e| { + let expanded = expand_with_args( + &crate_path, + &self.cfg, + get_build_target(self)?, + self.crate_name.as_deref(), + &self.macro_expansion_cargo_args, + ) + .map_err(|e| { GenerationError::MacroExpansion(crate_path.as_ref().to_path_buf(), e.to_string()) })?; let ast = syn::parse_file(&expanded) diff --git a/ctest/src/macro_expansion.rs b/ctest/src/macro_expansion.rs index fc5ff1e4b3121..9a3dcc4889651 100644 --- a/ctest/src/macro_expansion.rs +++ b/ctest/src/macro_expansion.rs @@ -1,4 +1,3 @@ -use std::env; use std::fs::canonicalize; use std::path::Path; use std::process::Command; @@ -14,19 +13,63 @@ pub fn expand>( cfg: &[(String, Option)], target: String, ) -> Result { - let rustc = env::var("RUSTC").unwrap_or_else(|_| String::from("rustc")); + expand_with_args(crate_path, cfg, target, None, &[]) +} + +/// Extension of `expand` which allows a crate_name override for +/// libc and other clients which require crate_name to match the +/// original crate's name. +pub(crate) fn expand_with_args>( + crate_path: P, + cfg: &[(String, Option)], + target: String, + crate_name: Option<&str>, + extra_cargo_args: &[String], +) -> Result { + let dir = tempfile::tempdir()?; + + // make a Cargo.toml pointing to the crate path + let cargo_toml_path = dir.path().join("Cargo.toml"); + let crate_name = crate_name.unwrap_or("ctest-expansion-tmp"); + // FIXME(#5238): allow building using an existing manifest + let cargo_toml = format!( + r#" +[package] +name = '''{crate_name}''' # Needs to match #![crate_name = "..."] if it exists. +edition = '''{EDITION}''' +[lib] +path = '''{}''' +[lints.rust] +unexpected_cfgs = "allow" +"#, + canonicalize(crate_path)?.display() + ); + std::fs::write(cargo_toml_path, cargo_toml)?; - let mut cmd = Command::new(rustc); + let mut cmd = Command::new(std::env::var("CARGO").unwrap_or("cargo".into())); cmd.env("RUSTC_BOOTSTRAP", "1") - .arg("-Zunpretty=expanded") - .arg("--edition") - .arg(EDITION) // By default, -Zunpretty=expanded uses 2015 edition. - .arg(canonicalize(crate_path)?); + .current_dir(dir.path()) + .arg("rustc") + .arg("--lib") + .arg("--profile") + .arg("check") + .args(extra_cargo_args); + + // In order to avoid warnings causing failures here when the + // environment's RUSTFLAGS contains -Dwarnings (or similar), + // we will clear RUSTFLAGS. + cmd.env_remove("RUSTFLAGS"); + + // set an independent target dir so we don't deadlock on the cargo build lock. + cmd.arg("--target-dir").arg(dir.path().join("target")); if !target.is_empty() { cmd.arg("--target").arg(target); } + cmd.arg("--"); + cmd.arg("-Zunpretty=expanded"); + // `libc` uses non standard cfg flags as well, which have to be manually expanded. for (k, v) in cfg { match v { @@ -39,7 +82,11 @@ pub fn expand>( if !output.status.success() { let stderr = std::str::from_utf8(&output.stderr)?; - return Err(format!("macro expansion failed with {}: {}", output.status, stderr).into()); + return Err(format!( + "macro expansion failed with {}: {}, {:?}", + output.status, stderr, cmd + ) + .into()); } let expanded = std::str::from_utf8(&output.stdout)?.to_string(); diff --git a/libc-test/build.rs b/libc-test/build.rs index d909df071b079..b45bdc652e3f6 100644 --- a/libc-test/build.rs +++ b/libc-test/build.rs @@ -106,6 +106,11 @@ fn ctest_cfg() -> ctest::TestGenerator { // FIXME(1.0): These aliases will eventually be removed. cfg.skip_alias(|ty| ty.ident() == "__uint128"); + if env::var("LIBC_CI_ZBUILD_STD").is_ok() { + *cfg.macro_expansion_cargo_args_mut() = vec!["-Zbuild-std=core,std".into()]; + } + cfg.crate_name("libc".into()); + cfg } @@ -4627,123 +4632,6 @@ fn test_linux(target: &str) { if uclibc { match name { - // The canonical uClibc toolchain, bootlin bleeding-edge-2024.02-1, - // uses linux 5.15, so several constants are not available. - - // requires linux 5.16 - "PR_SCHED_CORE_SCOPE_PROCESS_GROUP" - | "PR_SCHED_CORE_SCOPE_THREAD_GROUP" - | "PR_SCHED_CORE_SCOPE_THREAD" - | "NF_NETDEV_EGRESS" - | "SO_RESERVE_MEM" => return true, - - // TLS_CIPHER_SM4_[GC]CM requires linux 5.16 - "TLS_CIPHER_SM4_CCM_IV_SIZE" - | "TLS_CIPHER_SM4_CCM_KEY_SIZE" - | "TLS_CIPHER_SM4_CCM_REC_SEQ_SIZE" - | "TLS_CIPHER_SM4_CCM_SALT_SIZE" - | "TLS_CIPHER_SM4_CCM_TAG_SIZE" - | "TLS_CIPHER_SM4_CCM" - | "TLS_CIPHER_SM4_GCM_IV_SIZE" - | "TLS_CIPHER_SM4_GCM_KEY_SIZE" - | "TLS_CIPHER_SM4_GCM_REC_SEQ_SIZE" - | "TLS_CIPHER_SM4_GCM_SALT_SIZE" - | "TLS_CIPHER_SM4_GCM_TAG_SIZE" - | "TLS_CIPHER_SM4_GCM" => return true, - - // requires linux 5.17 - "PR_SET_VMA_ANON_NAME" - | "PR_SET_VMA" - | "RTNLGRP_MCTP_IFADDR" => return true, - - // requires linux 5.18 - "RTNLGRP_STATS" - | "RTNLGRP_TUNNEL" - | "TLS_TX_ZEROCOPY_RO" - | "MADV_DONTNEED_LOCKED" - | "NFQA_PRIORITY" - | "SO_TXREHASH" => return true, - - // requires linux 5.19 - "SECCOMP_FILTER_FLAG_WAIT_KILLABLE_RECV" - | "NLM_F_BULK" - | "SO_RCVMARK" - | "TLS_INFO_ZC_RO_TX" => return true, - - // CAN_* consts requiring linux 6.0 - "CAN_BUS_OFF_THRESHOLD" - | "CAN_CTRLMODE_TDC_AUTO" - | "CAN_CTRLMODE_TDC_MANUAL" - | "CAN_ERR_CNT" - | "CAN_ERROR_PASSIVE_THRESHOLD" - | "CAN_ERROR_WARNING_THRESHOLD" => return true, - - // requires linux 6.0 - "IFF_NO_CARRIER" - | "TLS_INFO_RX_NO_PAD" - | "TLS_RX_EXPECT_NO_PAD" => return true, - - // CAN_* consts requiring linux 6.1 - "CAN_RAW_XL_FRAMES" - | "CANXL_HDR_SIZE" - | "CANXL_MAX_DLC_MASK" - | "CANXL_MAX_DLC" - | "CANXL_MAX_DLEN" - | "CANXL_MAX_MTU" - | "CANXL_MIN_DLC" - | "CANXL_MIN_DLEN" - | "CANXL_MIN_MTU" - | "CANXL_MTU" - | "CANXL_PRIO_BITS" - | "CANXL_PRIO_MASK" - | "CANXL_SEC" - | "CANXL_XLF" => return true, - - // TLS_CIPHER_ARIA_GCM_* requires linux 6.1 - "TLS_CIPHER_ARIA_GCM_128_IV_SIZE" - | "TLS_CIPHER_ARIA_GCM_128_KEY_SIZE" - | "TLS_CIPHER_ARIA_GCM_128_REC_SEQ_SIZE" - | "TLS_CIPHER_ARIA_GCM_128_SALT_SIZE" - | "TLS_CIPHER_ARIA_GCM_128_TAG_SIZE" - | "TLS_CIPHER_ARIA_GCM_128" - | "TLS_CIPHER_ARIA_GCM_256_IV_SIZE" - | "TLS_CIPHER_ARIA_GCM_256_KEY_SIZE" - | "TLS_CIPHER_ARIA_GCM_256_REC_SEQ_SIZE" - | "TLS_CIPHER_ARIA_GCM_256_SALT_SIZE" - | "TLS_CIPHER_ARIA_GCM_256_TAG_SIZE" - | "TLS_CIPHER_ARIA_GCM_256" => return true, - - // requires linux 6.2 - "ALG_SET_KEY_BY_KEY_SERIAL" - | "PACKET_FANOUT_FLAG_IGNORE_OUTGOING" - | "SOF_TIMESTAMPING_OPT_ID_TCP" - | "TUN_F_USO4" - | "TUN_F_USO6" => return true, - - // FAN_* consts require kernel 6.3 - "FAN_INFO" - | "FAN_RESPONSE_INFO_AUDIT_RULE" - | "FAN_RESPONSE_INFO_NONE" => return true, - - // requires linux 6.3 - "MFD_EXEC" - | "MFD_NOEXEC_SEAL" - | "PR_GET_MDWE" - | "PR_SET_MDWE" => return true, - - // requires linux 6.4 - "PACKET_VNET_HDR_SZ" => return true, - "PR_GET_MEMORY_MERGE" => return true, - "PR_SET_MEMORY_MERGE" => return true, - - // requires linux 6.5 - "SO_PASSPIDFD" - | "SO_PEERPIDFD" => return true, - - // requires linux 6.6 - "PR_MDWE_NO_INHERIT" - | "PR_MDWE_REFUSE_EXEC_GAIN" => return true, - // defined as a synonym for EM_ARC_COMPACT in gnu but not uclibc "EM_ARC_A5" => return true, diff --git a/src/unix/linux_like/l4re/uclibc/mod.rs b/src/unix/linux_like/l4re/uclibc/mod.rs index b3dba2c37766c..acdbd55bb8e37 100644 --- a/src/unix/linux_like/l4re/uclibc/mod.rs +++ b/src/unix/linux_like/l4re/uclibc/mod.rs @@ -525,6 +525,10 @@ extern "C" { } +extern_ty! { + pub type fpos64_t; // FIXME(linux): fill this out with a struct +} + cfg_if! { if #[cfg(target_arch = "x86_64")] { mod x86_64; diff --git a/src/unix/linux_like/linux/uclibc/arm/mod.rs b/src/unix/linux_like/linux/uclibc/arm/mod.rs index 9d255b7388fcd..f8870d3267294 100644 --- a/src/unix/linux_like/linux/uclibc/arm/mod.rs +++ b/src/unix/linux_like/linux/uclibc/arm/mod.rs @@ -227,10 +227,13 @@ s! { pub shm_perm: crate::ipc_perm, pub shm_segsz: size_t, pub shm_atime: crate::time_t, + #[cfg(not(linux_time_bits64))] __unused1: Padding, pub shm_dtime: crate::time_t, + #[cfg(not(linux_time_bits64))] __unused2: Padding, pub shm_ctime: crate::time_t, + #[cfg(not(linux_time_bits64))] __unused3: Padding, pub shm_cpid: crate::pid_t, pub shm_lpid: crate::pid_t, diff --git a/src/unix/linux_like/linux/uclibc/mod.rs b/src/unix/linux_like/linux/uclibc/mod.rs index 6c3d8013f9173..8f67530187d97 100644 --- a/src/unix/linux_like/linux/uclibc/mod.rs +++ b/src/unix/linux_like/linux/uclibc/mod.rs @@ -133,6 +133,17 @@ s! { pub tcpi_rcv_space: u32, pub tcpi_total_retrans: u32, } + + pub struct mbstate_t { + __mask: crate::wchar_t, + __wc: crate::wchar_t, + } + + pub struct fpos64_t { + __pos: off64_t, + __mbstate: crate::mbstate_t, + __mblen_pending: c_int, + } } impl siginfo_t { diff --git a/src/unix/linux_like/linux_l4re_shared.rs b/src/unix/linux_like/linux_l4re_shared.rs index 1c3f0eeb6d99a..fd98192938b29 100644 --- a/src/unix/linux_like/linux_l4re_shared.rs +++ b/src/unix/linux_like/linux_l4re_shared.rs @@ -33,7 +33,7 @@ cfg_if! { pub type iconv_t = *mut c_void; cfg_if! { - if #[cfg(not(target_env = "gnu"))] { + if #[cfg(not(any(target_env = "gnu", target_env = "uclibc")))] { extern_ty! { pub type fpos64_t; // FIXME(linux): fill this out with a struct }