With the advent of desktop embedding for flutter, despite some of its shortcomings, this renowned and ever-evolving framework might turn into a popular tool for building desktop applications in the near future. In this regard, the fact that snap does not have a positive reputation among Linux users necessitates packaging flutter applications for different distros namely Debian-based and Red hat-based Linux distributions.
In this article, I will go through the process of building an RPM package for your flutter desktop application.
Building Flutter app for Linux
The first step is to build your application for the Linux platform using the command below in your project :
flutter build linux
Note: Building for each platform must be done in that specific platform, meaning that you cannot build for Linux on windows or vice versa. If you do not have a Linux OS, you could either use Docker, WSL, or a VM.
After the build process completes, you will notice that a build folder has been created in your project root. All the different builds for each platform will reside in this folder. Inside the build folder, there will be a folder called linux
and inside that, you will find a directory which its name corresponds to the architecture on which you got that build, e.g. x64
. Inside there, you can find a folder called bundle
which will be used for our rpm package. Copy this directory someplace else and rename it according to this semantic : name-version.
e.g. cool-app-1.0.0
For demonstration purposes, we will use cool-app as our application name throughout this guide.
Desktop Entry
Now you will need a desktop entry file (.desktop file). The OS uses this file to create the shortcut for your application so that you can search for it like any other application. For example, the reason why you can find Firefox in your Linux search menu is that there is a .desktop file that corresponds to Firefox and contains its metadata and resources like name, icon, type, etc.
For more information on desktop entry files, check out the arch wiki.
Now we will create a cool-app.desktop
file inside the cool-app-1.0.0
folder. The content of the file will look like the following :
[Desktop Entry]
Name=My Cool App
Comment=A cool app that does everything
Exec=/usr/bin/cool-app/cool-app
Icon=/usr/bin/cool-app/data/flutter_assets/assets/icon.svg
Terminal=false
Type=Application
Categories=Utility;
The Exec
parameter points to the path of our application’s executable. The executable file is the file with the same name as our application which was inside the bundle folder.
The Icon
parameter points to the path of the application icon. Inside my flutter project, I created the assets
folder and put the icon there. After the build, all flutter assets files will reside inside the flutter_assets
folder. You can find your icon based on your project structure and set the icon path accordingly. The only important point is that in the end, all the files that were inside the bundle folder will be copied to our binary base path (/usr/bin/cool-app)
.
RPath Issue
As of the time of writing this article, a problem exists with the Linux build process which results in the rpath of lib*_plugin.so
files pointing to the user’s build tree path. This mechanism will result in a build failure when trying to build the RPM file, we therefore need to resolve this issue before moving on to the next steps.
Make sure you have patchelf
installed and cd into the cool-app/lib
folder and run :
patchelf --print-rpath *
If any of the paths printed in the output points to a folder that exists in your user home directory, the rpath problem persists.
In order to resolve this issue, run the following command for any file which has an rpath pointing to a location in user home directory:
patchelf --set-rpath '$ORIGIN' <fileName>
Now if you run patchelf --print-rpath *
again, all files must point to $ORIGIN
.
RPMBuild Directory Structure
RpmBuild uses a standard directory structure to build rpm packages. In order to create these directories, run the following command in your home directory :
mkdir -p rpmbuild/{BUILD,RPMS,SOURCES,SPECS,SRPMS}
Now copy the cool-app-1.0.0
folder to ~/rpmbuild/SOURCES
and cd into the SOURCES
directory and run the following command :
tar --create --file cool-app-1.0.0.tar.gz cool-app-1.0.0
This compresses the folder into a tar.gz file which will be used by rpmbuild.
.spec File
The final step is to create a .spec file that contains the application metadata and build instructions.
Now we cd into ~/rpmbuild/SPECS
and create a new file called cool-app.spec
. The content of the file will look like the following :
Name: cool-app
Version: 1.0.0
Release: 1%{?dist}
Summary: Very cool app
BuildArch: x86_64
URL: https://github.com/CoolDev/cool-app
License: GPLv3
Source0: %{name}-%{version}.tar.gz
Requires: bash
%description
A very cool app that does everything
%prep
%setup -q
%install
rm -rf $RPM_BUILD_ROOT
mkdir -p $RPM_BUILD_ROOT/%{_bindir}/%{name}
cp %{name} $RPM_BUILD_ROOT/%{_bindir}/%{name}
cp -R lib $RPM_BUILD_ROOT/%{_bindir}/%{name}
cp -R data $RPM_BUILD_ROOT/%{_bindir}/%{name}
desktop-file-install %{name}.desktop
%clean
rm -rf $RPM_BUILD_ROOT
%files
%{_bindir}/%{name}
/usr/share/applications/
You can use this exact template and only change the Name,Version,Summery,Release,BuildArch,URL,License,%description
parameters and you will most likely be fine. However, I will go through and explain the %install
segment in case you need to change or add instructions according to your project requirements.
The commands specified in the %install
segment are used by rpm to install your package. The first two commands make sure to create the /usr/bin/cool-app
directory from scratch (recreating it if it already exists). The next three will copy your executable (cool-app), lib, and data directory to /usr/bin/cool-app
. The final command installs the .desktop file in the proper directory.
The %files
segment specifies the paths to which you wish to copy your files. If you need to copy an additional file somewhere else, specifying its command inside %install
doesn't suffice. You should also specify that path inside the %files
segment. Here we have used /usr/bin/cool-app
for our binary path and /usr/share/applications
for the .desktop file path.
Building the RPM package
Finally, to build your rpm package, run the following command :
rpmbuild -bb ~/rpmbuild/SPECS/cool-app.spec
RpmBuild will create the rpm package inside the ~/rpmbuild/RPMS
directory.