Cross-compiling lib/strtod.c failed on Mingw, as reported at http://savannah.gnu.org/bugs/?29965:
strtod.c:37: error: redefinition of 'strtod' /usr/i686-pc-mingw32/sys-root/mingw/include/stdlib.h:319: note: previous definition of 'strtod' was here The problem was the section of stdlib.h cited in the above message: double __cdecl __MINGW_NOTHROW __strtod (const char*, char**); #ifdef __cplusplus /* We require a function with external linkage. */ #else static #endif /* Not __cplusplus */ __inline__ double __cdecl __MINGW_NOTHROW strtod (const char* __restrict__ __nptr, char** __restrict__ __endptr) { return __strtod(__nptr, __endptr); } float __cdecl __MINGW_NOTHROW strtof (const char * __restrict__, char ** __restrict__); long double __cdecl __MINGW_NOTHROW strtold (const char * __restrict__, char ** __restrict__); As you can see, this defines an inline version of strtod() that conflicts with the out-of-line version in lib/strtod.c. Is there an idiomatic solution for this kind of problem? It is the first time that I have run into this particular form of brokenness before. I'm appending my fix, which I have not yet pushed out. --8<--------------------------cut here-------------------------->8-- >From 525a69cbe8d636ac1442aab4c6adb8df09b4b534 Mon Sep 17 00:00:00 2001 From: Ben Pfaff <b...@cs.stanford.edu> Date: Thu, 10 Jun 2010 21:10:51 -0700 Subject: [PATCH] Bypass broken inline strtod() definition in <stdlib.h> on Mingw. * m4/strtod.m4: Detect broken inline strtod(). * lib/stdlib.in.h: Bypass broken inline strtod(). --- lib/stdlib.in.h | 11 +++++++++++ m4/strtod.m4 | 37 +++++++++++++++++++++++++++++++++++++ 2 files changed, 48 insertions(+), 0 deletions(-) diff --git a/lib/stdlib.in.h b/lib/stdlib.in.h index d74c251..e982fea 100644 --- a/lib/stdlib.in.h +++ b/lib/stdlib.in.h @@ -29,9 +29,20 @@ #ifndef _GL_STDLIB_H +#ifdef HAVE_BROKEN_INLINE_STRTOD_DEFINITION +/* strtod() is broken and must be replaced, but <stdlib.h> defines a inline + strtod() that ordinarily prevents it from being replaced, so we must use a + macro to rename it temporarily. */ +#define strtod _gl_broken_inline_strtod +#endif + /* The include_next requires a split double-inclusion guard. */ #...@include_next@ @NEXT_STDLIB_H@ +#ifdef HAVE_BROKEN_INLINE_STRTOD_DEFINITION +#undef strtod +#endif + #ifndef _GL_STDLIB_H #define _GL_STDLIB_H diff --git a/m4/strtod.m4 b/m4/strtod.m4 index 4cccb6d..47597be 100644 --- a/m4/strtod.m4 +++ b/m4/strtod.m4 @@ -82,6 +82,43 @@ numeric_equal (double x, double y) _AC_LIBOBJ_STRTOD fi fi + + if test "$gl_cv_func_strtod_works" != yes; then + dnl Mingw defines an inline version of strtod() in <stdlib.h>, + dnl which prevents replacing it unless we #define strtod to + dnl something else before including <stdlib.h> and then #undef + dnl it afterward. + AC_CACHE_CHECK([whether strtod may safely be defined], + [gl_cv_func_strtod_may_define], + [AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ +#include <stdlib.h> +double strtod (const char *nptr, char **endptr) +{ +} +]])], + [gl_cv_func_strtod_may_define=yes], + [gl_cv_func_strtod_may_define=no])]) + if test $gl_cv_func_strtod_may_define = no; then + AC_CACHE_CHECK([whether strtod may be moved aside and defined], + [gl_cv_func_strtod_move_aside], + [AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ +#define strtod busted_strtod +#include <stdlib.h> +#undef strtod +double strtod (const char *nptr, char **endptr) +{ +} +]])], + [gl_cv_func_strtod_move_aside=yes], + [gl_cv_func_strtod_move_aside=no])]) + if test $gl_cv_func_strtod_move_aside = yes; then + AC_DEFINE([HAVE_BROKEN_INLINE_STRTOD_DEFINITION], [1], + [Define to 1 if a broken strtod() must be replaced, but + <stdlib.h> defines a inline strtod() that ordinarily + prevents it from being replaced.]) + fi + fi + fi ]) # Prerequisites of lib/strtod.c. -- 1.7.1 -- Ben Pfaff http://benpfaff.org