Software development notes
by Andrew
A recent change to libpldm added three visibility
classes to control its Application Binary
Interface (ABI). The approach is fairly
crude but also fairly effective. As outlined, the primary motivation is to allow
us to fix (break) new Application Programmer Interfaces (APIs) without getting
hung up on existing users. The testing
ABI visibility class allows functions
to exist in the library but remain out of reach for general use until we’re
confident that their API is reasonable.
The existence of the stable
visibility class implies that we shouldn’t break
the existence or behaviour any of its functions. This promise is only as good as
our ability to measure it. The ideal measurement is that any stable API and ABI
breaks are detected by Continuous Integration (CI). To that end I integrated
support for abi-compliance-checker into the build
system.
However, this integration requires the existence of reference dumps against which CI will measure proposed patches. The existence of reference dumps implies we also need to maintain them as functions come and go across library releases. This post aims to outline exactly how and when we should go about updating these reference dumps.
We find the reference dumps under libpldm
’s abi/
directory, namespaced by
the host architecture1 and compiler:
$ git ls-files abi/
abi/aarch64/gcc.dump
abi/x86_64/gcc.dump
$
As we can see the dumps currently cover the library’s ABI as produced by GCC on
aarch64
and x86_64
. Support for aarch64
is required because that’s the
architecture of my current laptop. The x86_64
reference dump is captured
because the architecture is reasonably popular, but crucially, the dominant
architecture used by the project’s CI.
Setting the reference dumps aside, each build also generates its own ABI dump if
the abi-dumper
and abi-compliance-checker
tools are found2. These
per-build dumps are currently written out as current.dump
in the root of the
build directory. The role of
abi-compliance-checker
is to test current.dump
against the appropriate
reference dump for the build.
A corollary of this is that the reference dumps can be updated by copying a
build’s current.dump
into the appropriate location under the abi/
directory.
However, before you copy that file, several details must be checked:
If you are unsure, these details are summarised in the meson
output:
$ meson setup -Dabi=deprecated,stable builds/aarch64/stable
...
C compiler for the host machine: ccache cc (gcc 13.1.1 "cc (GCC) 13.1.1 20230614 (Red Hat 13.1.1-4)")
...
C++ compiler for the host machine: ccache c++ (gcc 13.1.1 "c++ (GCC) 13.1.1 20230614 (Red Hat 13.1.1-4)")
...
Host machine cpu family: aarch64
Host machine cpu: aarch64
...
User defined options
abi : deprecated,stable
...
A critical issue is that any need to update a reference dump requires that all
reference dumps be updated. Further, it may be the case that you do not have
access to machines to cover all of the relevant host architectures. For
Debian-derived distributions you can set yourself up with the multiarch
instructions. Fedora is a bit more of a challenge,
however I’ve covered one possible approach if it is
your distro of choice. From there it’s a matter of choosing a build directory
naming scheme such as builds/${arch}/${compiler}
to keep your build
configurations separate4:
$ meson setup -Dabi=deprecated,stable --cross-file=... builds/${arch}/${compiler}
$ meson compile -C builds/${arch}/${compiler}
And once the build completes:
$ cp builds/${arch}/${compiler}/current.dump abi/${arch}/${compiler}.dump
Currently there are three circumstances:
deprecated
visibility class6The ABI dumps capture the library version in their metadata. This drives the need to update the dumps whenever a new release tag is created.
Stabilising a function is the explicit promise not to break its API or ABI going forward. It is thus criticial that it be integrated into the reference dumps so this promise can be upheld by CI.
Finally, once a function is deleted there’s no need to continue carrying its description in the reference dumps.
And with that, hopefully the lifecycle of the reference dumps is now clear!
In the sense of GCC’s configure terms ↩ ↩2
Under Linux they can both be installed through the system’s package
manager, e.g. with sudo dnf install abi-dumper abi-compliance-checker
or
sudo apt install abi-dumper abi-compliance-checker
. ↩
i.e. meson setup -Dabi=deprecated,stable ...
↩
Again, for a short intro to meson’s cross-files see my post covering cross-architecture work on Fedora ↩
That is, moving a function from the testing
visibility class to the
stable
visibility class by changing its visibility annotation from
LIBPLDM_ABI_TESTING
to LIBPLDM_ABI_STABLE
↩
Note that functions must never be deleted directly from the stable
visibility class. ↩