当前位置: 首页 > 面试题库 >

强制或禁止使用特定的次要版本的libstdc ++

顾赞
2023-03-14
问题内容

为了利用C 11和c 14功能,我有一个使用较新版本的gcc(4.9.1)和较新的libstdc
编译的应用程序。该应用程序由许多小程序组成,因此我将libstdc 作为共享库而不是静态库进行链接(即,我不希望使用-static-libstdc
++)

我希望将新版本的libstdc ++与应用程序一起放在/ opt // lib64下(注意:GPL的例外明确允许这样做)

libstdc 。so的新版本与目标平台上的版本仅次要版本不同。libstdc
设计为向前兼容,以便现有程序可以使用该库的新版本。但是,当某些程序使用新版本而不是旧版本时,我观察到了行为上的细微差异(即错误)。我希望防止这种情况。

我还发现,ld除非我将/ opt // lib64放在较早的LD_LIBRARY_PATH上,否则它将尝试将我的应用程序与libstdc
系统版本链接。可以使用强制链接到特定版本 -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与sost libstdc
++链接。我似乎已经完全解决了这个问题。

这让我感到有点棘手,所以我想在这里提出的问题是:

  • 这是一个好主意吗?

  • 如果不是,为什么不呢?

  • 有没有更好/更正确的方法?

注意:如果在RPM中将libstdc 打包为其他名称(例如lib_stdc 。so.6.0.20),则会缺少对它的依赖关系,需要使用–
nodeps进行安装。这是因为RPM扫描链接时间相关性。解决方法是也安装虚拟库。然后,RPM将从虚拟库中获取soname,并且不会声称它丢失。


问题答案:

libstdc
++常见问题解答条目如何确保找到动态链接的库,链接到手册部分“
查找动态或共享库”,该部分说明了如何使用RPATH。

我的首选方法是使用RPATH,$ORIGIN这意味着搜索动态库依赖项的起始位置与二进制文件所在的目录相同(请参阅ld.so(8))。因此,如果与链接'-Wl,-rpath,$ORIGIN'(请注意引号,以防止$
ORIGIN被shell扩展),则可以将共享库安装在与已安装的二进制文件相同的目录中,并且在运行二进制文件时可以找到它们。或者,'-Wl,-rpath,$ORIGIN/../lib'如果您希望在某个安装前缀下有单独的binlib目录,请使用。

由于该库与二进制文件一起安装在一些ldconfig不会扫描的自定义路径中,并且不会LD_LIBRARY_PATH破坏环境,因此不应该使用该版本的应用程序将永远找不到较新的libstdc
++。

确保还安装了libstdc++.so.6指向libstdc++.so.6.0.20文件的符号链接,以便DT_NEEDEDfor
libstdc++.so.6可以找到该文件。



 类似资料:
  • 渐变-泊坞插件和Spring靴版本 2.0.0.M4 M4 使用较新的客户端,并且使用 docker 插件以异常结尾,存在一个问题: 我的主项目中的构建脚本: 如您所见,我们加载spring-boot-gradle-plugin version=2.0.0。M4及其所有依赖项。 我的子项目构建:gradle: 最重要的是,docker.gradle文件与子项目的build.gradle文件位于同一

  • 我正在尝试将我们的存储库从SVN迁移到Git,我在一个非常大的项目中遇到了发布插件的问题。 问题: 这个项目有大约50个子模块,它试图将所有修改后的pom添加为一个git add -- '. 这打破了windows命令行的限制。 幸运的是,在maven-scm-提供者-gitexe的版本1.8.1中对此进行了修复,但是maven-resess-plugin目前设置为使用1.7,但没有修复。 我尝试

  • 如果我们看到。类文件结构,它说:偏移量0x04-0x05用于JDK的次要版本,偏移量0x06-0x07用于JDK的主要版本 我使用eclipse和JDK1进行java项目开发。为JRE系统库和类文件配置的5.0_7/JRE将偏移显示为0x00 0x00 0x00 0x31。 如何将编译器更改为JDK1。5.0_7以使偏移量变为0x00 0x07 0x00 0x31?

  • 我正在与Maven一起使用Pact JVM/Java(Version3)。中没有项目版本控制--它只是版本。在Pact Maven插件中配置的与Maven project version-相同。 我应该玩和吗?我是否应该升级到Pact版本4并使用消费者版本选择器?

  • 问题内容: 我正在使用Gson对此类进行序列化和反序列化。今天,我不得不在此对象中添加最终的UUID。我没有序列化的问题。我需要强制gson 在反序列化时使用构造函数。我该如何实现? 问题答案: 您可以实现一个自定义的JsonDeserializer并将其注册到GSON。 请记住,此代码尚未经过测试。