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

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.