使用MinGW进行静态和动态/共享链接

38

我想从一个简单的链接用法开始解释我的问题。假设有一个库z,它可以编译为共享库libz.dll(D:/libs/z/shared/libz.dll)或静态库libz.a (D:/libs/z/static/libz.a)。

如果我想要链接这个库,那么我会这样做:

gcc -o main.exe main.o -LD:/libs/z/static -lz
根据这份文档,gcc将搜索libz.a,它是“成员为目标文件的存档文件”。 我还可以执行以下操作:
gcc -o main.exe main.o -LD:/libs/z/shared -lz

上面的文档中没有提到 -l 标志将会搜索 lib<name>.so

如果我在同一个目录中有 libz.a 和 libz.dll,会发生什么?库会如何链接到程序?为什么需要使用 -Wl,-Bstatic-Wl,-Bdynamic 标志,如果 -l 既搜索共享库又搜索静态库?

为什么一些开发者为同一模块提供 .a 文件和 .dll 文件,如果我编译了共享库分发包呢?

例如,Qt 在 bin 目录中提供 .dll 文件,在 lib 目录中提供 .a 文件。它们是相同的库吗,但是分别构建为共享和静态库吗?还是 .a 文件是某种虚拟库,其提供与共享库的链接,而真正的库实现在其中?

另一个例子是 Windows 上的 OpenGL 库。为什么每个编译器都必须提供静态 OpenGL lib,例如 MingW 中的 libopengl32.a?

.dll.a 和 .la 扩展名的文件用途是什么?

P.S. 这里有很多问题,但我认为每个问题都取决于前一个问题,因此没有必要将它们拆分为多个问题。


让我们以cygwin为例:据我所知,使用cygwin编译的程序需要某个特定的dll才能运行。该dll绑定了某个特定的许可证(其中之一是免费的),并且必须存在于主机系统中以供程序使用。如果作为开发人员忘记将其与程序一起发布,则程序将无法运行。另一个例子是版本冲突的DLL(例如opengl)。每个系统具有不同的功能,因此具有某些DLL的不同实现。因此,有时开发人员喜欢使用正确的库版本=>静态链接。 - scones
1个回答

36

请查看ld和WIN32(cygwin/mingw)。特别是关于-l标志在LD的Windows端口上行为的直接链接到dll部分。摘录如下:

例如,当使用参数-lxxx调用ld时,它将尝试在其搜索路径的第一个目录中查找

libxxx.dll.a
xxx.dll.a
libxxx.a
cygxxx.dll (*)
libxxx.dll
xxx.dll

在搜索路径中的下一个目录之前移动。

(*) 实际上,这不是 cygxxx.dll,而是 <prefix>xxx.dll,其中 <prefix> 由 ld 选项 -dll-search-prefix=<prefix> 设置。在 cygwin 的情况下,标准的 gcc spec 文件包含 -dll-search-prefix=cyg,因此实际上我们实际上搜索的是 cygxxx.dll

注意: 如果您曾经使用MinGW构建Boost,则可能会记得Boost库的命名完全遵循上面链接中描述的模式。

以前在MinGW中直接连接到 *.dll 存在问题,因此建议创建一个静态库 lib*.a,并从 *.dll 中导出符号并链接到它。现在,指向这个MinGW wiki页面的链接已经无效了,因此我认为现在直接链接到 *.dll 应该是可以的。此外,我用最新的MinGW-w64发行版自己尝试了几次,并且没有任何问题。

您需要链接标志 -Wl,-Bstatic-Wl,-Bdynamic,因为有时您希望强制进行静态链接,例如当搜索路径中也存在相同名称的动态库时:

gcc object1.o object2.o -lMyLib2 -Wl,-Bstatic -lMyLib1 -Wl,-Bdynamic -o output

以上代码片段确保了-l标志的默认链接优先级被覆盖,用于MyLib1,即使MyLib1.dll在搜索路径中存在,LD也会选择libMyLib1.a进行链接。请注意,对于MyLib2,LD将再次优先选择动态版本。

注意:如果MyLib2依赖于MyLib1,那么不管是否使用了-Wl,-Bstatic(在这种情况下忽略它),MyLib1也会以动态方式链接。要防止这种情况发生,您也需要静态链接MyLib2


链接已失效...你是否有相关的参考资料可以更新答案。 - maple_shaft
你修复了链接,谢谢你的帮助,但是在文本中你仍然提到这个缺陷:“'The link to this MinGW wiki page is now dead, so I assume […]'”,这有点令人困惑。如果你有时间的话,请在这方面重新修改一下。提前感谢你的帮助。 - Wolf

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接