@@ -64,6 +64,7 @@ fn do_ctest() {
6464 t if t. contains ( "emscripten" ) => test_emscripten ( t) ,
6565 t if t. contains ( "freebsd" ) => test_freebsd ( t) ,
6666 t if t. contains ( "haiku" ) => test_haiku ( t) ,
67+ t if t. contains ( "l4re" ) => test_linux ( t) ,
6768 t if t. contains ( "linux" ) => test_linux ( t) ,
6869 t if t. contains ( "netbsd" ) => test_netbsd ( t) ,
6970 t if t. contains ( "openbsd" ) => test_openbsd ( t) ,
@@ -115,9 +116,10 @@ fn do_semver() {
115116 // NOTE: Android doesn't include the unix file (or the Linux file) because
116117 // there are some many definitions missing it's actually easier just to
117118 // maintain a file for Android.
118- // NOTE: AIX doesn't include the unix file because there are definitions
119- // missing on AIX. It is easier to maintain a file for AIX.
120- if family != os && !matches ! ( os. as_str( ) , "android" | "aix" ) && os != "vxworks" {
119+ // NOTE: AIX and L4Re do not include the unix file because there are
120+ // definitions missing on these systems. It is easier to maintain separate
121+ // files for them.
122+ if family != os && !matches ! ( os. as_str( ) , "android" | "aix" | "l4re" ) && os != "vxworks" {
121123 process_semver_file ( & mut output, & mut semver_root, & family) ;
122124 }
123125 // We don't do semver for unknown targets.
@@ -3659,19 +3661,28 @@ fn config_gnu_bits(target: &str, cfg: &mut ctest::TestGenerator) {
36593661 }
36603662}
36613663
3664+ // This also covers the L4Re targets since they have a similar API surface
36623665fn test_linux ( target : & str ) {
3663- assert ! ( target. contains( "linux" ) ) ;
3666+ assert ! ( target. contains( "linux" ) || target. contains( "l4re" ) ) ;
3667+
3668+ // target_os
3669+ let linux = target. contains ( "linux" ) ;
3670+ let l4re = target. contains ( "l4re" ) ;
36643671
36653672 // target_env
36663673 let gnu = target. contains ( "gnu" ) ;
36673674 let musl = target. contains ( "musl" ) || target. contains ( "ohos" ) ;
36683675 let uclibc = target. contains ( "uclibc" ) ;
36693676
3670- match ( gnu, musl, uclibc) {
3671- ( true , false , false ) => ( ) ,
3672- ( false , true , false ) => ( ) ,
3673- ( false , false , true ) => ( ) ,
3674- ( _, _, _) => panic ! ( "linux target lib is gnu: {gnu}, musl: {musl}, uclibc: {uclibc}" ) ,
3677+ match ( l4re, gnu, musl, uclibc) {
3678+ ( false , true , false , false ) => ( ) ,
3679+ ( false , false , true , false ) => ( ) ,
3680+ ( false , false , false , true ) => ( ) ,
3681+ ( true , false , false , true ) => ( ) ,
3682+ ( _, _, _, _) => panic ! (
3683+ "{} target lib is gnu: {gnu}, musl: {musl}, uclibc: {uclibc}" ,
3684+ if linux { "linux" } else { "l4re" }
3685+ ) ,
36753686 }
36763687
36773688 let arm = target. contains ( "arm" ) ;
@@ -3709,6 +3720,11 @@ fn test_linux(target: &str) {
37093720 . define ( "__GLIBC_USE_DEPRECATED_SCANF" , None ) ;
37103721
37113722 config_gnu_bits ( target, & mut cfg) ;
3723+ // The L4Re libc headers contain some L4Re helper functions which are not needed for the libc
3724+ // interface and must not be added to the libc crate
3725+ if l4re {
3726+ cfg. flag ( "-Wno-unused-function" ) ;
3727+ }
37123728
37133729 headers ! (
37143730 cfg,
@@ -3728,11 +3744,11 @@ fn test_linux(target: &str) {
37283744 "libgen.h" ,
37293745 "limits.h" ,
37303746 "link.h" ,
3731- "linux/sysctl.h" ,
3747+ ( !l4re , "linux/sysctl.h" ) ,
37323748 "locale.h" ,
37333749 "malloc.h" ,
37343750 "mntent.h" ,
3735- "mqueue.h" ,
3751+ ( !l4re , "mqueue.h" ) ,
37363752 "net/ethernet.h" ,
37373753 "net/if.h" ,
37383754 "net/if_arp.h" ,
@@ -3742,6 +3758,7 @@ fn test_linux(target: &str) {
37423758 "netinet/ip.h" ,
37433759 "netinet/tcp.h" ,
37443760 "netinet/udp.h" ,
3761+ ( l4re, "netpacket/packet.h" ) ,
37453762 "poll.h" ,
37463763 "pthread.h" ,
37473764 "pty.h" ,
@@ -3752,43 +3769,44 @@ fn test_linux(target: &str) {
37523769 "semaphore.h" ,
37533770 "shadow.h" ,
37543771 "signal.h" ,
3755- "spawn.h" ,
3756- "stddef.h" ,
3772+ ( !l4re , "spawn.h" ) ,
3773+ ( !l4re , "stddef.h" ) ,
37573774 "stdint.h" ,
37583775 "stdio.h" ,
37593776 "stdlib.h" ,
37603777 "string.h" ,
3761- "sys/epoll.h" ,
3762- "sys/eventfd.h" ,
3778+ ( l4re, "sys/auxv.h" ) ,
3779+ ( !l4re, "sys/epoll.h" ) ,
3780+ ( !l4re, "sys/eventfd.h" ) ,
37633781 "sys/file.h" ,
3764- "sys/fsuid.h" ,
3765- "sys/klog.h" ,
3766- "sys/inotify.h" ,
3782+ ( !l4re , "sys/fsuid.h" ) ,
3783+ ( !l4re , "sys/klog.h" ) ,
3784+ ( !l4re , "sys/inotify.h" ) ,
37673785 "sys/ioctl.h" ,
37683786 "sys/ipc.h" ,
37693787 "sys/mman.h" ,
37703788 "sys/mount.h" ,
3771- "sys/msg.h" ,
3772- "sys/personality.h" ,
3789+ ( !l4re , "sys/msg.h" ) ,
3790+ ( !l4re , "sys/personality.h" ) ,
37733791 "sys/prctl.h" ,
3774- "sys/ptrace.h" ,
3775- "sys/quota.h" ,
3776- "sys/random.h" ,
3777- "sys/reboot.h" ,
3792+ ( !l4re , "sys/ptrace.h" ) ,
3793+ ( !l4re , "sys/quota.h" ) ,
3794+ ( !l4re , "sys/random.h" ) ,
3795+ ( !l4re , "sys/reboot.h" ) ,
37783796 "sys/resource.h" ,
37793797 "sys/sem.h" ,
3780- "sys/sendfile.h" ,
3798+ ( !l4re , "sys/sendfile.h" ) ,
37813799 "sys/shm.h" ,
3782- "sys/signalfd.h" ,
3800+ ( !l4re , "sys/signalfd.h" ) ,
37833801 "sys/socket.h" ,
37843802 "sys/stat.h" ,
37853803 "sys/statvfs.h" ,
3786- "sys/swap.h" ,
3804+ ( !l4re , "sys/swap.h" ) ,
37873805 "sys/syscall.h" ,
37883806 "sys/time.h" ,
3789- "sys/timerfd.h" ,
3807+ ( !l4re , "sys/timerfd.h" ) ,
37903808 "sys/times.h" ,
3791- "sys/timex.h" ,
3809+ ( !l4re , "sys/timex.h" ) ,
37923810 "sys/types.h" ,
37933811 "sys/uio.h" ,
37943812 "sys/un.h" ,
@@ -3810,22 +3828,26 @@ fn test_linux(target: &str) {
38103828 // ARM: https://bugzilla.redhat.com/show_bug.cgi?id=1116162
38113829 // Also unavailable on gnueabihf with glibc 2.30.
38123830 // https://sourceware.org/git/?p=glibc.git;a=commitdiff;h=6b33f373c7b9199e00ba5fbafd94ac9bfb4337b1
3813- ( ( x86_64 || x86_32 || arm) && !gnueabihf, "sys/io.h" ) ,
3831+ ( ( x86_64 || x86_32 || arm) && !gnueabihf && !l4re , "sys/io.h" ) ,
38143832 // `sys/reg.h` is only available on x86 and x86_64
3815- ( x86_64 || x86_32, "sys/reg.h" ) ,
3833+ ( ( x86_64 || x86_32) && !l4re , "sys/reg.h" ) ,
38163834 // sysctl system call is deprecated and not available on musl
38173835 // It is also unsupported in x32, deprecated since glibc 2.30:
3818- ( !( x32 || musl || gnu) , "sys/sysctl.h" ) ,
3836+ ( !( x32 || musl || gnu || l4re ) , "sys/sysctl.h" ) ,
38193837 // <execinfo.h> is not supported by musl:
38203838 // https://www.openwall.com/lists/musl/2015/04/09/3
38213839 // <execinfo.h> is not present on uclibc.
38223840 ( !( musl || uclibc) , "execinfo.h" ) ,
38233841 ) ;
38243842
38253843 // Include linux headers at the end:
3826- headers ! ( cfg, ( loongarch64 || riscv64, "asm/hwcap.h" ) , "asm/mman.h" , ) ;
3844+ headers ! (
3845+ cfg,
3846+ ( ( loongarch64 || riscv64) && !l4re, "asm/hwcap.h" ) ,
3847+ ( !l4re, "asm/mman.h" ) ,
3848+ ) ;
38273849
3828- if !wasm32 {
3850+ if !wasm32 && !l4re {
38293851 headers ! (
38303852 cfg,
38313853 ( gnu, "linux/aio_abi.h" ) ,
@@ -3901,7 +3923,7 @@ fn test_linux(target: &str) {
39013923 // note: aio.h must be included before sys/mount.h
39023924 headers ! (
39033925 cfg,
3904- "sys/xattr.h" ,
3926+ ( !l4re , "sys/xattr.h" ) ,
39053927 "sys/sysinfo.h" ,
39063928 // AIO is not supported by uclibc:
39073929 ( !uclibc, "aio.h" ) ,
@@ -3931,10 +3953,11 @@ fn test_linux(target: &str) {
39313953
39323954 cfg. rename_type ( move |ty| {
39333955 match ty {
3934- "Ioctl" if gnu => Some ( "unsigned long" . to_string ( ) ) ,
3956+ "Ioctl" if gnu || uclibc => Some ( "unsigned long" . to_string ( ) ) ,
39353957 "Ioctl" => Some ( "int" . to_string ( ) ) ,
39363958 // LFS64 types have been removed in musl 1.2.4+
39373959 "off64_t" if musl => Some ( "off_t" . to_string ( ) ) ,
3960+ "fsword_t" if uclibc => Some ( "__SWORD_TYPE" . to_string ( ) ) ,
39383961 _ => None ,
39393962 }
39403963 } ) ;
@@ -4128,6 +4151,13 @@ fn test_linux(target: &str) {
41284151
41294152 cfg. skip_const ( move |constant| {
41304153 let name = constant. ident ( ) ;
4154+
4155+ // L4Re requires a min stack size of 64k; that isn't defined in uClibc, but
4156+ // somewhere in the core libraries. uClibc wants 16k, but that's not enough.
4157+ if l4re && name == "PTHREAD_STACK_MIN" {
4158+ return true ;
4159+ }
4160+
41314161 if !gnu {
41324162 // Skip definitions from the kernel on non-glibc Linux targets.
41334163 // They're libc-independent, so we only need to check them on one
@@ -4277,7 +4307,7 @@ fn test_linux(target: &str) {
42774307
42784308 // FIXME(musl): on musl the pthread types are defined a little differently
42794309 // - these constants are used by the glibc implementation.
4280- n if musl && n. contains ( "__SIZEOF_PTHREAD" ) => true ,
4310+ n if ( musl || uclibc ) && n. contains ( "__SIZEOF_PTHREAD" ) => true ,
42814311
42824312 // FIXME(linux): It was extended to 4096 since glibc 2.31 (Linux 5.4).
42834313 // We should do so after a while.
@@ -4698,6 +4728,8 @@ fn test_linux(target: &str) {
46984728 ( "bcm_msg_head" , "frames" ) => true ,
46994729 // FAM
47004730 ( "af_alg_iv" , "iv" ) => true ,
4731+ // FIXME(ctest): ctest does not translate the rust code which computes the padding size
4732+ ( "pthread_cond_t" , "__padding" ) if l4re => true ,
47014733 _ => false ,
47024734 }
47034735 } ) ;
@@ -4823,7 +4855,9 @@ fn test_linux(target: &str) {
48234855
48244856 ctest:: generate_test ( & mut cfg, "../src/lib.rs" , "ctest_output.rs" ) . unwrap ( ) ;
48254857
4826- test_linux_like_apis ( target) ;
4858+ if !l4re {
4859+ test_linux_like_apis ( target) ;
4860+ }
48274861}
48284862
48294863// This function tests APIs that are incompatible to test when other APIs
0 commit comments