spiegel-keyman/docs/core-api-verification.md
Eberhard Beilharz 612cd01743
maint(linux): allow to skip API check
This change adds an option to skip the API checks during a build.
This can be done by adding the trailer `Keyman-Api-Check: skip`
to the PR description.

Fixes: #10454
Test-bot: skip
Keyman-Api-Check: skip
2025-09-05 19:04:23 +02:00

147 lines
5.1 KiB
Markdown

# Keyman Core API verification
After the GHA Debian package build we verify that the API didn't change
without being documented in `linux/debian/libkeymancore.symbols`.
[Debian policy](https://www.debian.org/doc/debian-policy/ch-sharedlibs#run-time-shared-libraries)
mandates that the API version of a shared library gets changed when the shared
library ABI changes in a way that could break binaries linked against
older versions of the shared library. This means that the API version should
change any time an interface is removed from the shared library or the
signature of an interface changes.
## Format of the `libkeymancore.symbols` file
The format of the file is documented in the
[deb-src-symbols man page](https://www.man7.org/linux/man-pages/man5/deb-src-symbols.5.html).
The majority of the lines are API method names followed by the
Keyman version where that symbol got introduced. Note that the lines
have to begin with a space character.
Example:
```text
km_core_state_actions_get@Base 17.0.197
```
## What to do when the API verification check fails
If you change the API but forget to update the `.symbols` file or the
API version number, the API verfication step in the GitHub Action
Ubuntu packaging workflow will fail.
There are different reasons why the API verification step can fail:
### You added a new API method
If you added a new API method to Keyman Core but didn't update the
`libkeymancore.symbols` file, `dpkg-gensymbols` will output a diff
between the old and the new API. You can edit `libkeymancore.symbols`
and add the missing line(s) that the diff shows. Note that the version
number should be the Keyman version that is current when the PR gets
merged.
### `dpkg-gensymbols` complains about C++ symbols
Unfortunately, `dpkg-gensymbols` which processes `libkeymancore.symbols` doesn't
work particularly well with C++, so it might flag some C++ symbols even though
they aren't part of the API. This happens particularly with C++ template
instantiations.
To work around this, we list the C++ symbols as `optional` that get flagged:
```text
(c++|optional)"typeinfo name for std::codecvt_utf8_utf16<char16_t, 1114111ul, (std::codecvt_mode)0>@Base" 17.0.244
```
`dpkg-gensymbols` will report the mangled C++ name in the diff, e.g.
```text
+ _ZTSSt18codecvt_utf8_utf16IDsLm1114111ELSt12codecvt_mode0EE@Base 17.0.244
```
but for `libkeymancore.symbols` we need the demangled name. This can be
retrieved by running:
```bash
echo "_ZTSSt18codecvt_utf8_utf16IDsLm1114111ELSt12codecvt_mode0EE@Base" | c++filt
```
which will output the demangled name:
```text
typeinfo name for std::codecvt_utf8_utf16<char16_t, 1114111ul, (std::codecvt_mode)0>@Base
```
Add the full output in quotes to `libkeymancore.symbols`, preceded by
`(c++|optional)` and followed by the version number.
Note that here again a space at the beginning of the line is required.
### You added an old Keyman version number
The API verification will also fail if you add a new line to the
`libkeymancore.symbols` file but don't update the version number at the
end of the line to the current Keyman version. In this case simply
modify the version number to the value you find in `VERSION.md`.
### You forgot to update the API version number in the `.symbols` file
When you remove or modify existing lines in the `libkeymancore.symbols`
file, you'll have to update the API version number at the top of the file
(the "1" in `libkeymancore.so.1`).
### You forgot to update `CORE_API_VERSION.md`
When you remove or modify API methods, you'll also have to update
the API version number in `CORE_API_VERSION.md`. If the API version
numbers in `CORE_API_VERSION.md` and in `libkeymancore.symbols` don't
match the API verification will fail.
## Skipping the API check
Sometimes we have a PR that intentionally does not change the API version
number. To skip the API checks in this case, the trailer
```text
Keyman-Api-Check: skip
```
can be added to the PR description.
## How this works
`.github/workflows/api-verification.yml` contains a `Verify API` step
which will call `linux/scripts/deb-packaging.sh` with the `verify`
parameter. Before calling the script it will download and extract
the binary package artifacts.
`deb-packaging.sh` will call `dpkg-gensymbols` which will compare the
previous API with the current one. Then the script will run some
additional verifications:
- checks that the version number of inserted lines matches `VERSION.md`
- checks that the API version number in `libkeymancore.symbols` got
updated if necessary
- checks that `CORE_API_VERSION.md` got updated if necessary
`dpkg-gensymbols` will generate a new `symbols` file which the GHA
verification will archive.
Note that this `symbols` file can't be directly copied over
`libkeymancore.symbols` since it removes the C++ regex lines from the template.
### Running the API verification locally
It's possible to run the API verification locally. To do that, download
(or build) the binary package for at least one platform .
Then run
```bash
cd linux
dpkg -x libkeymancore*.deb /tmp
mkdir -p debian/tmp/DEBIAN
dpkg-gensymbols -v17.0.244 -plibkeymancore -e/tmp/usr/lib/x86_64-linux-gnu/libkeymancore.so* -c4
```