Win64 build of Bigloo

Joseph Donaldson <[email protected]>
Newsgroups gmane.lisp.scheme.bigloo
Message-ID <1849614188.1707545.1419098266935.JavaMail.yahoo@jws106131.mail.bf1.yahoo.com>

I have recently been working on getting Bigloo to compile under Win64. Initially, I though that this would be relatively straightforward but quickly discovered otherwise. The biggest problem is that Microsoft chose the LLP64 model for Win64 instead of LP64. For those not familiar with LLP64 and LP64, on LLP64 platforms, long long and pointer types are 64bit and long and int are 32 bit. Whereas LP64 platforms have long and pointers 64bit (and generally long long as well). All of the 64 bit platforms currently supported by Bigloo are LP64. This is readily seen in the pervasive assumption that a pointer value can reasonably fit in a long. To port Bigloo to Win64, I needed to address this incorrect assumption. To do so, I introduced the BGL_LONG_T and BGL_ULONG_T types. By default, these are defined to be intptr_t and uintptr_t, types guaranteed large enough to hold a pointer. I then replaced most uses of long and unsigned long in Bigloo with these types.The bulk of the changes in the attached LLP64.patch file are of this kind. However, there were a few instances where additional work was required. For example, I updated the format strings used in runtime/Clib/cwrite.c to use appropriate 64 bit type flags when compiling on Win64, added little endian versions of the __FLOAT_TO_INT_BITS and  __INT_BITS_TO_FLOAT macros, and rewrote bgl_bignum_to_long and bgl_bignum_to_llong. Additionally, I changed the type of various structure length attributes to BGL_LONG_T. For most things, this does not result in any noticeable differences. However, for vectors on 64 bit platforms, it increases the maximum size of vectors from 2^24 to 2^56; that may be useful in some applications. The changes in LLP64.patch are largely applicable to any LLP64 platform. My windows specific changes can  be found in the attached windows.patch file. They are largely process and networking related. The windows.patch assumes that the LLP64.patch has already been applied. The patches are against bigloo4.2a-alpha14Nov14.


With these changes, Bigloo can be compiled for Win64 using Msys2 and the mingw w64 x86_64 gcc compiler. All of the recette tests pass except for a few in the crypto library. I am still investigating these. I have also confirmed that the changes do not prevent the correct compilation under 64 bit linux (arch linux specifically). 


As an aside, the Msys2 project is very nice. It has ported the arch linux package manager to windows allowing the easy installation and management of packages. It is much nicer to work with then the older Msys system.


Let me know if there are any questions. And I hope this is useful. 


Best Regards,
Joseph Donaldson
llp64.patch (text/x-patch, 220.4 KB) - not displayed
windows.patch (text/x-patch, 13.8 KB)
diff --git a/autoconf/bigloo_config.h.in b/autoconf/bigloo_config.h.in
index c9e218a..25b5eeb 100755
--- a/autoconf/bigloo_config.h.in
+++ b/autoconf/bigloo_config.h.in
@@ -451,10 +451,6 @@
 #  include <io.h>
 #  include <string.h>
 #  define chdir _chdir
-/* !!!!! PROBABLY NOT PORTABLE !!!!! */
-#  define chmod _chmod                            
-#  define execl _execl
-#  define getcwd _getcwd
 /* SECOND ARG = UNIX MODE to make directory 0700 --> OWNER RWX GROUP --- OTHERS --- */
 #  define mkdir( a, b ) _mkdir( (a) )
 #  define rmdir _rmdir
diff --git a/configure b/configure
index a6c27fe..e38c7a4 100755
--- a/configure
+++ b/configure
@@ -2526,6 +2526,7 @@ if [ $action = "all" -o $action = "bigloo_config" ]; then
   # The long type in bigloo must be able to hold a ptr.
   # This is not true for the native c long type in Win64, so
   # we use a 64 bit types (i.e., intptr_t and long long)
+
   if [ "$HOSTOS " = "mingw " -a "$elongsize" = "64" ]; then
      bgl_strtol=strtoll
      bgl_strtoul=strtoull
diff --git a/runtime/Clib/cdate.c b/runtime/Clib/cdate.c
index 86ac7ff..cad9ee9 100644
--- a/runtime/Clib/cdate.c
+++ b/runtime/Clib/cdate.c
@@ -11,8 +11,6 @@
 #include <string.h>
 #include <bigloo.h>
 #if defined( _MSC_VER) || defined( _MINGW_VER )
