Skip to content

Add cygwin support #4279

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Mar 7, 2025
Merged
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
2 changes: 1 addition & 1 deletion build.rs
Original file line number Diff line number Diff line change
@@ -26,7 +26,7 @@ const CHECK_CFG_EXTRA: &'static [(&'static str, &'static [&'static str])] = &[
(
"target_os",
&[
"switch", "aix", "ohos", "hurd", "rtems", "visionos", "nuttx",
"switch", "aix", "ohos", "hurd", "rtems", "visionos", "nuttx", "cygwin",
],
),
("target_env", &["illumos", "wasi", "aix", "ohos"]),
170 changes: 170 additions & 0 deletions libc-test/build.rs
Original file line number Diff line number Diff line change
@@ -31,6 +31,7 @@ fn do_cc() {
|| target.contains("emscripten")
|| target.contains("fuchsia")
|| target.contains("bsd")
|| target.contains("cygwin")
{
cc::Build::new().file("src/makedev.c").compile("makedev");
}
@@ -60,6 +61,7 @@ fn do_ctest() {
t if t.contains("linux") => return test_linux(t),
t if t.contains("netbsd") => return test_netbsd(t),
t if t.contains("openbsd") => return test_openbsd(t),
t if t.contains("cygwin") => return test_cygwin(t),
t if t.contains("redox") => return test_redox(t),
t if t.contains("solaris") => return test_solarish(t),
t if t.contains("illumos") => return test_solarish(t),
@@ -642,6 +644,174 @@ fn test_openbsd(target: &str) {
cfg.generate(src_hotfix_dir().join("lib.rs"), "main.rs");
}

fn test_cygwin(target: &str) {
assert!(target.contains("cygwin"));

let mut cfg = ctest_cfg();
cfg.define("_GNU_SOURCE", None);

headers! { cfg:
"ctype.h",
"dirent.h",
"dlfcn.h",
"errno.h",
"fcntl.h",
"grp.h",
"iconv.h",
"langinfo.h",
"limits.h",
"locale.h",
"net/if.h",
"netdb.h",
"netinet/tcp.h",
"poll.h",
"pthread.h",
"pwd.h",
"resolv.h",
"sched.h",
"semaphore.h",
"signal.h",
"stddef.h",
"stdlib.h",
"string.h",
"sys/cpuset.h",
"sys/ioctl.h",
"sys/mman.h",
"sys/mount.h",
"sys/param.h",
"sys/quota.h",
"sys/random.h",
"sys/resource.h",
"sys/select.h",
"sys/socket.h",
"sys/statvfs.h",
"sys/times.h",
"sys/types.h",
"sys/uio.h",
"sys/un.h",
"sys/utsname.h",
"syslog.h",
"termios.h",
"unistd.h",
"utime.h",
"wait.h",
"wchar.h",
}

cfg.type_name(move |ty, is_struct, is_union| {
match ty {
// Just pass all these through, no need for a "struct" prefix
"FILE" | "DIR" | "Dl_info" | "fd_set" => ty.to_string(),

"Ioctl" => "int".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),

t => t.to_string(),
}
});

cfg.skip_const(move |name| {
match name {
// FIXME(cygwin): these constants do not exist on Cygwin
"ARPOP_REQUEST" | "ARPOP_REPLY" | "ATF_COM" | "ATF_PERM" | "ATF_PUBL"
| "ATF_USETRAILERS" => true,

// not defined on Cygwin, but [get|set]priority is, so they are
// useful
"PRIO_MIN" | "PRIO_MAX" => true,

// The following does not exist on Cygwin but is required by
// several crates
"FIOCLEX" | "SA_NOCLDWAIT" => true,

_ => false,
}
});

cfg.skip_signededness(move |c| match c {
n if n.starts_with("pthread") => true,

// For consistency with other platforms. Actually a function ptr.
"sighandler_t" => true,

_ => false,
});

cfg.skip_struct(move |ty| {
if ty.starts_with("__c_anonymous_") {
return true;
}

false
});

cfg.field_name(move |struct_, field| {
match field {
// Our stat *_nsec fields normally don't actually exist but are part
// of a timeval struct
s if s.ends_with("_nsec") && struct_.starts_with("stat") => {
s.replace("e_nsec", ".tv_nsec")
}

// FIXME(cygwin): sigaction actually contains a union with two variants:
// a sa_sigaction with type: (*)(int, struct __siginfo *, void *)
// a sa_handler with type sig_t
"sa_sigaction" if struct_ == "sigaction" => "sa_handler".to_string(),

s => s.to_string(),
}
});

cfg.skip_field(|struct_, field| {
match (struct_, field) {
// this is actually a union on linux, so we can't represent it well and
// just insert some padding.
("ifreq", "ifr_ifru") => true,
("ifconf", "ifc_ifcu") => true,

_ => false,
}
});

cfg.skip_fn(move |name| {
// skip those that are manually verified
match name {
// 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,

// FIXME(cygwin): does not exist on Cygwin
"mlockall" | "munlockall" => true,

_ => false,
}
});

cfg.generate("../src/lib.rs", "main.rs");
}

fn test_windows(target: &str) {
assert!(target.contains("windows"));
let gnu = target.contains("gnu");
27 changes: 27 additions & 0 deletions libc-test/semver/cygwin.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
FORK_NO_RELOAD
FORK_RELOAD
MOUNT_AUTOMATIC
MOUNT_BIND
MOUNT_CYGDRIVE
MOUNT_CYGWIN_EXEC
MOUNT_DEVFS
MOUNT_DONT_USE
MOUNT_DOS
MOUNT_EXEC
MOUNT_IHASH
MOUNT_IMMUTABLE
MOUNT_NOACL
MOUNT_NOPOSIX
MOUNT_NOTEXEC
MOUNT_OVERRIDE
MOUNT_PROC
MOUNT_RO
MOUNT_SPARSE
MOUNT_SYSTEM
MOUNT_TEXT
MOUNT_USER_TEMP
WINDOWS_HWND
WINDOWS_POST
WINDOWS_SEND
cygwin_umount
dlfork
2 changes: 1 addition & 1 deletion libc-test/src/makedev.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#include <sys/types.h>
#if defined(__linux__) || defined(__EMSCRIPTEN__)
#if defined(__linux__) || defined(__EMSCRIPTEN__) || defined(__CYGWIN__)
#include <sys/sysmacros.h>
#endif

2 changes: 2 additions & 0 deletions libc-test/test/makedev.rs
Original file line number Diff line number Diff line change
@@ -54,6 +54,7 @@ mod ret {
target_os = "linux",
target_os = "netbsd",
target_os = "openbsd",
target_os = "cygwin",
))]
mod t {
use libc::{self, c_uint, dev_t};
@@ -133,6 +134,7 @@ mod t {
target_os = "freebsd",
target_os = "fuchsia",
target_os = "linux",
target_os = "cygwin",
))]
#[test]
fn test_fbsd12_like() {
Loading