用于构建共享库的‘soname’选项是什么?

2024-10-29 08:35:00
admin
原创
52
摘要:问题描述:我学习了“ Program Library HOWTO ”。它提到使用soname以下命令管理版本:gcc -shared -fPIC -Wl,-soname,libfoo.so.1 -o libfoo.so.1.0.0 foo.c ln -s libfoo.so.1.0.0 libfoo.so...

问题描述:

我学习了“ Program Library HOWTO ”。它提到使用soname以下命令管理版本:

gcc -shared -fPIC -Wl,-soname,libfoo.so.1  -o libfoo.so.1.0.0 foo.c
ln -s libfoo.so.1.0.0  libfoo.so.1
ln -s libfoo.so.1 libfoo.so

我得到的信息是,如果soname没有设置,它将等于 libfoo.so.1.0.0,请从此处查看答案。

我发现它也可以在没有 soname 的情况下工作,如下所示

 gcc -shared -fPIC -o libfoo.so.1.0.0 foo.c
 ln -s libfoo.so.1.0.0  libfoo.so.1
 ln -s libfoo.so.1 libfoo.so

所以我认为唯一有用的一点是当您使用命令检查共享库时,该soname选项可以告诉您共享库的版本。readelf -d libfoo.so

它还能做什么?


解决方案 1:

soname 用于表明你的库支持哪些二进制 API 兼容性。

SONAME在编译时由链接器使用,以从库文件中确定实际的目标库版本。 gcc -lNAME将寻找 lib NAME.so 链接或文件,然后捕获其 SONAME,该 SONAME 肯定会更具体(例如 libnuke.so 链接到 libnuke.so.0.1.4 ,其中包含 SONAME libnuke.so.0 )。

在运行时,它将与此链接,然后将其设置到 ELF 动态部分中NEEDED,然后应该存在具有此名称的库(或指向它的链接)。运行时SONAME被忽略,因此只要链接或文件存在就足够了。

备注:SONAME 仅在链接/构建时强制执行,而不是在运行时强制执行。

可以使用“objdump -p file |grep SONAME”查看库的“SONAME”。可以使用“objdump -p file |grep NEEDED”查看二进制文件的“NEEDED”。

[编辑] 警告 以下是一般性评论,不是在 Linux 中部署的评论。请参阅末尾。

假设您有一个名为 libnuke.so.1.2 的库,并且您开发了一个新的 libnuke 库:

  • 如果你的新库是对以前的修复,没有改变 api,你应该保留相同的 soname,增加文件名的版本。即文件将是 libnuke.so.1.2.1,但 soname 仍然是 libnuke.so.1.2。

  • 如果您有一个新的库,它只添加了新功能,但没有破坏功能,并且仍然与以前的版本兼容,那么您希望使用与以前相同的 soname 加上新的后缀,如 .1。即文件和 soname 将为 libnuke.so.1.2.1。任何与 libnuke.1.2 链接的程序仍可与该程序一起使用。与 libnuke.1.2.1 链接的新程序只能与该程序一起使用(直到出现新的 subversion,如 libnuke.1.2.1.1)。

  • 如果你的新库与任何 libnuke 不兼容:libnuke.so.2

  • 如果你的新库与旧版本兼容:libnuke.so.1.3 [即仍然与 libnuke.so.1 兼容]

[编辑] 完成:linux 案例。

在 Linux 中,SONAME 具有特定格式:libNAME.so.[major-version] major-version 只是一个整数值,每次主要库更改时都会增加。API-VERSION 默认为空

前 libnuke.so.0

然后实际文件名包括次要版本和子版本,例如:libnuke.so.0.1.5

我认为不提供 soname 是一种不好的做法,因为重命名文件会改变其行为。

解决方案 2:

您按照命名传统 libname.{a}.{b}.{c} 创建了一个名为 libx.1.0.0 的动态库

{a} stand for primary version, should changes when APIs changes(which making things incompatible).
{b} stand for sub version, should changes by adding APIs.
{c} stand for mirror version, should changes by bug fixing or optimizing

现在您正在发布 libx.1.2.0,并且您需要声明 libx.1.2.0 与 libx.1.0.0 兼容,因为只需添加函数,人们的可执行文件就不会崩溃,只需像以前一样链接它即可:

将 libx.1.0.0 和 libx.1.2.0 设置为具有相同的 soname,例如 libx.1

这就是 soname 所做的。

解决方案 3:

下面是一个支持Johann Klasek 答案的例子。

简而言之,运行时需要 SONAME。编译时只需要一个链接器名称或真实名称(例如g++ main.cpp -L. -laddg++ main.cpp -L. -l:libadd.so.1.1)。链接器名称和真实名称的定义遵循Program Library HOWTO: 3. Shared Libraries。

源树:

├── add.cpp
├── add.h
├── main.cpp
└── Makefile

生成文件:

SOURCE_FILE=add.cpp
# main.cpp includes `add.h`, whose implementation is `add.cpp`
MAIN_FILE=main.cpp
SONAME=libadd.so.1
REAL_NAME=libadd.so.1.1
LINKER_NAME=libadd.so
OUTPUT_FILE=a.out

all:
   g++ -shared -fPIC -Wl,-soname,${SONAME} -o ${REAL_NAME} ${SOURCE_FILE}
   ln -s ${REAL_NAME} ${LINKER_NAME}
   g++ main.cpp -I. -L. -ladd -o ${OUTPUT_FILE} 
   # Same as `ldconfig -n .`, creates a symbolic link
   ln -s ${REAL_NAME} ${SONAME}
   #./a.out: error while loading shared libraries: libadd.so.1: cannot open 
   # shared object file: No such file or directory
   LD_LIBRARY_PATH=. ./${OUTPUT_FILE}
clean:
   rm ${SONAME} ${REAL_NAME} ${LINKER_NAME} ${OUTPUT_FILE}

解决方案 4:

假设 libA.so 依赖于 libB.so,并且它们都在一个目录中(当然动态链接器无法找到该目录)。如果你没有设置sonamedlopen不起作用:

auto pB = dlopen("./libB.so", RTLD_LAZY | RTLD_GLOBAL);
auto pA = dlopen("./libA.so", RTLD_LAZY | RTLD_GLOBAL);

因为运行时链接器找不到libB.so,所以pA设置为NULL

在这种情况下soname将拯救你免于地狱之苦......

解决方案 5:

另一方面:至少在 Linux 上,SONAME 条目为运行时链接器系统提供了如何在 /lib、/lib64 等中创建适当链接的提示。运行命令 ldconfig 会尝试创建一个以 SONAME 命名的符号链接,该链接也会被纳入运行时链接器缓存。标记相同 SONAME 的最新库将赢得链接竞争。如果某个软件依赖于特定的 SONAME,而您想要更新库,则必须提供此 SONAME 以使 ldconfig 坚持使用这个新库(如果使用 ldconfig 重建缓存和链接)。例如 libssl.so.6 和 libcrypto.so.6 就是这样的情况。

相关推荐
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   601  
  华为IPD与传统研发模式的8大差异在快速变化的商业环境中,产品研发模式的选择直接决定了企业的市场响应速度和竞争力。华为作为全球领先的通信技术解决方案供应商,其成功在很大程度上得益于对产品研发模式的持续创新。华为引入并深度定制的集成产品开发(IPD)体系,相较于传统的研发模式,展现出了显著的差异和优势。本文将详细探讨华为...
IPD流程是谁发明的   7  
  如何通过IPD流程缩短产品上市时间?在快速变化的市场环境中,产品上市时间成为企业竞争力的关键因素之一。集成产品开发(IPD, Integrated Product Development)作为一种先进的产品研发管理方法,通过其结构化的流程设计和跨部门协作机制,显著缩短了产品上市时间,提高了市场响应速度。本文将深入探讨如...
华为IPD流程   9  
  在项目管理领域,IPD(Integrated Product Development,集成产品开发)流程图是连接创意、设计与市场成功的桥梁。它不仅是一个视觉工具,更是一种战略思维方式的体现,帮助团队高效协同,确保产品按时、按质、按量推向市场。尽管IPD流程图可能初看之下显得错综复杂,但只需掌握几个关键点,你便能轻松驾驭...
IPD开发流程管理   8  
  在项目管理领域,集成产品开发(IPD)流程被视为提升产品上市速度、增强团队协作与创新能力的重要工具。然而,尽管IPD流程拥有诸多优势,其实施过程中仍可能遭遇多种挑战,导致项目失败。本文旨在深入探讨八个常见的IPD流程失败原因,并提出相应的解决方法,以帮助项目管理者规避风险,确保项目成功。缺乏明确的项目目标与战略对齐IP...
IPD流程图   8  
热门文章
项目管理软件有哪些?
云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用