-// force 32 bits time values as Bigloo requires sizeof(time_t) == sizeof(long)
-#  define _USE_32BIT_TIME_T 1
 #endif
 #include <time.h>
 #include <ctype.h>
diff --git a/runtime/Clib/csocket.c b/runtime/Clib/csocket.c
index c67c226..d899109 100644
--- a/runtime/Clib/csocket.c
+++ b/runtime/Clib/csocket.c
@@ -20,12 +20,17 @@
 /*=====================================================================*/
 #if defined( _MSC_VER) || defined( _MINGW_VER )
 #  define _BGL_WIN32_VER
+#  define WINVER  _WIN32_WINNT_WINXP  /* minimum supported windows version XP */
+#  define _WIN32_WINNT _WIN32_WINNT_WINXP
+#  define __MSYS__  1 /* disable inclusion of winsock.h in windows.h */
+#      
 #endif
 
 #include <stddef.h>
 #include <bigloo_config.h>
 #include <time.h>
 #ifndef _BGL_WIN32_VER
+#   define SOCKOPTVALTYPE void*
 #   include <sys/types.h> 
 #   include <sys/socket.h>
 #   include <netinet/in.h>
@@ -43,13 +48,14 @@
 #     include <unistd.h>
 #   endif
 #else
-#   if defined( _MINGW_VER )
-#      include "windows.h"
-#   endif
-#   include <winsock2.h>
-#   include <mswsock.h>
+#   define SOCKOPTVALTYPE char*
+
 #   include <ws2tcpip.h>
+#   include <mswsock.h>
 #   include <io.h>
+#   ifndef AI_ADDRCONFIG
+#      define AI_ADDRCONFIG 0
+#   endif
 #endif
 #include <fcntl.h>
 #include <memory.h>
