Skip to content

Commit

Permalink
Merge #1603
Browse files Browse the repository at this point in the history
1603: uclibc support r=rtzoeller a=skrap

uclibc is a libc alternative (peer to glibc and musl) which is used in low-resource embedded linux applications.

It's supported in rust as the `target_env` of several tier 3 targets, but `nix` currently doesn't build.  This patch provides a few customizations to get uclibc building.

To test:
* Get nightly rust
* Follow directions for getting a cross toolchain and env setup here: https://github.com/rust-lang/rust/blob/master/src/doc/rustc/src/platform-support/armv7-unknown-linux-uclibceabihf.md

Thanks for your consideration!



Co-authored-by: Jonah Petri <[email protected]>
  • Loading branch information
bors[bot] and skrap authored Jan 25, 2022
2 parents ae2b7b3 + 6c4b913 commit 5cd01a1
Show file tree
Hide file tree
Showing 16 changed files with 74 additions and 27 deletions.
3 changes: 3 additions & 0 deletions .cirrus.yml
Original file line number Diff line number Diff line change
Expand Up @@ -281,6 +281,9 @@ task:
- name: OpenBSD x86_64
env:
TARGET: x86_64-unknown-openbsd
- name: Linux armv7 uclibceabihf
env:
TARGET: armv7-unknown-linux-uclibceabihf
setup_script:
- rustup component add rust-src
<< : *BUILD
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ Tier 2:
* x86_64-unknown-netbsd

Tier 3:
* armv7-unknown-linux-uclibceabihf
* x86_64-fuchsia
* x86_64-unknown-dragonfly
* x86_64-unknown-linux-gnux32
Expand Down
1 change: 1 addition & 0 deletions bors.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ status = [
"Linux arm gnueabi",
"Linux arm-musleabi",
"Linux armv7 gnueabihf",
"Linux armv7 uclibceabihf",
"Linux i686 musl",
"Linux i686",
"Linux mipsel",
Expand Down
2 changes: 1 addition & 1 deletion src/sys/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
#[cfg(any(target_os = "dragonfly",
target_os = "freebsd",
target_os = "ios",
target_os = "linux",
all(target_os = "linux", not(target_env = "uclibc")),
target_os = "macos",
target_os = "netbsd"))]
feature! {
Expand Down
4 changes: 2 additions & 2 deletions src/sys/personality.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,13 @@ libc_bitflags! {
ADDR_NO_RANDOMIZE;
ADDR_LIMIT_32BIT;
ADDR_LIMIT_3GB;
#[cfg(not(target_env = "musl"))]
#[cfg(not(any(target_env = "musl", target_env = "uclibc")))]
FDPIC_FUNCPTRS;
MMAP_PAGE_ZERO;
READ_IMPLIES_EXEC;
SHORT_INODE;
STICKY_TIMEOUTS;
#[cfg(not(target_env = "musl"))]
#[cfg(not(any(target_env = "musl", target_env = "uclibc")))]
UNAME26;
WHOLE_SECONDS;
}
Expand Down
7 changes: 4 additions & 3 deletions src/sys/ptrace/linux.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@ use libc::user_regs_struct;

cfg_if! {
if #[cfg(any(all(target_os = "linux", target_arch = "s390x"),
all(target_os = "linux", target_env = "gnu")))] {
all(target_os = "linux", target_env = "gnu"),
target_env = "uclibc"))] {
#[doc(hidden)]
pub type RequestType = ::libc::c_uint;
} else {
Expand All @@ -30,8 +31,8 @@ cfg_if! {
}

libc_enum!{
#[cfg_attr(not(any(target_env = "musl", target_os = "android")), repr(u32))]
#[cfg_attr(any(target_env = "musl", target_os = "android"), repr(i32))]
#[cfg_attr(not(any(target_env = "musl", target_env = "uclibc", target_os = "android")), repr(u32))]
#[cfg_attr(any(target_env = "musl", target_env = "uclibc", target_os = "android"), repr(i32))]
/// Ptrace Request enum defining the action to be taken.
#[non_exhaustive]
pub enum Request {
Expand Down
10 changes: 5 additions & 5 deletions src/sys/resource.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@ pub use libc::rlim_t;
use std::mem;

cfg_if! {
if #[cfg(all(target_os = "linux", target_env = "gnu"))]{
if #[cfg(all(target_os = "linux", any(target_env = "gnu", target_env = "uclibc")))]{
use libc::{__rlimit_resource_t, rlimit, RLIM_INFINITY};
}else if #[cfg(any(
} else if #[cfg(any(
target_os = "freebsd",
target_os = "openbsd",
target_os = "netbsd",
Expand Down Expand Up @@ -199,9 +199,9 @@ pub fn getrlimit(resource: Resource) -> Result<(Option<rlim_t>, Option<rlim_t>)>
let mut old_rlim = mem::MaybeUninit::<rlimit>::uninit();

cfg_if! {
if #[cfg(all(target_os = "linux", target_env = "gnu"))]{
if #[cfg(all(target_os = "linux", any(target_env = "gnu", target_env = "uclibc")))]{
let res = unsafe { libc::getrlimit(resource as __rlimit_resource_t, old_rlim.as_mut_ptr()) };
}else{
} else {
let res = unsafe { libc::getrlimit(resource as c_int, old_rlim.as_mut_ptr()) };
}
}
Expand Down Expand Up @@ -253,7 +253,7 @@ pub fn setrlimit(
rlim_max: hard_limit.unwrap_or(RLIM_INFINITY),
};
cfg_if! {
if #[cfg(all(target_os = "linux", target_env = "gnu"))]{
if #[cfg(all(target_os = "linux", any(target_env = "gnu", target_env = "uclibc")))]{
let res = unsafe { libc::setrlimit(resource as __rlimit_resource_t, &new_rlim as *const rlimit) };
}else{
let res = unsafe { libc::setrlimit(resource as c_int, &new_rlim as *const rlimit) };
Expand Down
16 changes: 12 additions & 4 deletions src/sys/signal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ use std::str::FromStr;
#[cfg(any(target_os = "dragonfly", target_os = "freebsd"))]
use std::os::unix::io::RawFd;
use std::ptr;
use cfg_if::cfg_if;

#[cfg(not(any(target_os = "openbsd", target_os = "redox")))]
#[cfg(any(feature = "aio", feature = "signal"))]
Expand Down Expand Up @@ -420,10 +421,15 @@ pub const SIGPOLL : Signal = SIGIO;
/// Alias for [`SIGSYS`]
pub const SIGUNUSED : Signal = SIGSYS;

#[cfg(not(target_os = "redox"))]
type SaFlags_t = libc::c_int;
#[cfg(target_os = "redox")]
type SaFlags_t = libc::c_ulong;
cfg_if! {
if #[cfg(target_os = "redox")] {
type SaFlags_t = libc::c_ulong;
} else if #[cfg(target_env = "uclibc")] {
type SaFlags_t = libc::c_ulong;
} else {
type SaFlags_t = libc::c_int;
}
}
}

