Docs 菜单
Docs 主页
/ / /
C++ 驱动程序
/

ABI 版本控制

在此页面上

  • 二进制兼容性
  • 构建系统兼容性
  • 根命名空间重新声明
  • 弃用和删除

C++ 驱动程序使用 Ulrich Drepper 的《定义稳定性指南》、Linux 共享库“soname”约定和 CMake SOVERSION目标属性进行 ABI 版本控制。

Per Ulrich Drepper:

因此,稳定性的定义应以已记录的接口为基础。 接口的合法使用不应因实现的变更而受到影响;以未定义的方式使用接口会使保证失效。 使用完全未记录的内部符号也是如此。 根本不能使用这些内容。

根据 Linux文档项目:

每个共享库都有一个特殊名称,称为“soname”。 soname 包含前缀“lib”、库名称、短语“.so”、 后跟一个句点和一个版本号,只要接口发生变化,版本号就会递增(作为一个特殊例外,最低级别的C库不以“lib”开头)。 完全限定的 soname 包含其所在目录作为前缀;在工作系统上,完全限定的 soname 只是指向共享库的“真实名称”的符号链接。 *

根据 CMake 文档:

对于共享库,可使用VERSIONSOVERSION分别指定构建版本和 ABI 版本。 在构建或安装时,如果平台支持符号链接并且链接器支持 so-names,则会创建相应的符号链接。 如果仅指定了二者之一,则假定缺失的版本号相同。*

出于 ABI 版本控制的目的,我们区分了稳定 ABI不稳定 ABI

每当稳定 ABI 出现向后不兼容的更改(定义如下)时,ABI 版本号都会增加。

重要

只有稳定版 ABI 的稳定性是通过 ABI 版本号来传达的。 对不稳定 ABI 的向后(兼容)更改不会通过 ABI 版本号来传达。

注意

ABI 版本控制策略仅适用于共享库。 它应用用于静态库。

ABI命名空间在库的根命名空间内声明(请参阅源兼容性),以字母v为前缀,后跟整数或_noabi

ABI 命名空间的示例包括(相对于全局命名空间范围):

  • bsoncxx::v_noabi

  • bsoncxx::v1

  • bsoncxx::v2

  • bsoncxx::v99

不稳定的 ABI 命名空间是名称为v_noabi的命名空间。 任何其他 ABI 命名空间都是稳定的 ABI 命名空间。 根命名空间不是 ABI 命名空间。

稳定 ABI是公共 API 使用并在稳定 ABI 命名空间中声明的一组导出符号,但以下情况除外:

  • 符号或相应的公共 API 实体被明确记录为实验性的或尚未为 ABI 稳定性做好准备。

  • 该实体未在 ABI 命名空间中声明。

包括这些例外情况,所有其他导出的符号都被视为不稳定 ABI的一部分。

