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
- 41
- source
- i386
- debuginfo
- Packages
- x86_64
- debuginfo
- Packages
- 42
- source
- i386
- debuginfo
- Packages
- x86_64
- debuginfo
- Packages
- 43
- source
- i386
- debuginfo
- Packages
- x86_64
- debuginfo
- Packages
- 41
Then I run the following series of commands (after installing the
createrepo_c package):
createrepo_c -d ~/yum/41/source
createrepo_c -d ~/yum/41/i386/debuginfo
createrepo_c -d ~/yum/41/i386/Packages
createrepo_c -d ~/yum/41/x86_64/debuginfo
createrepo_c -d ~/yum/41/x86_64/Packages
createrepo_c -d ~/yum/42/source
createrepo_c -d ~/yum/42/i386/debuginfo
createrepo_c -d ~/yum/42/i386/Packages
createrepo_c -d ~/yum/42/x86_64/debuginfo
createrepo_c -d ~/yum/42/x86_64/Packages
createrepo_c -d ~/yum/43/source
createrepo_c -d ~/yum/43/i386/debuginfo
createrepo_c -d ~/yum/43/i386/Packages
createrepo_c -d ~/yum/43/x86_64/debuginfo
createrepo_c -d ~/yum/43/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/44/x86_64/Packages
enabled=1
skip_if_unavailable=True
"""
This is the contents of ~/.config/mock/jerry-42-x86_64.cfg:
include('fedora-42-x86_64.cfg')
config_opts['dnf.conf'] += """
[jerry]
name=jerry
baseurl=file:///home/jamesjer/yum/42/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 [ "$ARCH" = "i386" ]; then
DNFARCH="i686"
else
DNFARCH="$ARCH"
fi
if [ "$RELEASE" = "rawhide" ]; then
RELEASEVER=44
else
RELEASEVER=$RELEASE
fi
REPODIR=/home/$USER/yum/$RELEASEVER
MOCKCFG=$DISTRO-$RELEASE-$ARCH
MOCKDIR=$DISTRO-$RELEASE-$DNFARCH
cp -p /var/lib/mock/$MOCKDIR/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 --update $REPODIR/$ARCH/Packages
createrepo_c --update $REPODIR/$ARCH/debuginfo
createrepo_c --update $REPODIR/source
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=42 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.