关于Linux c++静态库

Posted

技术标签:

【中文标题】关于Linux c++静态库【英文标题】:about Linux c++ static library 【发布时间】:2014-03-13 10:37:48 【问题描述】:

这里我有几个静态库的问题需要你的帮助。

我从一些书上了解到,静态库(Linux 中的 .a)包含一组已编译的对象,当它链接到可执行文件时,链接工具只会取出那些实际引用的对象。

所以如果 .a 包含 1.o、2.o 和 3.o,而我的应用程序只使用 1.o 中的函数,那么只有 1.o 会被构建到可执行文件中,这样是否正确?

然后让我们更进一步,假设我们有 2 个 .a 库,第一个包含 1.o、2.o 和 3.o,第二个包含 3.o 4.o 和 5.o。如果我的应用程序只使用 1.o 2.o 3.o 和 4.o 中的函数,那么只有这 4 .o 将被构建到可执行文件中,是否正确?

我提出这个问题是因为我正在构建一些用于 MSVC 的 .a 文件。这些 .a 库是在 MinGW 中构建的,然后应该与 MSVC 兼容。我可以将这些库包含到 MSVC 项目中并成功构建我的程序。但是即使我的程序是空的(只有一个空的 main 函数),生成的可执行文件也是 5 MB(所有 .a 的总大小应该约为 8MB)。

这是否意味着,在 MSVC 或 .lib(Win 的静态库)中使用时,.a 将作为一个整体构建到可执行文件中,但不会以它在 Linux 下的行为方式构建?

我还有一个关于以下内容的问题

如果我可以使用 -static 链接到 lib tiff 的静态版本,那么为什么它需要链接到其他库?静态库是否应该已经包含它需要的所有代码?

谢谢

【问题讨论】:

linux标签有什么关系? 在 Linux 上尽可能避免使用静态库。 【参考方案1】:

静态库不会包含它需要的所有代码。想象一个使用printf() 输出错误消息的库。这个库仍然依赖于 libc 的静态版本,它不包含 printf 本身的代码。

在您的情况下,由于 Tiff 支持各种内部表示格式,其中一种是 jpeg,静态 libtiff 希望您链接静态 libjpeg。

windows 和 linux 之间没有根本区别。当您对 libtiff 和 libjpeg 进行静态链接时,只会链接 libtiff 实际需要的 libjpeg 函数,但不会链接处理 JFIF Jpeg 包装器的部分。

编辑 - 对 cme​​ts 的回答

在您的main() 被调用之前,有很多事情正在发生。在 linux/unix 上并没有那么多,操作系统以 main() 想要的方式传递参数,但在 Windows 上,一个不同的函数,通常称为 WinMain() 在程序启动时获得控制权。这个WinMain() 隐藏在库中。它将整个命令行放在一个字符串中,并且必须解析参数以将它们传递给main(),这意味着检查空格,这可能是使用isspace() 实现的,它引入了ctype,它引入了许多依赖于语言环境的东西,等等。您的 5 MB 中的大部分可能是用于使您的程序在 windows 中运行的代码,就像在 unix 中一样。此外,如果您使用调试选项进行编译,这些调试符号也会占用大量空间。

Keltar 关于调用动态库的静态库的评论也是正确的 - 但这增加了您并不经常需要的复杂性。静态链接或多或少有两个原因:

即使动态库出现问题,您也希望程序能够运行。如果我不小心rm /lib/libc.so.*,如果我有mountcp 的静态链接版本从其他地方复制它,我会很高兴。因此,安装程序和“紧急程序”通常是静态链接的 您希望确保您的程序使用特定版本的库,该版本是您编译时系统上的最新版本,而不是 5 年后可能安装在某些系统上的 dynalink 版本。

如果 some 而不是 all 库是静态的,那么这两个原因都没有多大意义。

但也有例外:假设您需要 libtiff 中的特定功能。您浏览文档,它没有说明该功能。您检查源代码并发现它实现了specific_feature(),并带有一个很大的“这是实验性的,可能会在未来的版本中消失”评论。如果您决定现在需要该功能,您可能希望静态链接 libtiff 以防止您的程序在未来版本的 libtiff 不再实现该功能时失败。当然,您仍然需要动态版本的 libjpeg 和 libc。如果这是一个好的做法,我会把决定留给你。

Windows 是一种特殊情况,因为它总是使用 kernel.dll 和 user32.dll,因为那里没有静态版本,即使您的程序的其余部分是静态链接的。

因此,虽然 libtiff.a 可能需要 libjpeg.so,而 libtiff.lib 可能需要 libjpeg.dll,但通常没有太多理由这样做.

【讨论】:

感谢 Guntram,那么您能否帮助解释第一个问题,为什么我的程序即使没有从那些 .a 库中调用任何函数也会变得如此之大? 它很可能包括 libgcc(特定于 mingw)。而且,为了澄清,静态库并不真正 必须 依赖于其他 static 库,它们可能是动态库(至少在 linux 上 - 有人可以区分windows版本?)

以上是关于关于Linux c++静态库的主要内容,如果未能解决你的问题,请参考以下文章

链接静态库 Vs。 Linux 中的共享库

请教关于linux中静态库与动态库的问题

关于Linux库文件的制作

关于linux下连接动态库问题

转载我使用过的Linux命令之ar - 创建静态库.a文件

Linux静态库和共享库