C++ 在将代码打包为库时,我应该创建.a还是.so?

C++ 在将代码打包为库时,我应该创建.a还是.so?,c++,linker,shared-libraries,C++,Linker,Shared Libraries,我有一个软件库,我经常创建.a文件,这样人们就可以安装并链接它们:g++foo.o-L/path/to-llibrary 但现在我经常遇到第三方库,其中只有.so文件可用(而不是.a),您只需在不使用-l开关的情况下链接它们,例如g++foo.o/path/to/libliblibrary.so 这些解决方案之间有什么区别?我应该更喜欢为我的库的用户创建.so文件吗?在 通常,libfoo.a是一个静态库,libfoo.so是一个共享库。您可以对静态链接或共享链接使用相同的-L/-L链接器选项。

我有一个软件库,我经常创建.a文件,这样人们就可以安装并链接它们:
g++foo.o-L/path/to-llibrary

但现在我经常遇到第三方库,其中只有.so文件可用(而不是.a),您只需在不使用
-l
开关的情况下链接它们,例如
g++foo.o/path/to/libliblibrary.so


这些解决方案之间有什么区别?我应该更喜欢为我的库的用户创建.so文件吗?


通常,
libfoo.a
是一个静态库,
libfoo.so
是一个共享库。您可以对静态链接或共享链接使用相同的
-L
/
-L
链接器选项。或者您可以使用static或shared来命名lib的完整路径。通常,库是静态和共享构建的,以便为应用程序开发人员提供他们想要的选择

静态库所需的所有代码都是最终可执行文件的一部分。这显然使它更大,但也意味着它是独立的。编译后,您可以在不使用lib的情况下运行应用程序

共享库中的代码不是可执行文件的一部分。只有一些钩子可以让可执行文件知道它需要的库的名称。为了运行您的应用程序,共享库必须出现在库搜索路径中(例如,
$LD\u LIBRARY\u path


如果您有两个共享相同代码的应用程序,它们可以针对共享库对每个应用程序进行链接,以减小二进制大小。如果你想升级部分应用程序而不重建整个应用程序,那么共享libs也很好。

一些功能在我之前看到的评论中并没有真正被调用

静态链接(.a/.lib)
在这些编译单元之间共享内存通常是可以的,因为它们都应该使用相同的运行时

静态链接意味着您可以避免“dll地狱”,但代价是重新编译以利用任何更改。如果最终可执行文件使用的共享库超过1个,则静态链接到共享库(.so)可能会导致奇怪的结果-全局变量可能存在多次,使用哪一个以及初始化时可能会导致完全不同的地狱

该库将是已装运产品的一部分,但已混淆,无法直接使用

共享/动态库(.so/.dll)
在这些编译单元之间共享内存可能是危险的,因为它们可能会选择使用不同的运行时。这意味着您可以根据调试/发布或单线程/多线程或

共享库(.so)比动态库(.dll)更不容易出现“dll地狱”,因为它们包含用于非常特定版本控制的选项

根据.so进行编译将捕获文件内部的版本信息(很难伪造),从而获得非常具体的.so用法。根据.lib/.dll编译只提供基本文件名,任何版本控制都由开发人员管理(使用命名或手动加载库并手动检查版本详细信息)

图书馆必须与最终产品一起发货(其他人可以拿起并使用)

但现在我经常遇到第三方库,其中只有.so文件可用[…],而您只需在不使用-l开关的情况下链接它们,例如g++foo.o/path/to/liblibrary.so

JFYI,如果您链接到一个没有SONAME集的共享库(与
readelf-a libliblibrary.so
)相比,您最终将把liblibrary.so的指定路径放入您的目标对象(可执行文件或另一个共享库),这通常是不需要的,对于用户来说,他们对将程序及其相关文件放在何处有自己的想法。首选的方法是使用-L/path/to-llibrary,如果这是最终路径,则可能与-Wl、-rpath、/whatever/path/to一起使用(例如,这种路径选择由Linux发行版决定)

我应该更喜欢为我的库的用户创建.so文件吗


如果您分发源代码,用户将做出特殊选择。

请参阅[C中静态库和共享库的区别]()。有时创建这两种类型的库是合适的。这取决于您想要哪种库。@Matthew-正是,.a和.so是完全不同的东西,即使我发布源代码,我也会做出选择,因为我提供了Makefile。用户几乎不必为下载的源代码编写自己的构建脚本或生成文件。