0

我的目标是了解 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 文件的情况下实现这一目标吗?

4

1 回答 1

0

要回答您的一般问题

是的,具有 GNU 构建系统(Autoconf,可选 Automake、Libtool 和 Gnulib)的 GNU 项目通常可以使用 MSVC 编译器构建。该compile脚本将传统 Unix 风格的编译器选项转换为 MSVC 的编译器选项。

使用 GNU libiconv、GNU gettext 和其他软件包(它们都具有基本相同的 INSTALL.windows 指令)的经验表明,这是完全可能的。但它通常需要在构建系统中进行调整,以应对 dllimport/dllexport、与反斜杠相关的问题、Cygwin 语法与本机 Windows 语法中的文件名等等。特别要注意的是,在 Windows 上,从共享库中导出变量很麻烦;导出函数要简单得多。

您通常可以忽略来自 MSVC 的有关函数的 dllimport/dllexport 的警告。这个警告仅仅意味着编译器在每个函数调用中添加了一个或两个额外的指令。

Gnulib 确实覆盖了许多 libc 函数,例如 free(),因此应用程序源代码不会因变通方法而变得混乱。每个覆盖的确切原因都记录在案。对于 free() 函数,在此处记录。虽然 Gnulib 有办法禁用特定的解决方法,但在这种情况下,我强烈建议不要这样做:错误errno值的影响可能是任何应用程序的严重故障。

要回答您关于 GNU libiconv 的具体问题

您遇到了特定的构建问题;软件包的 README 告诉您在哪里报告错误。

GNU 软件包有发行版。最新的 GNU libiconv 版本 1.16 没有这个问题。通常,在尝试从 git 存储库编译最新源代码之前,建议使用最新版本。这会更简单,因为它通常在发布之前已经过测试。

于 2021-12-31T00:12:24.700 回答