uptane / aktualizr

C++ Uptane Client
Mozilla Public License 2.0
15 stars 14 forks source link

Use versioned SONAMEs in libaktualizr #113

Open charles2910 opened 1 week ago

charles2910 commented 1 week ago

Hi,

I'm packaging aktualizr (actually our fork toradex/aktualizr) for Toradex and noticed libaktualizr does not use versioned SONAMEs.

Using SONAME for managing ABI compatibility is very important because it allows other users to compile a binary against one version of the library and continue using it with newer versions of aktualizr while there isn't a SONAME bump which indicates binary incompatibility.

CMake supports declaring SONAME via https://cmake.org/cmake/help/v3.30/prop_tgt/SOVERSION.html#soversion and it should be bumped every time there are incompatible changes in public exposed structs or functions.

Some good documentation on the matter is available at https://tldp.org/HOWTO/Program-Library-HOWTO/shared-libraries.html

cajun-rat commented 1 week ago

Thank you for participating it is good to have you on board!

Fixing the SONAME is unfortunately the easy bit of the work to ensure ABI compatibility. In order to make it work we'd need to have set of APIs into Aktualizr that have stable ABIs. This is notoriously difficult in C++, and most projects seem to use a C API, which is easier to keep stable. We kinda have one in aktualizr-c but it isn't very complete and I'm not aware of any active users.

The problem is that designing APIs that are a) stable and b) can continue to be provided as Aktualizr is expanded is hard. At the very least you need tooling to detect ABI changes (RedHat have some) and a suite of regression tests, but the main problem giving low enough level access to allow library users to usefully expand Aktualizr without making the codebase impossible to improve.

None of this is impossible, but it comes at significant engineering cost that cannot be spent elsewhere. The alternative, as practised by the Linux Kernel and Google is 'Live At Head'. This is what we've done until now in Aktualizr. The idea is that if you want to add a new use case, then don't depend on us as a library, instead add it directly to the codebase and enable it via runtime configuration. This way your tests for your feature are run on every commit, and everyone can make refactorings across what would otherwise be a hard ABI boundary. That lower friction for improvements allows for a higher quality codebase overall.

That said, I'm not against someone looking after the C API or improving it. What it the high level goal that you're trying to achieve?