强制或阻止使用特定次版本的libstdc ++ [英] Forcing or preventing use of a particular minor version of libstdc++

查看:376
本文介绍了强制或阻止使用特定次版本的libstdc ++的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

为了使用C ++ 11和c ++ 14的功能,我有一个应用程序使用
编译的新版本的gcc(4.9.1),因此更新版本的libstdc ++。该应用程序包含许多
小程序,所以我链接libstdc ++作为共享库,而不是静态
(即我不想使用-static-libstdc ++)



我想运行libstdc ++的新版本与/ opt // lib64
下的应用程序(注意:这是特别允许在GPL的异常下)



新版本的libstdc ++。因此与目标平台上的版本不同,只是次要版本。
libstdc ++旨在向前兼容,以便现有程序可以使用新版本的库。然而,当一些
程序使用新版本而不是旧版本时,我已经观察到行为的微妙差异(即错误)。我希望防止这种情况。



我也发现 ld 会尝试将我的应用程序与系统版本libstdc ++ unless
我在LD_LIBRARY_PATH上放置/ opt // lib64。
据推测,您可以使用 -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 ++是不够的,因为您需要更改文件中的soname,如readelf所示。即

  0x000000000000000e(SONAME)库soname:[libstdc ++。so.6] 

如果你在由 gcc 链接的正常程序上执行此操作,即使使用 -l:stdc ++。so.6.0.20 说你会注意到这个
给出了主版本,而不是具体的次版本。
ie。

  readelf -d< myapp> 
0x0000000e(SONAME)库soname:[libstdc ++。so.6]

  0x0000000e(SONAME)库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)共享库:[lib< vendor> _stdc ++。so.6.0.20]

而不是

  0x0000000000000001(NEEDED)共享库:[libstdc ++。so.6] 

dummycpp库包含libstdc ++中的所有符号,因为它是libstd ++,因此不需要gcc链接soname libstdc ++。我似乎已经完全解决了这个问题。



它打击了我作为一个微不足道的解决方案,所以我想问的问题是:




  • 这是个好主意吗?




注意:如果您使用不同的名称(例如lib_stdc ++。so.6.0.20)打包libstdc ++一个RPM你会得到一个缺失依赖它,需要使用--nodeps安装。这是因为RPM扫描链接时间依赖关系。解决方法是安装虚拟库。 RPM将从虚拟库中拾取soname,而不是声明它丢失。

解决方案

libstdc ++常见问题项如何确保动态链接的库将找到链接到手册部分查找动态或共享库,说明如何使用RPATH。


$我的首选方法是使用 $ ORIGIN 的RPATH,这意味着搜索动态库依赖关系在与二进制文件相同的目录中开始(参见 ld.so(8))。所以,如果你链接到' - wl,-rpath,$ ORIGIN'(注意引号以防止$ ORIGIN被扩展的shell),然后你可以安装共享库与安装的二进制文件相同的目录,它们将在运行二进制文件时找到。或者使用'-Wl,-rpath,$ ORIGIN /../ lib'如果你想要单独的 bin lib 目录下的一些安装前缀。



code> ldconfig 不扫描,并且没有 LD_LIBRARY_PATH 混乱环境,更新的libstdc ++永远不会被应用程序找到不应该使用该版本。


In order to make use of C++11 and c++14 features I have an application compiled using a newer version of gcc (4.9.1) and thus an newer version of libstdc++. The application consists of many small programs so I am linking with libstdc++ as a shared library rather than a static one (i.e. I don't wish to use -static-libstdc++)

I wish to ship the new version of libstdc++ with the application under /opt//lib64 (note: that this is specifically allowed under an exception to the GPL)

The new version of libstdc++.so differs with the version on the target platform only by minor version. libstdc++ is designed to be forward compatible so that existing programs can use the new version of the library. However, I have observed subtle differences in behaviour (i.e. bugs) when some programs use the new version rather than the older one. I wish to prevent this.

I also find that ld will try to link my application with the system version of libstdc++ unless I put /opt//lib64 earlier on the LD_LIBRARY_PATH. Supposedly you can force linking against a specific version using -l:<library>.<version>, however, this doesn't seem to work. I suspect that it would for a user created library but not for a language runtime library like libstd++ because gcc itself generates the linker script. Also on one of my target platforms (RHEL5) it is not even understood by gcc/ld. I presume this is possible via using -nostdlib and linking in everything required (e.g. -lgcc) in my build system rather than leaving it to gcc which I would prefer. So far I haven't tried this.

A simple way workaround for this is to ensure LD_LIBRARY_PATH contains /opt//lib64 when I run my application and not otherwise or equally I could use LD_PRELOAD with the correct library version. The problem with this if someone decides ignore my advice and runs

export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/opt/<vendor>/lib64 

it could lead to subtle and hard to diagnose problems. So I have been looking for a better way.

I wondered if there was some way I could rename libstdc++ as lib_stdc++ and link against that soname instead. Renaming libstdc++ is not enough as you need to alter the soname in the file as given by readelf. i.e

0x000000000000000e (SONAME)             Library soname: [libstdc++.so.6]

If you do this on a normal program linked by gcc even using -l:stdc++.so.6.0.20 say you will notice this gives the major version and not the specific minor version. i.e.

readelf -d <myapp>
0x0000000e (SONAME)                     Library soname: [libstdc++.so.6]

rather than:

0x0000000e (SONAME)                     Library soname: [libstdc++.so.6.0.20]

So I have instead created a dummy shared library with the soname I want to depend on in order to add a dependency as follows:

gcc dummy.o -Wl,-soname,lib<vendor>_stdc++.so.6.0.20 -nostdlib -shared -o lib<vender>_dummycpp.so

(where dummy.o is an empty object file made from an empty source file to stop -nostdlib leading to complaints)

then:

gcc <myapp> -l<vendor>_dummycpp

as desired I now get:

readelf -d <myapp>

0x0000000000000001 (NEEDED)             Shared library: [lib<vendor>_stdc++.so.6.0.20]

instead of

0x0000000000000001 (NEEDED)             Shared library: [libstdc++.so.6]

The dummycpp library contains all the symbols in libstdc++ because it is libstd++ so there is no need for gcc to link with the soname libstdc++ at all. I appear to have solved the issue completely.

It strikes me as a slightly hacky solution so the questions I want to ask here are:

  • Is this a good idea?

  • If not why not?

  • Is there a better/more correct way?

Note: that if you package the libstdc++ with a different name (e.g. lib_stdc++.so.6.0.20) in an RPM you will get a missing dependency on it and need to install using --nodeps. This is because RPM scans for link time dependencies. The workaround for this is to install the dummy library as well. RPM will then pick up the soname from the dummy library and not claim it is missing.

解决方案

The libstdc++ FAQ entry How do I insure that the dynamically linked library will be found links to the manual section Finding Dynamic or Shared Libraries which explains how to use RPATH instead.

My preferred method is to use an RPATH of $ORIGIN which means that searching for dynamic library dependencies starts in the same directory as the binary (see ld.so(8)). So if you link with '-Wl,-rpath,$ORIGIN' (note the quotes to prevent $ORIGIN being expanded by the shell) then you can install shared libraries in the same directory as your installed binary and they will be found when your binary is run. Or use '-Wl,-rpath,$ORIGIN/../lib' if you'd rather have separate bin and lib directories under some installation prefix.

With the library installed alongside the binary in some custom path that ldconfig doesn't scan, and no LD_LIBRARY_PATH messing up the environment, the newer libstdc++ will never be found by applications which are not supposed to use that version.

这篇关于强制或阻止使用特定次版本的libstdc ++的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