ABI stands for Application Binary Interface. It defines how compiled programs interact with a shared library at runtime.
For cuVS, ABI stability means that an application built against one supported version of the cuVS C library can run with a compatible newer cuVS runtime without needing to be rebuilt.
For example:
ABI stability is different from API stability:
A source-compatible change may still break ABI if it changes the binary layout, symbol names, function signatures, or expected runtime behavior.
cuVS is used by downstream projects and language bindings such as Java, Rust, Go, and database integrations.
These users often want to build their application once and allow the final runtime environment to provide cuVS separately. Without ABI stability, downstream consumers may need to rebuild or repackage every time cuVS changes.
ABI stability enables this model:
This is especially important for database vendors and other software providers that do not want to vendor or bundle a private copy of cuVS with every release.
ABI stability helps provide:
A cuVS runtime is ABI-compatible with an application when both of the following are true:
Example compatibility matrix:
The cuVS C shared library follows this pattern:
For example:
Where:
The SONAME uses only the ABI major version:
Applications that dynamically load cuVS should load the ABI-major versioned name:
They should not load the fully specified file name:
Loading the ABI-major versioned name allows compatible ABI-minor updates to work without relinking or rebuilding the application.
The ABI stability guarantee applies to the public C ABI.
It applies to public C interface items that meet these conditions:
include/cuvs/.h header filesextern "C" blockThe guarantee covers public C functions, enums, and structs that are exposed through the stable C interface.
It does not generally apply to internal implementation details or to the general C++ implementation ABI.
Structs require special care.
A struct is only ABI-stable when it is allocated, initialized, or managed by ABI-stable cuVS functions. User code should not directly depend on the internal layout of cuVS structs.
Recommended pattern:
Avoid this pattern:
The second example is risky because it depends on struct layout. If cuVS later adds, removes, reorders, or changes fields, compiled applications may break.
When changing public C headers, assume that existing applications may already be compiled against the current ABI.
Use this rule of thumb:
The following changes are generally safe during ABI-compatible releases:
Example of a safe additive change:
The original function remains unchanged, so existing binaries continue to work.
Do not make these changes in ABI-compatible releases:
Example of an ABI break:
Even though the function name is the same, the binary signature changed.
If a function needs an incompatible signature, do not change the existing function directly.
Instead, add a new suffixed function.
Example:
The old function remains available for existing binaries. New applications can use the new suffixed function.
The old function should be documented as deprecated or superseded, and release notes should explain which replacement should be used.
cuVS has planned releases where ABI-breaking changes are allowed. These are the releases where accumulated compatibility work can be consolidated.
During normal ABI-compatible releases, developers may accumulate suffixed replacement APIs:
During an ABI-breaking release, the highest replacement can become the canonical unsuffixed API:
For example:
At that point, older variants can be removed because the ABI major version has changed.
When performing ABI consolidation during a planned ABI-breaking release:
Example transition:
Before modifying a public C header, ask:
include/cuvs/?extern "C"?Use this decision guide:
ABI stability lets applications built against one cuVS C library version run with compatible newer cuVS runtimes without being rebuilt.
Developers should preserve existing public C ABI symbols during ABI-compatible releases. Add new symbols instead of changing existing ones. When an incompatible change is required, introduce a suffixed replacement such as _v1, keep the old symbol available, and document the migration path.
During planned ABI-breaking releases, developers can consolidate these suffixed replacements by promoting the newest version to the canonical unsuffixed API, removing obsolete variants, and incrementing the ABI major version.