During this time, if a developer wants to distribute their application to GNU/Linux, they need to package it for Debian, Ubuntu, Fedora, Arch Linux, and other distributions. But that is not possible, too heavy and complicated for someone to package applications for more than one distribution. Therefore, FLOSS (upstream) application developers generally package for large distributions such as Debian. They gave away the distribution of other distributions to each of the downstream developers.
He was born in 2004 in the hands of Simon Peter (Probono). Initially it was named as a click before changing its name to PortableLinuxApps in 2011. This tool began to be named AppImage in 2013 and was released with the MIT license.
Even though it is old, AppImage tends to be less popular compared to Flatpak, because AppImage is only "marketed" by one developer and community that is not too big, different compared to Flatpak, whose spread is supported by large projects like Fedora and its community.
For me, AppImage is the most favorite packaging format. In the realm of portable packaging (one binary file can be run on all GNU/Linux distributions) you know. Try to compare it with two other software that offer the same solution, Snap and Flatpak. There is special software that needs to be installed if you want to run both based applications, snapd (snapd package on Ubuntu) and flatpak (flatpak package on Ubuntu).
The work flow is like this. If you want to install a Snap based package. Install snapd (default on Ubuntu) → find the desired package by snap find → install the application package with snap install → run it with a snap run ...
With Flatpak the workflow is like this. Install flatpak → add repository with flatpak remote-add ... → install the application package with the flatpak install ... → run it with the flatpak run ...
Is AppImage?
Simply download the AppImage file → add executable mode to the file with chmod + x ... → run it by double-clicking the file.
Because of that simplicity, I became interested in trying to package an application with AppImage.
Package Write.as as AppImage
I need to use any FLOSS application that doesn't have an AppImage package. Actually there are still many, but because I just wanted to learn, I chose an application that was not too large, and finally the decision fell on Writeas-GTK. Write.as is a blog writing platform while Writeas-GTK itself is a desktop application for writing and publishing posts on the platform.
Writeas-GTK only requires GTK + 3, gtksourceview, vala, and Writeas-CLI dependencies. Optional last dependency, installed if the user wants to publish his writing directly to the Write.as platform. Not installed is okay because the application can still be used to write offline.
There are five ways to package an application to AppImage:
Convert binary packages like DEB to AppImage
Using OBS (Open Build Service)
Bundling the results of the Travis CI build into AppImage
Running Linux is deployed if your application is Qt based
Use Electron-builder if your application is based on Electron
Make the AppDir directory manually
The first way is to use a .ymy file or recipe file that contains scripts to download binary files (for example DEB) from the distro repository, then run some installation commands (install ...). This recipe file can then be built into AppImage using the pkg2appimage tool. Until now, Writeas-GTK is only officially available in the elementaryOS repository. Because I don't know the details of the distribution's repository URL, I passed this method.
I don't consider the second and third ways. I want to immediately learn to package AppImage without the need to learn to package with OBS and build with Travis CI. I also passed the fourth and fifth method because Writeas-GTK is not an application based on Qt and Electron.
So true! Because the application I want to change to AppImage is not too complicated, I decided to manually create an AppDir directory.
Preparation
Before forming the AppImage package for Writeas-GTK, I will download the source code and compile it manually. What for? To ensure which libraries are needed, they will be added to the AppImage file.
[git clone https://github.com/writeas/writeas-gtk.git]
The Writeas-gt manual compilation requires meson, ninja, GTK + 3 development package, package development vala, and package development gtksourceview, so make sure all five are installed on the operating system. To resolve not finding meson.build files in the write-gtk / fonts / lora directory, we need to create the file there.
[cd writeas-gtk]
[touch fonts/lora/meson.build]
now we using meson and ninja
[meson build && cd build]
[ninja]
On the laptop I use, the compilation process is only brief. The compiled Writeas-gtk binary file will appear in the build / src directory with the name com.github.writeas.writeas-gtk.
Build AppImage
As I said earlier, I will build the AppImage package for Writeas-GTK manually using it - create an AppDir directory and insert the application's binary files and libraries there. AppDir is a directory whose contents will be compressed into an AppImage file.
Create an AppDir directory.
[mkdir writeas.AppDir]
The write.AppDir directory contains at least the AppRun file, .desktop, the .png icon file, the usr / bin directory that contains the application's binary file, and the usr / lib directory that contains application libs.
The following is the contents of the write.AppDir that I made
writeas.AppDir
├── AppRun
├── com.github.writeas.writeas-gtk.png
├── usr
│ ├── bin
│ │ ├── com.github.writeas.writeas-gtk
│ └── lib
│ ├── libX11.so.6
│ ├── libXcomposite.so.1
│ ├── libXcursor.so.1
│ ├── libXdamage.so.1
│ ├── libXext.so.6
│ ├── libXfixes.so.3
│ ├── libXi.so.6
│ ├── libXinerama.so.1
│ ├── libXrandr.so.2
│ ├── libXrender.so.1
│ ├── libatk-1.0.so.0
│ ├── libatk-bridge-2.0.so.0
│ ├── libatspi.so.0
│ ├── libdatrie.so.1
│ ├── libdbus-1.so.3
│ ├── libexpat.so.1
│ ├── libffi.so.6
│ ├── libfribidi.so.0
│ ├── libgbm.so.1
│ ├── libgdk-3.so.0
│ ├── libgdk_pixbuf-2.0.so.0
│ ├── libgio-2.0.so.0
│ ├── libglib-2.0.so.0
│ ├── libgmodule-2.0.so.0
│ ├── libgobject-2.0.so.0
│ ├── libgraphite2.so.3
│ ├── libgtk-3.so.0
│ ├── libgtksourceview-3.0.so.1
│ ├── libpangocairo-1.0.so.0
│ ├── libpixman-1.so.0
│ ├── libpng16.so.16
│ ├── libthai.so.0
│ ├── libuuid.so.1
│ ├── libwayland-client.so.0
│ ├── libwayland-cursor.so.0
│ ├── libwayland-egl.so.1
│ ├── libxcb-render.so.0
│ ├── libxcb-shm.so.0
│ ├── libxcb.so.1
│ └── libxkbcommon.so.0
└── writeas.desktop
AppRun is an executable script that sets environment variables and calls application files in the usr/bin directory. If you don't really understand how AppRun works, you can download the AppRun binary file through the AppImageKit release page. Because I will make AppImage Writeas-GTK for x86_64, then I download AppRun-x86_64
The com.github.writeas.writeas-gtk.png file is a file that I copied from the Writeas-GTK source directory.
[cp writeas-gtk/data/icons/128/com.github.writeas.writeas-gtk.png writeas.AppDir/]
The contents of the usr / bin directory are binary files from the Writeas-GTK manual compilation.
[cp writeas-gtk/build/src/com.github.writeas.writeas-gtk writeas.AppDir/usr/bin/]
The contents of the usr/lib directory are libraries used by Writeas-GTK. To choose this library it's really tricky (full of tricks). Lib or lib must be a library that is not native to the GNU/Linux distribution. How do we know if this library is a default distribution and that the library is a special library for running Writeas-GTK? We can do research through search engines. I need to fly to do this, I doubt if the library that I copy to the usr / lib directory is correct.
To see what libraries are needed by Writeas-GTK, we can use the ldd tool.
# ldd writeas-gtk/build/src/com.github.writeas.writeas-gtk
linux-vdso.so.1 (0x00007ffdb87ba000)
libgtk-3.so.0 => /usr/lib/libgtk-3.so.0 (0x00007fb5121e0000)
libgdk-3.so.0 => /usr/lib/libgdk-3.so.0 (0x00007fb5120e6000)
libgio-2.0.so.0 => /usr/lib/libgio-2.0.so.0 (0x00007fb511f42000)
libgobject-2.0.so.0 => /usr/lib/libgobject-2.0.so.0 (0x00007fb511eee000)
libglib-2.0.so.0 => /usr/lib/libglib-2.0.so.0 (0x00007fb511dd0000)
libgtksourceview-3.0.so.1 => not found
libc.so.6 => /usr/lib/libc.so.6 (0x00007fb511c0d000)
libgmodule-2.0.so.0 => /usr/lib/libgmodule-2.0.so.0 (0x00007fb511c07000)
libpangocairo-1.0.so.0 => /usr/lib/libpangocairo-1.0.so.0 (0x00007fb5119f9000)
libX11.so.6 => /usr/lib/libX11.so.6 (0x00007fb5118b8000)
libXi.so.6 => /usr/lib/libXi.so.6 (0x00007fb5116a7000)
libXfixes.so.3 => /usr/lib/libXfixes.so.3 (0x00007fb5114a1000)
libcairo-gobject.so.2 => /usr/lib/libcairo-gobject.so.2 (0x00007fb511296000)
libcairo.so.2 => /usr/lib/libcairo.so.2 (0x00007fb510f60000)
libgdk_pixbuf-2.0.so.0 => /usr/lib/libgdk_pixbuf-2.0.so.0 (0x00007fb510d3b000)
libatk-1.0.so.0 => /usr/lib/libatk-1.0.so.0 (0x00007fb510b15000)
libatk-bridge-2.0.so.0 => /usr/lib/libatk-bridge-2.0.so.0 (0x00007fb5108e2000)
libepoxy.so.0 => /usr/lib/libepoxy.so.0 (0x00007fb5105b4000)
libm.so.6 => /usr/lib/libm.so.6 (0x00007fb51042f000)
libharfbuzz.so.0 => /usr/lib/libharfbuzz.so.0 (0x00007fb51032f000)
libpangoft2-1.0.so.0 => /usr/lib/libpangoft2-1.0.so.0 (0x00007fb51011a000)
libpango-1.0.so.0 => /usr/lib/libpango-1.0.so.0 (0x00007fb50fed4000)
libfontconfig.so.1 => /usr/lib/libfontconfig.so.1 (0x00007fb50fc90000)
libfreetype.so.6 => /usr/lib/libfreetype.so.6 (0x00007fb50f9c8000)
libpthread.so.0 => /usr/lib/libpthread.so.0 (0x00007fb50f9a5000)
libXinerama.so.1 => /usr/lib/libXinerama.so.1 (0x00007fb50f7a2000)
libXrandr.so.2 => /usr/lib/libXrandr.so.2 (0x00007fb50f597000)
libXcursor.so.1 => /usr/lib/libXcursor.so.1 (0x00007fb50f38c000)
libXcomposite.so.1 => /usr/lib/libXcomposite.so.1 (0x00007fb50f189000)
libXdamage.so.1 => /usr/lib/libXdamage.so.1 (0x00007fb50ef86000)
libxkbcommon.so.0 => /usr/lib/libxkbcommon.so.0 (0x00007fb50ed44000)
libwayland-cursor.so.0 => /usr/lib/libwayland-cursor.so.0 (0x00007fb50eb3c000)
libwayland-egl.so.1 => /usr/lib/libwayland-egl.so.1 (0x00007fb50e93a000)
libwayland-client.so.0 => /usr/lib/libwayland-client.so.0 (0x00007fb50e72b000)
libXext.so.6 => /usr/lib/libXext.so.6 (0x00007fb50e519000)
librt.so.1 => /usr/lib/librt.so.1 (0x00007fb50e50f000)
libdl.so.2 => /usr/lib/libdl.so.2 (0x00007fb50e508000)
libpcre.so.1 => /usr/lib/libpcre.so.1 (0x00007fb50e293000)
libffi.so.6 => /usr/lib/libffi.so.6 (0x00007fb50e08a000)
libz.so.1 => /usr/lib/libz.so.1 (0x00007fb50de73000)
libresolv.so.2 => /usr/lib/libresolv.so.2 (0x00007fb50de59000)
libmount.so.1 => /usr/lib/libmount.so.1 (0x00007fb50ddfa000)
/lib/ld-linux-x86-64.so.2 (0x00007fb51294d000)
libxcb.so.1 => /usr/lib/libxcb.so.1 (0x00007fb50ddce000)
libpixman-1.so.0 => /usr/lib/libpixman-1.so.0 (0x00007fb50dd28000)
libEGL.so.1 => /usr/lib/libEGL.so.1 (0x00007fb50dcea000)
libpng16.so.16 => /usr/lib/libpng16.so.16 (0x00007fb50dcb5000)
libxcb-shm.so.0 => /usr/lib/libxcb-shm.so.0 (0x00007fb50dcb0000)
libxcb-render.so.0 => /usr/lib/libxcb-render.so.0 (0x00007fb50dca1000)
libXrender.so.1 => /usr/lib/libXrender.so.1 (0x00007fb50da95000)
libGL.so.1 => /usr/lib/libGL.so.1 (0x00007fb50da1f000)
libdbus-1.so.3 => /usr/lib/libdbus-1.so.3 (0x00007fb50d9cc000)
libatspi.so.0 => /usr/lib/libatspi.so.0 (0x00007fb50d79a000)
libgraphite2.so.3 => /usr/lib/libgraphite2.so.3 (0x00007fb50d772000)
libthai.so.0 => /usr/lib/libthai.so.0 (0x00007fb50d566000)
libfribidi.so.0 => /usr/lib/libfribidi.so.0 (0x00007fb50d349000)
libexpat.so.1 => /usr/lib/libexpat.so.1 (0x00007fb50d10f000)
libuuid.so.1 => /usr/lib/libuuid.so.1 (0x00007fb50d106000)
libbz2.so.1 => /usr/lib/libbz2.so.1 (0x00007fb50cef6000)
libblkid.so.1 => /usr/lib/libblkid.so.1 (0x00007fb50ce9f000)
libXau.so.6 => /usr/lib/libXau.so.6 (0x00007fb50cc9b000)
libXdmcp.so.6 => /usr/lib/libXdmcp.so.6 (0x00007fb50ca95000)
libgbm.so.1 => /usr/lib/libgbm.so.1 (0x00007fb50ca85000)
libglapi.so.0 => /usr/lib/libglapi.so.0 (0x00007fb50ca51000)
libX11-xcb.so.1 => /usr/lib/libX11-xcb.so.1 (0x00007fb50ca4c000)
libxcb-dri2.so.0 => /usr/lib/libxcb-dri2.so.0 (0x00007fb50ca43000)
libxcb-xfixes.so.0 => /usr/lib/libxcb-xfixes.so.0 (0x00007fb50ca39000)
libdrm.so.2 => /usr/lib/libdrm.so.2 (0x00007fb50ca25000)
libwayland-server.so.0 => /usr/lib/libwayland-server.so.0 (0x00007fb50c812000)
libxcb-dri3.so.0 => /usr/lib/libxcb-dri3.so.0 (0x00007fb50c80c000)
libxcb-present.so.0 => /usr/lib/libxcb-present.so.0 (0x00007fb50c807000)
libxcb-sync.so.1 => /usr/lib/libxcb-sync.so.1 (0x00007fb50c7fb000)
libxshmfence.so.1 => /usr/lib/libxshmfence.so.1 (0x00007fb50c5f8000)
libxcb-glx.so.0 => /usr/lib/libxcb-glx.so.0 (0x00007fb50c5db000)
libXxf86vm.so.1 => /usr/lib/libXxf86vm.so.1 (0x00007fb50c3d5000)
libdatrie.so.1 => /usr/lib/libdatrie.so.1 (0x00007fb50c1cd000)
To copy the libdatrie library, for example, to the AppDir usr / lib directory:
[cp /usr/lib/libdatrie.so.1 writeas.AppDir/usr/lib/]
The last is to create the Writeas-GTK .desktop file. I just copy this file from the source code directory.
[cp writeas-gtk/data/com.githup.writeas.writeas-gtk.desktop writeas.AppDir/]
The Final Result
Already sure enough about the contents of write.AppDir, I then download the appimagetool tool through the AppImageKit release page. Then bundle the directory into AppImage with the command,
[chmod +x appimagetool-x86_64.AppImage]
[./appimagetool-x86_64.AppImage -v writeas.AppDir/ writeas-x86_64.AppImage]
Time for Trial our job!
Add the executable mode at write-x86_64.AppImage, then run it.
[chmod +x writeas-x86_64.AppImage]
[./writeas-x86_64.AppImage]
To download the AppImage file above, please download via dropbox.
COMMENTS