79230690

Date: 2024-11-27 14:31:15
Score: 0.5
Natty:
Report link

Final answer....

It turns out that one of my package dependencies (libpango, in my case) has a dependency on libicu, so I don't need to declare it in my package in order to get it installed. One could -- I suppose -- declare a dependency on libicu_dev as a last resort.

So the challenge then becomes how to dynamically load and use libicu. It's grim. All methods and classes have the major version number appened as a suffix via macro magic. So coll_open in source becomes coll_open_74 on Ubuntu 21.10, coll_open_72 on Ubuntu 21.04, coll_open_70 on Raspberry PI OS.

It might seem insane to try to dynamically load against a package that is absolutely determined to make every single update they release incompatible; but icu package documentation actually guarantees compatibility across major versions for "stable" apis, which are marked in the documentation as stable. All of the four functions I needed are stable APIs. So, as I read the documentation, this approach is explicitly supported.

So the recipe is:

  1. Convert your code to use ICU C Apis. C++ APIs are not stable and are impossible to dynamically load.

  2. Dynamically load libicui18n.so (which is symbolically linked to the actual major version implementation).

  3. Determine the major version number of the .so. A plausibly sensible approach would be to sequentially try to load an entry points until you find one that matches:

    int icuVersion = -1; for (int version = 70; version < 85; ++version) { // or for some arbitrary range. std::stringstream entryName = "coll_open_" << version; void * fn = dlsym(library_handle,entryName.str().c_str()); if (fn) {
    icuVersion = version; break; } } if (icuVersion == -1) { // ... decide how to handle not being able to use ICU. }

  4. Once the version has been identified, dynamically load the entry points you need, concatenating the major version suffix onto each symbol name.

  5. Provide fallback methods for collation (C.utf16 locale will have to do) in case anything goes wrong along the way.

I feel so dirty. But the alternative -- a .deb package for every version of every distro I want to support -- seems impossible.

Reasons:
  • Blacklisted phrase (0.5): I need
  • RegEx Blacklisted phrase (1): I want
  • Long answer (-1):
  • No code block (0.5):
  • Self-answer (0.5):
  • High reputation (-1):
Posted by: Robin Davies