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
(sudo) lbuild-11.1 foo.spec— build foo for 11.1 for the current arch (as obtained by `uname -m`)linux32 (sudo) lbuild-11.1 foo.spec(for 64-bit environments) — the linux32 wrapper causes the program personality to change to 32-bit, therefore building 32-bit packages.lbuild-sles11 ...— for example, SLES11 instead.
lbuild also accepts multiple .spec files as arguments, as well as .src.rpm files. It does however stop on the first error.
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.
jbuild-11.1 foo.spec bar.spec ...— remember again, sudo is implicitly called. Do not prefix jbuild with sudo.
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 || :;