Skip to content

Commit 151c3a9

Browse files
authored
Merge pull request #4450 from xingxue-ibm/enable-aix-libc-test
Enable libc-test and fix definitions/declarations for AIX
2 parents c7c63ef + c192a5c commit 151c3a9

File tree

7 files changed

+3396
-524
lines changed

7 files changed

+3396
-524
lines changed

libc-test/build.rs

Lines changed: 239 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ fn do_ctest() {
6868
t if t.contains("windows") => test_windows(t),
6969
t if t.contains("vxworks") => test_vxworks(t),
7070
t if t.contains("nto-qnx") => test_neutrino(t),
71+
t if t.contains("aix") => return test_aix(t),
7172
t => panic!("unknown target {t}"),
7273
}
7374
}
@@ -95,7 +96,9 @@ fn do_semver() {
9596
// NOTE: Android doesn't include the unix file (or the Linux file) because
9697
// there are some many definitions missing it's actually easier just to
9798
// maintain a file for Android.
98-
if family != os && os != "android" {
99+
// NOTE: AIX doesn't include the unix file because there are definitions
100+
// missing on AIX. It is easier to maintain a file for AIX.
101+
if family != os && !matches!(os.as_str(), "android" | "aix") {
99102
process_semver_file(&mut output, &mut semver_root, &family);
100103
}
101104
// We don't do semver for unknown targets.
@@ -5408,3 +5411,238 @@ fn test_haiku(target: &str) {
54085411
});
54095412
cfg.generate(src_hotfix_dir().join("lib.rs"), "main.rs");
54105413
}
5414+
5415+
fn test_aix(target: &str) {
5416+
assert!(target.contains("aix"));
5417+
5418+
// ctest generates arguments supported only by clang, so make sure to
5419+
// run with CC=clang. While debugging, "CFLAGS=-ferror-limit=<large num>"
5420+
// is useful to get more error output.
5421+
let mut cfg = ctest_cfg();
5422+
cfg.define("_THREAD_SAFE", None);
5423+
5424+
// Avoid the error for definitions such as '{0, 0, 0, 1}' for
5425+
// 'IN6ADDR_LOOPBACK_INIT' in netinent/in.h.
5426+
cfg.flag("-Wno-missing-braces");
5427+
5428+
headers! { cfg:
5429+
"aio.h",
5430+
"ctype.h",
5431+
"dirent.h",
5432+
"dlfcn.h",
5433+
"errno.h",
5434+
"fcntl.h",
5435+
"fnmatch.h",
5436+
"glob.h",
5437+
"grp.h",
5438+
"iconv.h",
5439+
"langinfo.h",
5440+
"libgen.h",
5441+
"limits.h",
5442+
"locale.h",
5443+
"malloc.h",
5444+
"mntent.h",
5445+
"mqueue.h",
5446+
"netinet/in.h", // this needs be before net/if.h
5447+
"poll.h", // this needs be before net/if.h
5448+
"sys/pollset.h", // this needs to be before net/if.h
5449+
"net/if.h",
5450+
"net/bpf.h", // this needs to be after net/if.h
5451+
"net/if_dl.h",
5452+
"netdb.h",
5453+
"netinet/tcp.h",
5454+
"pthread.h",
5455+
"pwd.h",
5456+
"rpcsvc/mount.h",
5457+
"rpcsvc/rstat.h",
5458+
"regex.h",
5459+
"resolv.h",
5460+
"sched.h",
5461+
"search.h",
5462+
"semaphore.h",
5463+
"signal.h",
5464+
"spawn.h",
5465+
"stddef.h",
5466+
"stdint.h",
5467+
"stdio.h",
5468+
"stdlib.h",
5469+
"string.h",
5470+
"strings.h",
5471+
"sys/aacct.h",
5472+
"sys/acct.h",
5473+
"sys/dr.h",
5474+
"sys/file.h",
5475+
"sys/io.h",
5476+
"sys/ioctl.h",
5477+
"sys/ipc.h",
5478+
"sys/ldr.h",
5479+
"sys/mman.h",
5480+
"sys/msg.h",
5481+
"sys/reg.h",
5482+
"sys/resource.h",
5483+
"sys/sem.h",
5484+
"sys/shm.h",
5485+
"sys/socket.h",
5486+
"sys/stat.h",
5487+
"sys/statfs.h",
5488+
"sys/statvfs.h",
5489+
"sys/stropts.h",
5490+
"sys/termio.h",
5491+
"sys/time.h",
5492+
"sys/times.h",
5493+
"sys/types.h",
5494+
"sys/uio.h",
5495+
"sys/un.h",
5496+
"sys/user.h",
5497+
"sys/utsname.h",
5498+
"sys/vattr.h",
5499+
"sys/vminfo.h",
5500+
"sys/wait.h",
5501+
"sys/xti.h",
5502+
"syslog.h",
5503+
"termios.h",
5504+
"thread.h",
5505+
"time.h",
5506+
"ucontext.h",
5507+
"unistd.h",
5508+
"utime.h",
5509+
"utmp.h",
5510+
"utmpx.h",
5511+
"wchar.h",
5512+
}
5513+
5514+
cfg.skip_type(move |ty| match ty {
5515+
// AIX does not define type 'sighandler_t'.
5516+
"sighandler_t" => true,
5517+
5518+
// The alignment of 'double' does not agree between C and Rust for AIX.
5519+
// We are working on a resolution.
5520+
"c_double" => true,
5521+
5522+
_ => false,
5523+
});
5524+
5525+
cfg.type_name(move |ty, is_struct, is_union| match ty {
5526+
"DIR" => ty.to_string(),
5527+
"FILE" => ty.to_string(),
5528+
"ACTION" => ty.to_string(),
5529+
5530+
// 'sigval' is a struct in Rust, but a union in C.
5531+
"sigval" => format!("union sigval"),
5532+
5533+
t if t.ends_with("_t") => t.to_string(),
5534+
t if is_struct => format!("struct {}", t),
5535+
t if is_union => format!("union {}", t),
5536+
t => t.to_string(),
5537+
});
5538+
5539+
cfg.skip_const(move |name| match name {
5540+
// Skip 'sighandler_t' assignments.
5541+
"SIG_DFL" | "SIG_ERR" | "SIG_IGN" => true,
5542+
5543+
_ => false,
5544+
});
5545+
5546+
cfg.skip_struct(move |ty| {
5547+
match ty {
5548+
// FIXME(union): actually a union.
5549+
"sigval" => true,
5550+
5551+
// '__poll_ctl_ext_u' and '__pollfd_ext_u' are for unnamed unions.
5552+
"__poll_ctl_ext_u" => true,
5553+
"__pollfd_ext_u" => true,
5554+
5555+
// 'struct fpreg_t' is not defined in AIX headers. It is created to
5556+
// allow type 'double' to be used in signal contexts.
5557+
"fpreg_t" => true,
5558+
5559+
_ => false,
5560+
}
5561+
});
5562+
5563+
cfg.skip_field_type(move |struct_, field| {
5564+
match (struct_, field) {
5565+
// AIX does not define 'sighandler_t'.
5566+
("sigaction", "sa_sigaction") => true,
5567+
5568+
// The type of 'fpr' is 'fpreg_t' which is created to allow type
5569+
// 'double' to be used in signal contexts.
5570+
("__context64", "fpr") => true,
5571+
("__tm_context_t", "fpr") => true,
5572+
5573+
_ => false,
5574+
}
5575+
});
5576+
5577+
cfg.skip_field(move |s, field| {
5578+
match s {
5579+
// The field 'u' is actually a unnamed union in the AIX header.
5580+
"poll_ctl_ext" if field == "u" => true,
5581+
5582+
// The field 'data' is actually a unnamed union in the AIX header.
5583+
"pollfd_ext" if field == "data" => true,
5584+
5585+
_ => false,
5586+
}
5587+
});
5588+
5589+
cfg.skip_fn(move |name| {
5590+
match name {
5591+
// 'sighandler_t' is not defined on AIX.
5592+
"signal" => true,
5593+
5594+
// The function is only available under macro _USE_IRS in 'netdb.h'.
5595+
"hstrerror" => true,
5596+
5597+
// _ALL_SOURCE signatures for these functions differ from POSIX's
5598+
// on AIX.
5599+
"poll" => true,
5600+
"readlinkat" => true,
5601+
"readlink" => true,
5602+
"pselect" => true,
5603+
5604+
// The AIX signature differs from POSIX's, issue opened.
5605+
"gai_strerror" => true,
5606+
5607+
// AIX implements POSIX-compliant versions of these functions
5608+
// using 'static' wrappers in the headers, which in turn call
5609+
// the corresponding system libc functions prefixed with '_posix_'
5610+
// (e.g., '_posix_aio_read' for 'aio_read').
5611+
// On the Rust side, these functions resolve directly to the
5612+
// POSIX-compliant versions in the system libc. As a result,
5613+
// function pointer comparisons between the C and Rust sides
5614+
// would fail.
5615+
"getpwuid_r" | "getpwnam_r" | "getgrgid_r" | "getgrnam_r"
5616+
| "aio_cancel" | "aio_error" | "aio_fsync" | "aio_read"
5617+
| "aio_return" | "aio_suspend" | "aio_write" | "select" => true,
5618+
5619+
// 'getdtablesize' is a constant in the AIX header but it is
5620+
// a real function in libc which the Rust side is resolved to.
5621+
// The function pointer comparison test would fail.
5622+
"getdtablesize" => true,
5623+
5624+
// FIXME(ctest): Our API is unsound. The Rust API allows aliasing
5625+
// pointers, but the C API requires pointers not to alias.
5626+
// We should probably be at least using '&'/'&mut' here, see:
5627+
// https://github.com/gnzlbg/ctest/issues/68.
5628+
"lio_listio" => true,
5629+
5630+
_ => false,
5631+
}
5632+
});
5633+
5634+
5635+
cfg.volatile_item(|i| {
5636+
use ctest::VolatileItemKind::*;
5637+
match i {
5638+
// 'aio_buf' is of type 'volatile void**' but since we cannot
5639+
// express that in Rust types, we have to explicitly tell the
5640+
// checker about it here.
5641+
StructField(ref n, ref f) if n == "aiocb" && f == "aio_buf" => true,
5642+
5643+
_ => false,
5644+
}
5645+
});
5646+
5647+
cfg.generate(src_hotfix_dir().join("lib.rs"), "main.rs");
5648+
}

0 commit comments

Comments
 (0)