Home > KDE, Kraft, Qt, Release > Learnings from Building an AppImage

Learnings from Building an AppImage

For some time I am offering an AppImage of Kraft to make installations for users as easy as possible. Unfortunately real linux packages are big effort for the variety of distributions, and having one way to rule them all seems very appealing.

My first AppImage versions were pretty faulty when looking into details. So I spent some time to improve it recently, with the great help of the friendly people from AppImage community.

Here is my little report about what I have learned. If there is something I can do better, please let me know (unless it is use $OTHERTOOL).

How to build an AppImage?

At first, it makes sense to build the AppImage automatically via Github Actions. GH Actions are powerful, and well integrated. I also looked into using the openSUSE Buildserver for that, which works, but Github Actions seemed easier.

I got convinced by @TheAssasin to use AppImageCraft to build the image. That simplifies the process significantly by hiding a lot of auto generating things under the hood. While that leads to very clean and short config files for the AppImage build, it is harder to deal with issues that might come up because things are covered.

If I would not have had help from the dev that I know personally, I probably would not have survived the process. Yet, AppImageCraft is an awesome utility, yet a bit better documentation would help a lot.

Python Components

Kraft has a few Python components that are called from Kraft to do specialized tasks that I did not want to reimplement in C++. For example, it uses the awesome tool weasyprint to generate PDF from html.

While the AppImage can call a weasyprint installation that is installed on the host system that is not a good solution as there is no way to control if the required tool is really installed. So bundled Python is needed with all the dependencies for the external deps.

To achieve that, there is a very useful linuxdeploy-plugin called conda that uses conda to install Python. It installs the required python libs via pip and make them available in the bundle. Very convenient.


To be a good citizen in the AppImage world, the app needs to be careful with pathes. When running in the AppImage, it is advisable to not use for example classes like QStandardPath directly or even worse hardcode paths that do any loading of files the app needs. Since the file tree of the AppImage is just mounted somewhere in the host system, the app needs to consider that it is not installed in standard locations.

A good rule of thumb when locating a file to load is to always check relative to the binary path first (ie. ../share/kraft/data/), and if that does not exist, continue to check the standard paths of the host system.

In Kraft there were already utility methods to adjust paths which I could simply extend to work fine in the AppImage. Still, that is kind of fiddly as there are more places to consider than one expects.

Locate translation files

Also a result of the challenge described before is that the app did not find the translation files to load in the filesystem of the AppImage. The translation system (KLocalizedString in Kraft) does obviously not check the correct path inside the AppImage mount.

Setting an additional relative path to look up translations at runtime fixes that problem.


Another issue that required quite some work were icons. Kraft used icons from the system theme quite a lot. As long these are installed, because the user has the same fitting desktop environment, that is not an issue, and icons are found.

However, if the icon theme is not installed, the app just lacks icons which make it bad looking or even hard to use.

That can be solved by using own icons as fallback in the app. For simplicity and consistency I switched to a complete set of own icons that are now coming with Kraft. They are bundled to the app with the Qt resource system now.

Dependencies to the Outside

Last but not least: When preparing an app for AppImage it needs to be checked if the app has binary dependencies that can (or should) not be packaged into the AppImage for efficiency reasons. Kraft for example uses Akonadi for contacts. With that users can use KAddressbook to manage addresses and Kraft uses the address lists via Akonadi. Life is too short for reinvention of an Addressbook.

Of course one could think of bundling the entire Akonadi and KAddressbook into the AppImage of Kraft. But that seems overkill, as that would mean bundling a lot of stuff, and would bring KDE users two instances of KAddressbook (the one from their desktop installation and the one from the AppImage). Seems not a good idea.

So this seems to be the only downside of the new Kraft AppImage now: It can not use the Akonadi based address management. To fix that, there needs to be a non binary dependant way. There could for example be a way to sync contacts to a local file system and let Kraft pick them up from there. That way, users could use the address management they want (also for example google) and Kraft could still pick addresses from there. That needs more thoughts.

The good news on this that Kraft is still fully functional as the Akonadi integration is great, but optional.


An AppImage seems to be a great way of distributing desktop applications, because there is only one build to run on all distributions. Well, fingers crossed…

However, building an AppImage that really works flawlessly is not a simple task, as this blog hopefully illustrates a bit.

One thing would have helped me: A simple option to understand when the app loads things from the host system, rather than from within the AppImage, for example as commnd line switch when running the AppImage. That would have eased the path adjustment development described above.

What is next in that area: User friendly updating of the AppImage and a solution to the address management problem.

All changes were merged in Kraft master today, the resulting AppImages can be found here.

Categories: KDE, Kraft, Qt, Release Tags: , , ,
  1. Noses.
    November 9, 2022 at 11:33

    But it is definitely working as expected with all supported databases. The only thing I still had to install were indirect dependencies for Weasyprint.

  1. No trackbacks yet.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: