AppImage Packaging
Introduction
An AppImage is yet another Linux package format, a 'bundle' of Linux files that tries to deliver an application's main binary and nearly all the associated files that it needs to run on a Linux system, all in one file. AppImage is completely open (unlike, perhaps Snaps) and does not have a centralised distribution system (unlike both Snaps and Flatpak). As a result, AppImages are easier to make and, from a user's point of view, perhaps not quite as 'safe'.
In practice, from a packager's perspective, in very simplistic terms, all an AppImage is, is a directory, structured like a Linux /usr directory but containing only the files needed to run the app. A bit of wrapping to ensure the bundled files, not locally available ones are used and the whole thing compressed. Fortunately, there are some tools to make assembling that directory easy and associated ones to wrap up and compress the directory. If your application can be built with a Makefile, its remarkably easy, even without the Makefile, not too bad at all.
Tools
linuxdeploy
Simple Example
Firstly, lets outline the really easy situation. Your gtk2 application already has an icon, a .desktop file and a Makefile. That Makefile can install your app and you set PREFIX to cause the install to put its file in a location of your choosing. Now, just a two step process -
$> make PREFIX="../AppDir/usr" appimage
$> linuxdeploy-x86_64.AppImage --appdir ../AppDir --output AppImage
- The first line uses your existing Makefile to build a 'fake' install of your app in ../AppDir.
- The second line asks linuxdeploy to have a look at your fake install and do what ever is necessary, it works out what extra libraries your app uses, copies them into your 'fake' install, checks for .desktop, icon etc. Adds the code to launch your app from within the AppImage. Then bundles them up, compresses the result.
On a good day, you will find that will make an AppImage, say, myapp-x86_64.AppImage, its already marked as executable so, run it -
$> ./myapp-x86_64.AppImage
Complications
Now, obviously, its not always that simple, probably never! So, what are the issues? One by one in no particular order -
A Makefile
You don't have a Makefile. OK, not a problem. The linuxdeploy command will create an AppDir for you with the right structure, you just need to put what files you have into it (in the right spots) and run linuxdeply again. You almost certainly want to script that, and maybe you need to consider making a Makefile too.
Desktop and AppStream Files
You don't have a .desktop or icon. Oh, come on, I know you have an icon, Lazarus creates one for you, might not be ideal but its somewhere to start. But really, you need at least a 48x48 .png in AppDir/usr/share/icon/hicolor/ with the same name as your application (plus the .png).
And you do need a .desktop file. linuxdeploy reads it for a number of things that must be present, it should provide, at least Name, Exec and Icon (minus the .png). See the freedesktop spec. Again, the desktop file could have the same name as your application plus .desktop but should, in all but the simplest cases, have a RDNS name, based on your web site is recommended. If you use github for example, the desktop file might be something like io.github.my_repo.my_app.appdate.xml - The desktop file must go in (AppDir)/usr/share/applications/
The AppStream stuff is more complicated. But fortunately optional ! But to later get AppStream working, you need to have used the RDNS desktop file naming approach. Worth considering early. The AppStream is a standard way to describe your app, eg, if it appears in a software repository. You will find linuxdeploy has a grizzle if you don't have a AppStream file. Incidentally, so does Debian but they give it a different name, replace "appdata" with "metainfo", sigh ...
Your app probably needs some other icon files, docs and other things, put them below the AppDir in the appropriate place.
GTK2 v Qt5 or Qt6 ?
Linuxdeploy takes some plugins, the most useful for us is the Qt one, same one for both Qt5 and Qt6. Download it from the same place as linuxdeploy add "--plugin qt" to your command line. That, at least was easy !
References
- https://github.com/linuxdeploy/
- https://github.com/linuxdeploy/linuxdeploy-plugin-qt
- https://docs.appimage.org/user-guide/troubleshooting/fuse.html
- https://github.com/AppImage/AppImageKit/wiki/FUSE
- https://github.com/tomboy-notes/tomboy-ng/blob/master/scripts/mkappimage.bash - an example script to build eg Qt5 and Qt5 FPC/Lazarus app.
appimagetool
Appimagetool is a basic tool to create AppImage packages from prepared AppDir directory with defined structure. This is a basic way how to create AppImages.
- GLIBC is not bundled by default and it is recommended to build AppImage on the oldest still supported Ubuntu LTS version.
- AppStream appdata file is optional.
Assume application name is App and AppImage packaging files are located in Packaging/AppImage subdirectory of the project.
- Create new build.sh script:
#!/bin/bash
lazbuild --build-mode=Release ../../App.lpi
install -Dm755 ../../App -t AppDir/usr/bin
install -Dm644 App.desktop AppDir/com.domain.App.desktop
install -Dm644 App.desktop AppDir/usr/share/applications/com.domain.App.desktop
install -Dm644 App.png AppDir/App.png
install -Dm644 App.png AppDir/usr/share/icons/hicolor/256x256/apps/com.domain.App.png
install -Dm644 ../../Languages/*.po -t AppDir/usr/share/App/Languages
install -Dm644 com.domain.App.appdata.xml -t AppDir/usr/share/metainfo
install -Dm755 AppRun -t AppDir
wget -nc https://github.com/AppImage/appimagetool/releases/download/continuous/appimagetool-x86_64.AppImage
chmod +x appimagetool-x86_64.AppImage
ARCH=x86_64 ./appimagetool-x86_64.AppImage AppDir App.AppImage
- Create new AppRun file:
#!/bin/bash
exec $APPDIR/usr/bin/App
- Run build script:
./build.sh
- Run generated AppImage:
./App.AppImage
References
External links
- AppImage homepage
- appimage.github.io - online catalogue of existing AppImages
- AppImageHub
- AppStream metadata documentation