-
Notifications
You must be signed in to change notification settings - Fork 1.2k
uclibc: fix build + CI, add unstable time64 support for newer uclibc toolchains #5046
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,20 @@ | ||
| #!/usr/bin/bash | ||
| # | ||
| # Installs the appropriate uclibc toolchain into /toolchain | ||
|
|
||
| set -eux | ||
|
|
||
| time64="$1" | ||
|
|
||
| if [ "${time64:-0}" != "0" ]; then | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I added this script to use a toolchain with or without 64-bit |
||
| version='bleeding-edge-2025.08-1' | ||
| else | ||
| version='bleeding-edge-2024.05-1' # last version with 32-bit time_t | ||
| fi | ||
|
Comment on lines
+11
to
+13
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Does this more or less mean that you're stuck on an old uclibc version if you want to use time APIs? There aren't the duplicate symbols and header config like glibc has? If so, I think we could flip the default at some point in the near future. Technically breaking but we can get away with it on T3 targets, and musl and glibc aren't quite as stuck.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ah, no - let me explain. uClibc is intended for use on embedded devices where space (and thus code size) is at a premium. A developer would typically build their own uclibc with only the features required for their use case. uclibc facilitates this customization by having a configuration step (via a menuconfig, like the kernel menuconfig system, if you've ever used that) where the developer chooses the features they like, including whether to use a 32-bit or 64-bit So we cannot say for sure within the The bootlin folks have chosen to enable the 64-bit This is why I expect everyone using uclibc with rust ends up either using |
||
|
|
||
| mkdir /toolchain | ||
|
|
||
| curl --retry 5 -L "https://toolchains.bootlin.com/downloads/releases/toolchains/armv7-eabihf/tarballs/armv7-eabihf--uclibc--${version}.tar.xz" | \ | ||
| tar xjf - -C /toolchain --strip-components=1 | ||
|
Comment on lines
+17
to
+18
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No need to change this of course but fyi,
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ah, TIL! |
||
|
|
||
| /toolchain/relocate-sdk.sh | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -3736,6 +3736,12 @@ fn test_linux(target: &str) { | |
| cfg.cfg("musl_redir_time64", None); | ||
| } | ||
| } | ||
| let uclibc_use_time64 = env::var("CARGO_CFG_LIBC_UNSTABLE_UCLIBC_TIME64") | ||
| .map(|val| val != "0") | ||
| .unwrap_or(false); | ||
| if uclibc && uclibc_use_time64 { | ||
| cfg.cfg("linux_time_bits64", None); | ||
| } | ||
| cfg.define("_GNU_SOURCE", None) | ||
| // This macro re-defines fscanf,scanf,sscanf to link to the symbols that are | ||
| // deprecated since glibc >= 2.29. This allows Rust binaries to link against | ||
|
|
@@ -3939,9 +3945,14 @@ fn test_linux(target: &str) { | |
| "linux/wait.h", | ||
| "linux/wireless.h", | ||
| "sys/fanotify.h", | ||
| // <sys/auxv.h> is not present on uclibc | ||
| (!uclibc, "sys/auxv.h"), | ||
| "sys/auxv.h", | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. uclibc has this header, at least in the toolchain versions in the CI. |
||
| (gnu || musl, "linux/close_range.h"), | ||
| (uclibc, "linux/fanotify.h"), | ||
| (uclibc, "linux/auxvec.h"), | ||
| (uclibc, "linux/close_range.h"), | ||
| (uclibc, "linux/if_packet.h"), | ||
| (uclibc, "linux/elf-em.h"), | ||
| (uclibc, "sys/resource.h"), | ||
| ); | ||
| } | ||
|
|
||
|
|
@@ -4177,6 +4188,18 @@ fn test_linux(target: &str) { | |
| // On 64 bits the size did not change, skip only for 32 bits. | ||
| "ptrace_syscall_info" if pointer_width == 32 => true, | ||
|
|
||
| "canxl_frame" | ||
| | "fanotify_event_info_header" // not in sys/fanotify.h in uclibc | ||
| | "fanotify_event_info_fid" // not in sys/fanotify.h in uclibc | ||
| | "tls12_crypto_info_sm4_gcm" | ||
| | "tls12_crypto_info_sm4_ccm" | ||
| | "tls12_crypto_info_aria_gcm_128" | ||
| | "tls12_crypto_info_aria_gcm_256" | ||
| if uclibc => | ||
| { | ||
| true | ||
| } | ||
|
|
||
| _ => false, | ||
| } | ||
| }); | ||
|
|
@@ -4302,6 +4325,170 @@ 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, | ||
|
|
||
| // 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, | ||
|
|
||
| /* | ||
| Here are a list of kernel UAPI constants which appear in linux/ headers, | ||
| but cannot be imported due to conflicts with the uclibc headers. | ||
| The conflicting linux/ header is noted. | ||
| */ | ||
|
Comment on lines
+4448
to
+4452
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What is the expected flow for these when you're writing C if there are conflicts?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. My view on it is that these constants are passed through the underlying target_env and to the kernel, rather than invoking specific behavior within the target_env c std lib. For constants where this is true, it means that they're safe and appropriate to use regardless of whether the c std lib re-exports them or not. The case where they could lead to unintentional bad behavior is when the c std lib needed to change behavior based on the constant. I am not individually researching and testing each of these, so it's possible that there's a bug here, but I would like to consider those issues as outside the scope of this PR. (This is just moving around these constants and fixing the build.) To answer your question, if I were writing a piece of C code and needed one of these constants, I would probably find a way to untangle the header mess or just copy the There are also of other examples in |
||
| // linux/signal.h | ||
| "BUS_MCEERR_AO" | ||
| | "BUS_MCEERR_AR" | ||
| // linux/termios.h | ||
| | "EXTPROC" | ||
| // linux/inotify.h | ||
| | "IN_MASK_CREATE" | ||
| // linux/in.h | ||
| | "IPPROTO_BEETPH" | ||
| | "IPPROTO_ETHERNET" | ||
| | "IPPROTO_MPLS" | ||
| | "IPPROTO_MPTCP" | ||
| // linux/in6.h | ||
| | "IPV6_HDRINCL" | ||
| | "IPV6_MULTICAST_ALL" | ||
| | "IPV6_PMTUDISC_INTERFACE" | ||
| | "IPV6_PMTUDISC_OMIT" | ||
| | "IPV6_ROUTER_ALERT_ISOLATE" | ||
| // linux/elf.h | ||
| | "NT_PRFPREG" | ||
| // linux/sem.h | ||
| | "SEM_STAT_ANY" | ||
| // linux/shm.h | ||
| | "SHM_EXEC" | ||
| // linux/signal.h | ||
| | "SI_DETHREAD" | ||
| | "TRAP_BRANCH" | ||
| | "TRAP_HWBKPT" | ||
| | "TRAP_UNK" | ||
| // linux/timerfd.h | ||
| | "TFD_TIMER_CANCEL_ON_SET" | ||
| // linux/udp.h | ||
| | "UDP_GRO" | ||
| | "UDP_SEGMENT" => return true, | ||
|
|
||
| _ => (), | ||
| } | ||
| } | ||
|
|
||
| match name { | ||
| // These constants are not available if gnu headers have been included | ||
| // and can therefore not be tested here | ||
|
|
@@ -4365,25 +4552,6 @@ fn test_linux(target: &str) { | |
| // Skip as this signal codes and trap reasons need newer headers | ||
| "TRAP_PERF" => true, | ||
|
|
||
| // kernel constants not available in uclibc 1.0.34 | ||
| "EXTPROC" | ||
| | "IPPROTO_BEETPH" | ||
| | "IPPROTO_MPLS" | ||
| | "IPV6_HDRINCL" | ||
| | "IPV6_MULTICAST_ALL" | ||
| | "IPV6_PMTUDISC_INTERFACE" | ||
| | "IPV6_PMTUDISC_OMIT" | ||
| | "IPV6_ROUTER_ALERT_ISOLATE" | ||
| | "PACKET_MR_UNICAST" | ||
| | "RUSAGE_THREAD" | ||
| | "SHM_EXEC" | ||
| | "UDP_GRO" | ||
| | "UDP_SEGMENT" | ||
| if uclibc => | ||
| { | ||
| true | ||
| } | ||
|
|
||
| // headers conflicts with linux/pidfd.h | ||
| "PIDFD_NONBLOCK" => true, | ||
| // Linux >= 6.9 | ||
|
|
@@ -4424,6 +4592,10 @@ fn test_linux(target: &str) { | |
| // value changed | ||
| "NF_NETDEV_NUMHOOKS" if sparc64 => true, | ||
|
|
||
| // Canonical uclibc latest from toolchains.bootlin.com is based on kernel 5.15, | ||
| // 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, | ||
|
|
||
|
|
@@ -4633,8 +4805,9 @@ fn test_linux(target: &str) { | |
| // Needs glibc 2.33 or later. | ||
| "mallinfo2" => true, | ||
|
|
||
| // Not defined in uclibc as of 1.0.34 | ||
| // Not defined in uclibc as of 1.0.45 | ||
| "gettid" if uclibc => true, | ||
| "getauxval" if uclibc => true, | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. libc doesn't define |
||
|
|
||
| // There are two versions of basename(3) on Linux with glibc, see | ||
| // | ||
|
|
@@ -4766,7 +4939,7 @@ fn test_linux(target: &str) { | |
| // FIXME(linux): `max_phase_adj` requires >= 5.19 kernel headers | ||
| // the rsv field shrunk when those fields got added, so is omitted too | ||
| ("ptp_clock_caps", "adjust_phase" | "max_phase_adj" | "rsv") | ||
| if loongarch64 || sparc64 => | ||
| if loongarch64 || sparc64 || uclibc => | ||
| { | ||
| true | ||
| } | ||
|
|
@@ -4783,7 +4956,7 @@ fn test_linux(target: &str) { | |
| ("bcm_msg_head", "frames") => true, | ||
| // FAM | ||
| ("af_alg_iv", "iv") => true, | ||
| ("file_handle", "f_handle") if musl => true, | ||
| ("file_handle", "f_handle") if musl || uclibc => true, | ||
| // FIXME(ctest): ctest does not translate the rust code which computes the padding size | ||
| ("pthread_cond_t", "__padding") if l4re => true, | ||
| _ => false, | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -2,15 +2,24 @@ use crate::off64_t; | |
| use crate::prelude::*; | ||
|
|
||
| pub type wchar_t = c_uint; | ||
| pub type time_t = c_long; | ||
|
|
||
| cfg_if! { | ||
| // Set cfg(libc_unstable_uclibc_time64) in rustflags if your uclibc has 64-bit time | ||
| if #[cfg(linux_time_bits64)] { | ||
| pub type time_t = c_longlong; | ||
| pub type suseconds_t = c_longlong; | ||
| } else { | ||
| pub type time_t = c_long; | ||
| pub type suseconds_t = c_long; | ||
| } | ||
| } | ||
|
Comment on lines
+6
to
+15
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do any structs need to be updated here? I know on other targets the padding in the timespec struct sometimes needs to be adjusted. I assume there are no function link names to update if uclibc had a pretty clean cut 32->64 transition.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I am relying on the libc-test infrastructure a bit here to catch errors, but I think everything should be OK. I am happy to be the point person for any issues raised for 64-bit |
||
|
|
||
| pub type clock_t = c_long; | ||
| pub type fsblkcnt_t = c_ulong; | ||
| pub type fsfilcnt_t = c_ulong; | ||
| pub type ino_t = c_ulong; | ||
| pub type off_t = c_long; | ||
| pub type pthread_t = c_ulong; | ||
| pub type suseconds_t = c_long; | ||
|
|
||
| pub type nlink_t = c_uint; | ||
| pub type blksize_t = c_long; | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.