链接时同方式传入的共享库为何在动态段中分别存名称和路径
问题成因
链接器处理共享库依赖时遵循如下逻辑:当你在链接命令中直接传入.so文件路径时,会优先读取该共享库内置的DT_SONAME动态段值,将其作为NEEDED项的内容写入最终可执行文件;如果共享库未设置DT_SONAME,链接器会直接把命令行传入的库路径原样写入NEEDED项。
- 你的
libmylib.so构建时配置了SONAME = libmylib.so,因此可执行文件的NEEDED项只保留了文件名。 libstring.so作为外部Bazel构建的依赖,没有配置标准SONAME,你观察到的版本定义段中的构建临时路径就是该库未规范配置SONAME的佐证,因此链接器直接将你传入的相对路径../libstring/libstring.so写入了NEEDED。
解决方法
因为你无法修改libstring.so的构建逻辑,可选择以下任意一种方案处理:
- 方案1:修改链接命令,用-l参数关联依赖
把直接传入.so路径的写法改为指定库搜索目录加-l链接参数,示例命令如下:
该方式下链接器会直接用库文件名作为NEEDED项内容,不会写入路径。后续运行时可以通过/usr/bin/c++ myexe.cpp.o -o myexe \ -L../mylib -L../libstring \ -lmylib -lstringLD_LIBRARY_PATH环境变量指定库搜索路径,或者给可执行文件添加RPATH、配置系统ld搜索目录即可正常运行。 - 方案2:用patchelf工具事后修正NEEDED项
保持现有链接流程不变,生成可执行文件后执行如下命令修改NEEDED内容即可:
该方案无需调整现有构建流程,改造成本最低。patchelf --replace-needed ../libstring/libstring.so libstring.so myexe - 不推荐的方案:保留现有NEEDED的相对路径,给可执行文件添加对应相对路径的RPATH。该方案下可执行文件的运行会受工作目录影响,稳定性差,仅适合临时测试使用。
内容的提问来源于stack exchange,提问作者Sogartar
相关产品推荐
相关产品推荐

