@@ -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) ,
@@ -686,6 +688,174 @@ fn test_openbsd(target: &str) {
686688 cfg. generate ( src_hotfix_dir ( ) . join ( "lib.rs" ) , "main.rs" ) ;
687689}
688690
691+ fn test_cygwin ( target : & str ) {
692+ assert ! ( target. contains( "cygwin" ) ) ;
693+
694+ let mut cfg = ctest_cfg ( ) ;
695+ cfg. define ( "_GNU_SOURCE" , None ) ;
696+
697+ headers ! { cfg:
698+ "ctype.h" ,
699+ "dirent.h" ,
700+ "dlfcn.h" ,
701+ "errno.h" ,
702+ "fcntl.h" ,
703+ "grp.h" ,
704+ "iconv.h" ,
705+ "langinfo.h" ,
706+ "limits.h" ,
707+ "locale.h" ,
708+ "net/if.h" ,
709+ "netdb.h" ,
710+ "netinet/tcp.h" ,
711+ "poll.h" ,
712+ "pthread.h" ,
713+ "pwd.h" ,
714+ "resolv.h" ,
715+ "sched.h" ,
716+ "semaphore.h" ,
717+ "signal.h" ,
718+ "stddef.h" ,
719+ "stdlib.h" ,
720+ "string.h" ,
721+ "sys/cpuset.h" ,
722+ "sys/ioctl.h" ,
723+ "sys/mman.h" ,
724+ "sys/mount.h" ,
725+ "sys/param.h" ,
726+ "sys/quota.h" ,
727+ "sys/random.h" ,
728+ "sys/resource.h" ,
729+ "sys/select.h" ,
730+ "sys/socket.h" ,
731+ "sys/statvfs.h" ,
732+ "sys/times.h" ,
733+ "sys/types.h" ,
734+ "sys/uio.h" ,
735+ "sys/un.h" ,
736+ "sys/utsname.h" ,
737+ "syslog.h" ,
738+ "termios.h" ,
739+ "unistd.h" ,
740+ "utime.h" ,
741+ "wait.h" ,
742+ "wchar.h" ,
743+ }
744+
745+ cfg. type_name ( move |ty, is_struct, is_union| {
746+ match ty {
747+ // Just pass all these through, no need for a "struct" prefix
748+ "FILE" | "DIR" | "Dl_info" | "fd_set" => ty. to_string ( ) ,
749+
750+ "Ioctl" => "int" . to_string ( ) ,
751+
752+ t if is_union => format ! ( "union {}" , t) ,
753+
754+ t if t. ends_with ( "_t" ) => t. to_string ( ) ,
755+
756+ // sigval is a struct in Rust, but a union in C:
757+ "sigval" => format ! ( "union sigval" ) ,
758+
759+ // put `struct` in front of all structs:.
760+ t if is_struct => format ! ( "struct {}" , t) ,
761+
762+ t => t. to_string ( ) ,
763+ }
764+ } ) ;
765+
766+ cfg. skip_const ( move |name| {
767+ match name {
768+ // FIXME(cygwin): these constants do not exist on Cygwin
769+ "ARPOP_REQUEST" | "ARPOP_REPLY" | "ATF_COM" | "ATF_PERM" | "ATF_PUBL"
770+ | "ATF_USETRAILERS" => true ,
771+
772+ // not defined on Cygwin, but [get|set]priority is, so they are
773+ // useful
774+ "PRIO_MIN" | "PRIO_MAX" => true ,
775+
776+ // The following does not exist on Cygwin but is required by
777+ // several crates
778+ "FIOCLEX" | "SA_NOCLDWAIT" => true ,
779+
780+ _ => false ,
781+ }
782+ } ) ;
783+
784+ cfg. skip_signededness ( move |c| match c {
785+ n if n. starts_with ( "pthread" ) => true ,
786+
787+ // For consistency with other platforms. Actually a function ptr.
788+ "sighandler_t" => true ,
789+
790+ _ => false ,
791+ } ) ;
792+
793+ cfg. skip_struct ( move |ty| {
794+ if ty. starts_with ( "__c_anonymous_" ) {
795+ return true ;
796+ }
797+
798+ false
799+ } ) ;
800+
801+ cfg. field_name ( move |struct_, field| {
802+ match field {
803+ // Our stat *_nsec fields normally don't actually exist but are part
804+ // of a timeval struct
805+ s if s. ends_with ( "_nsec" ) && struct_. starts_with ( "stat" ) => {
806+ s. replace ( "e_nsec" , ".tv_nsec" )
807+ }
808+
809+ // FIXME(cygwin): sigaction actually contains a union with two variants:
810+ // a sa_sigaction with type: (*)(int, struct __siginfo *, void *)
811+ // a sa_handler with type sig_t
812+ "sa_sigaction" if struct_ == "sigaction" => "sa_handler" . to_string ( ) ,
813+
814+ s => s. to_string ( ) ,
815+ }
816+ } ) ;
817+
818+ cfg. skip_field ( |struct_, field| {
819+ match ( struct_, field) {
820+ // this is actually a union on linux, so we can't represent it well and
821+ // just insert some padding.
822+ ( "ifreq" , "ifr_ifru" ) => true ,
823+ ( "ifconf" , "ifc_ifcu" ) => true ,
824+
825+ _ => false ,
826+ }
827+ } ) ;
828+
829+ cfg. skip_fn ( move |name| {
830+ // skip those that are manually verified
831+ match name {
832+ // There are two versions of the sterror_r function, see
833+ //
834+ // https://linux.die.net/man/3/strerror_r
835+ //
836+ // An XSI-compliant version provided if:
837+ //
838+ // (_POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600) && ! _GNU_SOURCE
839+ //
840+ // and a GNU specific version provided if _GNU_SOURCE is defined.
841+ //
842+ // libc provides bindings for the XSI-compliant version, which is
843+ // preferred for portable applications.
844+ //
845+ // We skip the test here since here _GNU_SOURCE is defined, and
846+ // test the XSI version below.
847+ "strerror_r" => true ,
848+
849+ // FIXME(cygwin): does not exist on Cygwin
850+ "mlockall" | "munlockall" => true ,
851+
852+ _ => false ,
853+ }
854+ } ) ;
855+
856+ cfg. generate ( "../src/lib.rs" , "main.rs" ) ;
857+ }
858+
689859fn test_windows ( target : & str ) {
690860 assert ! ( target. contains( "windows" ) ) ;
691861 let gnu = target. contains ( "gnu" ) ;
0 commit comments