UBports Robot Logo UBports Forum
    • Categories
    • Recent
    • Tags
    • Popular
    • Users
    • Groups
    • Search
    • Register
    • Login

    App developers' guide to publishing applications for Ubuntu Touch 24.04-1.x

    Scheduled Pinned until 12/09/2028, 20:51 Locked Moved App Development
    1 Posts 1 Posters 206 Views 2 Watching
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
      Reply
      • Reply as topic
      Log in to reply
      This topic has been deleted. Only users with topic management privileges can see it.
      • peat_psuwitP Offline
        peat_psuwit
        last edited by

        With Ubuntu Touch 24.04-1.0 nearing release, many app developers will probably want to make sure their applications are available after the users upgrade their phone. This post will answer a number of questions you might have in mind.

        Before we continue: version terminology

        Throughout this post, I may use 24.04-1.x and 24.04-1.0 interchangeably. Technically, 24.04-1.x is a series which represent 24.04-1.0, 24.04-1.1, 24.04-1.2 etc, while 24.04-1.0 is a specific version from the series. However, we intends to maintain application compatibility across all minor versions throughout 24.04-1.x series. So, from app developers perspective, what is true for 24.04-1.0 should be true for the entire 24.04-1.x series as well.

        I will indicate if I say something that is applicable for 24.04-1.0 but not for the rest of the series.

        Do I have to re-build my application against Ubuntu Touch 24.04-1.x?

        Surprisingly, the answer is complicated. At the most basic level, applications built against Ubuntu Touch 20.04 will still be downloadable on OpenStore for 24.04-1.x users, and applications that has already been installed will still be available on users' devices. However, depends on how the application is built, it might run fine on Ubuntu Touch 24.04-1.x, or it might outright crash from the beginning.

        The best way to answer this is to install Ubuntu Touch 24.04-1.0 RC 1 on one of your phone and then try to run your app on it. But the following are rules-of-thumb:

        • If your application is completely QML-only: most likely, your application will just run fine on Ubuntu Touch 24.04-1.x. However, you may still have to slightly modify the code to stop using unsupported types. For example, if you use Lomiri.OnlineAccounts 0.1, you'll have to change that to SSO.OnlineAccounts 0.1 since the former is not supposed to be used, even on 20.04.
        • If your application contains C or C++ code: now it depends on what library you're using:
          • If your app uses only Qt libraries (such as libQt5Core, libQt5Gui, libQt5Quick etc.), then your application should run fine, unless you use private symbols for them. [^1]
          • If your app uses other libraries, then we can't really say for sure if your application will work as-is; you'll have to test your application to be sure. In general, if your library's API/ABI is stable and used outside of Ubuntu Touch ecosystem (e.g. GLib), then chances are it'll work. But if you use some lesser-known one, then it's more likely that it won't.
          • The following non-exhaustive list of libraries lists libraries known to have API/ABI changed between 20.04 and 24.04-1.x and requires rebuild:
            • libssl1 (from OpenSSL)
            • Boost (if you use non-header-only parts; see here)
            • ICU (libicu*.so)
            • libtiff, libwebp
        • If your application is written in Rust or Go and you use Qt or QML, then you'll almost certainly have to rebuild your application. This is because the integration between Rust/Go and Qt uses Qt's private symbols which have changed between Qt 5.12 (20.04) and 5.15 (24.04-1.x).

        Note: if you intends to support armhf architecture (32-bit ARM), you'll have always have to recompile your application, as armhf binaries built against 20.04 will not run on 24.04-1.x. This is due to Ubuntu and Debian's 64-bit time_t transition. Note that there's currently no supported Ubuntu Touch devices with armhf architecture.

        [^1]: Ideally, the sdk-libs and sdk-libs-dev seeds should defines what is stable for applications to consume. In practice, this list is poorly maintained and most people don't think about this when writing their applications. There are things that we should not promise, and there are things that we should have promised, but doesn't. So for now this list is advisory. Also so see Canonical-era wiki page about Click frameworks.

        How do I build my applications against Ubuntu Touch 24.04-1.x?

        The steps are:

        1. Make sure you run Clickable version 8.4.0 or later, which include necessary fixes for uploading applications built against 24.04-1.x to OpenStore.
        2. In clickable.yaml, specify ubuntu-touch-24.04-1.x as the framework:
        framework: ubuntu-touch-24.04-1.x
        

        Alternatively, specify framework using CLICKABLE_FRAMEWORK environment variable (useful for dual-building against both 20.04 and 24.04-1.x, see below).

        export CLICKABLE_FRAMEWORK='ubuntu-touch-24.04-1.x'
        
        1. In your manifest.json, make sure to specify framework as "@CLICK_FRAMEWORK@". Most applications is probably doing this already, but it's worth checking to be sure.
            "framework": "@CLICK_FRAMEWORK@",
        
        1. In your AppArmor manifest file(s), specify policy_version as "@APPARMOR_POLICY@". This allows Clickable to fill in the correct AppArmor policy version corresponding to the Click framework. If you have multiple AppArmor manifiest files (e.g. for your main application and your push helper), make sure to update all of them.
            "policy_version": "@APPARMOR_POLICY@"
        
        1. Run clickable build as usual. Now the application should be built against Ubuntu Touch 24.04-1.x.

        Note that applications built against 24.04-1.x will not run on 20.04 devices. In fact, the device will outright refuse to install your Click. This is intended; your application might call APIs that has been added in between versions, so we prevent this to avoid surprises.

        If I upload applications built against 24.04-1.x to OpenStore, will it be offered to devices running 20.04?

        No. OpenStore will offer the latest version which is still compatible with a particular device. For example, if you uploaded version 1.2.2 built against 20.04, then subsequently upload version 1.3.0 built against 24.04-1.x, devices running 20.04 will receive version 1.2.2, while 24.04-1.x devices will receive version 1.3.0.

        I want to provide updates for my app to 20.04 devices after I upload a new version for 24.04-1.x. Can I do that?

        Yes. OpenStore has been updated to accept a new Click which is older than the current version, as long as the Click's framework is different. Using the previous example again, if you uploaded version 1.2.2 built against 20.04 then subsequently upload version 1.3.0 built against 24.04-1.x, you can then upload version 1.2.3 built against 20.04 and 20.04 devices will receive this update. At the same time, 1.3.0 will continue to be provided to 24.04-1.x users.

        I want to provide the same versions but built against both 20.04 and 24.04-1.x. Can I do that?

        Yes, with one caveat: your built Clicks must have unique versions.

        Wait, that's a "no", isn't it?

        Well, indeed. But here's the technique: with some configurations, you can build your application twice using the same code, and still get a different versions out of it. Here's the way I do it:

        • Make manifest.json a "build-time configured file". Then, add a build-time flag to define a suffix to the version of the Click.
        • In your build scripts/CI configuration, build your app twice, varying CLICKABLE_FRAMEWORK. This might be multiplied by architectures, so in practice you might build your apps 6 times.
        • In clickable.yaml, set the Click's version suffix based on the ${SDK_FRAMEWORK} environment variable, which Clickable will set to the framework you defined earlier. Note that shell's command substitution/variable expansion is available for you, so you can modify this variable further.
        • Make sure you leave "framework" in manifest.json as "@CLICK_FRAMEWORK@", and your "policy_version" in AppArmor manifest(s) as "@APPARMOR_POLICY@". This allows Clickable to fill in the appropriate values.

        For a concrete example, see this lomiri-calendar-app MR.

        Fun fact: Click package's version is not limited to just "major.minor.patch" format. Rather, it allows a full range of Debian package's version, including alphanumeric, ~, + and -. So you can include them in the version to help distinguish Git builds, Ubuntu Touch versions, and more.

        My app currently doesn't build against 24.04-1.x. The version built against 20.04 doesn't start on 24.04-1.x due to missing libraries. I'm currently short on time. Is there a workaround?

        There is one, indeed. Clickable has a feature to include libraries from the build environment into your Click (similar to Snapcraft's parts.<part-name>.stage). To do so, add the library names in the install-lib key of clickable.yml.

        install_lib:
        - libasound.so*
        

        When your application is launched, system will make sure that your Click's library is added into LD_LIBRARY_PATH environment variable, which will make your app look into your Click first for any library it wants.

        Note, however, that if you do this, you will want to make sure that the library you included is not actually depended on by one of the system library but under a different "soversion" [^2]. This is because 2 different soversions of the same library can have the same symbols; in that case, it's not guaranteed which version of the symbol will be used, and the behavior will be undefined [^3].

        One way to check this is to install your Click on a 24.04-1.x device, then run:

        LD_LIBRARY_PATH=/opt/click.ubuntu.com/<Click id>/current/lib/* \
          ldd /opt/click.ubuntu.com/<Click id>/current/<your app binary> | less
        

        Then, inspect the output to make sure the same library with different "soversion" does not appear twice e.g. make sure libwebp.so.6 and libwebp.so.7 does not appear together.

        (The exception to this rule is libicu*.so; ICU allows linking multiple versions of itself into one process by make sure all symbols have the version number appended. See ICU4C documentation.)

        [^2]: "soversion" is the first version number after .so in the file name. For example, if a library has a file name libcurl.so.4, its "soversion" is 4.
        [^3]: my understanding of the Click framework contract is that, if a library does not appear in sdk-libs or sdk-libs-dev, then you're supposed to bundle it in the Click package. However, due to this "soversion" clashing issue, I'm not sure this is the right approach to this problem...


        I hope this post answers some of your questions and ease a migration of your apps to 24.04-1.x. If you have any question, feel free to leave a reply to this post and I'll try to answer them as best as I can.

        1 Reply Last reply Reply Quote 6
        • arubislanderA arubislander pinned this topic
        • arubislanderA arubislander pinned this topic
        • arubislanderA arubislander pinned this topic
        • arubislanderA arubislander pinned this topic
        • arubislanderA arubislander pinned this topic
        • First post
          Last post