@@ -31,6 +31,7 @@ fn do_cc() {
3131 || target. contains ( "emscripten" )
3232 || target. contains ( "fuchsia" )
3333 || target. contains ( "bsd" )
34+ || target. contains ( "cygwin" )
3435 {
3536 cc:: Build :: new ( ) . file ( "src/makedev.c" ) . compile ( "makedev" ) ;
3637 }
@@ -60,6 +61,7 @@ fn do_ctest() {
6061 t if t. contains ( "linux" ) => return test_linux ( t) ,
6162 t if t. contains ( "netbsd" ) => return test_netbsd ( t) ,
6263 t if t. contains ( "openbsd" ) => return test_openbsd ( t) ,
64+ t if t. contains ( "cygwin" ) => return test_cygwin ( t) ,
6365 t if t. contains ( "redox" ) => return test_redox ( t) ,
6466 t if t. contains ( "solaris" ) => return test_solarish ( t) ,
6567 t if t. contains ( "illumos" ) => return test_solarish ( t) ,
@@ -642,6 +644,173 @@ fn test_openbsd(target: &str) {
642644 cfg. generate ( src_hotfix_dir ( ) . join ( "lib.rs" ) , "main.rs" ) ;
643645}
644646
647+ fn test_cygwin ( target : & str ) {
648+ assert ! ( target. contains( "cygwin" ) ) ;
649+
650+ let mut cfg = ctest_cfg ( ) ;
651+ cfg. define ( "_GNU_SOURCE" , None ) ;
652+
653+ headers ! { cfg:
654+ "ctype.h" ,
655+ "dirent.h" ,
656+ "dlfcn.h" ,
657+ "errno.h" ,
658+ "fcntl.h" ,
659+ "grp.h" ,
660+ "iconv.h" ,
661+ "langinfo.h" ,
662+ "limits.h" ,
663+ "locale.h" ,
664+ "net/if.h" ,
665+ "netdb.h" ,
666+ "netinet/tcp.h" ,
667+ "poll.h" ,
668+ "pthread.h" ,
669+ "pwd.h" ,
670+ "resolv.h" ,
671+ "sched.h" ,
672+ "semaphore.h" ,
673+ "signal.h" ,
674+ "stddef.h" ,
675+ "stdlib.h" ,
676+ "string.h" ,
677+ "sys/cpuset.h" ,
678+ "sys/ioctl.h" ,
679+ "sys/mman.h" ,
680+ "sys/mount.h" ,
681+ "sys/param.h" ,
682+ "sys/quota.h" ,
683+ "sys/random.h" ,
684+ "sys/resource.h" ,
685+ "sys/select.h" ,
686+ "sys/socket.h" ,
687+ "sys/statvfs.h" ,
688+ "sys/times.h" ,
689+ "sys/types.h" ,
690+ "sys/uio.h" ,
691+ "sys/un.h" ,
692+ "sys/utsname.h" ,
693+ "syslog.h" ,
694+ "termios.h" ,
695+ "unistd.h" ,
696+ "utime.h" ,
697+ "wait.h" ,
698+ "wchar.h" ,
699+ }
700+
701+ cfg. type_name ( move |ty, is_struct, is_union| {
702+ match ty {
703+ // Just pass all these through, no need for a "struct" prefix
704+ "FILE" | "DIR" | "Dl_info" | "fd_set" => ty. to_string ( ) ,
705+
706+ "Ioctl" => "int" . to_string ( ) ,
707+
708+ t if is_union => format ! ( "union {}" , t) ,
709+
710+ t if t. ends_with ( "_t" ) => t. to_string ( ) ,
711+
712+ // sigval is a struct in Rust, but a union in C:
713+ "sigval" => format ! ( "union sigval" ) ,
714+
715+ // put `struct` in front of all structs:.
716+ t if is_struct => format ! ( "struct {}" , t) ,
717+
718+ t => t. to_string ( ) ,
719+ }
720+ } ) ;
721+
722+ cfg. skip_const ( move |name| {
723+ match name {
724+ // FIXME(cygwin): these constants do not exist on Cygwin
725+ "ARPOP_REQUEST" | "ARPOP_REPLY" | "ATF_COM" | "ATF_PERM" | "ATF_PUBL"
726+ | "ATF_USETRAILERS" => true ,
727+
728+ // not defined on Cygwin, but [get|set]priority is, so they are
729+ // useful
730+ "PRIO_MIN" | "PRIO_MAX" => true ,
731+
732+ // The following does not exist on Cygwin but is required by
733+ // several crates
734+ "FIOCLEX" | "SA_NOCLDWAIT" => true ,
735+
736+ _ => false ,
737+ }
738+ } ) ;
739+
740+ cfg. skip_signededness ( move |c| match c {
741+ n if n. starts_with ( "pthread" ) => true ,
742+
743+ "sighandler_t" => true ,
744+
745+ _ => false ,
746+ } ) ;
747+
748+ cfg. skip_struct ( move |ty| {
749+ if ty. starts_with ( "__c_anonymous_" ) {
750+ return true ;
751+ }
752+
753+ false
754+ } ) ;
755+
756+ cfg. field_name ( move |struct_, field| {
757+ match field {
758+ // Our stat *_nsec fields normally don't actually exist but are part
759+ // of a timeval struct
760+ s if s. ends_with ( "_nsec" ) && struct_. starts_with ( "stat" ) => {
761+ s. replace ( "e_nsec" , ".tv_nsec" )
762+ }
763+
764+ // FIXME: sigaction actually contains a union with two variants:
765+ // a sa_sigaction with type: (*)(int, struct __siginfo *, void *)
766+ // a sa_handler with type sig_t
767+ "sa_sigaction" if struct_ == "sigaction" => "sa_handler" . to_string ( ) ,
768+
769+ s => s. to_string ( ) ,
770+ }
771+ } ) ;
772+
773+ cfg. skip_field ( |struct_, field| {
774+ match ( struct_, field) {
775+ // this is actually a union on linux, so we can't represent it well and
776+ // just insert some padding.
777+ ( "ifreq" , "ifr_ifru" ) => true ,
778+ ( "ifconf" , "ifc_ifcu" ) => true ,
779+
780+ _ => false ,
781+ }
782+ } ) ;
783+
784+ cfg. skip_fn ( move |name| {
785+ // skip those that are manually verified
786+ match name {
787+ // There are two versions of the sterror_r function, see
788+ //
789+ // https://linux.die.net/man/3/strerror_r
790+ //
791+ // An XSI-compliant version provided if:
792+ //
793+ // (_POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600) && ! _GNU_SOURCE
794+ //
795+ // and a GNU specific version provided if _GNU_SOURCE is defined.
796+ //
797+ // libc provides bindings for the XSI-compliant version, which is
798+ // preferred for portable applications.
799+ //
800+ // We skip the test here since here _GNU_SOURCE is defined, and
801+ // test the XSI version below.
802+ "strerror_r" => true ,
803+
804+ // FIXME(cygwin): does not exist on Cygwin
805+ "mlockall" | "munlockall" => true ,
806+
807+ _ => false ,
808+ }
809+ } ) ;
810+
811+ cfg. generate ( "../src/lib.rs" , "main.rs" ) ;
812+ }
813+
645814fn test_windows ( target : & str ) {
646815 assert ! ( target. contains( "windows" ) ) ;
647816 let gnu = target. contains ( "gnu" ) ;
0 commit comments