Subject: Re: bug#10474: Building guile 2.x under mingw + msys

From: Eli Zaretskii <[email-masked]>
Date: Sat, 21 Jan 2012 13:09:08 +0200

> Date: Thu, 19 Jan 2012 19:35:04 +0200
> From: Eli Zaretskii <[email-masked]>
> Cc: [email-masked], [email-masked]
> 
> > (The rest of your investigation is interesting!)
> 
> Here's some more ;-)

As promised, still more issues below.

1. Compilation warnings in deprecation.c:

       SNARF  deprecation.x
     deprecation.c:40:1: warning: "vsnprintf" redefined
     In file included from deprecation.c:25:
     ../lib/stdio.h:1605:1: warning: this is the location of the previous definition

This is because deprecation.c does this:

     /* Windows defines. */
     #ifdef __MINGW32__
     #define vsnprintf _vsnprintf
     #endif

but lib/stdio.h already did the same.  My solution was to add an
"#ifdef vsnprintf" condition to deprecation.c to avoid redefinition.

2. Compilation warning in expand.c:

       SNARF  expand.x
     expand.c:52:1: warning: "VOID" redefined
     In file included from d:/usr/include/windef.h:253,
		      from d:/usr/include/windows.h:48,
		      from d:/usr/include/winsock2.h:22,
		      from ../libguile/iselect.h:36,
		      from ../libguile/threads.h:30,
		      from ../libguile/gc.h:29,
		      from ../libguile/_scm.h:75,
		      from expand.c:27:
     d:/usr/include/winnt.h:75:1: warning: this is the location of the previous definition
     expand.c:54:1: warning: "CONST" redefined
     In file included from d:/usr/include/windows.h:48,
		      from d:/usr/include/winsock2.h:22,
		      from ../libguile/iselect.h:36,
		      from ../libguile/threads.h:30,
		      from ../libguile/gc.h:29,
		      from ../libguile/_scm.h:75,
		      from expand.c:27:
     d:/usr/include/windef.h:39:1: warning: this is the location of the previous definition

This is because expand.c does:

     #define VOID(src) \
       SCM_MAKE_EXPANDED_VOID(src)
     #define CONST(src, exp) \
       SCM_MAKE_EXPANDED_CONST(src, exp)

and Windows headers have their own definitions for VOID and CONST.

My solution was to add this to expand.c:

     #ifdef VOID
     #undef VOID
     #endif
     #ifdef CONST
     #undef CONST
     #endif

However, I really suggest that expand.c uses some less ubiquitous
symbol names, like SCM_CONST and SCM_VOID.

3. Compilation warning in filesys.c:

       SNARF  filesys.x
     filesys.c:119:1: warning: "mkdir" redefined
     In file included from ../lib/sys/stat.h:47,
		      from filesys.c:92:
     ../lib/sys/stat.h:808:1: warning: this is the location of the previous definition

This is because filesys.c does this:

     /* Some more definitions for the native Windows port. */
     #ifdef __MINGW32__
     # define mkdir(path, mode) mkdir (path)

