Package building on OpenSUSE with lbuild-jplus

September 08, 2009

lbuild-jplus is the name for a August 2009 package of Novell's “build” tool, plus changes from Ludwig Nussel, plus my changes, which add per-user configuration files, additional build environment defaults, and other fixes.

This HOWTO does not apply to versions of "lbuild" I shipped; it is exclusively for "lbuild-jplus", currently lbuild-jplus-0.1_git20090823. The package is available in my repository.

Let's start with an overview of the paths that are used by default:

~/lbuild/output-* "output repository", where RPM packages that were just built are stored
/var/tmp/build-root.* build environment (chroot)
/etc/lbuild/dists_common system-wide build environment settings for all distribution releases
/etc/lbuild/dists/ system-wide build environment settings for specific distribution releases
/usr/lib/lbuild/configs/ system-wide rpm settings for specific distribution releases
~/lbuild/config/dists_common user-specific build environment settings for all distribution releases
~/lbuild/config/dist-* user-specific build environment settings for specific distribution release
~/lbuild/config/*.conf user-specific rpm settings (ONLY macros supported at this time!) for specific distribution releases.

As you will notice, the user-specific configuration directory carries both build environment and rpm setting files. An example how all of this comes together when you want to define a new release are described in a later section.

In /etc/lbuild/dists_common you can define the path to the user-specific configuration files, by default it is set to $HOME/lbuild/config, which is what is described above.

Identity

You should define an identity that is written to each RPM package so that people can identify packages more easily. Edit ~/lbuild/config/defaults.conf and add the following line, of course replacing it with your real name and an address that bug reports can be sent to:

macros:
%jobs 8
%packager My Name <my-email@address.com>
%vendor My Name

You can also define %vendor, but that is usually only useful for groups or companies. NOTE: %packager, %vendor, %distribution, Packager:, Vendor: and Distribution: SHOULD NEVER be defined in a specfile.

Repositories

Now it is time to define the repositories that should be used during build. Of course you will need base packages like aaa_base, glibc and so on! In case you do not have the luxury to access an FTP server over NFS, you will have to find other means to make binary packages required for building available to lbuild, among which there is the DVD, or downloading them. lbuild supports yast2, repomd and rpmdir (no metadata at all) repository types.

In /etc/lbuild/dists/11.1, you will find the system-wide defaults for 11.1 packages, i.e. packages that you want to build for 11.1. (Similarly, /etc/lbuild/dists/sles11 is for SLES11.) They are:

add_sources="update base jeng"
url_update="file:/ftp/suse/update/11.1"
url_base="file:/ftp/pub/opensuse/distribution/11.1/repo/oss"
url_jeng="file:/data/repository/jengelh"

You probably need to adjust the paths. http: or ftp: is not supported, but you could use something like davfs or ftpfs, but note that it would repeatedly transfer data when the chroot is prepared.

The priority of the sources is from left to right, and lbuild-output is implicitly added with the highest priority — so that just-built (binary) packages always take precedence (when initializing the chroot) over those from other sources. Such makes it possible, for example, to build an older kernel and all the KMPs to it without having to muck around with priorities. This however also means that you should always be aware of what is still lurking in ~/lbuild/output/ and that you eventually move it out.

There must be NO .patch.rpm or .delta.rpm files in the source trees. cpio, called from Lbuild, would only choke on them. If NFS is not an option for you, you will have to rsync, perhaps using this shell script of mine as a starting point. It uses rsync, so you are always up-to-date. Look through it before use.

Build permissions

lbuild-jplus inherits whatever code upstream lbuild contributed, and it seems to support building in various types of virtual machines (of which some can be started in unprivileged mode).

Though the script's source as picked up from Novell suggests that building inside a Qemu, UML or Xen instance is possible, this article only concentrates on chroot-based building. Since setting up a chroot build environment requires root privileges, lbuild must inherently be started as root. To support multiple build users, we need to know who the calling user is. When sudo is used, it sets the SUDO_USER environment variable which lbuild will use to put the files into the proper directories and not mix users' packages. su can unfortunately not be used because it does not set any such environment variable.

sudo therefore needs to be configured to accept you starting certain commands at least, listed below.

Builders

Deep down, it is just one script (/usr/lib/lbuild/build), but if it was called with an alternate name (by means of symlinks), its behavior changes a little. The following commands are the most common ones.

lbuild calls

jbuild calls

jbuild is a wrapper around sudo and lbuild that will call it multiple times in succession so as to build 32- and 64-bit packages (where possible) in one go. Furthermore, it builds as much as possible in one go, i.e. proceeding with building other specfiles when some fail. This may be a feature (when just-built packages do not depend on another), or something to watch out for. Adding the -z paramter to jbuild will make it stop on the first error, just like lbuild.

Extra notes: Packages creating user accounts

To have a package automatically create a user account, it can do so in the %pre section. This must usually be done in %pre because the package may install files that are to belong to the new user, therefore, %post would be too late. The result status of commands to add a user and/or group must be ignored for there may be two cases: 1. the user already exists, 2. a build environment where useradd cannot complete for whatever reason.

# from openssh
%pre
/usr/sbin/groupadd -g 65 -o -r sshd 2>/dev/null || :;