链接libstdc ++静态:任何陷阱? [英] Linking libstdc++ statically: any gotchas?

查看:163
本文介绍了链接libstdc ++静态:任何陷阱?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要将一个基于Ubuntu 12.10的C ++应用程序与GCC 4.7的libstdc ++一起部署到运行Ubuntu 10.04的系统中,该系统带有相当老的版本的libstdc ++。

I need to deploy a C++ application built on Ubuntu 12.10 with GCC 4.7's libstdc++ to systems running Ubuntu 10.04, which comes with a considerably older version of libstdc++.

目前,我正在编写 -static-libstdc ++ -static-libgcc ,如本博客建议:链接libstdc ++静态。作者警告,在编译libstdc ++静态时,不使用任何动态加载的C ++代码,这是我还没有检查。仍然,一切似乎到目前为止顺利:我可以利用Ubuntu 10.04上的C ++ 11功能,这是我以后。

Currently, I'm compiling with -static-libstdc++ -static-libgcc, as suggested by this blog post: Linking libstdc++ statically. The author warns against using any dynamically-loaded C++ code when compiling libstdc++ statically, which is something I haven't yet checked. Still, everything seems to be going smoothly so far: I can make use of C++11 features on Ubuntu 10.04, which is what I was after.

我注意到这篇文章是从2005年,也许很多已经改变了从那时起。它的建议是否仍然最新?是否有任何潜在的问题我应该注意?

I note that this article is from 2005, and perhaps much has changed since then. Is its advice still current? Are there any lurking issues I should be aware of?

推荐答案

这篇博文很不准确。


据我所知,已经在每个主要版本的GCC(即具有不同的第一或第二版本号组件的版本)中引入了C ++ ABI更改。

As far as I know C++ ABI changes have been introduced with every major release of GCC (i.e. those with different first or second version number components).

不正确。自GCC 3.4以来,引入的唯一C ++ ABI更改是向后兼容的,这意味着C ++ ABI已经稳定了近九年了。

Not true. The only C++ ABI changes introduced since GCC 3.4 have been backward-compatible, meaning the C++ ABI has been stable for nearly nine years.


更糟糕的是,大多数主要的Linux发行版都使用GCC快照和/或补丁GCC版本,这使得几乎不可能准确知道在分发二进制文件时可能处理的GCC版本。

To make matters worse, most major Linux distributions use GCC snapshots and/or patch their GCC versions, making it virtually impossible to know exactly what GCC versions you might be dealing with when you distribute binaries.

GCC的分布修补版本之间的差异很小,而不是ABI更改,例如Fedora的4.6.3 20120306(Red Hat 4.6.3-2)与上游FSF 4.6.x版本兼容,几乎肯定与任何其他发行版本的4.6.x兼容。

The differences between distributions' patched versions of GCC are minor, and not ABI changing, e.g. Fedora's 4.6.3 20120306 (Red Hat 4.6.3-2) is ABI compatible with the upstream FSF 4.6.x releases and almost certainly with any 4.6.x from any other distro.

在GNU / Linux上,GCC的运行时库使用ELF符号版本控制,所以很容易检查对象和库所需的符号版本,如果你有一个 libstdc ++,所以提供这些符号,它将工作,它是否与另一个版本的发行版略有不同的修补版本无关紧要。

On GNU/Linux GCC's runtime libraries use ELF symbol versioning so it's easy to check the symbol versions needed by objects and libraries, and if you have a libstdc++.so that provides those symbols it will work, it doesn't matter if it's a slightly different patched version from another version of your distro.


but no C++ code (or any code using the C++ runtime support) may be linked dynamically if this is to work.

这并不是真的,因为C ++代码(或使用C ++运行时支持的任何代码) 。

This is not true either.

也就是说,静态链接到 libstdc ++。a 是您的一个选择。

That said, statically linking to libstdc++.a is one option for you.

如果动态加载库(使用 dlopen ),它可能不工作的原因是它依赖的libstdc ++符号可能不需要由您的应用程序,当您(静态)链接它,所以这些符号将不会出现在您的可执行文件。这可以通过将共享库动态链接到 libstdc ++来解决,因此(这是正确的做法,如果它取决于它。)ELF符号插入意味着符号存在于您的可执行文件将被共享库使用,但其他不存在于您的可执行文件将被发现在 libstdc ++。因此它链接到。如果你的应用程序不使用 dlopen ,你不需要关心这个。

The reason it might not work if you dynamically load a library (using dlopen) is that libstdc++ symbols it depends on might not have been needed by your application when you (statically) linked it, so those symbols will not be present in your executable. That can be solved by dynamically-linking the shared library to libstdc++.so (which is the right thing to do anyway if it depends on it.) ELF symbol interposition means symbols that are present in your executable will be used by the shared library, but others not present in your executable will be found in whichever libstdc++.so it links to. If your application doesn't use dlopen you don't need to care about that.

我喜欢的)是在你的应用程序旁边部署新的 libstdc ++。so ,并确保它在默认系统 libstdc ++之前找到。因此,可以通过在运行时使用 $ LD_LIBRARY_PATH 环境变量强制动态链接器查找正确的位置,或者通过设置 RPATH 在链接时的可执行文件。我喜欢使用 RPATH ,因为它不依赖于为应用程序正确设置的环境工作。如果你用'-Wl,-rpath,$ ORIGIN'链接你的应用程序(注意单引号,以防止shell尝试扩展 $ ORIGIN ),那么可执行文件将有一个 RPATH of $ ORIGIN ,它告诉动态链接器用于与可执行文件本身位于同一目录中的共享库。如果你把新的 libstdc ++。so 放在与可执行文件相同的目录下,那么问题就解决了。 (另一个选项是将可执行文件放在 / some / path / bin / 和较新的libstdc ++中,因此在 / some / path / lib / / code>并链接到' - Wl,-rpath,$ ORIGIN /../ lib'或相对于可执行文件的任何其他固定位置, RPATH相对于 $ ORIGIN

Another option (and the one I prefer) is to deploy the newer libstdc++.so alongside your application and ensure it is found before the default system libstdc++.so, which can be done by forcing the dynamic linker to look in the right place, either using $LD_LIBRARY_PATH environment variable at run-time, or by setting an RPATH in the executable at link-time. I prefer to use RPATH as it doesn't rely on the environment being set correctly for the application to work. If you link your application with '-Wl,-rpath,$ORIGIN' (note the single quotes to prevent the shell trying to expand $ORIGIN) then the executable will have an RPATH of $ORIGIN which tells the dynamic linker to look for shared libraries in the same directory as the executable itself. If you put the newer libstdc++.so in the same directory as the executable it will be found at run-time, problem solved. (Another option is to put the executable in /some/path/bin/ and the newer libstdc++.so in /some/path/lib/ and link with '-Wl,-rpath,$ORIGIN/../lib' or any other fixed location relative to the executable, and set the RPATH relative to $ORIGIN)

这篇关于链接libstdc ++静态:任何陷阱?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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