仅导出使用导出宏显式声明相应API实体的符号,这些符号由 CXX_VISIBILITY_PRESET 控制。 target属性。此外,显式(例如使用inline inline或隐式(例如 类定义中的成员函数定义、变量/函数模板实例化等) 不会 导出,由 VISIBILITY_INLINES_HIDDEN 控制 target属性。

如果存在应该导出的符号或是稳定 ABI 的一部分但目前未导出,请提交错误报告。

重要

不支持直接使用绕过公共 API 的导出符号。 所有导出的符号(稳定或不稳定)都必须通过公共 API 使用。 如果存在应该导出的符号或是稳定 ABI 的一部分但目前未导出,请提交错误报告。

重要

符号只需由公共 API 使用(即使是间接使用)即可被视为稳定 ABI 的一部分。 从未被任何公共 API 实体在任何先前版本中使用过的导出符号不被视为稳定 ABI 的一部分(请参阅上面的注释)。

重要

稳定 ABI 符号的行为也是稳定 ABI 的一部分。 这是为了确保具有相同 ABI 版本号的共享库之间的运行时行为一致且兼容。 该行为必须与使用该符号(即使是间接使用)的一个或多个公共 API 实体的文档一致,以便在具有相同 ABI 的版本之间,公共 API 行为(在显式记录的范围内)没有明显的变化版本号。

注意

属于公共 API 的某些实体可能不是稳定 ABI 的一部分(例如 内联函数、内联变量以及函数和变量的模板实例化)。 相反,属于稳定 ABI 的某些实体可能不是公共 API 的一部分(例如,导出的私有成员函数)。 请参阅API 版本控制。

有关构建系统属性的稳定 ABI 策略与针对公共API的策略基本相同(请参阅API构建系统兼容性),但存在以下差异:

  • 直接影响稳定 ABI 的属性被视为稳定 ABI 的一部分,而不是直接影响公共 API 的属性。

  • soname 被视为稳定版 ABI 的一部分。 这意味着,与公共 API 相比, BSONCXX_OUTPUT_NAME被视为稳定 ABI 的一部分,因为它直接影响生成的 bsoncxx 共享库的 soname。

  • “soname”在 Windows 上不适用。 请参阅共享库(仅限 MSVC)。

注意

我们支持stable API 每个构建配置 的 的稳定性。我们不支持stable API不同构建配置的兼容性。 例如,使用BSONCXX_OUTPUT_NAME=bsoncxx生成的共享库预计与针对使用包含BSONCXX_OUTPUT_NAME=bsoncxx-custom-basename的构建配置生成的稳定 ABI 进行编译的程序兼容。 (在使用 Visual Studio 等多配置生成器时,这一点尤其重要!)

根命名空间提供在 ABI命名空间中声明的实体的“重新声明”。 ABI命名空间可能因重新声明的实体而异。

例如,以下所有重新声明可能会同时出现:

  • bsoncxx::example::foo --> bsoncxx::v_noabi::example::foo

  • bsoncxx::example::bar --> bsoncxx::v1::example::bar

  • bsoncxx::example::baz --> bsoncxx::v2::example::baz

根命名空间重新声明旨在允许在vB中添加二进制不兼容的符号,而不会破坏vA符号的二进制兼容性。 它们有助于弃用稳定的 ABI 符号,同时提供从vAvB干净过渡的机会,而不会破坏二进制兼容性。 它们允许用户代码选择“重新声明升级”,从而减少从vA转换到vB时所需对源代码进行的更改。

这些重新声明升级旨在支持跨版本从已弃用、即将删除的 ABI 符号彻底过渡。 因此,鼓励用户默认使用根命名空间声明来选择进行这些升级。 但是,根据自己的稳定性策略,在自己的稳定 ABI 中引用 C++ 驱动程序实体时,用户可能需要使用显式 ABI 命名空间限定符。

以下兼容性表描述了何时由于不兼容的更改而必须更改 API 主版本号或 ABI 版本号:

更改类型
源兼容
二进制兼容
添加新的vB符号
将重新声明从vA升级到vB
可能[ 1 ]
删除vA符号(从公共 API 中)
No
可能[ 2 ]
删除vA符号(来自稳定的 ABI)
可能[ 2 ]
No
[1] 尽管需要使用不兼容的新的稳定 ABI 符号,但vB实体仍可与vA API 实现100 % 的源兼容。
[2]12稳定的 ABI 符号可以从公共API中删除(例如通过文档或从公共标头中删除),同时仍然提供导出的符号定义以实现向后兼容。 这种情况不太可能发生,但如果确实发生,那么源代码和二进制文件不兼容的更改可以分割到单独的版本中的情况很少见。

重要

ABI命名空间使用的整数并不直接对应于 ABI 版本号。 每当发生任何二进制不兼容的更改时,ABI 版本号都会增加,即使是从稳定的 ABI 中删除单个符号也是如此。 ABI 版本号从A提升到B并不意味着已弃用或删除在 ABI命名空间vA中声明的符号(如果存在)。

稳定 ABI 中符号的弃用和删除策略与公共API的相同。 有关更多信息,请参阅API弃用和删除。

包含二进制不兼容更改的版本将提高 ABI 版本号,而不是 API 主版本号。 但是,当 ABI 版本号发生冲突时,API 主版本号也可能会发生冲突,因为二进制不兼容的更改也可能是源不兼容的更改。

后退

API版本控制