Building packages

From SailfishOS Documentation

Building Packages

Packages may either be built locally (using mb2 or sb2 using the Platform SDK), or remotely (using the Mer OBS). Building locally has the advantage of being quick, simple, and low-latency. Building remotely has the advantage that build dependencies and other packaging requirements are enforced more strictly, and that upgrading packages built from OBS can be done via system upgrade rather than sideloaded via direct installation using `rpm`.


Building Packages Remotely

Packages may be built using the Open Build Service instance. This requires the user to create a home project, and then create a package under that project, with the appropriate `_service` file to specify how the project should be built and packaged. Once the build has been triggered, OBS will attempt to pull in the required dependencies and build the package.


See the page about deploying packages for information on how to install the package once built.

Building Packages Locally

Once the user has installed the Platform SDK and set up an SDK target, they can build packages locally for the target architecture using the build script called mb2 invoked from the Platform SDK. This script is a wrapper around ScratchBox2 (sb2) and rpmbuild which makes it simple to build packages from source repositories, given an RPM specification (.spec) file.


The mb2 script is invoked as follows to build a package:

mb2 -s <path/to/rpm.spec> -t <SDK_target> build

Note that the first two parameters are optional if there is only one single .spec file contained under the rpm/ subdirectory of the project.

For example, the following command will build most projects and package the results into an .rpm ready for installation, when run from the Platform SDK chroot prompt, within the project directory, assuming that an SDK target called "SailfishOS-armv7hl" has been installed:

mb2 -t SailfishOS-armv7hl build


The output .rpm files will be contained under the RPMS/ subdirectory of the project, and these may be installed to the device or SDK target as described in the page on deploying packages.


Installing Missing Dependencies

In some cases, the developer will have to add or enable repositories within their SDK target, if the mb2 script complains that a dependency cannot be installed. To do so, the user should enter ScratchBox2 within the SDK chroot environment, and then use:

ssu ar <repo_name> <repo_url>

to add repositories, and

ssu er <repo_name>

to enable repositories, and then

zypper ref -f

to update the installable package information. ssu lr may be used to list known repositories, and ssu rr <repo_name> will remove a repository.


Example:

# enter the Platform SDK chroot
~ $ /srv/mer/sdks/sdk/mer-sdk-chroot

# enter ScratchBox2 root shell in sdk-install mode
PlatformSDK ~ $ sb2 -t SailfishOS-armv7hl -m sdk-install -R

# enable the mer-core repository if not already enabled
[SB2 sdk-install SailfishOS-armv7hl] ~ # ssu er mer-core

# reload the package list
[SB2 sdk-install SailfishOS-armv7hl] ~ # zypper ref -f


To determine which repository provides a given package, a contributor should use the search feature of the Mer OBS instance, at https://build.merproject.org/search


It should be noted that device or hardware-platform-specific packages (especially those needed to build hybris-related packages) are best installed into a separate SDK target, to avoid complications. See Platform SDK Target Installation for more information on how to create new SDK targets.

Building Binaries Locally

In some cases, you will not want to build an entire package (.rpm) to install, but instead want to build a single binary from a simple (most likely Qt-based) project. This can be handy, for example, during testing or prototyping.


In this case, you simply need to build the project from within a build-mode ScratchBox2 prompt. For example, to build a simple Qt-based project (called "test", located under ~/test/ of the host) the following steps could be taken:

# enter the Platform SDK chroot
~ $ /srv/mer/sdks/sdk/mer-sdk-chroot

# enter ScratchBox2 shell in sdk-build mode
PlatformSDK ~ $ sb2 -t SailfishOS-armv7hl -m sdk-build

# run qmake && make from within sb2 build prompt
[SB2 sdk-build SailfishOS-armv7hl] ~ $ cd ~/test && qmake && make


The resulting ARMv7 binary can be copied to the device with scp and executed directly.

Packaging formats

tar_git packaging structure

Package in Sailfish OS are mostly packaged with format called tar_git. This format is relatively simple and as long as one follows some basic instructions tools like mb2 work nicely and if mb2 works then it is quite likely that also the package builds fine after integrating as part of the release process.

Some basic things to remember: the rpm .spec files are located in rpm/*.spec. There is no need to have .changes file, except for historical reasons, and in that case those are located in rpm/*.changes. Also all other files in rpm/ directory must be marked either with SourceX: or PatchX:.

tar_git package source code location in git

The sources are usually located either within the same git tree, in case the code upstream is Sailfish OS itself. It can be in the root of the git tree or src dir or something similar depending a bit on the package. Example of such package is for example mce at https://git.merproject.org/mer-core/mce/tree/master


If the package has upstream somewhere else and there are no heavy modification needed for the sources, the sources are usually located in directory named the same as the package Name: in .spec file. Example of such package crda at https://git.merproject.org/mer-core/crda/tree/master and usage instructions.


Then there is the third option where there are many modifications to the upstream that are not accepted as a part of the upstream (at least yet). In such cases there is submodule usually called upstream as well as directory matching to Name: in .spec that contains a copy of the upstream with the modifications. Example of such package e.g. connman at https://git.merproject.org/mer-core/connman/tree/master and usage instructions.


There can be also cases where there is no submodule located in the git tree, which usually is because upstream is either tarball, cvs or svn based and git submodule can not be done. TODO: add link to example of such package.

tar_git packages with patches

Some packages have patches but are not copied as separate tree from upstream, in such cases the patches are located in rpm/*.patch. Pulseaudio is an example of such package at https://git.merproject.org/mer-core/pulseaudio/tree/master


Those patches can be applied with mb2 apply to the submodule and can be unapplied with mb2 -R apply.

Dumb packages

This is obsolete format and is something that should not be used anymore and any packages using this should be converted to tar_git format explained above. These dumb packages are basically packages where the .spec file with tarball are located in the root of the git tree. Example of such packaging can be found at https://git.merproject.org/mer-core/libtalloc/tree/bb16d36c3aa6e85e4c75803beb076ae239fa428a


Such packages do not compile with the normal mb2 as the packages done with tar_git format, but these need to be build with more conventional tools, for example:
git clone https://git.merproject.org/mer-core/example-dumb-package.git
cd example-dumb-package
sb2 -t SailfishOS-armv7hl
rpmbuild --define "_topdir `pwd`" --define "_sourcedir `pwd`" -bb *.spec
instead of mb2 build.


Should be noted that when using rpmbuild you need to manually install also package build dependencies, where mb2 does that automatically.

Changelog generation

Changelogs are generated from git commits in tar_git packaged packages. Basically how it works is that each line that follows following format is added to the changelog:

[key] Summary. Contributes to xyz#123
[packaging] Updated Y to version X. Fixes xyz#124


NOTE: Run mb2 --help inside the SDK to learn how to generate changelogs when building a package with mb2 locally


This line does not need to be the first line in the git commit message and there can be multiple lines within one git commit message.


There are couple of ways to refer bugs in the git commit messages

Contributes to xyz#123 Means that this change contributes to the referred bug number, but does not fully fix it yet. This kind of lines are usually used when the required fixes to one bug are needed across multiple packages or for example the fix improves the issue, but there might still be some corner case that it might be reproduced.
Fixes xyz#124 Means that this change fixes the bug.


Currently known and accepted bug tags for the above xyz are:

MER For bugs at https://bugs.merproject.org/
NEMO For bugs at https://bugs.nemomobile.org/
JB For bugs in internal Jolla Bugzilla

These lines are picked to the changelog based on tags, meaning that between two tags all the lines that are following the format are picked up and added to the changelog.