This HOWTO last updated: 2008-12-03

Building packages with LBUILD

This howto concentrates on the lbuild package in my own repository, which contains patches for multi-user capable building. Minimum required version is lbuild-0.1_git200711191714-10.jen3.noarch.rpm (released 2008-12-03). No guarantee that lbuild packages not from me work.

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
~/lbuild-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 $hme/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:
%packager My Name <my-email@address.com>
%vendor My Name

You can also define %vendor, but that is 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.0, you will find the system-wide defaults for 11.0 packages (i.e. packages that you want to build for 11.0). They are:

add_sources="suse110u suse110"
url_suse110u="file:/ftp/suse/update/11.0"
url_suse110="file:/ftp/pub/opensuse/distribution/11.0/repo/oss"

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, because they are not supported by cpio, which lbuild uses for doing the first stage setup of the chroot.

If NFS is not an option for you, I suggest this shell script as a starting point. It uses rsync, so you are always up-to-date. For example, if you ran that script from within /home/lbuild-base, then the path you would have to specify in /etc/lbuild/dists/11.0 would have to be /home/lbuild-base/suse110 (if using the yast2 metadata) or /home/lbuild-base/suse110/suse (if using the repomd metadata) or or or — it depends on where the “common root” for metadata is. In Fedora for example, this common root is the directory in which the directory “repodata” is present. Please use yast metadata whenever possible.

Building a package from specfile

Since setting up the build environment (chroot), root privileges are required. As such, lbuild must be started as root. To support multiple build users, we need to know who the real 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. (That however does not mean that sudo is better than su—sudo always carries a security risk.)

Once you have sudo properly configured, run the build process. There are multiple ways to do this; we will see the latter method later again.

sudo lbuild-11.0 iptables.spec

sudo lbuild --dist=11.0-i386 --repo "" iptables.spec

When the build went well, the new files are in your output repository. Note that --repo "" does indeed take an empty argument (""), and --repo must come as the last option of all options.

Building a package from src.rpm

lbuild-11.0 foo.src.rpm

Adding a new distribution to build for - Example

Let's be unfaithful and take the opportunity to demonstrate how to build for another distribution or release. We begin by adding a new file at either /etc/lbuild/dists/fedora7 or ~/lbuild-config/dist-fedora7 with the following content:

repository="$hme/lbuild-output-fedora7"
url_repository="file:$repository"

add_sources="fedora7"
url_fedora7="file:/F/linux/fedora/linux/releases/7/Everything/i386/os"

You may want to add the symlinks fedora7-i386 and fedora7-x86_64 (or for user-specific configuration: dist-fedora7-i386 and dist-fedora7-x86_64) which point to the fedora7 file. This becomes important when building for multiple targets that share the same configuration but do need different chroot directories. (The name of the chroot directory is derived from the name, you will see use of --dist below.)

Next comes /usr/lib/lbuild/configs/fedora7.conf. This file must exist. (I have not worked on LBUILD that much yet to provide a user-specific "override-all" mode.) As we will soon see, this file is unlikely to remain empty.

Before doing that however, you will want to define a "Distribution" tag that will appear on all of the RPM packages generated for Fedora7. Put the following into either /usr/lib/lbuild/configs/fedora7.conf or ~/lbuild-config/fedora7.conf:

Macros:
%distribution Red-Hat (FC-7) (%_target_cpu)

(Strange as it seems, while the project changed their name from "Fedora Core" to "Fedora", they still use the "FC" keyword instead of "F". I did not make FC-7 up, this is how it is listed in the original Fedora7 RPM packages.)

Basically, this is all the boilerplate. That alone won't allow building, though. You need a list of packages that need to be preinstalled into the chroot to actually provide the basic utilities (bash, rpmbuild, and so on). This is distribution/release-specific and you have to find out unless someone already wrote it. (A fedora7.conf is provided with my variant of the lbuild package, should you be interested.) Said list(s) is/are then to be added to /usr/lib/lbuild/configs/fedora7.conf -- there is currently no way to put it into the user-specific location! Here is an excerpt of how it might look:

Preinstall: acl attr bash bzip2 bzip2-libs chkconfig coreutils db4
Preinstall: diffutils filesystem glibc grep libacl libattr
Preinstall: libgcc m4 ncurses pam
Preinstall: popt shadow-utils readline rpm rpm-libs sed tar zlib

Preinstall: beecrypt elfutils-libelf libselinux libsepol libstdc++ sqlite

And this is how you would start the build process then:

sudo lbuild --dist=fedora7-i386 --target=i586 --repo "" someprogram.spec

The use of --target=i586 is specific to the x86 version of Fedora7 and serves to create i586 optimized RPMs instead of the i386.rpm FC-7 default.

Multi-arch building

To actually cross-build for architectures, you should not use --target=, but the generic kernel personality wrapper. This is because by using --target only, `uname` would still return x86_64. This affects some RPM builds, for example kernel-source, whose helper binaries will be ELF-64 while the RPM is marked as i586 (= not good). The proper way is to use the linux32 (or linux64) personality changers:

linux32 lbuild-11.0 iptables.spec