#[cfg(feature = "signal")]
Expand Down Expand Up @@ -1046,6 +1052,8 @@ mod sigevent {
SigevNotify::SigevThreadId{..} => libc::SIGEV_THREAD_ID,
#[cfg(all(target_os = "linux", target_env = "gnu", not(target_arch = "mips")))]
SigevNotify::SigevThreadId{..} => libc::SIGEV_THREAD_ID,
#[cfg(all(target_os = "linux", target_env = "uclibc"))]
SigevNotify::SigevThreadId{..} => libc::SIGEV_THREAD_ID,
#[cfg(any(all(target_os = "linux", target_env = "musl"), target_arch = "mips"))]
SigevNotify::SigevThreadId{..} => 4 // No SIGEV_THREAD_ID defined
};
Expand Down
4 changes: 2 additions & 2 deletions src/sys/socket/addr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -120,10 +120,10 @@ pub enum AddressFamily {
#[cfg(any(target_os = "android", target_os = "linux"))]
#[cfg_attr(docsrs, doc(cfg(all())))]
Llc = libc::AF_LLC,
#[cfg(target_os = "linux")]
#[cfg(all(target_os = "linux", not(target_env = "uclibc")))]
#[cfg_attr(docsrs, doc(cfg(all())))]
Ib = libc::AF_IB,
#[cfg(target_os = "linux")]
#[cfg(all(target_os = "linux", not(target_env = "uclibc")))]
#[cfg_attr(docsrs, doc(cfg(all())))]
Mpls = libc::AF_MPLS,
#[cfg(any(target_os = "android", target_os = "linux"))]
Expand Down
34 changes: 29 additions & 5 deletions src/sys/statfs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,9 @@ type fs_type_t = libc::c_ulong;
type fs_type_t = libc::c_uint;
#[cfg(all(target_os = "linux", target_env = "musl"))]
type fs_type_t = libc::c_ulong;
#[cfg(all(target_os = "linux", not(any(target_arch = "s390x", target_env = "musl"))))]
#[cfg(all(target_os = "linux", target_env = "uclibc"))]
type fs_type_t = libc::c_int;
#[cfg(all(target_os = "linux", not(any(target_arch = "s390x", target_env = "musl", target_env = "uclibc"))))]
type fs_type_t = libc::__fsword_t;

/// Describes the file system type as known by the operating system.
Expand Down Expand Up @@ -71,7 +73,7 @@ pub const EXT3_SUPER_MAGIC: FsType = FsType(libc::EXT3_SUPER_MAGIC as fs_type_t)
#[cfg(all(target_os = "linux", not(target_env = "musl")))]
#[allow(missing_docs)]
pub const EXT4_SUPER_MAGIC: FsType = FsType(libc::EXT4_SUPER_MAGIC as fs_type_t);
#[cfg(all(target_os = "linux", not(target_env = "musl")))]
#[cfg(all(target_os = "linux", not(any(target_env = "musl", target_env = "uclibc"))))]
#[allow(missing_docs)]
pub const FUSE_SUPER_MAGIC: FsType = FsType(libc::FUSE_SUPER_MAGIC as fs_type_t);
#[cfg(all(target_os = "linux", not(target_env = "musl")))]
Expand Down Expand Up @@ -192,12 +194,19 @@ impl Statfs {
}

/// Optimal transfer block size
#[cfg(all(target_os = "linux", not(any(target_arch = "s390x", target_env = "musl"))))]
#[cfg(all(target_os = "linux", not(any(target_arch = "s390x", target_env = "musl", target_env = "uclibc"))))]
#[cfg_attr(docsrs, doc(cfg(all())))]
pub fn optimal_transfer_size(&self) -> libc::__fsword_t {
self.0.f_bsize
}

/// Optimal transfer block size
#[cfg(all(target_os = "linux", target_env = "uclibc"))]
#[cfg_attr(docsrs, doc(cfg(all())))]
pub fn optimal_transfer_size(&self) -> libc::c_int {
self.0.f_bsize
}

/// Optimal transfer block size
#[cfg(target_os = "dragonfly")]
#[cfg_attr(docsrs, doc(cfg(all())))]
Expand Down Expand Up @@ -237,7 +246,15 @@ impl Statfs {

/// Size of a block
// f_bsize on linux: https://github.com/torvalds/linux/blob/master/fs/nfs/super.c#L471
#[cfg(all(target_os = "linux", not(any(target_arch = "s390x", target_env = "musl"))))]
#[cfg(all(target_os = "linux", target_env = "uclibc"))]
#[cfg_attr(docsrs, doc(cfg(all())))]
pub fn block_size(&self) -> libc::c_int {
self.0.f_bsize
}

/// Size of a block
// f_bsize on linux: https://github.com/torvalds/linux/blob/master/fs/nfs/super.c#L471
#[cfg(all(target_os = "linux", not(any(target_arch = "s390x", target_env = "musl", target_env = "uclibc"))))]
#[cfg_attr(docsrs, doc(cfg(all())))]
pub fn block_size(&self) -> libc::__fsword_t {
self.0.f_bsize
Expand Down Expand Up @@ -286,7 +303,14 @@ impl Statfs {
}

/// Maximum length of filenames
#[cfg(all(target_os = "linux", not(any(target_arch = "s390x", target_env = "musl"))))]
#[cfg(all(target_os = "linux", target_env = "uclibc"))]
#[cfg_attr(docsrs, doc(cfg(all())))]
pub fn maximum_name_length(&self) -> libc::c_int {
self.0.f_namelen
}

/// Maximum length of filenames
#[cfg(all(target_os = "linux", not(any(target_arch = "s390x", target_env = "musl", target_env = "uclibc"))))]
#[cfg_attr(docsrs, doc(cfg(all())))]
pub fn maximum_name_length(&self) -> libc::__fsword_t {
self.0.f_namelen
Expand Down
8 changes: 6 additions & 2 deletions src/sys/uio.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ pub fn readv(fd: RawFd, iov: &mut [IoVec<&mut [u8]>]) -> Result<usize> {
#[cfg_attr(docsrs, doc(cfg(all())))]
pub fn pwritev(fd: RawFd, iov: &[IoVec<&[u8]>],
offset: off_t) -> Result<usize> {
#[cfg(target_env = "uclibc")]
let offset = offset as libc::off64_t; // uclibc doesn't use off_t
let res = unsafe {
libc::pwritev(fd, iov.as_ptr() as *const libc::iovec, iov.len() as c_int, offset)
};
Expand All @@ -52,6 +54,8 @@ pub fn pwritev(fd: RawFd, iov: &[IoVec<&[u8]>],
#[cfg_attr(docsrs, doc(cfg(all())))]
pub fn preadv(fd: RawFd, iov: &[IoVec<&mut [u8]>],
offset: off_t) -> Result<usize> {
#[cfg(target_env = "uclibc")]
let offset = offset as libc::off64_t; // uclibc doesn't use off_t
let res = unsafe {
libc::preadv(fd, iov.as_ptr() as *const libc::iovec, iov.len() as c_int, offset)
};
Expand Down Expand Up @@ -127,7 +131,7 @@ feature! {
/// [ptrace]: ../ptrace/index.html
/// [`IoVec`]: struct.IoVec.html
/// [`RemoteIoVec`]: struct.RemoteIoVec.html
#[cfg(target_os = "linux")]
#[cfg(all(target_os = "linux", not(target_env = "uclibc")))]
pub fn process_vm_writev(
pid: crate::unistd::Pid,
local_iov: &[IoVec<&[u8]>],
Expand Down Expand Up @@ -162,7 +166,7 @@ pub fn process_vm_writev(
/// [`ptrace`]: ../ptrace/index.html
/// [`IoVec`]: struct.IoVec.html
/// [`RemoteIoVec`]: struct.RemoteIoVec.html
#[cfg(any(target_os = "linux"))]
#[cfg(all(target_os = "linux", not(target_env = "uclibc")))]
pub fn process_vm_readv(
pid: crate::unistd::Pid,
local_iov: &[IoVec<&mut [u8]>],
Expand Down
1 change: 0 additions & 1 deletion src/time.rs
Original file line number Diff line number Diff line change
Expand Up @@ -237,7 +237,6 @@ pub fn clock_gettime(clock_id: ClockId) -> Result<TimeSpec> {
#[cfg(not(any(
target_os = "macos",
target_os = "ios",
target_env = "uclibc",
target_os = "redox",
target_os = "hermit",
)))]
Expand Down
2 changes: 1 addition & 1 deletion test/sys/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ mod test_signal;
// cases on DragonFly.
#[cfg(any(target_os = "freebsd",
target_os = "ios",
target_os = "linux",
all(target_os = "linux", not(target_env = "uclibc")),
target_os = "macos",
target_os = "netbsd"))]
mod test_aio;
Expand Down
1 change: 1 addition & 0 deletions test/sys/test_aio_drop.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#[test]
#[should_panic(expected = "Dropped an in-progress AioCb")]
#[cfg(all(not(target_env = "musl"),
not(target_env = "uclibc"),
any(target_os = "linux",
target_os = "ios",
target_os = "macos",
Expand Down
2 changes: 1 addition & 1 deletion test/sys/test_uio.rs
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,7 @@ fn test_preadv() {
}

#[test]
#[cfg(target_os = "linux")]
#[cfg(all(target_os = "linux", not(target_env = "uclibc")))] // uclibc doesn't implement process_vm_readv
// qemu-user doesn't implement process_vm_readv/writev on most arches
#[cfg_attr(qemu, ignore)]
fn test_process_vm_readv() {
Expand Down
5 changes: 5 additions & 0 deletions test/test_fcntl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@ use std::os::unix::fs;

#[test]
#[cfg(not(target_os = "redox"))]
// QEMU does not handle openat well enough to satisfy this test
// https://gitlab.com/qemu-project/qemu/-/issues/829
#[cfg_attr(qemu, ignore)]
fn test_openat() {
const CONTENTS: &[u8] = b"abcd";
let mut tmp = NamedTempFile::new().unwrap();
Expand Down Expand Up @@ -357,6 +360,7 @@ mod linux_android {

#[test]
#[cfg(all(target_os = "linux", not(target_env = "musl")))]
#[cfg_attr(target_env = "uclibc", ignore)] // uclibc doesn't support OFD locks, but the test should still compile
fn test_ofd_write_lock() {
use nix::sys::stat::fstat;
use std::mem;
Expand Down Expand Up @@ -394,6 +398,7 @@ mod linux_android {

#[test]
#[cfg(all(target_os = "linux", not(target_env = "musl")))]
#[cfg_attr(target_env = "uclibc", ignore)] // uclibc doesn't support OFD locks, but the test should still compile
fn test_ofd_read_lock() {
use nix::sys::stat::fstat;
use std::mem;
Expand Down

0 comments on commit 5cd01a1

Please sign in to comment.