@@ -36,6 +36,7 @@ fn do_cc() {
3636 || target. contains ( "android" )
3737 || target. contains ( "emscripten" )
3838 || target. contains ( "fuchsia" )
39+ || target. contains ( "dragonfly" )
3940 || target. contains ( "bsd" )
4041 || target. contains ( "cygwin" )
4142 {
@@ -1504,7 +1505,17 @@ fn test_netbsd(target: &str) {
15041505fn test_dragonflybsd ( target : & str ) {
15051506 assert ! ( target. contains( "dragonfly" ) ) ;
15061507 let mut cfg = ctest_cfg ( ) ;
1507- cfg. flag ( "-Wno-deprecated-declarations" ) ;
1508+ cfg. flag ( "-Wno-deprecated-declarations" )
1509+ . flag_if_supported ( "-Wno-address-of-packed-member" )
1510+ . flag_if_supported ( "-Wno-unknown-warning-option" ) ;
1511+
1512+ let dragonfly_version = if let Ok ( version) = env:: var ( "RUST_LIBC_UNSTABLE_DRAGONFLY_VERSION" ) {
1513+ let vers = parse_dragonfly_version ( & version) . unwrap ( ) ;
1514+ println ! ( "cargo:warning=setting DragonFly version to {vers}" ) ;
1515+ vers
1516+ } else {
1517+ which_dragonfly ( ) . unwrap_or ( 600_200 )
1518+ } ;
15081519
15091520 headers ! (
15101521 cfg,
@@ -1547,6 +1558,7 @@ fn test_dragonflybsd(target: &str) {
15471558 "sched.h" ,
15481559 "semaphore.h" ,
15491560 "signal.h" ,
1561+ "spawn.h" ,
15501562 "stddef.h" ,
15511563 "stdint.h" ,
15521564 "stdio.h" ,
@@ -1557,6 +1569,7 @@ fn test_dragonflybsd(target: &str) {
15571569 "sys/ioctl.h" ,
15581570 "sys/cpuctl.h" ,
15591571 "sys/eui64.h" ,
1572+ "sys/extattr.h" ,
15601573 "sys/ipc.h" ,
15611574 "sys/kinfo.h" ,
15621575 "sys/ktrace.h" ,
@@ -1566,6 +1579,7 @@ fn test_dragonflybsd(target: &str) {
15661579 "sys/procctl.h" ,
15671580 "sys/ptrace.h" ,
15681581 "sys/reboot.h" ,
1582+ "sys/random.h" ,
15691583 "sys/resource.h" ,
15701584 "sys/rtprio.h" ,
15711585 "sys/sched.h" ,
@@ -1591,8 +1605,8 @@ fn test_dragonflybsd(target: &str) {
15911605 "util.h" ,
15921606 "utime.h" ,
15931607 "utmpx.h" ,
1608+ "vm/vm.h" ,
15941609 "vfs/ufs/quota.h" ,
1595- "vm/vm_map.h" ,
15961610 "wchar.h" ,
15971611 "iconv.h" ,
15981612 ) ;
@@ -1613,6 +1627,12 @@ fn test_dragonflybsd(target: &str) {
16131627 match ty {
16141628 // FIXME(dragonflybsd): OSX calls this something else
16151629 "sighandler_t" => Some ( "sig_t" . to_string ( ) ) ,
1630+ "lwpstat" => Some ( "enum lwpstat" . to_string ( ) ) ,
1631+ "procstat" => Some ( "enum procstat" . to_string ( ) ) ,
1632+ "vm_map_t" => Some ( "struct vm_map *" . to_string ( ) ) ,
1633+ "vm_map_entry_t" => Some ( "struct vm_map_entry *" . to_string ( ) ) ,
1634+ "vm_eflags_t" => Some ( "unsigned int" . to_string ( ) ) ,
1635+ "vm_subsys_t" => Some ( "int" . to_string ( ) ) ,
16161636 _ => None ,
16171637 }
16181638 } ) ;
@@ -1663,11 +1683,34 @@ fn test_dragonflybsd(target: &str) {
16631683 _ => false ,
16641684 }
16651685 } ) ;
1686+ cfg. alias_is_c_enum ( move |e| matches ! ( e, "lwpstat" | "procstat" ) ) ;
16661687
16671688 cfg. skip_const ( move |constant| {
16681689 match constant. ident ( ) {
16691690 "SIG_DFL" | "SIG_ERR" | "SIG_IGN" => true , // sighandler_t weirdness
16701691
1692+ // Kernel-only symbols in DragonFly headers.
1693+ "DTYPE_VNODE" | "DTYPE_SOCKET" | "DTYPE_PIPE" | "DTYPE_FIFO" | "DTYPE_KQUEUE"
1694+ | "DTYPE_CRYPTO" | "DTYPE_MQUEUE" | "DTYPE_DMABUF" => true ,
1695+
1696+ // Not exposed by current DragonFly userland headers.
1697+ "REG_DUMP" | "REG_ASSERT" | "REG_ATOI" | "REG_ITOA" | "REG_TRACE" | "REG_LARGE"
1698+ | "IP_ADD_SOURCE_MEMBERSHIP" | "IP_DROP_SOURCE_MEMBERSHIP" | "IP_BLOCK_SOURCE"
1699+ | "IP_UNBLOCK_SOURCE" | "MAP_RENAME" | "MAP_NORESERVE" | "CTL_UNSPEC"
1700+ | "KERN_PROF" | "CTL_P1003_1B_UNUSED1" | "CTL_P1003_1B_SEM_VALUE_MAX"
1701+ | "DOWNTIME" | "SF_CACHE" => true ,
1702+
1703+ // libc exposes the 6.0-compatible value for this version-dependent mask.
1704+ "KERN_PROC_FLAGMASK" => true ,
1705+
1706+ // Renamed in current DragonFly headers.
1707+ "CPUCTL_RSMSR" | "UTX_DB_LASTLOG" => true ,
1708+
1709+ // Introduced after DragonFly 5.8.
1710+ "AF_ARP" | "PF_ARP" | "IP_SENDSRCADDR" | "F_GETPATH" | "ENOTRECOVERABLE" | "EOWNERDEAD"
1711+ | "SO_PASSCRED" | "PROC_PDEATHSIG_CTL" | "PROC_PDEATHSIG_STATUS"
1712+ | "KERN_STATIC_TLS_EXTRA" | "KERN_MAXID" if dragonfly_version < 600_000 => true ,
1713+
16711714 // weird signed extension or something like that?
16721715 "MS_NOUSER" => true ,
16731716 "MS_RMT_MASK" => true , // updated in glibc 2.22 and musl 1.1.13
@@ -1688,18 +1731,40 @@ fn test_dragonflybsd(target: &str) {
16881731 "prlimit" | "prlimit64" // non-int in 2nd arg
16891732 => true ,
16901733
1734+ // These are exposed unconditionally by libc, but older DragonFly
1735+ // headers cannot validate them.
1736+ "clock_nanosleep" | "fexecve" | "pthread_getname_np" | "pthread_setname_np"
1737+ if dragonfly_version < 600_000 => true ,
1738+ "pthread_getaffinity_np" | "pthread_setaffinity_np" if dragonfly_version < 600_000 => {
1739+ true
1740+ } ,
1741+ "fdatasync" | "getentropy" | "posix_fallocate" if dragonfly_version < 600_200 => true ,
1742+ "malloc_usable_size" if dragonfly_version < 600_400 => true ,
16911743 _ => false ,
16921744 }
16931745 } ) ;
16941746
1695- cfg. skip_struct_field_type ( move |struct_, field| {
1696- match ( struct_. ident ( ) , field. ident ( ) ) {
1697- // This is a weird union, don't check the type.
1698- ( "ifaddrs" , "ifa_ifu" ) => true ,
1699- // sighandler_t type is super weird
1700- ( "sigaction" , "sa_sigaction" ) => true ,
1701- // aio_buf is "volatile void*" and Rust doesn't understand volatile
1702- ( "aiocb" , "aio_buf" ) => true ,
1747+ cfg. skip_alias ( move |ty| {
1748+ match ty. ident ( ) {
1749+ // sighandler_t is crazy across platforms
1750+ "sighandler_t" => true ,
1751+ // Kernel-only or opaque types in userland.
1752+ "kvm_t" | "pmap" | "umtx_t" | "Elf32_Lword" => true ,
1753+ _ => false ,
1754+ }
1755+ } ) ;
1756+
1757+ cfg. skip_struct ( move |struct_| {
1758+ match struct_. ident ( ) {
1759+ // FIXME(dragonflybsd): These are tested as part of the linux_fcntl tests since
1760+ // there are header conflicts when including them with all the other
1761+ // structs.
1762+ "termios2" => true ,
1763+
1764+ // Not available as userland-complete structs on DragonFly.
1765+ "ip_mreq_source" | "vm_map_entry" | "vmspace" => true ,
1766+ "ip_mreqn" if dragonfly_version < 600_000 => true ,
1767+
17031768 _ => false ,
17041769 }
17051770 } ) ;
@@ -1711,13 +1776,77 @@ fn test_dragonflybsd(target: &str) {
17111776 ( "siginfo_t" , "_pad" ) => true ,
17121777 // sigev_notify_thread_id is actually part of a sigev_un union
17131778 ( "sigevent" , "sigev_notify_thread_id" ) => true ,
1779+ // Current DragonFly headers use these names instead.
1780+ ( "kinfo_cputime" , "cp_idel" ) => true ,
1781+ // conflicting with `p_type` macro from <resolve.h>.
1782+ ( "Elf32_Phdr" , "p_type" ) | ( "Elf64_Phdr" , "p_type" ) => true ,
1783+ ( "kinfo_lwp" , "kl_stat" ) | ( "kinfo_proc" , "kp_stat" ) => true ,
1784+ ( "utmpx" , "ut_type" ) => true ,
1785+ ( "mcontext_t" , "mc_fpregs" ) => true ,
17141786 _ => false ,
17151787 }
17161788 } ) ;
17171789
1790+ cfg. skip_struct_field_type ( move |struct_, field| {
1791+ match ( struct_. ident ( ) , field. ident ( ) ) {
1792+ // This is a weird union, don't check the type.
1793+ ( "ifaddrs" , "ifa_ifu" ) => true ,
1794+ // sighandler_t type is super weird
1795+ ( "sigaction" , "sa_sigaction" ) => true ,
1796+ // aio_buf is "volatile void*" and Rust doesn't understand volatile
1797+ ( "aiocb" , "aio_buf" ) => true ,
1798+ _ => false ,
1799+ }
1800+ } ) ;
1801+
1802+ cfg. skip_roundtrip ( move |ty| {
1803+ matches ! (
1804+ ty,
1805+ "kvm_t"
1806+ | "posix_spawnattr_t"
1807+ | "posix_spawn_file_actions_t"
1808+ | "umtx_t"
1809+ | "pmap"
1810+ | "ip_mreq_source"
1811+ )
1812+ } ) ;
1813+
17181814 ctest:: generate_test ( & mut cfg, "../src/lib.rs" , "ctest_output.rs" ) . unwrap ( ) ;
17191815}
17201816
1817+ fn parse_dragonfly_version ( version : & str ) -> Option < u32 > {
1818+ let version = version. trim ( ) ;
1819+
1820+ if let Ok ( version) = version. parse :: < u32 > ( ) {
1821+ // DragonFly's __DragonFly_version uses major * 100_000 + minor * 100.
1822+ // Accept compact test override spellings like 58, 60, 62, and 602.
1823+ return Some ( match version {
1824+ 0 ..=9 => version * 100_000 ,
1825+ 10 ..=99 => ( version / 10 ) * 100_000 + ( version % 10 ) * 100 ,
1826+ 100 ..=999 => ( version / 100 ) * 100_000 + ( version % 100 ) * 100 ,
1827+ _ => version,
1828+ } ) ;
1829+ }
1830+
1831+ let mut pieces = version. split ( [ '.' , '-' ] ) ;
1832+ let major = pieces. next ( ) ?. parse :: < u32 > ( ) . ok ( ) ?;
1833+ let minor = pieces. next ( ) ?. parse :: < u32 > ( ) . ok ( ) ?;
1834+ Some ( major * 100_000 + minor * 100 )
1835+ }
1836+
1837+ fn which_dragonfly ( ) -> Option < u32 > {
1838+ if env:: var ( "CARGO_CFG_TARGET_OS" ) . ok ( ) ?. as_str ( ) != "dragonfly" {
1839+ return None ;
1840+ }
1841+
1842+ if try_command_output ( "uname" , & [ "-s" ] ) ?. trim ( ) != "DragonFly" {
1843+ return None ;
1844+ }
1845+
1846+ let stdout = try_command_output ( "uname" , & [ "-r" ] ) ?;
1847+ parse_dragonfly_version ( stdout. trim ( ) )
1848+ }
1849+
17211850fn test_wasi ( target : & str ) {
17221851 assert ! ( target. contains( "wasi" ) ) ;
17231852 let p2 = target. contains ( "wasip2" ) ;
0 commit comments