【发布时间】:2019-01-24 17:37:07
【问题描述】:
考虑以下代码结构:
main.cpp -> depends on libone.a -> depends on libtwo.a
假设在main.cpp 中仅使用来自libone.a 的函数。所以实际上写main.cpp的程序员真的只关心libone.a。此时他们甚至不知道libone.a 依赖于libtwo.a。
他们尝试如下编译他们的代码并得到链接器错误:
g++ -o main main.cpp -lone
-- 错误!未定义的符号!
这成为一个问题,因为由于libone.a 依赖于libtwo.a,任何使用libone.a 的人都必须知道这种依赖关系......正如您可以想象的那样,这个问题可能会发生在比单个库更多的依赖关系时,并且可以很快就变成了连接的噩梦。
解决此问题的尝试 1:
解决此问题的第一个想法是“很简单,我将在编译 libone.a 时将 libone.a 与 libtwo.a 链接!
事实证明它并不像我希望的那么简单...编译libone.a 时无法链接libtwo.a。静态库在编译时不会链接到任何东西,而是在将库编译为可执行文件时必须链接所有依赖项。
例如,要编译依赖于一个静态库而又依赖于另一个静态库的main.cpp,您必须链接这两个库。总是。
g++ -o main main.cpp -lone -ltwo
解决此问题的尝试 2:
另一个想法是尝试将libone 编译为链接到libtwo.a 的动态库。
奇怪的是,这刚刚奏效!编译链接libone.so后,主程序只需要关心libone.so就不需要关心libtwo.a了。
g++ -o main main.cpp -lone
成功了!
在完成这个练习之后,仍然缺少一件。我似乎无法弄清楚为什么静态库不能链接到其他库,但动态库可以。事实上,动态库libone.so 在我链接libtwo.a 之前根本不会编译。不过这很好,因为作为libone.so 的作者,我会知道它对libtwo.a 的依赖——main.cpp 的作者,但是不知道。实际上他们不应该知道。
所以回到真正的问题......为什么动态库可以像这样链接到其他库而静态库不能?这似乎是动态库相对于静态库的明显优势,但我从未在任何地方看到过它!
【问题讨论】:
-
回复:“此时他们甚至不知道 libone.a 依赖于 libtwo.a。” ——那么他们就没有做好他们的工作。选择软件组件需要了解它们做什么以及如何做,包括它们依赖的任何其他组件。
-
@PeteBecker,当“libtwo.a”依赖于“libthree.a”时会发生什么,而“libthree.a”又依赖于“libx.a”、“liby.a”和“libz.a”......而那些依赖于其他库。要求每个其他图书馆都需要所有图书馆的知识是荒谬的。
-
这就是为什么您需要像 CMake 这样的工具来封装这些依赖项;)(在构建库时)。
-
@MatthieuBrucher,我们有那个工具......不幸的是,我们从那里获得软件的供应商使用“旧式”cmake - pre 2.8 - 并且没有获得它的依赖管理功能...... LOL (这是一个可悲的LOL...我真的在内心深处哭泣。)
-
我为你哭泣 :(
标签: c++ linker static-linking dynamic-linking