Distribute your XULRunner app
2 - Linux
2.4 Package as rpm
- 2.4.1 Prerequisites
- 2.4.2 RPM files
- 2.4.3 Create the rpm
2.4.1 Prerequisites
In this part we will create a rpm package, for rpm based distributions, like Red Hat, Fedora, Suse,... (I have tested only with Fedora, please let me know if there's any problems for others).
We can create this rpm from other Linux distributions as well, Debian
based for example (that's what I do), we just need the
rpmbuild
executable, we have just to install
rpm
:
apt-get install rpm
Some documentation links:
- The RPM Guide from Fedora
- The Packaging:Guidelines in the Fedora wiki.
- and the Maximum RPM guide from rpm.org
- This pdf documentation from www.gurulabs.com is useful to understand the creation of rpm.
I suppose we don't have any needed compilation, but if you have some, simply do it before packaging (despite the fact this is not recommended in this guide).
2.4.2 RPM files
To build a rpm, we're supposed to setup a user configuration for all rpm creation. But it is possible to do it in a local folder, that's what we will do.
We need to create the following folders, and a
myapp.spec
file:
|- samples_chapter_2/ |- myapp/ |- rpmbuild/ |- BUILD/ |- RPMS/ |- SOURCES/ |- SPECS/ |- SRPMS/ |- myapp.spec
In fact this is the same structure than the required rpm environnement, but locally.
The .spec
file is the 'script' used by
rpmbuild to create the rpm. It is supposed to use a source tar.gz
archive, that we will build especially later.
Here's the content of our spec:
Name: myapp Version: 1.0 Release: 1%{?dist} Summary: simple Hello World powered by XULRunner. Group: Development/Tools License: MPLv1.1 or GPLv2+ or LGPLv2+ URL: http://example.com/myapp/ Source: myapp-1.0.tar.gz BuildArch: noarch BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id} -un) #BuildRequires: Requires: firefox >= 3.6 %description simple Hello World Powered by XULRunner. %prep %setup %build %install rm -rf %{buildroot} mkdir -p %{buildroot}%{_libdir} cp -R myapp %{buildroot}%{_libdir}/ mkdir -p %{buildroot}%{_bindir} ln -s %{_libdir}/myapp/myapp.sh %{buildroot}%{_bindir}/myapp mkdir -p %{buildroot}%{_datadir}/applications cp data/myapp.desktop %{buildroot}%{_datadir}/applications/ mkdir -p %{buildroot}%{_datadir}/icons/hicolor/16x16/apps cp data/icons/icon16.png \ %{buildroot}%{_datadir}/icons/hicolor/16x16/apps/myapp.png mkdir -p %{buildroot}%{_datadir}/icons/hicolor/22x22/apps cp data/icons/icon22.png \ %{buildroot}%{_datadir}/icons/hicolor/22x22/apps/myapp.png mkdir -p %{buildroot}%{_datadir}/icons/hicolor/32x32/apps cp data/icons/icon32.png \ %{buildroot}%{_datadir}/icons/hicolor/32x32/apps/myapp.png mkdir -p %{buildroot}%{_datadir}/icons/hicolor/48x48/apps cp data/icons/icon48.png \ %{buildroot}%{_datadir}/icons/hicolor/48x48/apps/myapp.png mkdir -p %{buildroot}%{_datadir}/icons/hicolor/scalable/apps cp data/icons/icon48.svg \ %{buildroot}%{_datadir}/icons/hicolor/scalable/apps/myapp.svg %post touch --no-create %{_datadir}/icons/hicolor &>/dev/null || : if [ -x %{_bindir}/gtk-update-icon-cache ]; then %{_bindir}/gtk-update-icon-cache -q %{_datadir}/icons/hicolor; fi %postun touch --no-create %{_datadir}/icons/hicolor &>/dev/null || : if [ -x %{_bindir}/gtk-update-icon-cache ]; then %{_bindir}/gtk-update-icon-cache -q %{_datadir}/icons/hicolor; fi %clean rm -rf $RPM_BUILD_ROOT %files %defattr(-,root,root,-) %{_bindir}/myapp %{_libdir}/myapp %{_datadir}/applications/myapp.desktop %{_datadir}/icons/hicolor/16x16/apps/myapp.png %{_datadir}/icons/hicolor/22x22/apps/myapp.png %{_datadir}/icons/hicolor/32x32/apps/myapp.png %{_datadir}/icons/hicolor/48x48/apps/myapp.png %{_datadir}/icons/hicolor/scalable/apps/myapp.svg #%doc %changelog * Fri Oct 8 2010 John Doe <johndoe@example.com> 1.0-1 - first publication
Let see in detail some entries of this file:
The Name
should not contain any whitespace characters.
The Version
must contain only number and
digit, no string like "beta".
The Group
entry must be chosen in the
list in the /usr/share/doc/rpm/GROUPS
file. You should have
it on your computer since you have installed rpm.
The Release
is the version of the rpm for
this version of the app, and %{?dist}
will be replaced by
rpmbuild by the current distribution. It will not be completed on a non
rpm distribution, you can remove it if you want.
For the License
entry, you must choose a short keyword
from this list.
The Source
entry must match exactly the tar.gz that we will create later.
The BuildArch: noarch
line specify that our
app is not architecture specific. If your app contains some compiled code,
you must remove this line, and a rpm specific to the current architecture
will be build.
The BuildRoot
value is a usual one.
The BuildRequires
is commented (with a
#
), as we have no compilations.
Finally, the
Requires
entry contains the other packages that are needed by our
app. You could add others, separated by comma (,
). Note that you
can't declare alternative dependencies like with deb. That's why we declare
Firefox and not XULRunner as dependencies, in the eventual case where the Firefox
of the distribution is not XULRunner based.
Later we will copy the tar.gz archive of our app into the SOURCES folder.
Then the
%prep
section and the %setup
instruction
will unpack it into the BUILD folder.
The %build
section is empty, because we have no compilation
to do.
In the %install
section, we install our app.
These are some shell commands, the current working directory is the unpacked
source tar.gz. %{buildroot}
is the root of the local
installation of our app, this will be the computer root /
in
the real installation.
%{_libdir}
, %{_bindir}
, and %{_datadir}
corresponds respectively to /usr/lib/
, /usr/bin/
,
and /usr/share/
. I guess that's the case for main rpm based distros,
If I'm wrong, please correct me, it means that some these variables
should be redefined.
So in this section, we re-create the initial buildroot folder.
Then we create the link to our launcher in /usr/bin/
,
copy our app in /usr/lib/
, and copy the desktop file and our icons
into the right location in /usr/share/
.
The %post
and %postun
sections declare some actions after that our app will be installed and uninstalled.
We update the icons database for the windows manager.
If the app handle some mime types, i.e. can open some type of files, this should be
specified in the .desktop file.
And you must add the following code in these
%post
and %postun
sections:
if [ -x /usr/bin/update-desktop-database ]; then update-desktop-database &> /dev/null || : fi
The %files
section is required, and contains the
complete list of files/folders installed by our app.
Finally, the format of the %changelog
section,
is described in this doc.
2.4.3 Create the rpm
So now that we have all that we need, we will create a script to create a fake source archive for rpmbuild, which contains our app, our desktop file, and our icons. We will place this archive in the SOURCES folder, then invoke rpmbuild locally with our spec file. And in fact, we will doing all of this in a temporary folder, to let our sources clean.
Note: rmpbuild
seems to bug if there's some whitespace in
the path of the working folder, so be careful with the name of the
(sub)directories where you place your sources.
The following script will abort if this is the case.
Here this script:
#!/bin/bash # exit the script on errors set -e TMP_DIR=./tmp SRC_VERSION=1.0 # get the absolute path of our TMP_DIR folder TMP_DIR=$(readlink -f -- "$TMP_DIR") # re-create the TMP_DIR folder rm -rfv "$TMP_DIR" mkdir -v "$TMP_DIR" # copy the rmpbuild tree folder cp -rv rpmbuild/* "$TMP_DIR/" # create a source tar.gz archive for rpmbuild into SOURCES mkdir -v "$TMP_DIR/myapp-$SRC_VERSION" cp -rv myapp "$TMP_DIR/myapp-$SRC_VERSION/" cp -rv data "$TMP_DIR/myapp-$SRC_VERSION/" cd "$TMP_DIR" # clean eventual tempory files find . -type f -name *.*~ -exec rm {} \; tar -zcvf "$TMP_DIR/SOURCES/myapp-$SRC_VERSION.tar.gz" \ "myapp-$SRC_VERSION" cd - rm -rv "$TMP_DIR/myapp-$SRC_VERSION" # rmpbuild seems to have a bug, it can't handle a _topdir with whitespace if [ -n "$(echo "$TMP_DIR" | grep '[ ]')" ]; then echo "the path '$TMP_DIR' contains whitespace, rpmbuild will failed. script aborted!" exit 1 fi # build the rpm from our spec, specify our local build tree rpmbuild --define="_topdir $TMP_DIR" -bb "$TMP_DIR/myapp.spec" # and finally copy our created rpm in to into the current folder cp -v "$TMP_DIR/RPMS/noarch/myapp-$SRC_VERSION-1.noarch.rpm" ./
To create our rpm, in a terminal:
cd samples_chapter_2
sh ./build_rpm.sh
And as result we have finally the file myapp-1.0-1.noarch.rpm
in the myapp-src folder :) .
You can download all the samples of this chapter 2 (Linux) in the samples_chapter_2.tar.gz archive.
The myapp application, from developer.mozilla.org is in the Public Domain.
The icon used is from the Tango Desktop Project, and is in the Public Domain.
All added data, and sample files, of this chapter 2, are in the Public Domain too.