为了使用C ++ 11和c ++ 14的功能,我有一个使用的应用程序 更新版本的gcc(4.9.1),因此是更新版本的libstdc ++。该应用程序包含许多 小程序所以我将libstdc ++作为共享库而不是静态库链接 (即我不想使用-static-libstdc ++)
我希望使用/ opt // lib64下的应用程序发布新版本的libstdc ++ (注意:这是在GPL例外情况下特别允许的)
新版本的libstdc ++。与目标平台上的版本只有次要版本不同。 libstdc ++旨在向前兼容,以便现有程序可以使用新版本的库。但是,我观察到一些行为(即错误)的微妙差异 程序使用新版本而不是旧版本。我希望阻止这一点。
我还发现ld
会尝试将我的应用程序与libstdc ++的系统版本链接起来,除非
我先把/ opt // lib64放在LD_LIBRARY_PATH上。
据说你可以使用-l:<library>.<version>
强制链接特定版本,但是,这似乎不起作用。我怀疑它会为用户创建的库而不是
一个像libstd ++这样的语言运行库,因为gcc本身会生成链接描述文件。
同样在我的一个目标平台(RHEL5)上,gcc / ld甚至都不理解它。
我认为这可以通过使用-nostdlib并在我的构建系统中链接所需的所有内容(例如-lgcc)
而不是把它留给我更喜欢的gcc。到目前为止,我还没试过这个。
一种简单的解决方法是在运行我的应用程序时确保LD_LIBRARY_PATH包含/ opt // lib64 而不是其他或同样我可以使用LD_PRELOAD与正确的库版本。 如果有人决定忽略我的建议并运行
,问题就出现了export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/opt/<vendor>/lib64
它可能导致细微且难以诊断的问题。所以我一直在寻找更好的方法。
我想知道是否有某种方法我可以将libstdc ++重命名为lib_stdc ++并链接到该soname。 重命名libstdc ++是不够的,因为您需要更改readelf给出的文件中的soname。即
0x000000000000000e (SONAME) Library soname: [libstdc++.so.6]
如果您对gcc
链接的普通程序执行此操作,即使使用-l:stdc++.so.6.0.20
,您也会注意到这一点
给出主要版本而不是特定的次要版本。
即。
readelf -d <myapp>
0x0000000e (SONAME) Library soname: [libstdc++.so.6]
而不是:
0x0000000e (SONAME) Library soname: [libstdc++.so.6.0.20]
所以我创建了一个虚拟共享库,其中包含我想要依赖的soname,以便按如下方式添加依赖项:
gcc dummy.o -Wl,-soname,lib<vendor>_stdc++.so.6.0.20 -nostdlib -shared -o lib<vender>_dummycpp.so
(其中dummy.o是一个空的目标文件,由空的源文件制成,以阻止-nostdlib导致投诉)
然后:
gcc <myapp> -l<vendor>_dummycpp
根据需要我现在得到:
readelf -d <myapp>
0x0000000000000001 (NEEDED) Shared library: [lib<vendor>_stdc++.so.6.0.20]
而不是
0x0000000000000001 (NEEDED) Shared library: [libstdc++.so.6]
dummycpp库包含libstdc ++中的所有符号,因为它是libstd ++,因此根本不需要gcc与soname libstdc ++链接。我似乎完全解决了这个问题。
这让我感到有些狡猾,因此我想问的问题是:
这是个好主意吗?
如果不是为什么不呢?
有更好/更正确的方法吗?
注意:如果在RPM中使用不同的名称(例如lib_stdc ++。so.6.0.20)打包libstdc ++,则会缺少对它的依赖,需要使用--nodeps进行安装。这是因为RPM扫描链接时间依赖性。解决方法是安装虚拟库。然后RPM将从虚拟库中获取soname而不是声称它丢失了。
答案 0 :(得分:2)
libstdc ++ FAQ条目How do I insure that the dynamically linked library will be found链接到手册部分Finding Dynamic or Shared Libraries,该部分解释了如何使用RPATH。
我首选的方法是使用$ORIGIN
的RPATH,这意味着搜索动态库依赖项会在与二进制文件相同的目录中开始(请参阅ld.so(8))。因此,如果您链接'-Wl,-rpath,$ORIGIN'
(注意引号以防止shell扩展$ ORIGIN),那么您可以在与安装的二进制文件相同的目录中安装共享库,并在运行二进制文件时找到它们。如果您希望在某个安装前缀下有单独的'-Wl,-rpath,$ORIGIN/../lib'
和bin
目录,请使用lib
。
在ldconfig
无法扫描的某个自定义路径中将二进制文件与二进制文件一起安装,并且没有LD_LIBRARY_PATH
弄乱环境,新的libstdc ++将永远不会被应用程序找到不应该使用那个版本。
确保您还安装了指向libstdc++.so.6
文件的libstdc++.so.6.0.20
符号链接,以便DT_NEEDED
libstdc++.so.6
可以找到该文件。