I announced libnbd yesterday. The libnbd 0.9.8 is a pre-release for the upcoming 1.0 where we will finalize the API and offer API and ABI stability.
Stable APIs aren’t in fashion these days, but they’re important because people who choose to use your platform for their software shouldn’t be screwed over and have to change their software every time you change your mind. In C it’s reasonably easy to offer a stable API while allowing long term evolution and even incompatible changes. This is what we do for nbdkit and will be doing for libnbd.
The first concept to get to know is ELF symbol versioning. Chapter 3 of Uli’s paper on the subject covers this in great detail. In libnbd all our initial symbols will be labelled with
The second concept is not as well known, but is used in glibc, nbdkit and elsewhere: Allowing callers to opt in to newer versions of the API. Let’s say we want to add a new parameter to
nbd_connect_uri. The current definition is:
int nbd_connect_uri (struct nbd_handle *h, const char *uri);
but we decide to add flags:
int nbd_connect_uri (struct nbd_handle *h, const char *uri, uint32_t flags);
You can cover up the ABI change with ELF symbol versions. However the API has still changed, and you’re forcing your callers to change their source code eventually. To prevent breaking the API, you can allow callers to opt in to the change by defining a new symbol:
#define LIBNBD_API_VERSION 2 #include <libnbd.h>
The definition is saying “I want to upgrade to the new version and I’ve made the required changes”, but crucially if the definition is missing or has an earlier version number then you continue to offer the earlier version, perhaps with a simple wrapper that calls the new version with a default flags value.
That’s what we intend to do with libnbd to offer a stable API and ABI (once 1.0 is released) without breaking callers either at the source or binary level.