@@ -990,7 +996,7 @@ gethwaddr( char *intf ) {
 #if( BGL_HAVE_GETHWADDRS )
     struct ifreq buffer;
     int s;
-    if( (s = socket( PF_INET, SOCK_DGRAM, 0 )) == -1 ) {
+    if( BAD_SOCKET(s = socket( PF_INET, SOCK_DGRAM, 0 ))) {
        return BFALSE;
     } else {
        char buf[ 6 * 3 + 1 ];
@@ -1075,7 +1081,7 @@ bgl_gethostinterfaces() {
    obj_t res = BNIL;
    void *tmpAddrPtr = 0L;
 
-   if( (fd = socket( AF_INET, SOCK_DGRAM, 0 )) >= 0 ) {
+   if( !BAD_SOCKET(fd = socket( AF_INET, SOCK_DGRAM, 0 ))) {
       conf.ifc_len = sizeof( data );
       conf.ifc_buf = (caddr_t)data;
 
@@ -1136,7 +1142,7 @@ socket_startup() {
 
    result = setsockopt( INVALID_SOCKET,
 			SOL_SOCKET, SO_OPENTYPE,
-			(const char *)&val,
+			(SOCKOPTVALTYPE)&val,
 			sizeof( val ) );
    if( 0 != result ) {
       socket_error( "make_server_socket",
@@ -1397,7 +1403,7 @@ bgl_make_client_socket( obj_t hostname, int port, int timeo, obj_t inb, obj_t ou
 	       tcp_client_socket_error( hostname, port, "Connection failed", errno );
 	    } else {
 	       int len = sizeof( int );
-	       int r = getsockopt( s, SOL_SOCKET, SO_ERROR, (void *)&err, (socklen_t *)&len );
+	       int r = getsockopt( s, SOL_SOCKET, SO_ERROR, (SOCKOPTVALTYPE)&err, (socklen_t *)&len );
 
 	       if( (r < 0) || (err != 0) ) {
 		  /* we have experienced a failure so we */
@@ -1544,7 +1550,7 @@ bgl_make_server_socket( obj_t hostname, int portnum, int backlog ) {
 
    /* set the reuse flag */
    if( setsockopt( s, SOL_SOCKET, SO_REUSEADDR,
-		   &sock_opt, sizeof( sock_opt ) ) < 0 ) {
+		   (SOCKOPTVALTYPE)&sock_opt, sizeof( sock_opt ) ) < 0 ) {
 	 system_error( msg, BINT( portnum ) );
    }
 
@@ -1826,13 +1832,10 @@ get_socket_hostname( int fd, obj_t hostip ) {
    struct hostent *host = 0;
    char *hip = BSTRING_TO_STRING( hostip );
 
-#if( BGL_HAVE_INET_ATON || BGL_HAVE_INET_PTON )
    struct sockaddr_in sin;
-#else
-   struct sockaddr_in *sin;
-#endif      
+    
       
-#if( BGL_HAVE_GETADDRINFO )
+#if(BGL_HAVE_GETADDRINFO)
    socklen_t len = sizeof( sin );
 
    /* cannot fail because we have created the socket */
@@ -1842,19 +1845,22 @@ get_socket_hostname( int fd, obj_t hostip ) {
       sin.sin_family = AF_INET;
    }
 #endif
+
+
       
 #if( BGL_HAVE_INET_ATON )
    /* For IPv4 prefer inet_aton when available because it */
    /* supports more IP format than inet_pton.             */
    if( inet_aton( BSTRING_TO_STRING( hostip ), &(sin.sin_addr) ) )
       host = bglhostbyaddr( &sin );
+   
 #else
 #  if( BGL_HAVE_INET_PTON )	 
    if( inet_pton( AF_INET, BSTRING_TO_STRING( hostip ), &sin.sin_addr ) )
       host = bglhostbyaddr( &sin );
 #  else
-   sin = inet_addr( hostip );
-   host = bglhostbyaddr( sin );
+   sin.sin_addr.s_addr = inet_addr( BSTRING_TO_STRING( hostip ) );
+   host = bglhostbyaddr( &sin );
 #  endif
 #endif      
       
@@ -2028,7 +2034,7 @@ bgl_getprotobynumber( int number ) {
       type _v;								\
       socklen_t _l = sizeof( type );					\
       									\
-      if( getsockopt( SOCKET( s ).fd, level, optname, &_v, &_l ) ) {	\
+      if( getsockopt( SOCKET( s ).fd, level, optname, (SOCKOPTVALTYPE)&_v, &_l ) ) { \
 	 return BUNSPEC;						\
       } else {								\
 	 return conv( _v );						\
@@ -2043,7 +2049,7 @@ bgl_getprotobynumber( int number ) {
       type _v = val;							\
       socklen_t _l = sizeof( type );					\
       									\
-      if( setsockopt( SOCKET( s ).fd, level, optname, &_v, _l ) ) {	\
+      if( setsockopt( SOCKET( s ).fd, level, optname, (SOCKOPTVALTYPE)&_v, _l ) ) { \
 	 return BFALSE;							\
       } else {								\
 	 return s;							\
@@ -2303,7 +2309,7 @@ bgl_setsockopt( obj_t socket, obj_t option, obj_t val ) {
       mreq.imr_interface.s_addr = htonl( INADDR_ANY );
       
       if( setsockopt( SOCKET( socket ).fd, IPPROTO_IP,
-	 IP_ADD_MEMBERSHIP, &mreq, sizeof( struct ip_mreq ) ) )
+		      IP_ADD_MEMBERSHIP, (SOCKOPTVALTYPE)&mreq, sizeof( struct ip_mreq ) ) )
 	 return BFALSE;
       else
 	 return socket;
@@ -2320,7 +2326,7 @@ bgl_setsockopt( obj_t socket, obj_t option, obj_t val ) {
       mreq.imr_multiaddr.s_addr = inet_addr( BSTRING_TO_STRING( val ) );
       mreq.imr_interface.s_addr = htonl( INADDR_ANY );
       if( setsockopt( SOCKET( socket ).fd, IPPROTO_IP,
-	 IP_DROP_MEMBERSHIP, &mreq, sizeof( struct ip_mreq ) ) )
+		      IP_DROP_MEMBERSHIP, (SOCKOPTVALTYPE)&mreq, sizeof( struct ip_mreq ) ) )
 	 return BFALSE;
       else
 	 return socket;
@@ -2358,11 +2364,18 @@ datagram_socket_write( obj_t port, void *buf, size_t len ) {
 			"socket closed",
 			sock );
    }
-
-   if( (n = sendto( fd, buf, len, 0,
+    #ifdef _BGL_WIN32_VER
+    SOCKET s2 = _get_osfhandle(fd);
+    n = sendto( s2, buf, len, 0,
+	       (struct sockaddr *)&BGL_DATAGRAM_SOCKET( sock ).server,
+	       sizeof( struct sockaddr_in ));
+    #else
+    n = sendto( fd, buf, len, 0,
 		    (struct sockaddr *)&BGL_DATAGRAM_SOCKET( sock ).server,
-		    sizeof( struct sockaddr_in ) )) == -1 ) {
-      char buffer[ 512 ];
+		sizeof( struct sockaddr_in ));
+    #endif		     
+   if( n  == -1 ) {
+     char buffer[ 512 ];
       
       BGL_MUTEX_LOCK( socket_mutex );
       sprintf( buffer, "%s (%d)", strerror( errno ), errno );
@@ -2407,10 +2420,12 @@ bgl_make_datagram_client_socket( obj_t hostname, int port, bool_t broadcast ) {
       datagram_client_socket_error( hostname, port, "cannot create socket", errno );
    }
 
+   
+
    // configure the socket
    if( broadcast ) {
       int bcast = 1;
-      if( setsockopt( s, SOL_SOCKET, SO_BROADCAST, &bcast, sizeof( bcast ) ) == -1) {
+      if( setsockopt( s, SOL_SOCKET, SO_BROADCAST, (SOCKOPTVALTYPE)&bcast, sizeof( bcast ) ) == -1) {
 	 datagram_client_socket_error( hostname, port,
 				       "cannot configure socket for broadcast",
 				       errno );
@@ -2435,6 +2450,9 @@ bgl_make_datagram_client_socket( obj_t hostname, int port, bool_t broadcast ) {
    a_socket->datagram_socket_t.hostname = hname;
    a_socket->datagram_socket_t.hostip = bgl_inet_ntop( &(server->sin_addr) );
    a_socket->datagram_socket_t.stype = BGL_SOCKET_CLIENT;
+   #ifdef _BGL_WIN32_VER
+   s = _open_osfhandle( s, _O_RDWR );
+   #endif
    a_socket->datagram_socket_t.fd = s;
    
    /* socket port */
@@ -2498,13 +2516,13 @@ bgl_make_datagram_server_socket( int portnum ) {
    for( p = servinfo; p != NULL; p = p->ai_next ) {
       int sock_opt = 1;
       
-      if( (s = socket( p->ai_family, p->ai_socktype, p->ai_protocol )) == -1 ) {
+      if( BAD_SOCKET(s = (int)socket( p->ai_family, p->ai_socktype, p->ai_protocol ))) {
 	 socket_error( msg, "cannot create socket", BINT( portnum ) );
       }
 
       /* set the reuse flag */
       if( setsockopt( s, SOL_SOCKET, SO_REUSEADDR,
-		      &sock_opt, sizeof( sock_opt ) ) < 0 ) {
+		      (SOCKOPTVALTYPE)&sock_opt, sizeof( sock_opt ) ) < 0 ) {
 	 system_error( msg, BINT( portnum ) );
       }
 
@@ -2524,6 +2542,9 @@ bgl_make_datagram_server_socket( int portnum ) {
    sock->datagram_socket_t.portnum = portnum;
    sock->datagram_socket_t.hostname = BUNSPEC;
    sock->datagram_socket_t.hostip = BFALSE;
+   #ifdef _BGL_WIN32_VER
+   s = _open_osfhandle( s, _O_RDWR );
+   #endif
    sock->datagram_socket_t.fd = s;
    sock->datagram_socket_t.stype = BGL_SOCKET_SERVER;
 
@@ -2575,7 +2596,7 @@ bgl_make_datagram_unbound_socket( obj_t family ) {
       socket_error( msg, "unsupported socket family", family );
    }
 
-   if( (s = socket( fam, SOCK_DGRAM, 0 )) == -1 ) {
+   if( BAD_SOCKET(s = (int)socket( fam, SOCK_DGRAM, 0 ))) {
       socket_error( msg, "cannot create socket", family );
    }
 
@@ -2584,6 +2605,9 @@ bgl_make_datagram_unbound_socket( obj_t family ) {
    sock->datagram_socket_t.portnum = 0;
    sock->datagram_socket_t.hostname = BUNSPEC;
    sock->datagram_socket_t.hostip = BFALSE;
+   #ifdef _BGL_WIN32_VER
+   s = _open_osfhandle( s, _O_RDWR );
+   #endif
    sock->datagram_socket_t.fd = s;
    sock->datagram_socket_t.stype = BGL_SOCKET_SERVER;
 
@@ -2709,8 +2733,16 @@ bgl_datagram_socket_receive( obj_t sock, BGL_LONG_T sz ) {
    }
 
    addr_len = sizeof( their_addr );
-   if( (n = recvfrom( fd, buf, sz - 1 , 0,
-		      (struct sockaddr *)&their_addr, &addr_len )) == -1 ) {
+
+   #ifdef _BGL_WIN32_VER 
+   SOCKET s2 = _get_osfhandle(fd);
+   n = recvfrom( s2, buf, sz - 1 , 0,
+		 (struct sockaddr *)&their_addr, &addr_len );
+   #else
+   n = recvfrom( fd, buf, sz - 1 , 0,
+		 (struct sockaddr *)&their_addr, &addr_len );
+   #endif
+   if( n == -1 ) {
       socket_error( "datagram-socket-receive", "cannot receive datagram", sock );
    } else {
       obj_t env = BGL_CURRENT_DYNAMIC_ENV();
@@ -2750,6 +2782,7 @@ bgl_datagram_socket_send( obj_t sock, obj_t str, obj_t host, int port ) {
 			sock );
    }
 
+#if BGL_HAVE_INET_PTON 
    /* FIXME: No support for AF_UNIX, etc.  */
    if( !inet_pton( AF_INET, BSTRING_TO_STRING( host ),
 		   &((struct sockaddr_in *)&their_addr)->sin_addr ) ) {
@@ -2768,8 +2801,66 @@ bgl_datagram_socket_send( obj_t sock, obj_t str, obj_t host, int port ) {
       slen = sizeof( struct sockaddr_in );
    }
 
+#elif BGL_HAVE_GETADDRINFO
+   {
+     struct addrinfo hints;
+     struct addrinfo *results = NULL;
+     int ret = 0;
+     
+     memset(&hints, 0, sizeof(struct addrinfo));
+     hints.ai_family = AF_UNSPEC;
+     hints.ai_socktype = SOCK_DGRAM;
+     hints.ai_flags = 0;
+     hints.ai_protocol = 0;
+     
+     ret = getaddrinfo(BSTRING_TO_STRING( host ),
+		       NULL,
+		       &hints,
+		       &results);
+     
+     if(0 != ret || NULL == results){
+       socket_error( "datagram-socket-send",
+		     "cannot convert destination address", sock );
+     } else {
+       /* only use the first result */
+       if(AF_INET6 == results->ai_family){
+	 
+	 ((struct sockaddr_in6 *)&their_addr)->sin6_addr = ((struct sockaddr_in6*)&(results->ai_addr))->sin6_addr;
+	 ((struct sockaddr_in6 *)&their_addr)->sin6_port = htons( port );
+	 ((struct sockaddr *)&their_addr)->sa_family = AF_INET6;
+	 slen = sizeof( struct sockaddr_in6 );
+       
+       } else if (AF_INET == results->ai_family){
+	 
+	 ((struct sockaddr_in *)&their_addr)->sin_addr = ((struct sockaddr_in*)&(results->ai_addr))->sin_addr;
+	 ((struct sockaddr_in *)&their_addr)->sin_port = htons( port );
+	 ((struct sockaddr *)&their_addr)->sa_family = AF_INET;
+	 slen = sizeof( struct sockaddr_in );
+	 
+       }
+       
+     }
+
+     if(NULL != results){
+       freeaddrinfo(results);
+     }
+   }
+#else
+
+#error "inet_pton or getaddrinfo needed for bgl_datagram_socket_send"
+
+#endif /* BGL_HAVE_INET_PTON */
+
+
+   #ifdef _BGL_WIN32_VER
+   SOCKET s2 = _get_osfhandle(fd);
+   sent = sendto( s2, BSTRING_TO_STRING( str ), STRING_LENGTH( str ), 0,
+		  (struct sockaddr *) &their_addr, slen );
+   
+   #else
    sent = sendto( fd, BSTRING_TO_STRING( str ), STRING_LENGTH( str ), 0,
 		  (struct sockaddr *) &their_addr, slen );
+   #endif
    if( sent < 0 ) {
       socket_error( "datagram-socket-send", "cannot send datagram", sock );
    }
diff --git a/runtime/Clib/csystem.c b/runtime/Clib/csystem.c
index 3008b84..c95ac00 100644
--- a/runtime/Clib/csystem.c
+++ b/runtime/Clib/csystem.c
@@ -572,6 +572,13 @@ bgl_symlink( char *s1, char *s2 ) {
 #endif   
 }
 
+#if defined(_BGL_WIN32_VER)
+BGL_RUNTIME_DEF int getppid() {
+  return 0;
+}
+#endif 
+
+
 /*---------------------------------------------------------------------*/
 /*    bits conversions (see bigloo.h for GCC versions).                */
 /*---------------------------------------------------------------------*/
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.