在Linux上编译一个共享库以针对所有发行版
Compiling one shared library on Linux to target all distributions
我们想要创建一个共享库(.so)来针对所有发行版,包括旧的发行版。代码是用c++编写的,并使用了c++ 11的特性,因此编译器必须至少是gcc 4.7。我们注意到,如果我们在安装了gcc 4.7.2(例如Ubuntu 12.10)的Linux机器上编译我们的代码,那么产生的。so是"版本1 (GNU/Linux)",而在旧的操作系统(例如CentOS 5.6)上,版本是"版本1 (SYSV)"-并且GNU/Linux新版本的库不能在旧的操作系统上使用。
所以我们尝试了在CentOS 5.6机器上安装gcc 4.7的方法,用这个编译器编译我们的代码,并静态地链接到libstdc++ (-static-libstdc++) -这产生了一个。So,它可以在我们找到的所有linux上使用。
对于32位元,这工作得很好。然而,当我们在64位操作系统(CentOS)上遵循相同的方法时,这失败了,错误是现有的libstdc++。a我们试图链接到编译时没有-fPIC。
所以我们尝试用"-with-pic"选项编译gcc 4.7.2源代码,但是我们无法链接到新的libstdc++。A -错误是:
/opt/centos/devtoolset - 1.1/根/usr/libexec/gcc/x86_64-CentOS-linux/4.7.2/ld:/usr/local/lib/libFoo.没有找到符号_ZNSs7_M_copyEPcPKcm@GLIBCXX_3.4的版本节点/opt/centos/devtoolset-1.1/root/usr/libexec/gcc/x86_64-CentOS-linux/4.7.2/ld: failed to set dynamic section sizes: Bad value
收集2:error: ld returned 1 exit status
我们搜索了一下,用-fPIC编译libstdc++可能会有问题,但为什么它适用于32位而不是64位操作系统?有没有其他建议的方法为所有Linux发行版创建一个。so ?
我在https://gcc.gnu.org/ml/libstdc++/2014-05/msg00107.html上回答了这个问题
这看起来像https://gcc.gnu.org/bugzilla/show_bug.cgi?id=54482,所以可能会在GCC 4.7.3中修复(但我不确定)
…
PIC在x86和x86_64中实现不同,因为64位模式已内置支持
静态链接到libc/libstdc++不应该这样做,即使它工作!这是相当危险的,因为很多安全方面都需要对libc进行更新。如果静态链接在没有更新可以填补空白。
我不敢相信有一个通用的libc可以在所有的linux平台上运行。libc是安装系统的接口,这是一个巨大的差异池。一个自由如何适合所有人?
链接时可以尝试
-static-libstdc++ -static-libgcc
作为old的选项,也许这有帮助。但我永远不会那样做!
- 如何使用 CMake 在 android 构建上编译和共享两个 c++ 库
- 将预编译的 C 共享库与 JNI/NDK 结合使用
- c++ 是否保证标头初始化的静态 const 成员跨编译单元和库共享单个实例?
- CMake 添加和删除宏定义以编译共享库/可执行文件
- 使用 Flutter 从 Android 上的原生编译共享库中调用函数
- 在VS2017中,我们如何在项目成员之间共享编译设置
- 使用共享库编译可执行文件时仅链接所需的符号
- 运行程序时找不到共享对象库,但在编译过程中链接了它
- 使用 -O1 优化标志编译项目时共享库崩溃
- GCC 中使用 -O3 的共享库编译不会导出与 -O0 中那样多的符号
- 如何使用Makevars链接到RCPP中已经编译的外部共享库
- 编译为"共享库"的源代码
- Qt项目与自定义共享库交叉编译Qt
- 交叉编译 qt:加载共享库时出错
- 使用运行时参数与编译时参数在类之间共享代码
- 构建共享对象 - 使用 Ninja 编译适用于 OSX 和 Windows 上的 Ubuntu Crush
- 加载共享库时出现 Codelite 错误,但我可以编译它
- 将函数从控制台应用程序移动到共享库项目似乎会带来不相关的编译错误
- 如何将所有依赖项和共享库编译为一个二进制文件
- 如何测试共享对象/共享库已正确编译