我有一个软件库,我曾经创建.a文件,以便人们可以安装它们并链接它们:g++ foo.o -L/path/to -llibrary
但是现在我经常遇到只有.so文件可用的第三方库(而不是.a),而你只是在没有-l
开关的情况下链接它们,例如g++ foo.o /path/to/liblibrary.so
。
这些解决方案有何区别?我是否更愿意为我的图书馆用户创建.so文件?
答案 0 :(得分:9)
通常,libfoo.a
是静态库,libfoo.so
是共享库。您可以对静态或共享使用相同的-L
/ -l
链接器选项。或者,您可以使用static或shared命名lib的完整路径。通常,库是静态的和共享的,以便为应用程序开发人员提供他们想要的选择。
静态库所需的所有代码都是最终可执行文件的一部分。这显然使它更大,但它也意味着它是独立的。编译完成后,您可以在不使用lib的情况下运行应用程序。
来自共享库的代码不是可执行文件的一部分。只有一些钩子可以使可执行文件知道它需要的lib的名称。为了运行您的应用程序,共享库必须存在于lib搜索路径中(例如$LD_LIBRARY_PATH
)。
如果您有两个共享相同代码的应用程序,则每个应用程序都可以链接到共享库以保持二进制文件大小不变。如果你想升级应用程序的某些部分而不重建整个应用程序,那么共享库也很适合。
答案 1 :(得分:1)
答案 2 :(得分:1)
到目前为止,我已经看过的评论中没有真正提到的一些功能。
静态链接(.a / .lib)
在这些编译单元之间共享内存通常是可以的,因为它们应该(?将)使用相同的运行时。
静态链接意味着你避免'dll hell',但是重新编译成本是为了使用任何变化。如果最终可执行文件使用了多个这样的共享库,则静态链接到共享库(.so)会导致奇怪的结果 - 全局变量可能存在多次,使用哪一个以及初始化它们会导致完全不同地狱。
该库将成为已发布产品的一部分,但会进行模糊处理,无法直接使用。
共享/动态库(.so / .dll)
在这些编译单元之间共享内存可能是危险的,因为他们可能选择使用不同的运行时。这可能意味着您基于调试/发布或单/多线程或...
共享库(.so)不太容易'dll hell'然后动态库(.dll)因为它们包含非常特定的版本控制的选项。
针对.so进行编译将捕获文件内部的版本信息(难以伪造),以便您获得非常具体的.so用法。针对.lib / .dll进行编译只提供基本文件名,任何版本控制都由开发人员管理(使用命名或手动加载库并手动检查版本详细信息)
图书馆必须附带最终产品(其他人可以拿起并使用它)
答案 3 :(得分:0)
但是现在我经常遇到第三方库,其中只有.so文件可用[...]而你只是在没有-l开关的情况下链接它们,例如g ++ foo.o /path/to/liblibrary.so。
JFYI,如果您链接到没有SONAME集的共享库(与readelf -a liblibrary.so
比较),您将最终将指定的liblibrary.so路径放入目标对象(可执行文件或其他共享库)因为用户对于放置程序及其相关文件的位置有自己的想法,所以这通常是不受欢迎的。首选方法是使用-L / path / to -llibrary,可能与-Wl,-rpath,/ whatever / path /一起使用,如果这是最终路径(例如,这些路径决策由Linux发行版决定)。 / p>
我是否更愿意为我的图书馆用户创建.so文件?
如果您分发源代码,用户将做出特定选择。