静态链接 libxml2 时出错

问题描述 投票:0回答:1

尝试使用 libxml2 静态构建应用程序

我遇到类似错误
undefined reference to `__imp_xmlTextReaderRead'

删除 
-static

选项,效果完美。

我使用的命令是:
gcc -o myapp.exe `xml2-config --cflags` -I /mingw64/include myapp.c `xml2-config --libs` -static
gcc linker libxml2
1个回答
0
投票

要纠正对 
__imp_xml*
 形式的符号的未定义引用,请预定义预处理器宏 
LIBXML_STATIC
在您的 
gcc

命令行上,如下所示:
gcc -DLIBXML_STATIC -o myapp.exe `xml2-config --cflags` \
    -I /mingw64/include myapp.c `xml2-config --libs` -static
    

为什么?

您正在 Windows 上使用 
gcc
__imp_xml*
 形式的未定义引用表明您的编译器正在按照您的预期工作
代码将在运行时动态链接到 
libxml2.dll
,为此将链接到
在构建时该 DLL 的导入库
libxml2.lib
__imp_xml*
 参考文献将通过以下方式解决:
libxml2.dll
代理中的构建时导入库。您的编译器正在将这些引用发出到
释放在源代码中找到的 
__declspec(dllimport) xml*

形式的 DLL 导入声明, 预处理后。

这些 
dllimport 声明的存在证明编译器正在看到预处理的代码 not
旨在启用针对
libxml2
的静态链接,即针对静态库
libxml2.a
的链接,
其中定义的符号没有 
__imp_

前缀。

但是你是一个指定的静态链接(
-static
)。这禁止链接器考虑导入库,
即使它们可用。通过 shell 扩展在命令行中产生的库选项
xml2-config --libs
 的形式为 
-l xml2 [...]
。在存在 
-static
 的情况下,链接器将尝试
通过仅扫描其搜索目录以查找 
-l xml2
,而不是 
libxml2.a
 来解决 

libxml2.lib

因此,正如您所观察到的,当您从项目中删除 
__imp_xml*
 选项时,未定义的 
-static
 参考错误就会消失。
命令行 - 因为链接器可以自由搜索 
libxml2.lib

由于您想要静态链接,编译器不应该看到用于动态链接的预处理代码 连锁。但是,无论编译器可以解决这个问题,

-static
选项都不会这样做,因为 这是一个链接选项,不影响编译。

预处理器确实会影响编译,并且

libxml2
使用预处理器宏
LIBXML_STATIC
作为 switch 来决定其公共头文件中的 API 函数声明是否会从预处理中出现 以
__declspec(dllimport)
为前缀,或以
__declspec(dllexport)
为前缀,或两者都不带。相关的 预处理器样板文件可在头文件
libxml2/libxml/exmlexports.h
中找到,该文件将包含在 您在自己的代码中包含的任何
libxml2
公共头文件。

...[cut]...
#if defined(_WIN32) || defined(__CYGWIN__)  /* We are on Windows */

#ifdef LIBXML_STATIC        /* We are building for static linkage * 
  #define XMLPUBLIC         /* Our public API symbols are left as seen */
/* Else we are building for dynamic linkage  
#elif defined(IN_LIBXML)    /* If we are building libxml2 itself */
  #define XMLPUBLIC __declspec(dllexport)   /* DLL export our API symbols */ 
#else /* We are building client code */
  #define XMLPUBLIC __declspec(dllimport)   /* DLL import our API names */
#endif
...[cut]...

(评论都是我的。)

这就是为什么你需要在编译开始之前定义

LIBXML_STATIC
, 每个命令行选项
-DLIBXML_STATIC
,抑制客户端的默认生成 假定动态链接的代码。

但是...

预先警告,并非所有未定义的符号链接错误都一定会随着__imp_xml*

错误而消失。
如果您指定 
-static
,则链接器必须找到程序所需的 
all 库的静态版本: 不仅是 libxml2
,还包括 
libxml2
 递归依赖的所有内容。有相当多的
这些,您很可能还没有安装它们的静态版本。

如果您确实拥有所有这些,您的应用程序将是一个非常大的可执行文件,但功率重量比非常小。你 可能已经或可能没有考虑到这一点。如果链接

libxml2

 本身足以满足您的需求
静态地,但不是它的整个依赖链,你也可以这样做。请参阅 
GNU 链接器的命令行选项 了解相关链接器选项 -Bstatic
-Bdynamic
,以及 
GCC 的命令行选项 关于选项 -Wl
,了解 
gcc
 如何将链接器特定的选项传递给链接器。

© www.soinside.com 2019 - 2024. All rights reserved.