ABI Versioning
On this page
The C++ Driver uses Ulrich Drepper's guide to Defining Stability, the Linux shared library "soname" convention, and the CMake SOVERSION
target property for ABI versioning.
Per Ulrich Drepper:
The definition of stability should therefore use the documented interface as the basis. Legitimate uses of interfaces should not be affected by changes in the implementation; using interfaces in an undefined way void the warranty. The same is true for using completely undocumented, internal symbols. Those must not be used at all.
Per The Linux Documentation Project:
Every shared library has a special name called the ` ` soname''. The soname has the prefix ` ` lib'', the name of the library, the phrase ` ` .so'', followed by a period and a version number that is incremented whenever the interface changes (as a special exception, the lowest-level C libraries don't start with ` ` lib''). A fully-qualified soname includes as a prefix the directory it's in; on a working system a fully-qualified soname is simply a symbolic link to the shared library's ` ` real name''.*
For shared libraries
VERSION
andSOVERSION
can be used to specify the build version and ABI version respectively. When building or installing appropriate symlinks are created if the platform supports symlinks and the linker supports so-names. If only one of both is specified the missing is assumed to have the same version number.*
For purposes of ABI versioning, we distinguish between the stable ABI and the unstable ABI.
The ABI version number is bumped whenever there is a backward incompatible change to the stable ABI as defined below.
Important
Only the stability of the stable ABI is communicated by the ABI version number. Backward (in)compatible changes to the unstable ABI are not communicated by the ABI version number.
Note
The ABI versioning policy is only applicable to shared libraries. It does not apply to static libraries.
Binary Compatibility
An ABI namespace is declared within the library's root namespace (see Source Compatibility), prefixed with the letter v
and followed by either an integer or _noabi
.
Examples of ABI namespaces include (relative to the global namespace scope):
bsoncxx::v_noabi
bsoncxx::v1
bsoncxx::v2
bsoncxx::v99
An unstable ABI namespace is a namespace with the name v_noabi
. Any other ABI namespace is a stable ABI namespace. The root namespace is not an ABI namespace.
The stable ABI is the set of exported symbols that are used by the public API and declared in a stable ABI namespace, with the following exceptions:
The symbol or corresponding public API entities are explicitly documented as experimental or not yet prepared for ABI stability.
The entity is not declared within an ABI namespace.
Including these exceptions, all other exported symbols are considered to be part of the unstable ABI.
Only symbols whose corresponding API entity is explicitly declared with an
export macro are exported, as controlled by the CXX_VISIBILITY_PRESET target
property. Additionally, entities that are declared inline
, either explicitly
(e.g. with inline
) or implicitly (e.g. member function definitions in class
definitions, variable/function template instantiations, etc.) are not
exported, as controlled by the
VISIBILITY_INLINES_HIDDEN
target property.
If there is a symbol that should be exported or part of the stable ABI, but is currently not, please submit a bug report.
Important
Direct use of exported symbols that bypasses the public API is not supported. All exported symbols (stable or unstable) must be used via the public API. If there is a symbol that should be exported or part of the stable ABI, but is currently not, please submit a bug report.
Important
A symbol only needs to be used by the public API (even indirectly) to be considered part of the stable ABI. An exported symbol that has never been used by any public API entity in any prior release is not considered part of the stable ABI (see note above).
Important
The behavior of a stable ABI symbol is also part of the stable ABI. This is to ensure consistent and compatible runtime behavior between shared libraries with the same ABI version number. The behavior must be consistent with the documentation of one or more public API entities that uses the symbol (even indirectly) such that there is no observable change in public API behavior (within the scope of what is explicitly documented) across releases with the same ABI version number.
Note
Some entities that are part of the public API may not be part of the stable ABI (e.g. inline functions, inline variables, and template instantiations of functions and variables). Conversely, some entities that are part of the stable ABI may not be part of the public API (e.g. an exported private member function). See API Versioning.
Build System Compatibility
The stable ABI policy concerning properties of the build system is mostly the same as that for the public API (see API Build System Compatibility) with the following differences:
Instead of properties that directly impact the public API, properties that directly impact the stable ABI are considered part of the stable ABI.
The soname is considered part of the stable ABI. This means, in contrast to the public API,
BSONCXX_OUTPUT_NAME
is considered part of the stable ABI, as it directly impacts the soname of the resulting bsoncxx shared library.The "soname" is not applicable on Windows. See Shared Libraries (MSVC Only).
Note
We support the stability of the stable API per build configuration. We
do not support compatibility of the stable API across different build
configurations. For example, a shared library generated with
BSONCXX_OUTPUT_NAME=bsoncxx
is not expected to be compatible with a
program compiled against a stable ABI produced using a build configuration
with BSONCXX_OUTPUT_NAME=bsoncxx-custom-basename
. (This is particularly
important when using multi-config generators such as Visual Studio!)
Root Namespace Redeclarations
The root namespace provides "redeclarations" of entities declared in an ABI namespace. The ABI namespace may differ across entities being redeclared.
For example, all of the following redeclarations may be present simultaneously:
bsoncxx::example::foo
-->bsoncxx::v_noabi::example::foo
bsoncxx::example::bar
-->bsoncxx::v1::example::bar
bsoncxx::example::baz
-->bsoncxx::v2::example::baz
Root namespace redeclarations are designed to allow for the addition of binary incompatible symbols in vB
without breaking binary compatibility of vA
symbols.
They facilitate the deprecation of stable ABI symbols while providing the opportunity for a clean transition from vA
to vB
without breaking binary compatibility.
They allow user code to opt into "redeclaration upgrades" that reduces required changes to source code when transitioning from vA
to vB
.
These redeclaration upgrades are intended to support a clean transition away from deprecated, to-be-removed ABI symbols across releases. Accordingly, users are encouraged to use the root namespace declarations by default to opt into these upgrades. However, users may need to use explicit ABI namespace qualifiers when referencing C++ Driver entities in their own stable ABIs depending on their own stability policy.
The following compatibility table describes when the API major version number or ABI version number must be bumped due to an incompatible change:
Change Type | Source Compatible | Binary Compatible |
Add a new | Yes | Yes |
Upgrade a redeclaration from | Maybe [1] | Yes |
Remove a | No | Maybe [2] |
Remove a | Maybe [2] | No |
[1] | A vB entity could be 100% source compatible with the vA API
despite requiring use of a new, incompatible stable ABI symbol. |
[2] | (1, 2) A stable ABI symbol could be removed from the public API (e.g. via documentation or removal from public headers) while still providing an exported symbol definition for backward compatibility. This is probably unlikely to happen, but if it does, it would be a rare case where the source and binary incompatible changes can be split into separate releases. |
Important
The integer used by an ABI namespace does NOT directly correspond to an ABI version number. The ABI version number is bumped whenever any binary incompatible change occurs, even when it is the removal of a single symbol from the stable ABI. An ABI version number bump from A
to B
does NOT imply the deprecation or removal of symbols declared in the ABI namespace vA
(if one exists).
Deprecation and Removal
The policy for deprecation and removal of symbols in the stable ABI is the same as that for the public API. For more information, see API Deprecation and Removal.
A release containing binary incompatible changes will bump the ABI version number rather than the API major version number. However, it is likely that when the ABI version number is bumped, the API major version number will also be bumped, as a binary incompatible change is likely to also be a source incompatible change.