Is GNU libraries able to link to dynamic MSVC runtime using autoconf build system when relying on gnulib?

302 views Asked by At

My goal is to understand a GNU libraries autoconf build system. I am aware that libiconv can be build successfully using a crafted MS Visual Studio project with manully added source code files. So the question is more academical rather than practical. I took into account there is no official support of Windows platform for gnulib also.

Following the guide from INSTALL.windows to build libiconv, I faced with next compilation error when built iconv againts dynamic MSVC runtime(cl /MD or cl /MDd).

C:\Program Files (x86)\Windows Kits\10\Include\10.0.18362.0\ucrt\corecrt_malloc.h(85): error C2375: 'rpl_free': redefinition; different linkage
D:\work\env\build-env\msvc2019\shared-debug-shared-runtime\iconv\srclib\string.h(599): note: see declaration of 'rpl_free'

Configure invocation:

/cygdrive/d/work/src/libiconv/configure --enable-relocatable --enable-static=no --enable-shared=yes --host=x86_64-w64-mingw32 --prefix=/iconv 'CFLAGS=/MDd /Z7 /Od /D_DEBUG /RTC1' 'CXXFLAGS=/MDd /Z7 /Od /D_DEBUG /RTC1'

Compiler invocation:

compile cl /nologo -DHAVE_CONFIG_H -DEXEEXT=\".exe\" -I. -I/cygdrive/d/work/src/libiconv/srclib -I.. -I../lib  -DDEPENDS_ON_LIBICONV=1 -DDEPENDS_ON_LIBINTL=1 /D_WIN32_WINNT=_WIN32_WINNT_WIN7 /DWIN32 /D_WIN64 /D_UNICODE /D_CRT_SECURE_NO_WARNINGS   /MDd /Z7 /Od /D_DEBUG /RTC1 /D_DLL -c -o stat.obj `cygpath -w '/cygdrive/d/work/src/libiconv/srclib/stat.c'`
stat.c

Configure generated iconv/srclib/string.h

/* Declare 'free' if needed for _GL_ATTRIBUTE_DEALLOC_FREE.  */
_GL_EXTERN_C void free (void *);
#if 1
# if (1 && !defined free \
      && !(defined __cplusplus && defined GNULIB_NAMESPACE))
#  define free rpl_free
_GL_EXTERN_C void free (void *);
# endif
#endif

WinSDK/include/ucrt/corecrt_malloc.h

_ACRTIMP _CRT_HYBRIDPATCHABLE
void __cdecl free(
    _Pre_maybenull_ _Post_invalid_ void* _Block
    );

WinSDK/include/ucrt/corecrt.h defines next

#ifndef _ACRTIMP
    #if defined _CRTIMP && !defined _VCRT_DEFINED_CRTIMP
        #define _ACRTIMP _CRTIMP
    #elif !defined _CORECRT_BUILD && defined _DLL
        #define _ACRTIMP __declspec(dllimport)
    #else
        #define _ACRTIMP
    #endif
#endif

After research and investigation I found out that gnulib(as a part of GNU autoconf build system for libiconv) replaces unsatisfying function calls with its own implementation. rpl_free is a replacement name to replace regular free() function from the C runtime as MSVC free function is not recognized as a POSIX compliant. It seems to me there is no option to tell to configure not to replace suck functions. An hack with environment variable REPLACE_FREE=0 did the trick and I have turned off function replacement.

However, MSVC compiler still complaints on different linkage. I believe, MSVC runtime exports its API functions with __declspec(dllimport) for consumers when gnulib declares its free() function signature with no extra attributes.

I wonder, is there a 'paved-road' to build libiconv(or other GNU library that leverage gnulib) linked to dynamic MSVC runtime using original autoconf system? Can I achieve that with no gnulib m4 files alteration?

1

There are 1 answers

0
Bruno Haible On

To answer your general question:

Yes, GNU projects with the GNU build system (Autoconf, optionally Automake, Libtool, and Gnulib) can in general be built with the MSVC compiler. The compile script translates compiler options in the traditional Unix style to compiler options for MSVC.

The experience with GNU libiconv, GNU gettext, and other packages, which all have essentially the same INSTALL.windows instructions, shows that this is well possible. But it often requires tweaks in the build system, to cope with dllimport/dllexport, issues related to backslashes, to file names in Cygwin syntax vs. native Windows syntax, and so on. In particular, note that on Windows, it is hairy to export variables from a shared library; exporting functions is much simpler.

You can typically ignore warnings from MSVC regarding the dllimport/dllexport of functions. This warning merely means that the compiler has added one or two extra instructions per function invocation.

Gnulib indeed overrides many libc functions, such as free(), so that the application source code does not get cluttered with workarounds. The precise reason for each override is documented. For the free() function, it is documented here. While Gnulib has ways to disable specific workarounds, in this case I would strongly advise against it: the effects of a wrong errno value can be severe malfunction of any application.

To answer your specific problem about GNU libiconv:

You have encountered a specific build problem; the README of the package tells you where to report bugs.

GNU packages have releases. The latest GNU libiconv release, version 1.16, does not have the problem. In general, before attempting to compile the newest sources from the git repository, it is advisable to use the newest release. This will be simpler, as it has usually been tested before the release.