我的目标是了解 GNU 库 autoconf 构建系统。我知道 libiconv 可以使用精心制作的 MS Visual Studio 项目和手动添加的源代码文件成功构建。所以这个问题更多的是学术而不是实际。我考虑到 gnulib 也没有 Windows 平台的官方支持。
按照 INSTALL.windows 构建 libiconv 的指南,当构建 iconv 与动态 MSVC 运行时(cl /MD 或 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'
配置调用:
/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'
编译器调用:
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
配置生成的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 定义下一个
#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
经过研究和调查,我发现 gnulib(作为 libiconv 的 GNU autoconf 构建系统的一部分)用自己的实现替换了不令人满意的函数调用。rpl_free 是从 C 运行时替换常规 free() 函数的替代名称,因为 MSVC 自由函数不被识别为 POSIX 兼容。在我看来,没有选项可以告诉配置不要替换吸吮功能。使用环境变量 REPLACE_FREE=0 破解成功了,我关闭了函数替换。
但是,MSVC 编译器仍然抱怨不同的链接。我相信,当 gnulib 声明其 free() 函数签名且没有额外属性时,MSVC 运行时会为消费者导出其 API 函数和 __declspec(dllimport)。
我想知道,是否有一条“铺平道路”来使用原始 autoconf 系统构建链接到动态 MSVC 运行时的 libiconv(或其他利用 gnulib 的 GNU 库)?我可以在不更改 gnulib m4 文件的情况下实现这一目标吗?