I repeatedly see other people doing the mistake, so a little reminder doesn’t hurt.

  • API: Application Programming Interface
  • ABI: Application Binary Interface

The difference can be easily explained by knowing what to do for some code when the API or ABI breaks in a library that the code depends on:

  • If only the ABI breaks, then you just need to re-compile the code.
  • If the API breaks, you need to adapt the code.
  • When the code doesn’t compile anymore, you need to adapt it, so it’s both an API and ABI break.
  • When the code still compiles fine but you need to adapt it, it’s only an API break.

Example of an ABI break only: when the size of a public struct changes.

Example of an ABI and API break: when a function is renamed.

Example of an API break only: CSS in GTK+ 3.20, or when a function doesn’t do the same as what was documented before (in an incompatible way).

That’s it.

6 thoughts on “API vs ABI”

  1. “Example of an API break only: CSS in GTK+ 3.20, or when a function doesn’t do the same as what was documented before.”

    Er, surely this is an ABI break too?

    It’s an ABI break because compiling an app or dependent library against GTK 3.18, then upgrading 3.18 to 3.20 without recompiling that app, can result in breakage; it’s an API break because you may have to change the app’s source code to fix it.

    API-only breaks are quite rare, and mostly involve macros. One example is the removal of GTK_STOCK_CANCEL (and other macros like it) between GTK 2 and GTK 3: its old definition would be “baked in” to the GTK 2 app, but recompiling that same app with GTK 3 would fail, even if nothing else had incompatible changes.

  2. CSS in GTK+ 3.20 is an API break only because the binary interface didn’t break. For example gtk_css_provider_load_from_data() is still the same, it takes the same types of parameters and has still the same return type.

    An application with CSS as written for GTK+ 3.18, but that runs with GTK+ 3.20 will be broken, but at run-time. Not at compile time nor at link time. From the ABI point of view, everything is fine.

  3. In general, if updating a library causes an application (built against a previous version of the library) to crash or otherwise not work properly, that’s an ABI break. When a user’s application breaks, they don’t care about the details of the specific programming language or platform. A runtime break is a runtime break.

    Back when I was on the GNOME release team, I wrote up this as part of our module requirements:
    I don’t think they are really officially in effect any more.

    If the API/ABI in question is marked as unstable, then it’s the developer’s fault for using an unstable ABI, of course. I have no idea if that’s the case here. But breaking an unstable ABI is still breaking an ABI. Calling an behaviour break an API break instead doesn’t help.

    1. Wikipedia to the rescue:

      And also:
      (section 3, Maintaining APIs and ABIs)

      So, if a library changes the cos() implementation to return the sine, it’s not an ABI break. The ELF objects and the linker don’t care. But if in the previous version of the library, the cos() API documentation said that it returned the cosine, then that’s an API break.

      And as you said, API/ABI breaks are orthogonal to API/ABI stability guarantees.

Leave a Reply

Your email address will not be published. Required fields are marked *