Debian / Ubuntu packaging
Avalonia Linux programs can be executed in most Linux distros by double-clicking the executable or by starting it from the terminal. Nevertheless, for a better user experience, it is recommended to have the program installed, so the user can start it via desktop shortcut, that exists in desktop environments such as GNOME and KDE, or via command-line, by having the program added to PATH.
Debian and Ubuntu related distros have their applications packaged in .deb
files, that can be installed via sudo apt install ./your_package.deb
.
Tutorial
In this tutorial, we will use the dpkg-deb
tool to compile your .deb
package.
1) Organize program files in a staging folder
Debian packages follow this basic structure:
./staging_folder/
├── DEBIAN
│ └── control # package control file
└── usr
├── bin
│ └── myprogram # starter script
├── lib
│ └── myprogram
│ ├── libHarfBuzzSharp.so # Avalonia native library
│ ├── libSkiaSharp.so # Avalonia native library
│ ├── other_native_library_1.so
│ ├── myprogram_executable # main executable
│ ├── myprogram.dll
│ ├── my_other_dll.dll
│ ├── ... # all files from dotnet publish
└── share
├── applications
│ └── MyProgram.desktop # desktop shortcut file
├── icons
│ └── hicolor
│ ├── ... # other resolution icons (optional)
└── pixmaps
└── myprogram.png # main application icon
Meaning of each folder:
DEBIAN
: contains thecontrol
file./usr/bin/
: contains the starter script (recommended for starting your program via command-line)./usr/lib/myprogram/
: where all files generated bydotnet publish
go into./usr/share/applications/
: folder for the desktop shortcut./usr/share/pixmaps/
and/usr/share/icons/hicolor/**
: folders for application icons.
The /usr/share/icons/hicolor/**
are optional, as in your app icon will probably show up on desktop even without those images, however, it is recommended to have them for better resolution.
2) Make the control
file
The control
file goes inside the DEBIAN
folder.
This file describes general aspects of your program, such as its name, version, category, dependencies, maintainer, processor architecture and licenses. Debian docs have a more thorough description of all possible fields in the file.
Don't worry too much about filling all possible fields, most aren't required. This tutorial is to make a "good-enough" Debian package.
The .NET dependencies can be listed by running apt show dotnet-runtime-deps-8.0
(suffix changes for other .NET versions); they will appear on the line starting with Depends: .... You can also check them in the .NET Core repo.
Avalonia required dependencies are: libx11-6, libice6, libsm6, libfontconfig1
.
Overall, all .NET and Avalonia dependencies are required, plus any others specific of your app.
Below is a simple example of a control
file.
Package: myprogram
Version: 3.1.0
Section: devel
Priority: optional
Architecture: amd64
Installed-Size: 68279
Depends: libx11-6, libice6, libsm6, libfontconfig1, ca-certificates, tzdata, libc6, libgcc1 | libgcc-s1, libgssapi-krb5-2, libstdc++6, zlib1g, libssl1.0.0 | libssl1.0.2 | libssl1.1 | libssl3, libicu | libicu74 | libicu72 | libicu71 | libicu70 | libicu69 | libicu68 | libicu67 | libicu66 | libicu65 | libicu63 | libicu60 | libicu57 | libicu55 | libicu52
Maintainer: Ken Lee <kenlee@outlook.com>
Homepage: https://github.com/kenlee/myprogram
Description: This is MyProgram, great for doing X.
Copyright: 2022-2024 Ken Lee <kenlee@outlook.com>
3) Make the starter script
This step is recommended for two reasons: first, to reduce the complexity of the desktop shortcut, and second, to make your app runnable from Terminal.
The starter script file name should preferrably be myprogram
(without .sh
extension), so whenever your user types "myprogram" on the Terminal, he / she will start your program.
The myprogram_executable file usually has the same name as its .NET project, e.g., if your Avalonia .csproj project is named MyProgram.Desktop, then the main executable generated by dotnet publish will be MyProgram.Desktop
.
Example of starter script:
#!/bin/bash
# use exec to not have the wrapper script staying as a separate process
# "$@" to pass command line arguments to the app
exec /usr/lib/myprogram/myprogram_executable "$@"
4) Make the desktop shortcut
The desktop shortcut file follows the freedesktop specification. Arch Linux Wiki also has good related information.
Below is an example of a desktop shortcut file.
[Desktop Entry]
Name=MyProgram
Comment=MyProgram, great for doing X
Icon=myprogram
Exec=myprogram
StartupWMClass=myprogram
Terminal=false
Type=Application
Categories=Development
GenericName=MyProgram
Keywords=keyword1; keyword2; keyword3
If your app is supposed to open files, append %F at the end of the Exec line, after myprogram
; if it's supposed to open URLs, then append %U.
5) Add hicolor icons (optional)
Hicolor icons follow a folder structure like below.
This blog post advises us to put icons on both hicolor
and pixmaps
directories, according to Debian Menu System docs and FreeDesktop docs.
├── icons
│ └── hicolor
│ ├── 128x128
│ │ └── apps
│ │ └── myprogram.png
│ ├── 16x16
│ │ └── apps
│ │ └── myprogram.png
│ ├── 256x256
│ │ └── apps
│ │ └── myprogram.png
│ ├── 32x32
│ │ └── apps
│ │ └── myprogram.png
│ ├── 48x48
│ │ └── apps
│ │ └── myprogram.png
│ ├── 512x512
│ │ └── apps
│ │ └── myprogram.png
│ ├── 64x64
│ │ └── apps
│ │ └── myprogram.png
│ └── scalable
│ └── apps
│ └── myprogram.svg
6) Compile the .deb
package
# for x64 architectures, the suggested suffix is amd64.
dpkg-deb --root-owner-group --build ./staging_folder/ "./myprogram_${versionName}_amd64.deb"
Example of a Linux shell script for the entire process
#!/bin/bash
# Clean-up
rm -rf ./out/
rm -rf ./staging_folder/
# .NET publish
# self-contained is recommended, so final users won't need to install .NET
dotnet publish "./src/MyProgram.Desktop/MyProgram.Desktop.csproj" \
--verbosity quiet \
--nologo \
--configuration Release \
--self-contained true \
--runtime linux-x64 \
--output "./out/linux-x64"
# Staging directory
mkdir staging_folder
# Debian control file
mkdir ./staging_folder/DEBIAN
cp ./src/MyProgram.Desktop.Debian/control ./staging_folder/DEBIAN
# Starter script
mkdir ./staging_folder/usr
mkdir ./staging_folder/usr/bin
cp ./src/MyProgram.Desktop.Debian/myprogram.sh ./staging_folder/usr/bin/myprogram
chmod +x ./staging_folder/usr/bin/myprogram # set executable permissions to starter script
# Other files
mkdir ./staging_folder/usr/lib
mkdir ./staging_folder/usr/lib/myprogram
cp -f -a ./out/linux-x64/. ./staging_folder/usr/lib/myprogram/ # copies all files from publish dir
chmod -R a+rX ./staging_folder/usr/lib/myprogram/ # set read permissions to all files
chmod +x ./staging_folder/usr/lib/myprogram/myprogram_executable # set executable permissions to main executable
# Desktop shortcut
mkdir ./staging_folder/usr/share
mkdir ./staging_folder/usr/share/applications
cp ./src/MyProgram.Desktop.Debian/MyProgram.desktop ./staging_folder/usr/share/applications/MyProgram.desktop
# Desktop icon
# A 1024px x 1024px PNG, like VS Code uses for its icon
mkdir ./staging_folder/usr/share/pixmaps
cp ./src/MyProgram.Desktop.Debian/myprogram_icon_1024px.png ./staging_folder/usr/share/pixmaps/myprogram.png
# Hicolor icons
mkdir ./staging_folder/usr/share/icons
mkdir ./staging_folder/usr/share/icons/hicolor
mkdir ./staging_folder/usr/share/icons/hicolor/scalable
mkdir ./staging_folder/usr/share/icons/hicolor/scalable/apps
cp ./misc/myprogram_logo.svg ./staging_folder/usr/share/icons/hicolor/scalable/apps/myprogram.svg
# Make .deb file
dpkg-deb --root-owner-group --build ./staging_folder/ ./myprogram_3.1.0_amd64.deb
To install
sudo apt install ./myprogram_3.1.0_amd64.deb
To uninstall / remove
sudo apt remove myprogram