aboutsummaryrefslogtreecommitdiff
path: root/libc/libc-test/build.rs
diff options
context:
space:
mode:
Diffstat (limited to 'libc/libc-test/build.rs')
-rw-r--r--libc/libc-test/build.rs1311
1 files changed, 427 insertions, 884 deletions
diff --git a/libc/libc-test/build.rs b/libc/libc-test/build.rs
index 6541fd5..5087906 100644
--- a/libc/libc-test/build.rs
+++ b/libc/libc-test/build.rs
@@ -37,14 +37,22 @@ fn main() {
}
macro_rules! headers {
- ($cfg:ident: $header:expr) => {
+ ($cfg:ident: [$m:expr]: $header:literal) => {
+ if $m {
+ $cfg.header($header);
+ }
+ };
+ ($cfg:ident: $header:literal) => {
$cfg.header($header);
};
- ($cfg:ident: $($header:expr),*) => {
- $(headers!($cfg: $header);)*
+ ($($cfg:ident: $([$c:expr]:)* $header:literal,)*) => {
+ $(headers!($cfg: $([$c]:)* $header);)*
+ };
+ ($cfg:ident: $( $([$c:expr]:)* $header:literal,)*) => {
+ headers!($($cfg: $([$c]:)* $header,)*);
};
- ($cfg:ident: $($header:expr,)*) => {
- $(headers!($cfg: $header);)*
+ ($cfg:ident: $( $([$c:expr]:)* $header:literal),*) => {
+ headers!($($cfg: $([$c]:)* $header,)*);
};
}
@@ -135,10 +143,7 @@ fn test_apple(target: &str) {
"utmpx.h",
"wchar.h",
"xlocale.h",
- }
-
- if x86_64 {
- headers! { cfg: "crt_externs.h" }
+ [x86_64]: "crt_externs.h",
}
cfg.skip_struct(move |ty| {
@@ -313,11 +318,9 @@ fn test_openbsd(target: &str) {
cfg.skip_fn(move |name| {
match name {
+ // FIXME: https://github.com/rust-lang/libc/issues/1272
"execv" | "execve" | "execvp" | "execvpe" => true,
- // typed 2nd arg
- "gettimeofday" => true,
-
// Removed in OpenBSD 6.5
// https://marc.info/?l=openbsd-cvs&m=154723400730318
"mincore" => true,
@@ -388,12 +391,8 @@ fn test_windows(target: &str) {
"sys/utime.h",
"time.h",
"wchar.h",
- }
-
- if gnu {
- headers! { cfg: "ws2tcpip.h" }
- } else {
- headers! { cfg: "Winsock2.h" };
+ [gnu]: "ws2tcpip.h",
+ [!gnu]: "Winsock2.h",
}
cfg.type_name(move |ty, is_struct, is_union| {
@@ -461,7 +460,7 @@ fn test_windows(target: &str) {
cfg.skip_fn(move |name| {
match name {
- // FIXME: API error:
+ // FIXME: https://github.com/rust-lang/libc/issues/1272
"execv" | "execve" | "execvp" | "execvpe" => true,
_ => false,
@@ -852,7 +851,6 @@ fn test_netbsd(target: &str) {
cfg.skip_signededness(move |c| {
match c {
"LARGE_INTEGER" | "float" | "double" => true,
- // uuid_t is a struct, not an integer.
n if n.starts_with("pthread") => true,
// sem_t is a struct or pointer
"sem_t" => true,
@@ -876,12 +874,8 @@ fn test_netbsd(target: &str) {
cfg.skip_fn(move |name| {
match name {
- // FIXME: incorrect API
- "execv" |
- "execve" |
- "execvp" |
- "execvpe" |
- "fexecve" => true,
+ // FIXME: https://github.com/rust-lang/libc/issues/1272
+ "execv" | "execve" | "execvp" => true,
"getrlimit" | "getrlimit64" | // non-int in 1st arg
"setrlimit" | "setrlimit64" | // non-int in 1st arg
@@ -1028,14 +1022,9 @@ fn test_dragonflybsd(target: &str) {
s.replace("e_nsec", ".tv_nsec")
}
"u64" if struct_ == "epoll_event" => "data.u64".to_string(),
- "type_"
- if struct_ == "input_event"
- || struct_ == "input_mask"
- || struct_ == "ff_effect"
- || struct_ == "rtprio" =>
- {
- "type".to_string()
- }
+ // Field is named `type` in C but that is a Rust keyword,
+ // so these fields are translated to `type_` in the bindings.
+ "type_" if struct_ == "rtprio" => "type".to_string(),
s => s.to_string(),
}
});
@@ -1105,17 +1094,13 @@ fn test_dragonflybsd(target: &str) {
cfg.skip_fn(move |name| {
// skip those that are manually verified
match name {
- "execv" | // crazy stuff with const/mut
- "execve" |
- "execvp" |
- "execvpe" |
- "fexecve" => true,
+ // FIXME: https://github.com/rust-lang/libc/issues/1272
+ "execv" | "execve" | "execvp" => true,
"getrlimit" | "getrlimit64" | // non-int in 1st arg
"setrlimit" | "setrlimit64" | // non-int in 1st arg
- "prlimit" | "prlimit64" | // non-int in 2nd arg
- // typed 2nd arg on linux
- "gettimeofday" => true,
+ "prlimit" | "prlimit64" // non-int in 2nd arg
+ => true,
_ => false,
}
@@ -1226,14 +1211,6 @@ fn test_android(target: &str) {
let mut cfg = ctest::TestGenerator::new();
cfg.define("_GNU_SOURCE", None);
- // FIXME: still necessary?
- cfg.flag("-Wno-deprecated-declarations");
-
- // Android doesn't actually have in_port_t but it's much easier if we
- // provide one for us to test against
- // FIXME: still necessary?
- cfg.define("in_port_t", Some("uint16_t"));
-
headers! { cfg:
"arpa/inet.h",
"asm/mman.h",
@@ -1300,6 +1277,7 @@ fn test_android(target: &str) {
"sys/personality.h",
"sys/prctl.h",
"sys/ptrace.h",
+ "sys/random.h",
"sys/reboot.h",
"sys/resource.h",
"sys/sendfile.h",
@@ -1317,6 +1295,7 @@ fn test_android(target: &str) {
"sys/un.h",
"sys/utsname.h",
"sys/vfs.h",
+ "sys/xattr.h",
"sys/wait.h",
"syslog.h",
"termios.h",
@@ -1326,30 +1305,24 @@ fn test_android(target: &str) {
"utmp.h",
"wchar.h",
"xlocale.h",
- }
-
- if target_pointer_width == 32 {
- // time64_t is not defined for 64-bit targets If included it will
- // generate the error 'Your time_t is already 64-bit'
- cfg.header("time64.h");
- }
- if x86 {
- cfg.header("sys/reg.h");
+ // time64_t is not defined for 64-bit targets If included it will
+ // generate the error 'Your time_t is already 64-bit'
+ [target_pointer_width == 32]: "time64.h",
+ [x86]: "sys/reg.h",
}
cfg.type_name(move |ty, is_struct, is_union| {
match ty {
// Just pass all these through, no need for a "struct" prefix
- // FIXME: still required ?
- "FILE" | "fd_set" | "Dl_info" | "DIR" | "Elf32_Phdr"
- | "Elf64_Phdr" | "Elf32_Shdr" | "Elf64_Shdr" | "Elf32_Sym"
- | "Elf64_Sym" | "Elf32_Ehdr" | "Elf64_Ehdr" | "Elf32_Chdr"
- | "Elf64_Chdr" => ty.to_string(),
+ "FILE" | "fd_set" | "Dl_info" => ty.to_string(),
t if is_union => format!("union {}", t),
t if t.ends_with("_t") => t.to_string(),
+ // sigval is a struct in Rust, but a union in C:
+ "sigval" => format!("union sigval"),
+
// put `struct` in front of all structs:.
t if is_struct => format!("struct {}", t),
@@ -1364,7 +1337,7 @@ fn test_android(target: &str) {
s if s.ends_with("_nsec") && struct_.starts_with("stat") => {
s.to_string()
}
- // FIXME: still necessary?
+ // FIXME: appears that `epoll_event.data` is an union
"u64" if struct_ == "epoll_event" => "data.u64".to_string(),
s => s.to_string(),
}
@@ -1372,8 +1345,8 @@ fn test_android(target: &str) {
cfg.skip_type(move |ty| {
match ty {
- // sighandler_t is crazy across platforms
- // FIXME: still necessary?
+ // FIXME: `sighandler_t` type is incorrect, see:
+ // https://github.com/rust-lang/libc/issues/1359
"sighandler_t" => true,
_ => false,
}
@@ -1381,71 +1354,24 @@ fn test_android(target: &str) {
cfg.skip_struct(move |ty| {
match ty {
- // This is actually a union, not a struct
- // FIXME: still necessary
- "sigval" => true,
-
- // These structs have changed since unified headers in NDK r14b.
- // `st_atime` and `st_atime_nsec` have changed sign.
- // FIXME: unskip it for next major release
- "stat" | "stat64" => true,
-
// These are tested as part of the linux_fcntl tests since there are
// header conflicts when including them with all the other structs.
- // FIXME: still necessary
"termios2" => true,
_ => false,
}
});
- cfg.skip_signededness(move |c| {
- match c {
- // FIXME: still necessary?
- "LARGE_INTEGER" | "float" | "double" => true,
- // FIXME: still necessary?
- n if n.starts_with("pthread") => true,
- _ => false,
- }
- });
-
cfg.skip_const(move |name| {
match name {
- // FIXME: still necessary?
- "SIG_DFL" | "SIG_ERR" | "SIG_IGN" => true, // sighandler_t weirdness
- // FIXME: still necessary?
- "SIGUNUSED" => true, // removed in glibc 2.26
-
- // weird signed extension or something like that?
- // FIXME: still necessary?
- "MS_NOUSER" => true,
- // FIXME: still necessary?
- "MS_RMT_MASK" => true, // updated in glibc 2.22 and musl 1.1.13
-
- // Android uses old kernel headers
- // These are constants used in getrandom syscall
- // FIXME: still necessary?
- "GRND_NONBLOCK" | "GRND_RANDOM" => true,
-
- // Defined by libattr not libc on linux (hard to test).
- // See constant definition for more details.
- // FIXME: still necessary?
+ // FIXME: deprecated: not available in any header
+ // See: https://github.com/rust-lang/libc/issues/1356
"ENOATTR" => true,
// FIXME: still necessary?
- "BOTHER" => true,
-
- // MFD_HUGETLB is not available in some older libc versions on the CI builders. On the
- // x86_64 and i686 builders it seems to be available for all targets, so at least test
- // it there.
- // FIXME: still necessary?
- "MFD_HUGETLB" => true,
-
- // These change all the time from release to release of linux
- // distros, let's just not bother trying to verify them. They
- // shouldn't be used in code anyway...
- // FIXME: still necessary?
- "AF_MAX" | "PF_MAX" => true,
+ "SIG_DFL" | "SIG_ERR" | "SIG_IGN" => true, // sighandler_t weirdness
+ // FIXME: deprecated - removed in glibc 2.26
+ "SIGUNUSED" => true,
_ => false,
}
@@ -1454,128 +1380,72 @@ fn test_android(target: &str) {
cfg.skip_fn(move |name| {
// skip those that are manually verified
match name {
- // FIXME: still necessary?
- "execv" | // crazy stuff with const/mut
- "execve" |
- "execvp" |
- "execvpe" |
- "fexecve" => true,
-
- // typed 2nd arg on android
- // FIXME: still necessary?
- "gettimeofday" => true,
-
- // not declared in newer android toolchains
- // FIXME: still necessary?
- "getdtablesize" => true,
-
- // FIXME: still necessary?
- "dlerror" => true, // const-ness is added
-
- // Apparently the NDK doesn't have this defined on android, but
- // it's in a header file?
- // FIXME: still necessary?
- "endpwent" => true,
-
- // Apparently res_init exists on Android, but isn't defined in a header:
- // https://mail.gnome.org/archives/commits-list/2013-May/msg01329.html
- // FIXME: still necessary?
- "res_init" => true,
+ // FIXME: https://github.com/rust-lang/libc/issues/1272
+ "execv" | "execve" | "execvp" | "execvpe" | "fexecve" => true,
- // Definition of those functions as changed since unified headers from NDK r14b
- // These changes imply some API breaking changes but are still ABI compatible.
- // We can wait for the next major release to be compliant with the new API.
- // FIXME: unskip these for next major release
- "strerror_r" | "madvise" | "msync" | "mprotect" | "recvfrom" | "getpriority" |
- "setpriority" | "personality" => true,
- // In Android 64 bits, these functions have been fixed since unified headers.
- // Ignore these until next major version.
- "bind" | "writev" | "readv" | "sendmsg" | "recvmsg"
- if target_pointer_width == 64 => true,
+ // There are two versions of the sterror_r function, see
+ //
+ // https://linux.die.net/man/3/strerror_r
+ //
+ // An XSI-compliant version provided if:
+ //
+ // (_POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600) && ! _GNU_SOURCE
+ //
+ // and a GNU specific version provided if _GNU_SOURCE is defined.
+ //
+ // libc provides bindings for the XSI-compliant version, which is
+ // preferred for portable applications.
+ //
+ // We skip the test here since here _GNU_SOURCE is defined, and
+ // test the XSI version below.
+ "strerror_r" => true,
_ => false,
}
});
- cfg.skip_static(move |name| {
- match name {
- // Internal constant, not declared in any headers.
- // FIXME: still necessary
- "__progname" => true,
- _ => false,
- }
- });
-
- // FIXME: still necessary?
cfg.skip_field_type(move |struct_, field| {
// This is a weird union, don't check the type.
(struct_ == "ifaddrs" && field == "ifa_ifu") ||
- // sighandler_t type is super weird
- (struct_ == "sigaction" && field == "sa_sigaction") ||
// sigval is actually a union, but we pretend it's a struct
- (struct_ == "sigevent" && field == "sigev_value") ||
- // aio_buf is "volatile void*" and Rust doesn't understand volatile
- (struct_ == "aiocb" && field == "aio_buf")
+ (struct_ == "sigevent" && field == "sigev_value")
});
- // FIXME: still necessary?
cfg.skip_field(move |struct_, field| {
// this is actually a union on linux, so we can't represent it well and
// just insert some padding.
(struct_ == "siginfo_t" && field == "_pad") ||
+ // FIXME: `sa_sigaction` has type `sighandler_t` but that type is
+ // incorrect, see: https://github.com/rust-lang/libc/issues/1359
+ (struct_ == "sigaction" && field == "sa_sigaction") ||
// sigev_notify_thread_id is actually part of a sigev_un union
(struct_ == "sigevent" && field == "sigev_notify_thread_id") ||
- // signalfd had SIGSYS fields added in Linux 4.18, but no libc release has them yet.
- (struct_ == "signalfd_siginfo" && (field == "ssi_addr_lsb" ||
- field == "_pad2" ||
- field == "ssi_syscall" ||
+ // signalfd had SIGSYS fields added in Android 4.19, but CI does not have that version yet.
+ (struct_ == "signalfd_siginfo" && (field == "ssi_syscall" ||
field == "ssi_call_addr" ||
field == "ssi_arch"))
});
- // FIXME: remove
- cfg.fn_cname(move |name, _cname| name.to_string());
-
cfg.generate("../src/lib.rs", "main.rs");
- // On Android also generate another script for testing linux/fcntl
- // declarations. These cannot be tested normally because including both
- // `linux/fcntl.h` and `fcntl.h` fails.
- //
- // FIXME: is still necessary?
- let mut cfg = ctest::TestGenerator::new();
- cfg.skip_type(|_| true)
- .skip_fn(|_| true)
- .skip_static(|_| true);
- cfg.header("linux/fcntl.h");
- cfg.header("net/if.h");
- cfg.header("linux/if.h");
- cfg.header("linux/quota.h");
- cfg.header("asm/termbits.h");
- cfg.skip_const(move |name| match name {
- "F_CANCELLK" | "F_ADD_SEALS" | "F_GET_SEALS" => false,
- "F_SEAL_SEAL" | "F_SEAL_SHRINK" | "F_SEAL_GROW" | "F_SEAL_WRITE" => {
- false
- }
- "BOTHER" => false,
- _ => true,
- });
- cfg.skip_struct(|s| s != "termios2");
- cfg.type_name(move |ty, is_struct, is_union| match ty {
- t if is_struct => format!("struct {}", t),
- t if is_union => format!("union {}", t),
- t => t.to_string(),
- });
- cfg.generate("../src/lib.rs", "linux_fcntl.rs");
+ test_linux_like_apis(target);
}
fn test_freebsd(target: &str) {
assert!(target.contains("freebsd"));
- let x86 = target.contains("i686") || target.contains("x86_64");
-
let mut cfg = ctest::TestGenerator::new();
+
+ let freebsd_ver = which_freebsd();
+
+ if let Some(12) = freebsd_ver {
+ // If the host is FreeBSD 12, run FreeBSD 12 tests
+ cfg.cfg("freebsd12", None);
+ }
+
// Required for `getline`:
cfg.define("_WITH_GETLINE", None);
+ // Required for making freebsd11_stat available in the headers
+ cfg.define("_WANT_FREEBSD11_STAT", None);
headers! { cfg:
"aio.h",
@@ -1655,19 +1525,18 @@ fn test_freebsd(target: &str) {
cfg.type_name(move |ty, is_struct, is_union| {
match ty {
// Just pass all these through, no need for a "struct" prefix
- // FIXME: still required?
- "FILE" | "fd_set" | "Dl_info" | "DIR" | "Elf32_Phdr"
- | "Elf64_Phdr" | "Elf32_Shdr" | "Elf64_Shdr" | "Elf32_Sym"
- | "Elf64_Sym" | "Elf32_Ehdr" | "Elf64_Ehdr" | "Elf32_Chdr"
- | "Elf64_Chdr" => ty.to_string(),
+ "FILE" | "fd_set" | "Dl_info" | "DIR" => ty.to_string(),
- // FIXME: still required?
+ // FIXME: https://github.com/rust-lang/libc/issues/1273
"sighandler_t" => "sig_t".to_string(),
t if is_union => format!("union {}", t),
t if t.ends_with("_t") => t.to_string(),
+ // sigval is a struct in Rust, but a union in C:
+ "sigval" => format!("union sigval"),
+
// put `struct` in front of all structs:.
t if is_struct => format!("struct {}", t),
@@ -1682,125 +1551,40 @@ fn test_freebsd(target: &str) {
s if s.ends_with("_nsec") && struct_.starts_with("stat") => {
s.replace("e_nsec", ".tv_nsec")
}
- // FIXME: still required?
- "u64" if struct_ == "epoll_event" => "data.u64".to_string(),
- // FIXME: still required?
- "type_"
- if struct_ == "input_event"
- || struct_ == "input_mask"
- || struct_ == "ff_effect"
- || struct_ == "rtprio" =>
- {
- "type".to_string()
- }
+ // Field is named `type` in C but that is a Rust keyword,
+ // so these fields are translated to `type_` in the bindings.
+ "type_" if struct_ == "rtprio" => "type".to_string(),
s => s.to_string(),
}
});
- cfg.skip_type(move |ty| {
- match ty {
- // sighandler_t is crazy across platforms
- // FIXME: still required?
- "sighandler_t" => true,
-
- _ => false,
- }
- });
-
- cfg.skip_struct(move |ty| {
- match ty {
- // This is actually a union, not a struct
- // FIXME: still required?
- "sigval" => true,
-
- // These are tested as part of the linux_fcntl tests since there are
- // header conflicts when including them with all the other structs.
- // FIXME: still required?
- "termios2" => true,
-
- _ => false,
- }
- });
-
- cfg.skip_signededness(move |c| {
- match c {
- // FIXME: still required?
- "LARGE_INTEGER" | "float" | "double" => true,
- // FIXME: still required?
- n if n.starts_with("pthread") => true,
- // sem_t is a struct or pointer
- // FIXME: still required?
- "sem_t" => true,
- // mqd_t is a pointer on FreeBSD
- // FIXME: still required?
- "mqd_t" => true,
-
- _ => false,
- }
- });
-
cfg.skip_const(move |name| {
match name {
- // FIXME: still required?
- "SIG_DFL" | "SIG_ERR" | "SIG_IGN" => true, // sighandler_t weirdness
- // FIXME: still required?
- "SIGUNUSED" => true, // removed in glibc 2.26
-
- // weird signed extension or something like that?
- // FIXME: still required?
- "MS_NOUSER" => true,
- // FIXME: still required?
- "MS_RMT_MASK" => true, // updated in glibc 2.22 and musl 1.1.13
+ // These constants were introduced in FreeBSD 12:
+ "SF_USER_READAHEAD"
+ | "EVFILT_EMPTY"
+ | "SO_REUSEPORT_LB"
+ | "IP_ORIGDSTADDR"
+ | "IP_RECVORIGDSTADDR"
+ | "IPV6_ORIGDSTADDR"
+ | "IPV6_RECVORIGDSTADDR"
+ if Some(12) != freebsd_ver =>
+ {
+ true
+ }
+ // FIXME: There are deprecated - remove in a couple of releases.
// These constants were removed in FreeBSD 11 (svn r273250) but will
// still be accepted and ignored at runtime.
- "MAP_RENAME" | "MAP_NORESERVE" => true,
+ "MAP_RENAME" | "MAP_NORESERVE" if Some(10) != freebsd_ver => true,
+ // FIXME: There are deprecated - remove in a couple of releases.
// These constants were removed in FreeBSD 11 (svn r262489),
// and they've never had any legitimate use outside of the
// base system anyway.
"CTL_MAXID" | "KERN_MAXID" | "HW_MAXID" | "NET_MAXID"
| "USER_MAXID" => true,
- // These constants were added in FreeBSD 11
- // FIXME: still required?
- "EVFILT_PROCDESC" | "EVFILT_SENDFILE" | "EVFILT_EMPTY"
- | "PD_CLOEXEC" | "PD_ALLOWED_AT_FORK" => true,
-
- // These constants were added in FreeBSD 12
- // FIXME: still required?
- "SF_USER_READAHEAD" | "SO_REUSEPORT_LB" => true,
-
- // These constants are tested in a separate test program generated
- // below because there are header conflicts if we try to include the
- // headers that define them here.
- // FIXME: still required?
- "F_CANCELLK" | "F_ADD_SEALS" | "F_GET_SEALS" => true,
- // FIXME: still required?
- "F_SEAL_SEAL" | "F_SEAL_SHRINK" | "F_SEAL_GROW"
- | "F_SEAL_WRITE" => true,
- // FIXME: still required?
- "BOTHER" => true,
-
- // MFD_HUGETLB is not available in some older libc versions on the
- // CI builders. On the x86_64 and i686 builders it seems to be
- // available for all targets, so at least test it there.
- // FIXME: still required?
- "MFD_HUGETLB" if !x86 => true,
-
- // These change all the time from release to release of linux
- // distros, let's just not bother trying to verify them. They
- // shouldn't be used in code anyway...
- // FIXME: still required?
- "AF_MAX" | "PF_MAX" => true,
-
- // FreeBSD 12 required, but CI has FreeBSD 11.
- // FIXME: still required?
- "IP_ORIGDSTADDR"
- | "IP_RECVORIGDSTADDR"
- | "IPV6_ORIGDSTADDR"
- | "IPV6_RECVORIGDSTADDR" => true,
-
_ => false,
}
});
@@ -1808,84 +1592,42 @@ fn test_freebsd(target: &str) {
cfg.skip_fn(move |name| {
// skip those that are manually verified
match name {
- // FIXME: still required?
- "execv" | // crazy stuff with const/mut
- "execve" |
- "execvp" |
- "execvpe" |
- "fexecve" => true,
-
- // FIXME: for some reason, our signature is wrong
- "gettimeofday" => true,
-
- // The `uname` function in freebsd is now an inline wrapper that
- // delegates to another, but the symbol still exists, so don't check
- // the symbol.
- // FIXME: still required?
- "uname" => true,
-
- // FIXME: need to upgrade FreeBSD version; see https://github.com/rust-lang/libc/issues/938
- // FIXME: still required?
- "setgrent" => true,
+ // FIXME: https://github.com/rust-lang/libc/issues/1272
+ "execv" | "execve" | "execvp" | "execvpe" | "fexecve" => true,
- // aio_waitcomplete's return type changed between FreeBSD 10 and 11.
- // FIXME: still required?
- "aio_waitcomplete" => true,
+ // The `uname` function in the `utsname.h` FreeBSD header is a C
+ // inline function (has no symbol) that calls the `__xuname` symbol.
+ // Therefore the function pointer comparison does not make sense for it.
+ "uname" => true,
- // lio_listio confuses the checker, probably because one of its
- // arguments is an array
- // FIXME: still required?
+ // FIXME: Our API is unsound. The Rust API allows aliasing
+ // pointers, but the C API requires pointers not to alias.
+ // We should probably be at least using `&`/`&mut` here, see:
+ // https://github.com/gnzlbg/ctest/issues/68
"lio_listio" => true,
- // Definition of those functions as changed since unified headers from NDK r14b
- // These changes imply some API breaking changes but are still ABI compatible.
- // We can wait for the next major release to be compliant with the new API.
- // FIXME: unskip these for next major release
- // FIXME: still required ?
- "strerror_r" | "madvise" | "msync" | "mprotect" | "recvfrom" | "getpriority" |
-
_ => false,
}
});
- cfg.skip_field_type(move |struct_, field| {
- // This is a weird union, don't check the type.
- // FIXME: still required?
- (struct_ == "ifaddrs" && field == "ifa_ifu") ||
- // FIXME: still required?
- // sighandler_t type is super weird
- (struct_ == "sigaction" && field == "sa_sigaction") ||
- // FIXME: still required?
- // sigval is actually a union, but we pretend it's a struct
- (struct_ == "sigevent" && field == "sigev_value") ||
- // aio_buf is "volatile void*" and Rust doesn't understand volatile
- // FIXME: still required?
- (struct_ == "aiocb" && field == "aio_buf") ||
- // stack_t.ss_sp's type changed from FreeBSD 10 to 11 in svn r294930
- // FIXME: still required?
- (struct_ == "stack_t" && field == "ss_sp")
+ cfg.volatile_item(|i| {
+ use ctest::VolatileItemKind::*;
+ match i {
+ // aio_buf is a volatile void** but since we cannot express that in
+ // Rust types, we have to explicitly tell the checker about it here:
+ StructField(ref n, ref f) if n == "aiocb" && f == "aio_buf" => {
+ true
+ }
+ _ => false,
+ }
});
cfg.skip_field(move |struct_, field| {
- // this is actually a union on linux, so we can't represent it well and
- // just insert some padding.
- // FIXME: still required?
- (struct_ == "siginfo_t" && field == "_pad") ||
- // sigev_notify_thread_id is actually part of a sigev_un union
- // FIXME: still required?
- (struct_ == "sigevent" && field == "sigev_notify_thread_id") ||
- // signalfd had SIGSYS fields added in Linux 4.18, but no libc release has them yet.
- // FIXME: still required?
- (struct_ == "signalfd_siginfo" && (field == "ssi_addr_lsb" ||
- field == "_pad2" ||
- field == "ssi_syscall" ||
- field == "ssi_call_addr" ||
- field == "ssi_arch"))
+ // FIXME: `sa_sigaction` has type `sighandler_t` but that type is
+ // incorrect, see: https://github.com/rust-lang/libc/issues/1359
+ (struct_ == "sigaction" && field == "sa_sigaction")
});
- // FIXME: remove
- cfg.fn_cname(move |name, _cname| name.to_string());
-
cfg.generate("../src/lib.rs", "main.rs");
}
@@ -1893,11 +1635,7 @@ fn test_emscripten(target: &str) {
assert!(target.contains("emscripten"));
let mut cfg = ctest::TestGenerator::new();
- // FIXME: still necessary?
- cfg.define("_GNU_SOURCE", None);
-
- // FIXME: still necessary?
- cfg.flag("-Wno-deprecated-declarations");
+ cfg.define("_GNU_SOURCE", None); // FIXME: ??
headers! { cfg:
"aio.h",
@@ -1990,11 +1728,7 @@ fn test_emscripten(target: &str) {
cfg.type_name(move |ty, is_struct, is_union| {
match ty {
// Just pass all these through, no need for a "struct" prefix
- // FIXME: is this necessary?
- "FILE" | "fd_set" | "Dl_info" | "DIR" | "Elf32_Phdr"
- | "Elf64_Phdr" | "Elf32_Shdr" | "Elf64_Shdr" | "Elf32_Sym"
- | "Elf64_Sym" | "Elf32_Ehdr" | "Elf64_Ehdr" | "Elf32_Chdr"
- | "Elf64_Chdr" => ty.to_string(),
+ "FILE" | "fd_set" | "Dl_info" | "DIR" => ty.to_string(),
t if is_union => format!("union {}", t),
@@ -2014,7 +1748,7 @@ fn test_emscripten(target: &str) {
s if s.ends_with("_nsec") && struct_.starts_with("stat") => {
s.replace("e_nsec", ".tv_nsec")
}
- // FIXME: is this necessary?
+ // FIXME: appears that `epoll_event.data` is an union
"u64" if struct_ == "epoll_event" => "data.u64".to_string(),
s => s.to_string(),
}
@@ -2032,157 +1766,31 @@ fn test_emscripten(target: &str) {
cfg.skip_struct(move |ty| {
match ty {
- // FIXME: is this necessary?
- "sockaddr_nl" => true,
-
// This is actually a union, not a struct
// FIXME: is this necessary?
"sigval" => true,
- // Linux kernel headers used on musl are too old to have this
- // definition. Because it's tested on other Linux targets, skip it.
- // FIXME: is this necessary?
- "input_mask" => true,
-
- // These are tested as part of the linux_fcntl tests since there are
- // header conflicts when including them with all the other structs.
- // FIXME: is this necessary?
- "termios2" => true,
-
_ => false,
}
});
- cfg.skip_signededness(move |c| match c {
- // FIXME: is this necessary?
- "LARGE_INTEGER" | "float" | "double" => true,
- // FIXME: is this necessary?
- n if n.starts_with("pthread") => true,
- _ => false,
- });
-
- cfg.skip_const(move |name| {
+ cfg.skip_fn(move |name| {
match name {
- // FIXME: is this necessary?
- "SIG_DFL" | "SIG_ERR" | "SIG_IGN" => true, // sighandler_t weirdness
- // FIXME: is this necessary?
- "SIGUNUSED" => true, // removed in glibc 2.26
-
- // types on musl are defined a little differently
- // FIXME: is this necessary?
- n if n.contains("__SIZEOF_PTHREAD") => true,
-
- // Skip constants not defined in MUSL but just passed down to the
- // kernel regardless
- // FIXME: is this necessary?
- "RLIMIT_NLIMITS"
- | "TCP_COOKIE_TRANSACTIONS"
- | "RLIMIT_RTTIME"
- | "MSG_COPY"
- =>
- {
- true
- }
-
- // weird signed extension or something like that?
- // FIXME: is this necessary?
- "MS_NOUSER" => true,
- // FIXME: is this necessary?
- "MS_RMT_MASK" => true, // updated in glibc 2.22 and musl 1.1.13
-
- // Musl uses old, patched kernel headers
- // FIXME: is this necessary?
- "FALLOC_FL_COLLAPSE_RANGE"
- | "FALLOC_FL_ZERO_RANGE"
- | "FALLOC_FL_INSERT_RANGE"
- | "FALLOC_FL_UNSHARE_RANGE"
- | "RENAME_NOREPLACE"
- | "RENAME_EXCHANGE"
- | "RENAME_WHITEOUT"
- // ALG_SET_AEAD_* constants are available starting from kernel 3.19
- | "ALG_SET_AEAD_ASSOCLEN"
- | "ALG_SET_AEAD_AUTHSIZE"
- =>
- {
- true
- }
-
- // musl uses old kernel headers
- // These are constants used in getrandom syscall
- // FIXME: is this necessary?
- "GRND_NONBLOCK" | "GRND_RANDOM" => true,
-
-
- // These constants are tested in a separate test program generated below because there
- // are header conflicts if we try to include the headers that define them here.
- // FIXME: is this necessary?
- "F_CANCELLK" | "F_ADD_SEALS" | "F_GET_SEALS" => true,
- // FIXME: is this necessary?
- "F_SEAL_SEAL" | "F_SEAL_SHRINK" | "F_SEAL_GROW"
- | "F_SEAL_WRITE" => true,
- // FIXME: is this necessary?
- "BOTHER" => true,
-
- // FIXME: is this necessary?
- "MFD_CLOEXEC" | "MFD_ALLOW_SEALING" => true,
- // MFD_HUGETLB is not available in some older libc versions on the CI builders. On the
- // x86_64 and i686 builders it seems to be available for all targets, so at least test
- // it there.
- // FIXME: is this necessary?
- "MFD_HUGETLB" =>
- {
- true
- }
-
- // These are defined for Solaris 11, but the crate is tested on
- // illumos, where they are currently not defined
- // FIXME: is this necessary?
- "EADI"
- | "PORT_SOURCE_POSTWAIT"
- | "PORT_SOURCE_SIGNAL"
- | "PTHREAD_STACK_MIN" => true,
-
- // These change all the time from release to release of linux
- // distros, let's just not bother trying to verify them. They
- // shouldn't be used in code anyway...
- // FIXME: is this necessary?
- "AF_MAX" | "PF_MAX" => true,
+ // FIXME: https://github.com/rust-lang/libc/issues/1272
+ "execv" | "execve" | "execvp" | "execvpe" | "fexecve" => true,
_ => false,
}
});
- cfg.skip_fn(move |name| {
- // skip those that are manually verified
+ cfg.skip_const(move |name| {
match name {
- // FIXME: is this necessary?
- "execv" | // crazy stuff with const/mut
- "execve" |
- "execvp" |
- "execvpe" |
- "fexecve" => true,
+ // FIXME: deprecated - SIGNUNUSED was removed in glibc 2.26
+ // users should use SIGSYS instead
+ "SIGUNUSED" => true,
- "getrlimit" | "getrlimit64" | // non-int in 1st arg
- "setrlimit" | "setrlimit64" | // non-int in 1st arg
- "prlimit" | "prlimit64" | // non-int in 2nd arg
-
- // int vs uint. Sorry musl, your prototype declarations are "correct" in the sense that
- // they match the interface defined by Linux verbatim, but they conflict with other
- // send*/recv* syscalls
- // FIXME: is this necessary?
- "sendmmsg" | "recvmmsg" => true,
-
- // FIXME: is this necessary?
- "dladdr" => true, // const-ness only added recently
-
- // FIXME: is this necessary?
- "lio_listio" => true,
-
- // Definition of those functions as changed since unified headers from NDK r14b
- // These changes imply some API breaking changes but are still ABI compatible.
- // We can wait for the next major release to be compliant with the new API.
- // FIXME: unskip these for next major release
- "strerror_r" | "madvise" | "msync" | "mprotect" | "recvfrom" | "getpriority" |
+ // FIXME: emscripten uses different constants to constructs these
+ n if n.contains("__SIZEOF_PTHREAD") => true,
_ => false,
}
@@ -2224,9 +1832,7 @@ fn test_emscripten(target: &str) {
field == "ssi_arch"))
});
- // FIXME: remove
- cfg.fn_cname(move |name, _cname| name.to_string());
-
+ // FIXME: test linux like
cfg.generate("../src/lib.rs", "main.rs");
}
@@ -2248,22 +1854,21 @@ fn test_linux(target: &str) {
),
}
- let mips = target.contains("mips");
- let i686 = target.contains("i686");
+ let arm = target.contains("arm");
let x86_64 = target.contains("x86_64");
- let x32 = target.ends_with("gnux32");
+ let x86_32 = target.contains("i686");
+ let x32 = target.contains("x32");
+ let mips = target.contains("mips");
+ let mips32_musl = mips && !target.contains("64") && musl;
+ let sparc64 = target.contains("sparc64");
let mut cfg = ctest::TestGenerator::new();
- // FIXME: still necessary?
cfg.define("_GNU_SOURCE", None);
// This macro re-deifnes fscanf,scanf,sscanf to link to the symbols that are
// deprecated since glibc >= 2.29. This allows Rust binaries to link against
// glibc versions older than 2.29.
cfg.define("__GLIBC_USE_DEPRECATED_SCANF", None);
- // FIXME: still necessary?
- cfg.flag("-Wno-deprecated-declarations");
-
headers! { cfg:
"ctype.h",
"dirent.h",
@@ -2319,6 +1924,8 @@ fn test_linux(target: &str) {
"sys/prctl.h",
"sys/ptrace.h",
"sys/quota.h",
+ // FIXME: the mips-musl CI build jobs use ancient musl 1.0.15:
+ [!mips32_musl]: "sys/random.h",
"sys/reboot.h",
"sys/resource.h",
"sys/sem.h",
@@ -2347,86 +1954,61 @@ fn test_linux(target: &str) {
"unistd.h",
"utime.h",
"utmp.h",
+ "utmpx.h",
"wchar.h",
"errno.h",
+ // `sys/io.h` is only available on x86*, Alpha, IA64, and 32-bit
+ // ARM: https://bugzilla.redhat.com/show_bug.cgi?id=1116162
+ [x86_64 || x86_32 || arm]: "sys/io.h",
+ // `sys/reg.h` is only available on x86 and x86_64
+ [x86_64 || x86_32]: "sys/reg.h",
+ // sysctl system call is deprecated and not available on musl
+ // It is also unsupported in x32:
+ [!(x32 || musl)]: "sys/sysctl.h",
+ // <execinfo.h> is not supported by musl:
+ // https://www.openwall.com/lists/musl/2015/04/09/3
+ [!musl]: "execinfo.h",
}
// Include linux headers at the end:
headers! {
cfg:
+ "asm/mman.h",
+ "linux/dccp.h",
"linux/falloc.h",
- "linux/futex.h",
"linux/fs.h",
+ "linux/futex.h",
"linux/genetlink.h",
+ // FIXME: musl version 1.0.15 used by mips build jobs is ancient
+ [!mips32_musl]: "linux/if.h",
+ "linux/if_addr.h",
"linux/if_alg.h",
"linux/if_ether.h",
"linux/if_tun.h",
"linux/input.h",
+ "linux/magic.h",
+ "linux/memfd.h",
"linux/module.h",
"linux/net_tstamp.h",
+ "linux/netfilter/nf_tables.h",
"linux/netfilter_ipv4.h",
"linux/netfilter_ipv6.h",
"linux/netlink.h",
+ "linux/quota.h",
"linux/random.h",
+ "linux/reboot.h",
+ "linux/rtnetlink.h",
"linux/seccomp.h",
"linux/sockios.h",
- }
-
- if x86_64 {
- headers! { cfg: "sys/io.h" };
- }
- if i686 || x86_64 {
- headers! { cfg: "sys/reg.h" };
- }
-
- if !musl {
- assert!(uclibc || gnu);
- headers! { cfg:
- "asm/mman.h",
- "linux/if.h",
- "linux/magic.h",
- "linux/netfilter/nf_tables.h",
- "linux/reboot.h",
- "sys/auxv.h",
- };
-
- if !x32 {
- assert!((gnu || uclibc) && !x32);
- headers! { cfg: "sys/sysctl.h", }
- }
- if !uclibc {
- assert!(gnu);
- headers! { cfg:
- "execinfo.h",
- "utmpx.h",
- }
- }
- if !mips {
- assert!((gnu || uclibc) && !mips);
- headers! { cfg: "linux/quota.h" };
- }
- }
-
- // DCCP support
- if !uclibc && !musl {
- assert!(gnu);
- headers! { cfg: "linux/dccp.h" };
- }
-
- if !musl || mips {
- assert!(gnu || uclibc || (mips && musl));
- headers! { cfg: "linux/memfd.h" };
+ "sys/auxv.h",
}
// note: aio.h must be included before sys/mount.h
- if !uclibc {
- assert!(gnu || musl);
- // optionally included in uclibc
- headers! { cfg:
- "sys/xattr.h",
- "sys/sysinfo.h",
- "aio.h",
- }
+ headers! {
+ cfg:
+ "sys/xattr.h",
+ "sys/sysinfo.h",
+ "aio.h",
}
cfg.type_name(move |ty, is_struct, is_union| {
@@ -2455,42 +2037,48 @@ fn test_linux(target: &str) {
s if s.ends_with("_nsec") && struct_.starts_with("stat") => {
s.replace("e_nsec", ".tv_nsec")
}
- // FIXME: is this necessary?
+ // FIXME: epoll_event.data is actuall a union in C, but in Rust
+ // it is only a u64 because we only expose one field
+ // http://man7.org/linux/man-pages/man2/epoll_wait.2.html
"u64" if struct_ == "epoll_event" => "data.u64".to_string(),
- // FIXME: is this necessary?
+ // The following structs have a field called `type` in C,
+ // but `type` is a Rust keyword, so these fields are translated
+ // to `type_` in Rust.
"type_"
if struct_ == "input_event"
|| struct_ == "input_mask"
- || struct_ == "ff_effect"
- || struct_ == "rtprio" =>
+ || struct_ == "ff_effect" =>
{
"type".to_string()
}
+
s => s.to_string(),
}
});
cfg.skip_type(move |ty| {
match ty {
- // sighandler_t is crazy across platforms
- // FIXME: is this necessary?
+ // FIXME: `sighandler_t` type is incorrect, see:
+ // https://github.com/rust-lang/libc/issues/1359
"sighandler_t" => true,
// These cannot be tested when "resolv.h" is included and are tested
- // below.
+ // in the `linux_elf.rs` file.
"Elf64_Phdr" | "Elf32_Phdr" => true,
+ // This type is private on Linux. It is implemented as a C `enum`
+ // (`c_uint`) and this clashes with the type of the `rlimit` APIs
+ // which expect a `c_int` even though both are ABI compatible.
+ "__rlimit_resource_t" => true,
+
_ => false,
}
});
cfg.skip_struct(move |ty| {
match ty {
- // FIXME: is this necessary?
- "sockaddr_nl" if musl => true,
-
// These cannot be tested when "resolv.h" is included and are tested
- // below.
+ // in the `linux_elf.rs` file.
"Elf64_Phdr" | "Elf32_Phdr" => true,
// On Linux, the type of `ut_tv` field of `struct utmpx`
@@ -2498,184 +2086,79 @@ fn test_linux(target: &str) {
// which is absent in glibc, has to be defined.
"__timeval" => true,
- // This is actually a union, not a struct
+ // FIXME: This is actually a union, not a struct
"sigval" => true,
- // Linux kernel headers used on musl are too old to have this
- // definition. Because it's tested on other Linux targets, skip it.
- // FIXME: is this necessary?
- "input_mask" if musl => true,
-
- // These are tested as part of the linux_fcntl tests since there are
- // header conflicts when including them with all the other structs.
- // FIXME: is this necessary?
+ // This type is tested in the `linux_termios.rs` file since there
+ // are header conflicts when including them with all the other
+ // structs.
"termios2" => true,
+ // FIXME: musl version using by mips build jobs 1.0.15 is ancient:
+ "ifmap" | "ifreq" | "ifconf" if mips32_musl => true,
+
_ => false,
}
});
- cfg.skip_signededness(move |c| match c {
- // FIXME: is this necessary?
- "LARGE_INTEGER" | "float" | "double" => true,
- // FIXME: is this necessary?
- n if n.starts_with("pthread") => true,
- _ => false,
- });
-
cfg.skip_const(move |name| {
match name {
- // FIXME: is this necessary?
- "SIG_DFL" | "SIG_ERR" | "SIG_IGN" => true, // sighandler_t weirdness
- // FIXME: is this necessary?
- "SIGUNUSED" => true, // removed in glibc 2.26
-
- // types on musl are defined a little differently
- // FIXME: is this necessary?
- n if musl && n.contains("__SIZEOF_PTHREAD") => true,
-
- // Skip constants not defined in MUSL but just passed down to the
- // kernel regardless
- // FIXME: is this necessary?
- "RLIMIT_NLIMITS"
- | "TCP_COOKIE_TRANSACTIONS"
- | "RLIMIT_RTTIME"
- | "MSG_COPY"
- if musl =>
- {
- true
- }
- // work around super old mips toolchain
- // FIXME: is this necessary?
- "SCHED_IDLE" | "SHM_NORESERVE" => mips,
-
- // weird signed extension or something like that?
- // FIXME: is this necessary?
- "MS_NOUSER" => true,
- // FIXME: is this necessary?
- "MS_RMT_MASK" => true, // updated in glibc 2.22 and musl 1.1.13
-
- // These are either unimplemented or optionally built into uClibc
- // FIXME: is this necessary?
- "LC_CTYPE_MASK"
- | "LC_NUMERIC_MASK"
- | "LC_TIME_MASK"
- | "LC_COLLATE_MASK"
- | "LC_MONETARY_MASK"
- | "LC_MESSAGES_MASK"
- | "MADV_MERGEABLE"
- | "MADV_UNMERGEABLE"
- | "MADV_HWPOISON"
- | "IPV6_ADD_MEMBERSHIP"
- | "IPV6_DROP_MEMBERSHIP"
- | "IPV6_MULTICAST_LOOP"
- | "IPV6_V6ONLY"
- | "MAP_STACK"
- | "RTLD_DEEPBIND"
- | "SOL_IPV6"
- | "SOL_ICMPV6"
- if uclibc =>
- {
- true
- }
+ // These constants are not available if gnu headers have been included
+ // and can therefore not be tested here
+ //
+ // The IPV6 constants are tested in the `linux_ipv6.rs` tests:
+ | "IPV6_FLOWINFO"
+ | "IPV6_FLOWLABEL_MGR"
+ | "IPV6_FLOWINFO_SEND"
+ | "IPV6_FLOWINFO_FLOWLABEL"
+ | "IPV6_FLOWINFO_PRIORITY"
+ // The F_ fnctl constants are tested in the `linux_fnctl.rs` tests:
+ | "F_CANCELLK"
+ | "F_ADD_SEALS"
+ | "F_GET_SEALS"
+ | "F_SEAL_SEAL"
+ | "F_SEAL_SHRINK"
+ | "F_SEAL_GROW"
+ | "F_SEAL_WRITE" => true,
- // Musl uses old, patched kernel headers
- // FIXME: is this necessary?
- "FALLOC_FL_COLLAPSE_RANGE"
- | "FALLOC_FL_ZERO_RANGE"
- | "FALLOC_FL_INSERT_RANGE"
+ // The musl-sanitized kernel headers used in CI
+ // target the Linux kernel 4.4 and do not contain the
+ // following constants:
+ //
+ // Requires Linux kernel 4.9
| "FALLOC_FL_UNSHARE_RANGE"
- | "RENAME_NOREPLACE"
- | "RENAME_EXCHANGE"
- | "RENAME_WHITEOUT"
- // ALG_SET_AEAD_* constants are available starting from kernel 3.19
- | "ALG_SET_AEAD_ASSOCLEN"
- | "ALG_SET_AEAD_AUTHSIZE"
- if musl =>
- {
- true
- }
-
- // musl uses old kernel headers
- // These are constants used in getrandom syscall
- // FIXME: is this necessary?
- "GRND_NONBLOCK" | "GRND_RANDOM" if musl => true,
-
- // Defined by libattr not libc on linux (hard to test).
- // See constant definition for more details.
- // FIXME: is this necessary?
+ //
+ // Require Linux kernel 5.x:
+ | "MSG_COPY"
+ if musl => true,
+ // Require Linux kernel 5.1:
+ "F_SEAL_FUTURE_WRITE" => true,
+
+ // The musl version 1.0.22 used in CI does not
+ // contain these glibc constants yet:
+ | "RLIMIT_RTTIME" // should be in `resource.h`
+ | "TCP_COOKIE_TRANSACTIONS" // should be in the `netinet/tcp.h` header
+ if musl => true,
+
+ // FIXME: deprecated: not available in any header
+ // See: https://github.com/rust-lang/libc/issues/1356
"ENOATTR" => true,
- // On mips*-unknown-linux-gnu* CMSPAR cannot be included with the set of headers we
- // want to use here for testing. It's originally defined in asm/termbits.h, which is
- // also included by asm/termios.h, but not the standard termios.h. There's no way to
- // include both asm/termbits.h and termios.h and there's no way to include both
- // asm/termios.h and ioctl.h (+ some other headers) because of redeclared types.
- // FIXME: is this necessary?
- "CMSPAR" if mips && !musl => true,
-
- // On mips Linux targets, MADV_SOFT_OFFLINE is currently missing, though it's been added but CI has too old
- // of a Linux version. Since it exists on all other Linux targets, just ignore this for now and remove once
- // it's been fixed in CI.
- // FIXME: is this necessary?
- "MADV_SOFT_OFFLINE" if mips => true,
+ // FIXME: SIGUNUSED was removed in glibc 2.26
+ // Users should use SIGSYS instead.
+ "SIGUNUSED" => true,
- // These constants are tested in a separate test program generated below because there
- // are header conflicts if we try to include the headers that define them here.
- // FIXME: is this necessary?
- "F_CANCELLK" | "F_ADD_SEALS" | "F_GET_SEALS" => true,
- // FIXME: is this necessary?
- "F_SEAL_SEAL" | "F_SEAL_SHRINK" | "F_SEAL_GROW"
- | "F_SEAL_WRITE" => true,
- // FIXME: is this necessary?
- "QFMT_VFS_OLD" | "QFMT_VFS_V0" | "QFMT_VFS_V1"
- if mips =>
- {
- true
- } // Only on MIPS
- // FIXME: is this necessary?
+ // FIXME: conflicts with glibc headers and is tested in
+ // `linux_termios.rs` below:
"BOTHER" => true,
- // FIXME: is this necessary?
- "MFD_CLOEXEC" | "MFD_ALLOW_SEALING" if !mips && musl => true,
- // MFD_HUGETLB is not available in some older libc versions on the CI builders. On the
- // x86_64 and i686 builders it seems to be available for all targets, so at least test
- // it there.
- // FIXME: is this necessary?
- "MFD_HUGETLB"
- if !(x86_64 || i686) || musl =>
- {
- true
- }
-
- // These are defined for Solaris 11, but the crate is tested on
- // illumos, where they are currently not defined
- // FIXME: is this necessary?
- "EADI"
- | "PORT_SOURCE_POSTWAIT"
- | "PORT_SOURCE_SIGNAL"
- | "PTHREAD_STACK_MIN" => true,
-
- // These change all the time from release to release of linux
- // distros, let's just not bother trying to verify them. They
- // shouldn't be used in code anyway...
- // FIXME: is this necessary?
- "AF_MAX" | "PF_MAX" => true,
+ // FIXME: on musl the pthread types are defined a little differently
+ // - these constants are used by the glibc implementation.
+ n if musl && n.contains("__SIZEOF_PTHREAD") => true,
- // These are not in a glibc release yet, only in kernel headers.
- // FIXME: is this necessary?
- "AF_XDP"
- | "PF_XDP"
- | "SOL_XDP"
- | "IPV6_FLOWINFO"
- | "IPV6_FLOWLABEL_MGR"
- | "IPV6_FLOWINFO_SEND"
- | "IPV6_FLOWINFO_FLOWLABEL"
- | "IPV6_FLOWINFO_PRIORITY"
- =>
- {
- true
- }
+ // FIXME: musl version 1.0.15 used by mips build jobs is ancient
+ t if mips32_musl && t.starts_with("IFF") => true,
+ "MFD_HUGETLB" | "AF_XDP" | "PF_XDP" if mips32_musl => true,
_ => false,
}
@@ -2684,70 +2167,41 @@ fn test_linux(target: &str) {
cfg.skip_fn(move |name| {
// skip those that are manually verified
match name {
- "execv" | // crazy stuff with const/mut
- "execve" |
- "execvp" |
- "execvpe" |
- "fexecve" => true,
-
- "getrlimit" | "getrlimit64" | // non-int in 1st arg
- "setrlimit" | "setrlimit64" | // non-int in 1st arg
- "prlimit" | "prlimit64" // non-int in 2nd arg
- => true,
-
- // int vs uint. Sorry musl, your prototype declarations are "correct" in the sense that
- // they match the interface defined by Linux verbatim, but they conflict with other
- // send*/recv* syscalls
- // FIXME: is this necessary?
- "sendmmsg" | "recvmmsg" if musl => true,
-
- // typed 2nd arg on linux
- // FIXME: is this necessary?
- "gettimeofday" => true,
-
- // FIXME: is this necessary?
- "dladdr" if musl => true, // const-ness only added recently
+ // FIXME: https://github.com/rust-lang/libc/issues/1272
+ "execv" | "execve" | "execvp" | "execvpe" | "fexecve" => true,
- // There seems to be a small error in EGLIBC's eventfd.h header. The
- // [underlying system call][1] always takes its first `count`
- // argument as an `unsigned int`, but [EGLIBC's <sys/eventfd.h>
- // header][2] declares it to take an `int`. [GLIBC's header][3]
- // matches the kernel.
+ // There are two versions of the sterror_r function, see
//
- // EGLIBC is no longer actively developed, and Debian, the largest
- // distribution that had been using it, switched back to GLIBC in
- // April 2015. So effectively all Linux <sys/eventfd.h> headers will
- // be using `unsigned int` soon.
+ // https://linux.die.net/man/3/strerror_r
//
- // [1]: https://git.kernel.org/cgit/linux/kernel/git/stable/linux-stable.git/tree/fs/eventfd.c?id=refs/tags/v3.12.51#n397
- // [2]: http://bazaar.launchpad.net/~ubuntu-branches/ubuntu/trusty/eglibc/trusty/view/head:/sysdeps/unix/sysv/linux/sys/eventfd.h
- // [3]: https://sourceware.org/git/?p=glibc.git;a=blob;f=sysdeps/unix/sysv/linux/sys/eventfd.h;h=6295f32e937e779e74318eb9d3bdbe76aef8a8f3;hb=4e42b5b8f89f0e288e68be7ad70f9525aebc2cff#l34
- // FIXME: is this necessary?
- "eventfd" => true,
-
+ // An XSI-compliant version provided if:
+ //
+ // (_POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600)
+ // && ! _GNU_SOURCE
+ //
+ // and a GNU specific version provided if _GNU_SOURCE is defined.
+ //
+ // libc provides bindings for the XSI-compliant version, which is
+ // preferred for portable applications.
+ //
+ // We skip the test here since here _GNU_SOURCE is defined, and
+ // test the XSI version below.
+ "strerror_r" => true,
+
+ // FIXME: Our API is unsound. The Rust API allows aliasing
+ // pointers, but the C API requires pointers not to alias.
+ // We should probably be at least using `&`/`&mut` here, see:
+ // https://github.com/gnzlbg/ctest/issues/68
"lio_listio" if musl => true,
- // These are either unimplemented or optionally built into uClibc
- // or "sysinfo", where it's defined but the structs in linux/sysinfo.h and sys/sysinfo.h
- // clash so it can't be tested
- "getxattr" | "lgetxattr" | "fgetxattr" | "setxattr" | "lsetxattr" | "fsetxattr" |
- "listxattr" | "llistxattr" | "flistxattr" | "removexattr" | "lremovexattr" |
- "fremovexattr" |
- "backtrace" |
- "sysinfo" | "newlocale" | "duplocale" | "freelocale" | "uselocale" |
- "nl_langinfo_l" | "wcslen" | "wcstombs" if uclibc => true,
-
- // Definition of those functions as changed since unified headers from NDK r14b
- // These changes imply some API breaking changes but are still ABI compatible.
- // We can wait for the next major release to be compliant with the new API.
- // FIXME: unskip these for next major release
- "strerror_r" | "madvise" | "msync" | "mprotect" | "recvfrom" | "getpriority" => true,
+ // FIXME: the glibc version used by the Sparc64 build jobs
+ // which use Debian 10.0 is too old.
+ "statx" if sparc64 => true,
_ => false,
}
});
- // FIXME: is this necessary?
cfg.skip_field_type(move |struct_, field| {
// This is a weird union, don't check the type.
(struct_ == "ifaddrs" && field == "ifa_ifu") ||
@@ -2757,12 +2211,22 @@ fn test_linux(target: &str) {
(struct_ == "utmpx" && field == "ut_tv") ||
// sigval is actually a union, but we pretend it's a struct
(struct_ == "sigevent" && field == "sigev_value") ||
- // aio_buf is "volatile void*" and Rust doesn't understand volatile
- (struct_ == "aiocb" && field == "aio_buf") ||
// this one is an anonymous union
(struct_ == "ff_effect" && field == "u")
});
+ cfg.volatile_item(|i| {
+ use ctest::VolatileItemKind::*;
+ match i {
+ // aio_buf is a volatile void** but since we cannot express that in
+ // Rust types, we have to explicitly tell the checker about it here:
+ StructField(ref n, ref f) if n == "aiocb" && f == "aio_buf" => {
+ true
+ }
+ _ => false,
+ }
+ });
+
cfg.skip_field(move |struct_, field| {
// this is actually a union on linux, so we can't represent it well and
// just insert some padding.
@@ -2773,7 +2237,8 @@ fn test_linux(target: &str) {
(musl && struct_ == "statvfs" && field == "__f_unused") ||
// sigev_notify_thread_id is actually part of a sigev_un union
(struct_ == "sigevent" && field == "sigev_notify_thread_id") ||
- // signalfd had SIGSYS fields added in Linux 4.18, but no libc release has them yet.
+ // signalfd had SIGSYS fields added in Linux 4.18, but no libc release
+ // has them yet.
(struct_ == "signalfd_siginfo" && (field == "ssi_addr_lsb" ||
field == "_pad2" ||
field == "ssi_syscall" ||
@@ -2781,70 +2246,148 @@ fn test_linux(target: &str) {
field == "ssi_arch"))
});
- // FIXME: remove
- cfg.fn_cname(move |name, _cname| name.to_string());
-
cfg.generate("../src/lib.rs", "main.rs");
- // On Linux also generate another script for testing linux/fcntl declarations.
- // These cannot be tested normally because including both `linux/fcntl.h` and `fcntl.h`
- // fails on a lot of platforms.
- let mut cfg = ctest::TestGenerator::new();
- cfg.skip_type(|_| true)
- .skip_fn(|_| true)
- .skip_static(|_| true);
- // musl defines these directly in `fcntl.h`
- if musl {
- cfg.header("fcntl.h");
- } else {
- cfg.header("linux/fcntl.h");
+ test_linux_like_apis(target);
+}
+
+// This function tests APIs that are incompatible to test when other APIs
+// are included (e.g. because including both sets of headers clashes)
+fn test_linux_like_apis(target: &str) {
+ let musl = target.contains("musl");
+ let linux = target.contains("linux");
+ let emscripten = target.contains("emscripten");
+ let android = target.contains("android");
+ assert!(linux || android || emscripten);
+
+ if linux || android || emscripten {
+ // test strerror_r from the `string.h` header
+ let mut cfg = ctest::TestGenerator::new();
+ cfg.skip_type(|_| true).skip_static(|_| true);
+
+ headers! { cfg: "string.h" }
+ cfg.skip_fn(|f| match f {
+ "strerror_r" => false,
+ _ => true,
+ })
+ .skip_const(|_| true)
+ .skip_struct(|_| true);
+ cfg.generate("../src/lib.rs", "linux_strerror_r.rs");
}
- if !musl {
- cfg.header("net/if.h");
- cfg.header("linux/if.h");
+
+ if linux || android || emscripten {
+ // test fcntl - see:
+ // http://man7.org/linux/man-pages/man2/fcntl.2.html
+ let mut cfg = ctest::TestGenerator::new();
+
+ if musl {
+ cfg.header("fcntl.h");
+ } else {
+ cfg.header("linux/fcntl.h");
+ }
+
+ cfg.skip_type(|_| true)
+ .skip_static(|_| true)
+ .skip_struct(|_| true)
+ .skip_fn(|_| true)
+ .skip_const(move |name| match name {
+ // test fcntl constants:
+ "F_CANCELLK" | "F_ADD_SEALS" | "F_GET_SEALS"
+ | "F_SEAL_SEAL" | "F_SEAL_SHRINK" | "F_SEAL_GROW"
+ | "F_SEAL_WRITE" => false,
+ _ => true,
+ })
+ .type_name(move |ty, is_struct, is_union| match ty {
+ t if is_struct => format!("struct {}", t),
+ t if is_union => format!("union {}", t),
+ t => t.to_string(),
+ });
+
+ cfg.generate("../src/lib.rs", "linux_fcntl.rs");
}
- cfg.header("linux/quota.h");
- cfg.header("asm/termbits.h");
- cfg.skip_const(move |name| match name {
- "F_CANCELLK" | "F_ADD_SEALS" | "F_GET_SEALS" => false,
- "F_SEAL_SEAL" | "F_SEAL_SHRINK" | "F_SEAL_GROW" | "F_SEAL_WRITE" => {
- false
- }
- "QFMT_VFS_OLD" | "QFMT_VFS_V0" | "QFMT_VFS_V1" if mips => false,
- "BOTHER" => false,
- _ => true,
- });
- cfg.skip_struct(|s| s != "termios2");
- cfg.type_name(move |ty, is_struct, is_union| match ty {
- t if is_struct => format!("struct {}", t),
- t if is_union => format!("union {}", t),
- t => t.to_string(),
- });
- cfg.generate("../src/lib.rs", "linux_fcntl.rs");
- // Test Elf64_Phdr and Elf32_Phdr
- // These types have a field called `p_type`, but including
- // "resolve.h" defines a `p_type` macro that expands to `__p_type`
- // making the tests for these fails when both are included.
- let mut cfg = ctest::TestGenerator::new();
- cfg.skip_fn(|_| true)
- .skip_const(|_| true)
- .skip_static(|_| true)
- .type_name(move |ty, _is_struct, _is_union| {
- ty.to_string()
- });
- cfg.skip_struct(move |ty| {
- match ty {
- "Elf64_Phdr" | "Elf32_Phdr" => false,
- _ => true,
- }
- });
- cfg.skip_type(move |ty| {
- match ty {
- "Elf64_Phdr" | "Elf32_Phdr" => false,
- _ => true,
- }
- });
- cfg.header("elf.h");
- cfg.generate("../src/lib.rs", "linux_elf.rs");
+ if linux || android {
+ // test termios
+ let mut cfg = ctest::TestGenerator::new();
+ cfg.header("asm/termbits.h");
+ cfg.skip_type(|_| true)
+ .skip_static(|_| true)
+ .skip_fn(|_| true)
+ .skip_const(|c| c != "BOTHER")
+ .skip_struct(|s| s != "termios2")
+ .type_name(move |ty, is_struct, is_union| match ty {
+ t if is_struct => format!("struct {}", t),
+ t if is_union => format!("union {}", t),
+ t => t.to_string(),
+ });
+ cfg.generate("../src/lib.rs", "linux_termios.rs");
+ }
+
+ if linux || android {
+ // test IPV6_ constants:
+ let mut cfg = ctest::TestGenerator::new();
+ headers! {
+ cfg:
+ "linux/in6.h"
+ }
+ cfg.skip_type(|_| true)
+ .skip_static(|_| true)
+ .skip_fn(|_| true)
+ .skip_const(|_| true)
+ .skip_struct(|_| true)
+ .skip_const(move |name| match name {
+ "IPV6_FLOWINFO"
+ | "IPV6_FLOWLABEL_MGR"
+ | "IPV6_FLOWINFO_SEND"
+ | "IPV6_FLOWINFO_FLOWLABEL"
+ | "IPV6_FLOWINFO_PRIORITY" => false,
+ _ => true,
+ })
+ .type_name(move |ty, is_struct, is_union| match ty {
+ t if is_struct => format!("struct {}", t),
+ t if is_union => format!("union {}", t),
+ t => t.to_string(),
+ });
+ cfg.generate("../src/lib.rs", "linux_ipv6.rs");
+ }
+
+ if linux || android {
+ // Test Elf64_Phdr and Elf32_Phdr
+ // These types have a field called `p_type`, but including
+ // "resolve.h" defines a `p_type` macro that expands to `__p_type`
+ // making the tests for these fails when both are included.
+ let mut cfg = ctest::TestGenerator::new();
+ cfg.header("elf.h");
+ cfg.skip_fn(|_| true)
+ .skip_static(|_| true)
+ .skip_fn(|_| true)
+ .skip_const(|_| true)
+ .type_name(move |ty, _is_struct, _is_union| ty.to_string())
+ .skip_struct(move |ty| match ty {
+ "Elf64_Phdr" | "Elf32_Phdr" => false,
+ _ => true,
+ })
+ .skip_type(move |ty| match ty {
+ "Elf64_Phdr" | "Elf32_Phdr" => false,
+ _ => true,
+ });
+ cfg.generate("../src/lib.rs", "linux_elf.rs");
+ }
+}
+
+fn which_freebsd() -> Option<i32> {
+ let output = std::process::Command::new("freebsd-version")
+ .output()
+ .ok()?;
+ if !output.status.success() {
+ return None;
+ }
+
+ let stdout = String::from_utf8(output.stdout).ok()?;
+
+ match &stdout {
+ s if s.starts_with("11") => Some(11),
+ s if s.starts_with("12") => Some(12),
+ _ => None,
+ }
}