Oracle® Developer Studio 12.5:GCC 兼容性指南

退出打印视图

更新时间: 2016 年 7 月
 
 

运行时支持兼容性

本节介绍与运行时支持有关的问题。

libgcc 支持

编译器在需要时会自动与 libgcc 链接,但如果出现问题,了解库的设计用途将很有帮助。gcc 支持库 (libgcc) 含有各种帮助程序例程,这些例程有两种格式,一种是称为 libgcc.a 的归档库,另一种是称为 libgcc_s.so 的共享库。libgcc 包含支持异常的例程以及支持整数和浮点运算的例程,这些运算在当前体系结构中可能没有直接指令。该库的功能如 gcc 文档中的 GCC 底层运行时库中所述。

使用 gcc 编译器创建的可执行文件会与 libgcc.a 链接,而不会与 libgcc_s.so 建立动态依赖关系。使用 g++ 编译器创建的可执行文件会使用 libgcc_s.so,而且会与该库建立动态依赖关系。

Oracle Developer Studio C 编译器生成的代码不会与 libgcc 建立依赖关系。

在 Sun 模式 (–compat=5) 下编译时,Oracle Developer Studio C++ 编译器生成的代码不会依赖于 libgcc,但在 GNU 兼容性模式(–compat=g–std=c++03–std=c++11–std=c++14)下编译时会具有此依赖关系。

在 Oracle Linux 上,名为 libc_supp.a 的类似库会随 Oracle Developer Studio 附带。

C++ 运行时支持

使用 Oracle Developer Studio C++ 编译器编译的源文件需要使用 Oracle Developer Studio C++ 编译器进行链接,以确保使用正确的运行时库、CRT 文件和链接程序选项。g++ 对象文件应与 g++ 链接。由于对象文件中使用了大量不兼容的实现细节,因此不支持将来自 Oracle Developer Studio C++ 和 g++ 编译器的对象文件混合到同一个可执行文件或共享库中。

GNU ABI 兼容性

Oracle Developer Studio C++ 在 GNU 兼容性模式(使用选项 –compat=g–std=c++03–std=c++11–std=c++14)下创建的共享库可与 g++ 编译器创建的共享库混合,并链接至任一编译器创建的主程序,但它们必须使用相同版本的 g++ ABI。

在 GNU 兼容性模式下操作时,Oracle Developer Studio C++ 编译器与标准库对象的库接口、名称改编和二进制布局区域中的 g++ 代码具备二进制兼容性。但是,它仍为许多底层实现方面使用不同的机制。外部内联函数、模板实例、RTTI 记录和异常范围信息都使用 COMDAT 按不同方式实现。异常范围信息以 Studio 专用方式设置格式。这限制了使用 Oracle Developer Studio C++ 编译的对象文件和归档库与使用 g++ 编译的对象文件和归档库之间的混合程度。

GNU C++ ABI 5.x 变更

由于 4.x 和 5.x 存在一个不兼容的 GNU C++ ABI 变更,使用 g++ 编译的可执行文件和库必须统一使用一个 ABI 才能正常工作。5.x GNU C++ 库同时支持两个 ABI,但编译器(GCC 或 Oracle Developer Studio)一次只能生成一个 ABI。g++ 编译器缺省使用 5.x ABI.要选择 4.x ABI,编译时请使用 –D_GLIBCXX_USE_CXX11_ABI=0

Oracle Developer Studio 12.5 C++ 编译器仅实现了 4.x ABI.要混合共享库和可执行文件,请使用上述选项编译 g++ 部分。有关此问题的 g++ 文档可在 https://gcc.gnu.org/onlinedocs/libstdc++/manual/using_dual_abi.html 找到。

从技术上来说,将 4.x 库或可执行文件与 5.x 库或可执行文件一起使用不存在任何障碍,但它们无法使用在两个 ABI 中不同的库类进行彼此调用。这些类中有一些很常用(例如字符串类),因此混合两个 ABI 起不到太大作用。

main 函数

C++ 中的 main 函数采用了某些额外的机制。编译对象文件及 main 时使用的编译器也应用来链接可执行文件。编译器驱动程序使用的 crt 对象文件与对象文件 main 中嵌入的机制匹配。

libCrunG3.so 库

在 GNU 模式下编译代码时,Oracle Developer Studio C++ 编译器会使用 GNU C++ 库,但它也需要链接名为 libCrunG3.so 的另一个库,以便为 RTTI、异常和其他语言功能提供支持函数。此库对应于在 Sun 模式 (–compat=5) 下使用的 libCrun.so 库。

不同版本的 GNU C++ 库

Oracle Developer Studio 12.5 C++ 编译器(在 GNU 兼容性模式下)使用 5.1.x 版本的 GNU C++ 库。您可以将使用不同版本的 GNU C++ 库编译的共享库和应用程序混合起来,但用于编译和链接主应用程序的编译器的版本至少要与用来创建任意共享库的编译器版本一样新。如果使用 Oracle Developer Studio C++ 编译了任何共享库,主应用程序应使用 Oracle Developer Studio C++ 或使用 g++ 编译器(都支持 5.1.x GNU C++ 库)编译。

运行时库位置

C++ 运行时库位于各种位置。

以下 Sun 模式 (–compat=5) C++ 库位于 Oracle Solaris 上的 /usr/lib,但在 Oracle Linux 上并不位于该位置:

  • libCstd.so

  • libCrun.so

  • libdemangle.so

  • libiostream.so

  • libstdcxx.so

以下 GNU 模式 C++ 库在 Oracle Solaris 上位于 /usr/lib,但在 Oracle Linux 上并不位于该位置:

  • libCrunG3.so(但是,您可能需要修补 Oracle Solaris 软件包 SUNWlibC

  • libdemangle.so

所有其他 C++ 运行时库都位于编译器安装目录。

Oracle Developer Studio C++ 编译器针对 Oracle Developer Studio 捆绑的任意共享库进行链接时,它通常会将必要的 RPATH 设置添加到可执行文件中,以便在运行时查找库。您可通过添加 –xnorunpath 选项并添加相应的 –R 选项来防止此行为并配置 RPATH 设置。

OpenMP

使用 –xopenmp 编译源代码时会在系统库上生成运行时依赖关系,对 Oracle Developer Studio 编译器来说,该系统库就是 libmtsk 库。在 Oracle Solaris 上,此库位于 /usr/lib 中。在 Oracle Linux 上,此库位于编译器安装目录中。由于线程管理是一个进程范围内的操作,在一个程序中,请仅使用一个 OpenMP 实现。如果共享库使用 OpenMP,主应用程序将无法使用不同的 OpenMP 实现。Oracle Developer Studio 的 OpenMP 实现与 GCC 的 OpenMP 实现不兼容。

原子

原子是 C 2011 和 C++ 2011 标准中新增的语言功能,而且它需要来自操作系统的运行时支持。Oracle Developer Studio 编译器使用初步绑定的运行时库(该库与部分版本的 GCC 运行时库兼容)支持此功能(请参见Oracle Developer Studio 12.5:C++ 用户指南 中的 捆绑的原子库),而且您可以使用 –xatomic 选项选择链接程序和库时使用哪个运行时库。

线程本地

GCC 和 Oracle Developer Studio 编译器实现了线程局部数据 (__thread declarations),且采用的实现方法符合 OS ABI(Oracle Solaris 或 Oracle Linux),因此相关功能在 Oracle Developer Studio 和 GCC 编译器编译的代码之间兼容。有关适用于线程局部数据的 Oracle Solaris ABI 的更多信息,请参见Oracle Solaris 11.3 链接程序和库指南