Contents
Testing package builds with mock
You have created a source RPM using either rpmbuild -bs
or fedpkg srpm
.
Now you are ready to try building the package. To do so, run this command:
mock -r fedora-rawhide-x86_64 --rebuild [name of src.rpm]
That will build the package for x86_64 Fedora Rawhide. Look in /etc/mock
for all of the architectures and distributions you can target. Each file
that ends with .cfg
defines a mock configuration. If you want to build
for an architecture that differs from the CPU in your computer (e.g., you want
to build an aarch64 package on an x86_64 computer), then you will need to
have the qemu-user-static
package installed. Alternatively, if you are a
member of the Fedora packager group, then you can build on test machines of
the architecture of interest: see
Test Machine Resources For Package Maintainers.
Chroots and mock configurations
Mock builds packages in what is known as a chrooted environment
(or just
chroot
for short). This means that the processes invoked as part of the
build see only a portion of the filesystem. For those processes, the root
directory /
is what you see as /var/lib/mock/[configuration]/root
. Mock
installs all of the packages that your package specifies as BuildRequires
into the chroot, then invokes rpmbuild -ba [package].spec
inside the chroot.
Build logs
Whether the package build succeeds or fails, look in
/var/lib/mock/[configuration]/result
for information about the build. This
directory contains several log files, including:
- root.log
- contains terminal output while installing BuildRequires
- build.log
- contains terminal output during the build
Both are useful for diagnosing build failures, and even for finding lurking
problems when a build succeeds. A successful build is analogous to successful
compilation of a program: it means that your spec file is syntactically
correct, but doesn’t mean that it actually functions as desired. When I build
packages with C or C++ source code, I like to run a shell script
~/bin/warnmock
with these contents:
#!/bin/sh
#
# Written by Jerry James <loganjerry@gmail.com>.
# Released under the Creative Commons CC0 license (effectively public domain).
# See https://creativecommons.org/share-your-work/public-domain/cc0/ for
# details.
: "${DISTRO:=fedora}"
: "${RELEASE:=rawhide}"
: "${ARCH:=x86_64}"
: "${MOCKDIR:=/var/lib/mock/$DISTRO-$RELEASE-$ARCH/result}"
sed -n 's/.*\[\(-W[^]]*\)\].*/\1/p' $MOCKDIR/build.log | sort | uniq
That produces a list of the compiler warnings issued during the build. Many
compiler warnings are innocuous, but warnings such as -Wformat
,
-Wnull-dereference
, -Wsequence-point
, and -Wstrict-aliasing
bear
investigation, as they may point to serious bugs in the software.
Local repository
When working with a set of dependent packages in mock, it is often useful to have a local repository to store the packages that have been built, to be used in future mock builds. There are many ways this could be done. I will describe the method I use.
In my home directory, I have a subdirectory named “yum” (named that way many years ago and never changed since dnf was released). That directory is the root of a tree that looks like this:
- yum
- 34
- source
- i386
- debuginfo
- Packages
- x86_64
- debuginfo
- Packages
- 35
- source
- i386
- debuginfo
- Packages
- x86_64
- debuginfo
- Packages
- 36
- source
- i386
- debuginfo
- Packages
- x86_64
- debuginfo
- Packages
- 34
Then I run the following series of commands (after installing the
createrepo_c
package):
createrepo_c -d ~/yum/34/source
createrepo_c -d ~/yum/34/i386/debuginfo
createrepo_c -d ~/yum/34/i386/Packages
createrepo_c -d ~/yum/34/x86_64/debuginfo
createrepo_c -d ~/yum/34/x86_64/Packages
createrepo_c -d ~/yum/35/source
createrepo_c -d ~/yum/35/i386/debuginfo
createrepo_c -d ~/yum/35/i386/Packages
createrepo_c -d ~/yum/35/x86_64/debuginfo
createrepo_c -d ~/yum/35/x86_64/Packages
createrepo_c -d ~/yum/36/source
createrepo_c -d ~/yum/36/i386/debuginfo
createrepo_c -d ~/yum/36/i386/Packages
createrepo_c -d ~/yum/36/x86_64/debuginfo
createrepo_c -d ~/yum/36/x86_64/Packages
Then I create mock configurations in ~/.config/mock
that reference my local
repositories and inherit from the system’s mock configurations. This is the
contents of ~/.config/mock/jerry-rawhide-x86_64.cfg
:
include('fedora-rawhide-x86_64.cfg')
config_opts['dnf.conf'] += """
[jerry]
name=jerry
baseurl=file:///home/jamesjer/yum/36/x86_64/Packages
enabled=1
skip_if_unavailable=True
"""
This is the contents of ~/.config/mock/jerry-35-x86_64.cfg
:
include('fedora-35-x86_64.cfg')
config_opts['dnf.conf'] += """
[jerry]
name=jerry
baseurl=file:///home/jamesjer/yum/35/x86_64/Packages
enabled=1
skip_if_unavailable=True
"""
See how that works? Each configuration file begins with an include
directive that gives me whatever the system mock configuration is for that
Fedora release and architecture, and I add my own repository (named “jerry”)
to it.
When I build a package in mock, if I build with mock -r jerry-rawhide-x86_64
[source RPM]
instead of mock -r fedora-rawhide-x86_64 [source RPM]
, then
the build is able to install RPMs from my local repository.
To easily move built RPMs from the mock results directory to my repository, I
have a script in ~/bin/mymock
that looks like this:
#!/bin/sh
#
# Update my personal mock repo
# Written by Jerry James <loganjerry@gmail.com>.
# Released under the Creative Commons CC0 license (effectively public domain).
# See https://creativecommons.org/share-your-work/public-domain/cc0/ for
# details.
: "${DISTRO:=fedora}"
: "${RELEASE:=rawhide}"
: "${ARCH:=x86_64}"
if [ "$RELEASE" = "rawhide" ]; then
RELEASEVER=36
else
RELEASEVER=$RELEASE
fi
REPODIR=/home/$USER/yum/$RELEASEVER
MOCKCFG=$DISTRO-$RELEASE-$ARCH
cp -p /var/lib/mock/$MOCKCFG/result/*.rpm $REPODIR/$ARCH/Packages
chgrp $USER $REPODIR/$ARCH/Packages/*.rpm
mv $REPODIR/$ARCH/Packages/*debuginfo* $REPODIR/$ARCH/debuginfo || :
mv $REPODIR/$ARCH/Packages/*debugsource* $REPODIR/$ARCH/debuginfo || :
mv $REPODIR/$ARCH/Packages/*.src.rpm $REPODIR/source
createrepo_c -d --update $REPODIR/$ARCH/Packages
createrepo_c -d --update $REPODIR/$ARCH/debuginfo
createrepo_c -d --update $REPODIR/source
exec mock -r $MOCKCFG --dnf-cmd clean metadata
By default, it assumes I built for fedora-rawhide-x86_64 (which, in fact,
accounts for the vast majority of the mock builds that I do), but I can
override that choice by invoking RELEASE=35 mymock
, for example. Doing so
copies the built artifacts into my repository and updates the repodata so that
those artifacts are ready to use in the next build.