Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
156 changes: 146 additions & 10 deletions libc-test/build.rs

@tgross35 tgross35 Jun 25, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Commit "style: fix DragonFly CI checks": please squash this one, think it can just go into the previous commit

View changes since the review

Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ fn do_cc() {
|| target.contains("android")
|| target.contains("emscripten")
|| target.contains("fuchsia")
|| target.contains("dragonfly")
|| target.contains("bsd")
|| target.contains("cygwin")
{
Expand Down Expand Up @@ -1535,6 +1536,14 @@ fn test_dragonflybsd(target: &str) {
let mut cfg = ctest_cfg();
cfg.flag("-Wno-deprecated-declarations");

let dragonfly_version = if let Ok(version) = env::var("RUST_LIBC_UNSTABLE_DRAGONFLY_VERSION") {
let vers = parse_dragonfly_version(&version).unwrap();
println!("cargo:warning=setting DragonFly version to {vers}");
vers
} else {
which_dragonfly().unwrap_or(600_200)
};

headers!(
cfg,
"aio.h",
Expand Down Expand Up @@ -1576,6 +1585,7 @@ fn test_dragonflybsd(target: &str) {
"sched.h",
"semaphore.h",
"signal.h",
"spawn.h",
"stddef.h",
"stdint.h",
"stdio.h",
Expand All @@ -1586,6 +1596,7 @@ fn test_dragonflybsd(target: &str) {
"sys/ioctl.h",
"sys/cpuctl.h",
"sys/eui64.h",
"sys/extattr.h",
"sys/ipc.h",
"sys/kinfo.h",
"sys/ktrace.h",
Expand All @@ -1595,6 +1606,7 @@ fn test_dragonflybsd(target: &str) {
"sys/procctl.h",
"sys/ptrace.h",
"sys/reboot.h",
"sys/random.h",
"sys/resource.h",
"sys/rtprio.h",
"sys/sched.h",
Expand All @@ -1620,8 +1632,8 @@ fn test_dragonflybsd(target: &str) {
"util.h",
"utime.h",
"utmpx.h",
"vm/vm.h",
"vfs/ufs/quota.h",
"vm/vm_map.h",
"wchar.h",
"iconv.h",
);
Expand All @@ -1642,6 +1654,10 @@ fn test_dragonflybsd(target: &str) {
match ty {
// FIXME(dragonflybsd): OSX calls this something else
"sighandler_t" => Some("sig_t".to_string()),
"lwpstat" => Some("enum lwpstat".to_string()),
"procstat" => Some("enum procstat".to_string()),
"vm_map_t" => Some("struct vm_map *".to_string()),
"vm_map_entry_t" => Some("struct vm_map_entry *".to_string()),
_ => None,
}
});
Expand Down Expand Up @@ -1676,7 +1692,7 @@ fn test_dragonflybsd(target: &str) {
"termios2" => true,

// Extern types
"DIR" | "FILE" | "fpos_t" => true,
"DIR" | "FILE" | "fpos_t" | "sem" | "timezone" => true,

_ => false,
}
Expand All @@ -1695,11 +1711,58 @@ fn test_dragonflybsd(target: &str) {
_ => false,
}
});
cfg.alias_is_c_enum(move |e| match e {
"lwpstat" | "procstat" => true,
_ => false,
});

cfg.skip_const(move |constant| {
match constant.ident() {
"SIG_DFL" | "SIG_ERR" | "SIG_IGN" => true, // sighandler_t weirdness

// Kernel-only symbols in DragonFly headers.
"DTYPE_VNODE" | "DTYPE_SOCKET" | "DTYPE_PIPE" | "DTYPE_FIFO" | "DTYPE_KQUEUE"
| "DTYPE_CRYPTO" | "DTYPE_MQUEUE" | "DTYPE_DMABUF" => true,

// Not exposed by current DragonFly userland headers.
"REG_DUMP"
| "REG_ASSERT"
| "REG_ATOI"
| "REG_ITOA"
| "REG_TRACE"
| "REG_LARGE"
| "MAP_RENAME"
| "MAP_NORESERVE"
| "CTL_UNSPEC"
| "KERN_PROF"
| "CTL_P1003_1B_UNUSED1"
| "CTL_P1003_1B_SEM_VALUE_MAX"
| "DOWNTIME"
| "SF_CACHE" => true,

// libc exposes the 6.0-compatible value for this version-dependent mask.
"KERN_PROC_FLAGMASK" => true,

// Renamed in current DragonFly headers.
"CPUCTL_RSMSR" | "UTX_DB_LASTLOG" => true,
Comment on lines +1723 to +1747

@tgross35 tgross35 Jun 18, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since dragonfly is tier 3, you can make the relevant updates in the library (change or delete as needed) rather than adding test skips.

View changes since the review

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed by moving the freebsd-only pieces.


// Introduced after DragonFly 5.8.
"AF_ARP"
| "PF_ARP"
| "IP_SENDSRCADDR"
| "F_GETPATH"
| "ENOTRECOVERABLE"
| "EOWNERDEAD"
| "SO_PASSCRED"
| "PROC_PDEATHSIG_CTL"
| "PROC_PDEATHSIG_STATUS"
| "KERN_STATIC_TLS_EXTRA"
| "KERN_MAXID"
if dragonfly_version < 600_000 =>
{
true
}

@tgross35 tgross35 Jun 18, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is 5.x still in active enough use that this is worth worrying about? Per https://www.dragonflybsd.org/releases/ 5.8 is from 2020 and 6.0 was in 2021.

View changes since the review


// weird signed extension or something like that?
"MS_NOUSER" => true,
"MS_RMT_MASK" => true, // updated in glibc 2.22 and musl 1.1.13
Expand All @@ -1720,18 +1783,39 @@ fn test_dragonflybsd(target: &str) {
"prlimit" | "prlimit64" // non-int in 2nd arg
=> true,

// These are exposed unconditionally by libc, but older DragonFly
// headers cannot validate them.
"clock_nanosleep" | "fexecve" | "pthread_getname_np" | "pthread_setname_np"
if dragonfly_version < 600_000 => true,
"pthread_getaffinity_np" | "pthread_setaffinity_np" if dragonfly_version < 600_000 => {
true
},
"fdatasync" | "getentropy" | "posix_fallocate" if dragonfly_version < 600_200 => true,
"malloc_usable_size" if dragonfly_version < 600_400 => true,
_ => false,
}
});

cfg.skip_alias(move |ty| {
match ty.ident() {
// sighandler_t is crazy across platforms
"sighandler_t" => true,
// Same as FreeBSD: `kvm_t` is an opaque handle used through
// pointers, and libc does not bind the private `struct __kvm`.
"kvm_t" => true,
_ => false,
}
});

cfg.skip_struct_field_type(move |struct_, field| {
match (struct_.ident(), field.ident()) {
// This is a weird union, don't check the type.
("ifaddrs", "ifa_ifu") => true,
// sighandler_t type is super weird
("sigaction", "sa_sigaction") => true,
// aio_buf is "volatile void*" and Rust doesn't understand volatile
("aiocb", "aio_buf") => true,
cfg.skip_struct(move |struct_| {
match struct_.ident() {
// FIXME(dragonflybsd): These are tested as part of the linux_fcntl tests since
// there are header conflicts when including them with all the other
// structs.
"termios2" => true,

"ip_mreqn" if dragonfly_version < 600_000 => true,

_ => false,
}
});
Expand All @@ -1743,13 +1827,65 @@ fn test_dragonflybsd(target: &str) {
("siginfo_t", "_pad") => true,
// sigev_notify_thread_id is actually part of a sigev_un union
("sigevent", "sigev_notify_thread_id") => true,
// Current DragonFly headers use these names instead.
("kinfo_cputime", "cp_idel") => true,
// conflicting with `p_type` macro from <resolve.h>.
("Elf32_Phdr", "p_type") | ("Elf64_Phdr", "p_type") => true,
("kinfo_lwp", "kl_stat") | ("kinfo_proc", "kp_stat") => true,
("utmpx", "ut_type") => true,
("mcontext_t", "mc_fpregs") => true,
_ => false,
}
});

cfg.skip_struct_field_type(move |struct_, field| {
match (struct_.ident(), field.ident()) {
// This is a weird union, don't check the type.
("ifaddrs", "ifa_ifu") => true,
// sighandler_t type is super weird
("sigaction", "sa_sigaction") => true,
// aio_buf is "volatile void*" and Rust doesn't understand volatile
("aiocb", "aio_buf") => true,
_ => false,
}
});

ctest::generate_test(&mut cfg, "../src/lib.rs", "ctest_output.rs").unwrap();
}

fn parse_dragonfly_version(version: &str) -> Option<u32> {
let version = version.trim();

if let Ok(version) = version.parse::<u32>() {
// DragonFly's __DragonFly_version uses major * 100_000 + minor * 100.
// Accept compact test override spellings like 58, 60, 62, and 602.
return Some(match version {
0..=9 => version * 100_000,
10..=99 => (version / 10) * 100_000 + (version % 10) * 100,
100..=999 => (version / 100) * 100_000 + (version % 100) * 100,
_ => version,
});
}

let mut pieces = version.split(['.', '-']);
let major = pieces.next()?.parse::<u32>().ok()?;
let minor = pieces.next()?.parse::<u32>().ok()?;
Some(major * 100_000 + minor * 100)
}
Comment on lines +1856 to +1874

@tgross35 tgross35 Jun 23, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this constant available in a header? If so, once #5188 merges you'll be able to use that similar to __FreeBSD_version rather than needing uname, in the rare case that host and target differ.

View changes since the review

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, DragonFly does expose a __DragonFly_version macro in both <sys/param.h> and <osreldate.h>. On my DragonFly 5.8, 6.0, 6.2, and 6.4 machine it has value 500800, 600000, 600200, and 600401. so it should be able to use the same header-based version detection in #5188.


fn which_dragonfly() -> Option<u32> {
if env::var("CARGO_CFG_TARGET_OS").ok()?.as_str() != "dragonfly" {
return None;
}

if try_command_output("uname", &["-s"])?.trim() != "DragonFly" {
return None;
}

let stdout = try_command_output("uname", &["-r"])?;
parse_dragonfly_version(stdout.trim())
}

fn test_wasi(target: &str) {
assert!(target.contains("wasi"));
let p2 = target.contains("wasip2");
Expand Down
Loading