But gnulib already redirected `mkdir' to its replacement function.  My
solution: don't define if already redirected.  To that end, I added
the following condition before the above #define:

     /* When configured to use the gnulib replacement, don't redefine
	mkdir, as it is already redirected to the replacement, see
	lib/sys/stat.h.  */
     # if !GNULIB_defined_rpl_mkdir

I'm not sure using GNULIB_defined_rpl_mkdir is TRT here, but I didn't
find a better way.

4. Missing setenv needed by dynl.c:

       CC     dynl.lo
     dynl.c: In function `augment_env':
     dynl.c:141: warning: implicit declaration of function `setenv'

Solution: add a setenv implementation.  However, I think Guile would
be better off using a more portable putenv instead.

5. Compilation error in net_db.c:

       CC     net_db.lo
     net_db.c:460: error: `AI_ALL' undeclared here (not in a function)
     net_db.c:460: error: bit-field `_gl_verify_error_if_negative' width not an integer constant
     net_db.c:482: warning: "struct addrinfo" declared inside parameter list
     net_db.c:482: warning: its scope is only this definition or declaration, which is probably not what you want
     net_db.c: In function `scm_from_addrinfo':
     net_db.c:490: error: dereferencing pointer to incomplete type
     net_db.c:491: error: dereferencing pointer to incomplete type
     net_db.c:492: error: dereferencing pointer to incomplete type
     net_db.c:493: error: dereferencing pointer to incomplete type
     net_db.c:494: error: dereferencing pointer to incomplete type
     net_db.c:494: error: dereferencing pointer to incomplete type
     net_db.c:496: error: dereferencing pointer to incomplete type
     net_db.c:496: error: dereferencing pointer to incomplete type
     net_db.c: In function `scm_getaddrinfo':
     net_db.c:614: error: storage size of 'c_hints' isn't known
     net_db.c:657: warning: implicit declaration of function `getaddrinfo'
     net_db.c:665: error: dereferencing pointer to incomplete type
     net_db.c:665: warning: left-hand operand of comma expression has no effect
     net_db.c:668: warning: implicit declaration of function `freeaddrinfo'
     net_db.c:614: warning: unused variable `c_hints'
     net_db.c: At top level:
     net_db.c:680: error: `EAI_BADFLAGS' undeclared here (not in a function)
     net_db.c:680: error: bit-field `_gl_verify_error_if_negative' width not an integer constant
     net_db.c: In function `scm_gai_strerror':
     net_db.c:744: warning: implicit declaration of function `gai_strerror'
     net_db.c:744: warning: passing arg 1 of `scm_from_locale_string' makes pointer from integer without a cast
     In file included from net_db.c:755:
     ../libguile/net_db.x: In function `scm_init_net_db':
     ../libguile/net_db.x:17: error: `AI_PASSIVE' undeclared (first use in this function)
     ../libguile/net_db.x:17: error: (Each undeclared identifier is reported only once
     ../libguile/net_db.x:17: error: for each function it appears in.)
     ../libguile/net_db.x:18: error: `AI_CANONNAME' undeclared (first use in this function)
     ../libguile/net_db.x:19: error: `AI_NUMERICHOST' undeclared (first use in this function)
     ../libguile/net_db.x:20: error: `AI_NUMERICSERV' undeclared (first use in this function)
     ../libguile/net_db.x:21: error: `AI_V4MAPPED' undeclared (first use in this function)
     ../libguile/net_db.x:23: error: `AI_ADDRCONFIG' undeclared (first use in this function)
     ../libguile/net_db.x:27: error: `EAI_NONAME' undeclared (first use in this function)
     ../libguile/net_db.x:28: error: `EAI_AGAIN' undeclared (first use in this function)
     ../libguile/net_db.x:29: error: `EAI_FAIL' undeclared (first use in this function)
     ../libguile/net_db.x:30: error: `EAI_FAMILY' undeclared (first use in this function)
     ../libguile/net_db.x:31: error: `EAI_SOCKTYPE' undeclared (first use in this function)
     ../libguile/net_db.x:32: error: `EAI_SERVICE' undeclared (first use in this function)
     ../libguile/net_db.x:33: error: `EAI_MEMORY' undeclared (first use in this function)
     ../libguile/net_db.x:34: error: `EAI_SYSTEM' undeclared (first use in this function)
     ../libguile/net_db.x:35: error: `EAI_OVERFLOW' undeclared (first use in this function)
     net_db.c: In function `scm_getaddrinfo':
     net_db.c:663: warning: value computed is not used
     make[3]: *** [net_db.lo] Error 1

The reason is that this condition in net_db.c:

     #ifdef HAVE_WINSOCK2_H
     #include <winsock2.h>
     #else
     #include <sys/socket.h>
     #include <netdb.h>
     #include <netinet/in.h>
     #include <arpa/inet.h>
     #endif

is inappropriate when gnulib was used to wrap Windows socket
functions.  When gnulib _is_ used, the missing macros are already
defined by lib/sys/socket.h.  Therefore, I modified the condition to:

     #if HAVE_WINSOCK2_H && !GNULIB_TEST_SOCKET
     #include <winsock2.h>
     # if HAVE_WS2TCPIP_H
     #  include <ws2tcpip.h>
     # endif
     #else
     #include <sys/socket.h>
     #include <netdb.h>
     #include <netinet/in.h>
     #include <arpa/inet.h>
     #endif

using GNULIB_TEST_SOCKET as evidence that gnulib is being used.  I'm
not sure GNULIB_TEST_SOCKET is TRT, but I saw no better candidate.
Maybe gnulib should provide us with a better macro.

6. Compilation warnings in socket.c:

       CC     socket.lo
     socket.c: In function `scm_inet_ntop':
     socket.c:349: warning: implicit declaration of function `inet_ntop'
     socket.c:349: warning: assignment makes pointer from integer without a cast
     socket.c:357: warning: assignment makes pointer from integer without a cast
     socket.c: In function `scm_inet_pton':
     socket.c:397: warning: implicit declaration of function `inet_pton'

This is again because gnulib headers are not included although
available, due to exclusive test of HAVE_WINSOCK2_H.  Solution: change
this in socket.c:

     #ifdef HAVE_WINSOCK2_H

to say this:

     #if HAVE_WINSOCK2_H && !GNULIB_TEST_SOCKET

The same caveat about GNULIB_TEST_SOCKET applies here.

This completes the description of problems I needed to overcome for
building Guile with MinGW+MSYS.  You may notice that my report is
slightly different from Commander Sirow's report that started this bug
report, where we cover the same turf:

 . I didn't need to define a `struct timespec', probably because I
   don't have Pthreads-w32 installed, and so pthread.h did not get
   included in my build.

 . I solved the problems in net_db.c differently (see above), and I
   believe more correctly.