静态链接libstdc ++:有陷阱吗?

尼克·哈钦森(Nick Hutchinson):

我需要将基于GCC 4.7的libstdc ++的,在Ubuntu 12.10上构建的C ++应用程序部署到运行Ubuntu 10.04的系统,该系统随附相当老的libstdc ++版本。

目前,我正在-static-libstdc++ -static-libgcc按照此博客文章的建议进行编译静态链接libstdc ++作者警告不要在静态编译libstdc ++时使用任何动态加载的C ++代码,这是我尚未检查过的事情。尽管如此,到目前为止一切似乎都进展顺利:我可以使用Ubuntu 10.04上的C ++ 11功能。

我注意到这篇文章是从2005年开始的,此后也许已经发生了很大的变化。它的建议仍然有效吗?我应该注意哪些潜伏问题?

乔纳森·韦克利(Jonathan Wakely):

该博客文章非常不准确。

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

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

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

发行版的GCC补丁版本之间的差异很小,并且不会更改ABI,例如Fedora的4.6.3 20120306(Red Hat 4.6.3-2)与上游的FSF 4.6.x版本以及几乎所有4.6都兼容ABI。 x来自任何其他发行版。

在GNU / Linux上,GCC的运行时库使用ELF符号版本控制,因此可以很容易地检查对象和库所需的符号版本,如果您提供了libstdc++.so可以使用的符号版本,则它与修补版本稍有不同也没关系从另一个发行版本开始。

但是如果可行,则不能动态链接C ++代码(或使用C ++运行时支持的任何代码)。

这也不是事实。

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

如果(使用dlopen动态加载库,它可能不起作用的原因是,(静态)链接它时,应用程序可能不需要依赖它的libstdc ++符号,因此这些符号将不会出现在可执行文件中。这可以通过动态链接共享库来解决libstdc++.so(如果依赖共享库,这是正确的选择。)ELF符号插入意味着可执行文件中存在的符号将由共享库使用,而其他符号则不会可执行文件中的任何libstdc++.so链接都可以找到它。如果您的应用程序不使用dlopen,则无需担心。

另一种选择(也是我更喜欢的一种选择)是将较新libstdc++.so的应用程序部署在您的应用程序旁边,并确保在默认系统之前找到它libstdc++.so,这可以通过$LD_LIBRARY_PATH在运行时使用环境变量强制动态链接器在正确的位置进行查找来完成。时间,或RPATH在链接时在可执行文件中设置一个我更喜欢使用RPATH它,因为它不依赖于正确设置应用程序正常工作的环境。如果您将应用程序与链接'-Wl,-rpath,$ORIGIN'(请注意使用单引号防止外壳扩展$ORIGIN),则可执行文件将带有一个RPATH$ORIGIN其告诉动态链接程序在与可执行文件本身相同的目录中查找共享库。如果你把新的libstdc++.so在与可执行文件相同的目录中,它将在运行时找到,问题已解决。(另一种选择是将可执行文件放入其中/some/path/bin/,将较新的libstdc ++。so放入其中,/some/path/lib/并链接'-Wl,-rpath,$ORIGIN/../lib'到可执行文件或相对于可执行文件的任何其他固定位置,并相对于设置RPATH $ORIGIN

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章