rubinius/rubinius

View on GitHub
rakelib/platform.rake

Summary

Maintainability
Test Coverage
require File.expand_path('../../library/ffi/generators', __FILE__)

deps = ["Rakefile",
        "rakelib/platform.rake"
] + Dir['lib/ffi/*rb']

file "#{BUILD_CONFIG[:builddir]}#{BUILD_CONFIG[:codedbdir]}/platform.conf" => deps do |task|
  puts "GEN codedb/platform.conf"

  File.open task.name, "wb" do |f|
    Rubinius::FFI::Generators::Structures.new 'addrinfo' do |s|
      if BUILD_CONFIG[:windows]
        s.include "ws2tcpip.h"
      else
        s.include 'sys/socket.h'
        s.include 'netdb.h'
      end
      s.name 'struct addrinfo'
      s.field :ai_flags, :int
      s.field :ai_family, :int
      s.field :ai_socktype, :int
      s.field :ai_protocol, :int
      s.field :ai_addrlen, :int
      s.field :ai_addr, :pointer
      s.field :ai_canonname, :string
      s.field :ai_next, :pointer
    end.write_config(f)

    Rubinius::FFI::Generators::Structures.new 'ifaddrs' do |s|
      s.include 'sys/types.h'
      s.include 'ifaddrs.h'

      s.name 'struct ifaddrs'

      s.field :ifa_next, :pointer
      s.field :ifa_name, :string
      s.field :ifa_flags, :int
      s.field :ifa_addr, :pointer
      s.field :ifa_netmask, :pointer
      s.field :ifa_broadaddr, :pointer
      s.field :ifa_dstaddr, :pointer
    end.write_config(f)

    Rubinius::FFI::Generators::Structures.new 'sockaddr' do |s|
      s.include 'sys/socket.h'

      s.name 'struct sockaddr'

      s.field :sa_data, :char_array
      s.field :sa_family, :sa_family_t
    end.write_config(f)

    Rubinius::FFI::Generators::Structures.new 'dirent' do |s|
      s.include "sys/types.h"
      s.include "dirent.h"
      s.name 'struct dirent'
      s.field :d_ino, :ino_t
      s.field :d_reclen, :ushort
      s.field :d_name, :char_array
    end.write_config(f)

    struct = Rubinius::FFI::Generators::Structures.new 'timeval' do |s|
      s.include "sys/time.h"
      s.name 'struct timeval'
      s.field :tv_sec, :time_t
      s.field :tv_usec, :suseconds_t
    end

    struct.write_config(f)
    struct.write_class(f)

    Rubinius::FFI::Generators::Structures.new 'sockaddr_in' do |s|
      if BUILD_CONFIG[:windows]
        s.include "ws2tcpip.h"
      else
        s.include "netinet/in.h"
        s.include "sys/socket.h"
      end
      s.include "fcntl.h"
      s.include "sys/stat.h"
      s.name 'struct sockaddr_in'
      s.field :sin_family, :sa_family_t
      s.field :sin_port, :ushort
      s.field :sin_addr
      s.field :sin_zero, :char_array
    end.write_config(f)

    Rubinius::FFI::Generators::Structures.new 'sockaddr_in6' do |s|
      if BUILD_CONFIG[:windows]
        s.include "ws2tcpip.h"
      else
        s.include "netinet/in.h"
        s.include "sys/socket.h"
      end
      s.include "fcntl.h"
      s.include "sys/stat.h"
      s.name 'struct sockaddr_in6'
      s.field :sin6_family, :sa_family_t
      s.field :sin6_port, :ushort
      s.field :sin6_flowinfo
      s.field :sin6_addr, :char_array
      s.field :sin6_scope_id
    end.write_config(f)

    unless BUILD_CONFIG[:windows]
      sockaddr_un = Rubinius::FFI::Generators::Structures.new 'sockaddr_un' do |s|
        s.include "sys/un.h"
        s.name 'struct sockaddr_un'
        s.field :sun_family, :sa_family_t
        s.field :sun_path, :char_array
      end

      sockaddr_un.write_config f if sockaddr_un.found?
    end

    Rubinius::FFI::Generators::Structures.new 'hostent' do |s|
      s.include 'netdb.h'
      s.name 'struct hostent'

      s.field :h_name, :string
      s.field :h_aliases, :pointer
      s.field :h_addrtype, :int
      s.field :h_length, :int
      s.field :h_addr_list, :pointer
    end.write_config(f)

    Rubinius::FFI::Generators::Structures.new 'linger' do |s|
      if BUILD_CONFIG[:windows]
        s.include "winsock2.h"
      else
        s.include "sys/socket.h"
      end
      s.name "struct linger"
        s.field :l_onoff
        s.field :l_linger
    end.write_config(f)

    Rubinius::FFI::Generators::Structures.new 'iovec' do |s|
      s.include 'sys/socket.h'
      s.name 'struct iovec'

      s.field :iov_base, :pointer
      s.field :iov_len, :size_t
    end.write_config(f)

    Rubinius::FFI::Generators::Structures.new 'msghdr' do |s|
      s.include 'sys/socket.h'
      s.name 'struct msghdr'

      s.field :msg_name, :pointer
      s.field :msg_namelen, :int
      s.field :msg_iov, :pointer
      s.field :msg_iovlen, :size_t
      s.field :msg_control, :pointer
      s.field :msg_controllen, :size_t
      s.field :msg_flags, :int
    end.write_config(f)

    Rubinius::FFI::Generators::Structures.new 'servent' do |s|
      if BUILD_CONFIG[:windows]
        s.include "winsock2.h"
      else
        s.include "netdb.h"
      end
      s.name 'struct servent'
      s.field :s_name, :pointer
      s.field :s_aliases, :pointer
      s.field :s_port, :int
      s.field :s_proto, :pointer
    end.write_config(f)

    Rubinius::FFI::Generators::Structures.new 'stat' do |s|
      unless BUILD_CONFIG[:windows]
        s.include "sys/types.h"
        s.include "unistd.h"
        s.include "time.h"
      end
      s.include "sys/stat.h"
      s.name 'struct stat'
      s.field :st_dev, :dev_t
      s.field :st_ino, :ino_t
      s.field :st_mode, :mode_t
      if BUILD_CONFIG[:windows]
        s.field :st_nlink, :short
        s.field :st_uid, :short
        s.field :st_gid, :short
      else
        s.field :st_nlink, :nlink_t
        s.field :st_uid, :uid_t
        s.field :st_gid, :gid_t
      end
      s.field :st_rdev, :dev_t
      s.field :st_size, :off_t
      unless BUILD_CONFIG[:windows]
        s.field :st_blksize
        s.field :st_blocks
      end
      s.field :st_atime, :time_t
      s.field :st_mtime, :time_t
      s.field :st_ctime, :time_t
    end.write_config(f)

    Rubinius::FFI::Generators::Structures.new 'pwd' do |s|
      s.include "sys/types.h"
      s.include "pwd.h"

      s.name "struct passwd"
      s.field :pw_name, :string
      s.field :pw_passwd, :string
      s.field :pw_uid, :uid_t
      s.field :pw_gid, :gid_t
      s.field :pw_gecos, :string
      s.field :pw_dir, :string
      s.field :pw_shell, :string
    end.write_config(f)

    Rubinius::FFI::Generators::Structures.new 'grp' do |s|
      s.include "sys/types.h"
      s.include "grp.h"

      s.name "struct group"
      s.field :gr_name, :string
      s.field :gr_passwd, :string
      s.field :gr_gid, :gid_t
      s.field :gr_mem, :pointer
    end.write_config(f)

    unless BUILD_CONFIG[:windows]
      Rubinius::FFI::Generators::Structures.new 'rlimit' do |s|
        s.include "sys/types.h"
        s.include "sys/time.h"
        s.include "sys/resource.h"
        s.name 'struct rlimit'
        s.field :rlim_cur, :rlim_t
        s.field :rlim_max, :rlim_t
      end.write_config(f)
    end

    # FIXME these constants don't have standard names.  LOCK_SH == Linux,
    # O_SHLOCK on Bsd/Darwin, etc.  Binary doesn't exist at all in many non-Unix
    # variants.  This should come out of something like config.h

    # fixme_constants = %w{
    #   LOCK_SH
    #   LOCK_EX
    #   LOCK_NB
    #   LOCK_UN
    #   BINARY
    # }

    Rubinius::FFI::Generators::Constants.new 'rbx.platform.file' do |cg|
      cg.include 'stdio.h'
      cg.include 'fcntl.h'
      cg.include 'sys/stat.h'

      file_constants = %w[
        O_RDONLY
        O_WRONLY
        O_RDWR
        O_CREAT
        O_EXCL
        O_NOCTTY
        O_TRUNC
        O_APPEND
        O_NONBLOCK
        O_SYNC
        O_CLOEXEC
        S_IRUSR
        S_IWUSR
        S_IXUSR
        S_IRGRP
        S_IWGRP
        S_IXGRP
        S_IROTH
        S_IWOTH
        S_IXOTH
        S_IFMT
        S_IFIFO
        S_IFCHR
        S_IFDIR
        S_IFBLK
        S_IFREG
        S_IFLNK
        S_IFSOCK
        S_IFWHT
        S_ISUID
        S_ISGID
        S_ISVTX
      ]

      file_constants.each { |c| cg.const c }
    end.write_constants(f)

    Rubinius::FFI::Generators::Constants.new 'rbx.platform.io' do |cg|
      cg.include 'stdio.h'

      io_constants = %w[
        SEEK_SET
        SEEK_CUR
        SEEK_END
      ]

      io_constants.each { |c| cg.const c }
    end.write_constants(f)
    
    Rubinius::FFI::Generators::Constants.new 'rbx.platform.select' do |cg|
      cg.include 'sys/select.h'
      
      select_constants = %w[
        FD_SETSIZE
      ]
      
      select_constants.each { |c| cg.const c }
    end.write_constants(f)

    # Not available on all platforms. Try to load these constants anyway.
    Rubinius::FFI::Generators::Constants.new 'rbx.platform.advise' do |cg|
      cg.include 'fcntl.h'

      advise_constants = %w[
        POSIX_FADV_NORMAL
        POSIX_FADV_SEQUENTIAL
        POSIX_FADV_RANDOM
        POSIX_FADV_WILLNEED
        POSIX_FADV_DONTNEED
        POSIX_FADV_NOREUSE
      ]

      advise_constants.each { |c| cg.const c }
    end.write_constants(f)

    Rubinius::FFI::Generators::Constants.new 'rbx.platform.fcntl' do |cg|
      cg.include 'fcntl.h'

      fcntl_constants = %w[
        F_DUPFD
        F_GETFD
        F_GETLK
        F_SETFD
        F_GETFL
        F_SETFL
        F_SETLK
        F_SETLKW
        FD_CLOEXEC
        F_RDLCK
        F_UNLCK
        F_WRLCK
        O_CREAT
        O_EXCL
        O_NOCTTY
        O_TRUNC
        O_APPEND
        O_NONBLOCK
        O_NDELAY
        O_RDONLY
        O_RDWR
        O_WRONLY
        O_ACCMODE
      ]

      fcntl_constants.each { |c| cg.const c }
    end.write_constants(f)

    Rubinius::FFI::Generators::Constants.new 'rbx.platform.syslog' do |cg|
      cg.include 'syslog.h'

      syslog_constants = %w[
        LOG_EMERG
        LOG_ALERT
        LOG_ERR
        LOG_CRIT
        LOG_WARNING
        LOG_NOTICE
        LOG_INFO
        LOG_DEBUG
        LOG_PID
        LOG_CONS
        LOG_ODELAY
        LOG_NDELAY
        LOG_NOWAIT
        LOG_PERROR
        LOG_AUTH
        LOG_AUTHPRIV
        LOG_CONSOLE
        LOG_CRON
        LOG_DAEMON
        LOG_FTP
        LOG_KERN
        LOG_LPR
        LOG_MAIL
        LOG_NEWS
        LOG_NTP
        LOG_SECURITY
        LOG_SYSLOG
        LOG_USER
        LOG_UUCP
        LOG_LOCAL0
        LOG_LOCAL1
        LOG_LOCAL2
        LOG_LOCAL3
        LOG_LOCAL4
        LOG_LOCAL5
        LOG_LOCAL6
        LOG_LOCAL7
      ]

      syslog_constants.each { |c| cg.const c }
    end.write_constants(f)

    Rubinius::FFI::Generators::Constants.new 'rbx.platform.socket' do |cg|
      cg.include 'sys/types.h'

      if BUILD_CONFIG[:windows]
        cg.include "winsock2.h"
      else
        cg.include 'sys/socket.h'
        cg.include 'netdb.h'
        cg.include 'netinet/in_systm.h'
        cg.include 'netinet/tcp.h'
        cg.include 'netinet/udp.h'
        cg.include 'netinet/in.h'
        cg.include 'net/if.h'
      end

      socket_constants = %w[
        AF_APPLETALK
        AF_AX25
        AF_INET
        AF_INET6
        AF_IPX
        AF_ISDN
        AF_LOCAL
        AF_MAX
        AF_PACKET
        AF_ROUTE
        AF_SNA
        AF_UNIX
        AF_UNSPEC
        AI_ADDRCONFIG
        AI_ALL
        AI_CANONNAME
        AI_NUMERICHOST
        AI_NUMERICSERV
        AI_PASSIVE
        AI_V4MAPPED
        EAI_ADDRFAMILY
        EAI_AGAIN
        EAI_BADFLAGS
        EAI_FAIL
        EAI_FAMILY
        EAI_MEMORY
        EAI_NODATA
        EAI_NONAME
        EAI_OVERFLOW
        EAI_SERVICE
        EAI_SOCKTYPE
        EAI_SYSTEM
        FNM_CASEFOLD
        FNM_DOTMATCH
        FNM_EXTGLOB
        FNM_NOESCAPE
        FNM_PATHNAME
        FNM_SYSCASE
        IFF_ALLMULTI
        IFF_AUTOMEDIA
        IFF_BROADCAST
        IFF_DEBUG
        IFF_DYNAMIC
        IFF_LOOPBACK
        IFF_MASTER
        IFF_MULTICAST
        IFF_NOARP
        IFF_NOTRAILERS
        IFF_POINTOPOINT
        IFF_PORTSEL
        IFF_PROMISC
        IFF_RUNNING
        IFF_SLAVE
        IFF_UP
        IF_NAMESIZE
        INADDR_ALLHOSTS_GROUP
        INADDR_ANY
        INADDR_BROADCAST
        INADDR_LOOPBACK
        INADDR_MAX_LOCAL_GROUP
        INADDR_NONE
        INADDR_UNSPEC_GROUP
        INET6_ADDRSTRLEN
        INET_ADDRSTRLEN
        IPPORT_RESERVED
        IPPORT_USERRESERVED
        IPPROTO_AH
        IPPROTO_DSTOPTS
        IPPROTO_EGP
        IPPROTO_ESP
        IPPROTO_FRAGMENT
        IPPROTO_HOPOPTS
        IPPROTO_ICMP
        IPPROTO_ICMPV6
        IPPROTO_IDP
        IPPROTO_IGMP
        IPPROTO_IP
        IPPROTO_IPV6
        IPPROTO_NONE
        IPPROTO_PUP
        IPPROTO_RAW
        IPPROTO_ROUTING
        IPPROTO_TCP
        IPPROTO_TP
        IPPROTO_UDP
        IPV6_CHECKSUM
        IPV6_DONTFRAG
        IPV6_DSTOPTS
        IPV6_HOPLIMIT
        IPV6_HOPOPTS
        IPV6_JOIN_GROUP
        IPV6_LEAVE_GROUP
        IPV6_MULTICAST_HOPS
        IPV6_MULTICAST_IF
        IPV6_MULTICAST_LOOP
        IPV6_NEXTHOP
        IPV6_PATHMTU
        IPV6_PKTINFO
        IPV6_RECVDSTOPTS
        IPV6_RECVHOPLIMIT
        IPV6_RECVHOPOPTS
        IPV6_RECVPATHMTU
        IPV6_RECVPKTINFO
        IPV6_RECVRTHDR
        IPV6_RECVTCLASS
        IPV6_RTHDR
        IPV6_RTHDRDSTOPTS
        IPV6_RTHDR_TYPE_0
        IPV6_TCLASS
        IPV6_UNICAST_HOPS
        IPV6_V6ONLY
        IP_ADD_MEMBERSHIP
        IP_ADD_SOURCE_MEMBERSHIP
        IP_BLOCK_SOURCE
        IP_DEFAULT_MULTICAST_LOOP
        IP_DEFAULT_MULTICAST_TTL
        IP_DROP_MEMBERSHIP
        IP_DROP_SOURCE_MEMBERSHIP
        IP_FREEBIND
        IP_HDRINCL
        IP_IPSEC_POLICY
        IP_MAX_MEMBERSHIPS
        IP_MINTTL
        IP_MSFILTER
        IP_MTU
        IP_MTU_DISCOVER
        IP_MULTICAST_IF
        IP_MULTICAST_LOOP
        IP_MULTICAST_TTL
        IP_OPTIONS
        IP_PASSSEC
        IP_PKTINFO
        IP_PKTOPTIONS
        IP_PMTUDISC_DO
        IP_PMTUDISC_DONT
        IP_PMTUDISC_WANT
        IP_RECVERR
        IP_RECVOPTS
        IP_RECVRETOPTS
        IP_RECVTOS
        IP_RECVTTL
        IP_RETOPTS
        IP_ROUTER_ALERT
        IP_TOS
        IP_TRANSPARENT
        IP_TTL
        IP_UNBLOCK_SOURCE
        IP_XFRM_POLICY
        LOCK_EX
        LOCK_NB
        LOCK_SH
        LOCK_UN
        MCAST_BLOCK_SOURCE
        MCAST_EXCLUDE
        MCAST_INCLUDE
        MCAST_JOIN_GROUP
        MCAST_JOIN_SOURCE_GROUP
        MCAST_LEAVE_GROUP
        MCAST_LEAVE_SOURCE_GROUP
        MCAST_MSFILTER
        MCAST_UNBLOCK_SOURCE
        MSG_CONFIRM
        MSG_CTRUNC
        MSG_DONTROUTE
        MSG_DONTWAIT
        MSG_EOR
        MSG_ERRQUEUE
        MSG_FASTOPEN
        MSG_FIN
        MSG_MORE
        MSG_NOSIGNAL
        MSG_OOB
        MSG_PEEK
        MSG_PROXY
        MSG_RST
        MSG_SYN
        MSG_TRUNC
        MSG_WAITALL
        NI_DGRAM
        NI_MAXHOST
        NI_MAXSERV
        NI_NAMEREQD
        NI_NOFQDN
        NI_NUMERICHOST
        NI_NUMERICSERV
        PF_APPLETALK
        PF_AX25
        PF_INET
        PF_INET6
        PF_IPX
        PF_ISDN
        PF_KEY
        PF_LOCAL
        PF_MAX
        PF_PACKET
        PF_ROUTE
        PF_SNA
        PF_UNIX
        PF_UNSPEC
        SCM_CREDENTIALS
        SCM_RIGHTS
        SCM_TIMESTAMP
        SCM_TIMESTAMPING
        SCM_TIMESTAMPNS
        SCM_WIFI_STATUS
        SEEK_CUR
        SEEK_DATA
        SEEK_END
        SEEK_HOLE
        SEEK_SET
        SHUT_RD
        SHUT_RDWR
        SHUT_WR
        SOCK_DGRAM
        SOCK_PACKET
        SOCK_RAW
        SOCK_RDM
        SOCK_SEQPACKET
        SOCK_STREAM
        SOL_IP
        SOL_SOCKET
        SOL_TCP
        SOL_UDP
        SO_ACCEPTCONN
        SO_ATTACH_FILTER
        SO_BINDTODEVICE
        SO_BPF_EXTENSIONS
        SO_BROADCAST
        SO_BUSY_POLL
        SO_DEBUG
        SO_DETACH_FILTER
        SO_DOMAIN
        SO_DONTROUTE
        SO_ERROR
        SO_GET_FILTER
        SO_KEEPALIVE
        SO_LINGER
        SO_LOCK_FILTER
        SO_MARK
        SO_MAX_PACING_RATE
        SO_NOFCS
        SO_NO_CHECK
        SO_OOBINLINE
        SO_PASSCRED
        SO_PASSSEC
        SO_PEEK_OFF
        SO_PEERCRED
        SO_PEERNAME
        SO_PEERSEC
        SO_PRIORITY
        SO_PROTOCOL
        SO_RCVBUF
        SO_RCVBUFFORCE
        SO_RCVLOWAT
        SO_RCVTIMEO
        SO_REUSEADDR
        SO_REUSEPORT
        SO_RXQ_OVFL
        SO_SECURITY_AUTHENTICATION
        SO_SECURITY_ENCRYPTION_NETWORK
        SO_SECURITY_ENCRYPTION_TRANSPORT
        SO_SELECT_ERR_QUEUE
        SO_SNDBUF
        SO_SNDBUFFORCE
        SO_SNDLOWAT
        SO_SNDTIMEO
        SO_TIMESTAMP
        SO_TIMESTAMPING
        SO_TIMESTAMPNS
        SO_TYPE
        SO_WIFI_STATUS
        TCP_CONGESTION
        TCP_COOKIE_TRANSACTIONS
        TCP_CORK
        TCP_DEFER_ACCEPT
        TCP_FASTOPEN
        TCP_INFO
        TCP_KEEPCNT
        TCP_KEEPIDLE
        TCP_KEEPINTVL
        TCP_LINGER2
        TCP_MAXSEG
        TCP_MD5SIG
        TCP_NODELAY
        TCP_QUEUE_SEQ
        TCP_QUICKACK
        TCP_REPAIR
        TCP_REPAIR_OPTIONS
        TCP_REPAIR_QUEUE
        TCP_SYNCNT
        TCP_THIN_DUPACK
        TCP_THIN_LINEAR_TIMEOUTS
        TCP_TIMESTAMP
        TCP_USER_TIMEOUT
        TCP_WINDOW_CLAMP
        UDP_CORK
        SOMAXCONN
      ]

      socket_constants.each { |c| cg.const c }
    end.write_constants(f)

    unless BUILD_CONFIG[:windows]
      Rubinius::FFI::Generators::Constants.new 'rbx.platform.process' do |cg|
        cg.include 'sys/wait.h'
        cg.include 'sys/resource.h'
        cg.include 'stdlib.h'

        process_constants = %w{
          EXIT_SUCCESS
          EXIT_FAILURE

          WNOHANG
          WUNTRACED
          PRIO_PROCESS
          PRIO_PGRP
          PRIO_USER
          RLIMIT_CPU
          RLIMIT_FSIZE
          RLIMIT_DATA
          RLIMIT_STACK
          RLIMIT_CORE
          RLIMIT_RSS
          RLIMIT_NPROC
          RLIMIT_NOFILE
          RLIMIT_MEMLOCK
          RLIMIT_AS
          RLIMIT_SBSIZE
          RLIMIT_RTPRIO
          RLIMIT_RTTIME
          RLIMIT_SIGPENDING
          RLIMIT_MSGQUEUE
          RLIMIT_NICE
        }

        process_constants.each { |c| cg.const c }

        long_process_constants = %w[
          RLIM_INFINITY
          RLIM_SAVED_MAX
          RLIM_SAVED_CUR
        ]

        long_process_constants.each { |c|
          cg.const c, "%llu", "(unsigned long long)"
        }
      end.write_constants(f)
    end

    # The constants come from MRI's signal.c. This means that some of them might
    # be missing.

    Rubinius::FFI::Generators::Constants.new 'rbx.platform.signal' do |cg|
      cg.include 'signal.h'
      unless BUILD_CONFIG[:windows] or RUBY_PLATFORM.match(/linux-musl$/)
        cg.include 'sys/signal.h'
      end

      signal_constants = %w{
        SIGHUP
        SIGINT
        SIGQUIT
        SIGILL
        SIGTRAP
        SIGIOT
        SIGABRT
        SIGEMT
        SIGFPE
        SIGKILL
        SIGBUS
        SIGSEGV
        SIGSYS
        SIGPIPE
        SIGALRM
        SIGTERM
        SIGURG
        SIGSTOP
        SIGTSTP
        SIGCONT
        SIGCHLD
        SIGCLD
        SIGCHLD
        SIGTTIN
        SIGTTOU
        SIGIO
        SIGXCPU
        SIGXFSZ
        SIGVTALRM
        SIGPROF
        SIGWINCH
        SIGUSR1
        SIGUSR2
        SIGLOST
        SIGMSG
        SIGPWR
        SIGPOLL
        SIGDANGER
        SIGMIGRATE
        SIGPRE
        SIGGRANT
        SIGRETRACT
        SIGSOUND
        SIGINFO
      }

      signal_constants.each { |c| cg.const c }
    end.write_constants(f)

    Rubinius::FFI::Generators::Constants.new 'rbx.platform.zlib' do |cg|
      cg.include_dir 'build/libraries/zlib' if BUILD_CONFIG[:vendor_zlib]
      cg.include 'zlib.h'

      zlib_constants = %w[ZLIB_VERSION]

      zlib_constants.each { |c| cg.const c, "%s", "(char *)" }
    end.write_constants(f)

    unless BUILD_CONFIG[:windows]
      Rubinius::FFI::Generators::Constants.new 'rbx.platform.dlopen' do |cg|
        cg.include 'dlfcn.h'

        dlopen_constants = %w[
          RTLD_LAZY
          RTLD_NOW
          RTLD_LOCAL
          RTLD_GLOBAL
        ]

        dlopen_constants.each { |c| cg.const c }
      end.write_constants(f)
    end

    f.puts Rubinius::FFI::Generators::Types.new.generate
  end
end