3 Building Non-Modular Source RPM Packages
This chapter describes how to build non-modular source RPM packages. Two methods are provided: the first is more direct and uses the rpmbuild utility directly; the second requires that you set up the mock utility and configure the system to process builds using this tool. There are several advantages to using the mock utility to build packages and you should consider using this tool if you intend to do mutliple or regular builds of different packages.
Using rpmbuild Directly
The simplest approach for building is to use the
rpmbuild --rebuild command to build a binary
RPM package directly from the source RPM package. This tool
takes the source RPM package and extracts it into a standard
hierarchy within ~/rpmbuild/
; the tool checks
that all of the build dependencies specified in the associated
SPEC file that is stored in ~/rpmbuild/SPECS
are satisfied; the source tarballs in
~/rpmbuild/SOURCES
are extracted into a build
directory, and are each built before being packaged into a
binary RPM package, which is stored in
~/rpmbuild/RPMS
.
Important:
Do not build source RPM packages as the
root
user. The build processes often run
scripts and processes that you may not have full control over
and that could easily cause system failure or could compromise
a system.
Note:
When using the rpmbuild tool to build source RPM packages directly, you may see warning messages similar to the following:
warning: user mockbuild does not exist - using root
These warnings can be ignored, as they are related to the way
these source packages are set up for build by using the
mock
utility within a more complex build
environment.
If the build dependencies that are specified in the SPEC file are not satisfied, the rpmbuild --rebuild command errors out and lists the failed dependencies, for example:
rpmbuild --rebuild bash-4.4.19-12.el8.src.rpm
Installing bash-4.4.19-12.el8.src.rpm ... error: Failed build dependencies: autoconf is needed by bash-4.4.19-12.el8.x86_64 ncurses-devel is needed by bash-4.4.19-12.el8.x86_64 texinfo is needed by bash-4.4.19-12.el8.x86_64
You can either manually install each dependency that is listed in the warning; or, you can use the dnf builddep command to resolve all of the build dependencies specified in the SPEC file that was extracted when you ran the rpmbuildcommand, for example:
sudo dnf builddep -y ~/rpmbuild/SPECS/bash.spec
If all of the build dependencies are satisfied and the source
package has been created appropriately, the rpmbuild
--rebuild command completes after the binary package
build is complete. You can access the package in
~/rpmbuild/RPMS
.
If you need to modify source, apply alternative patches, or edit the SPEC file to perform alternate actions during different stages of the build process, you can do so and then build the binary and source packages again directly from the SPEC file, for example:
rpmbuild -ba ~/rpmbuild/SPECS/bash.spec
Using the mock Utility to Build Sources
The mock utility provides a wrapper that can help build sources safely and can handle build dependency resolution for you in the background. This tool sets up a chroot directory to handle the build process. By creating a chroot environment, several potential build issues are handled automatically. Most importantly, the build process itself is kept safe from affecting the host system. The chroot environment can install build dependency packages and everything that is required to complete the build, without actually installing unwanted packages into the host system so that the host system can remain relatively clean of build artifacts. Because the chroot environment contains the build process and protects the host system, build processes are effectively privileged within the contained environment, which helps facilitate a straightforward build and minimize potential errors. Finally, build dependencies can be automatically resolved by using the mock utility, which can safely and automatically trigger the appropriate dnf builddep command, as required.
The mock utility requires some preliminary
configuration before using it to build for Oracle Linux sources.
A useful starting point is to create a
/etc/mock/templates/ol-8.tpl
template file
with a configuration similar to the following:
config_opts['chroot_setup_cmd'] = 'install tar gcc-c++ redhat-rpm-config oraclelinux-release which xz sed \ make bzip2 gzip gcc coreutils unzip shadow-utils diffutils cpio bash gawk \ rpm-build info patch util-linux findutils grep' config_opts['dist'] = 'el8' # only useful for --resultdir variable subst config_opts['extra_chroot_dirs'] = [ '/run/lock', ] config_opts['releasever'] = '8' config_opts['package_manager'] = 'dnf' config_opts['root'] = 'ol-8-{{ target_arch }}' config_opts['dnf.conf'] = """ [main] keepcache=1 debuglevel=2 reposdir=/dev/null logfile=/var/log/yum.log retries=20 obsoletes=1 gpgcheck=1 assumeyes=1 syslog_ident=mock syslog_device= install_weak_deps=0 metadata_expire=0 best=1 module_platform_id=platform:el8 protected_packages= # repos [ol8_baseos_latest] name=Oracle Linux 8 BaseOS Latest ($basearch) baseurl=https://yum.oracle.com/repo/OracleLinux/OL8/baseos/latest/$basearch/ gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-oracle gpgcheck=1 enabled=1 [ol8_appstream] name=Oracle Linux 8 Application Stream ($basearch) baseurl=https://yum.oracle.com/repo/OracleLinux/OL8/appstream/$basearch/ gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-oracle gpgcheck=1 enabled=1 [ol8_codeready_builder] name=Oracle Linux 8 CodeReady Builder ($basearch) - Unsupported baseurl=https://yum.oracle.com/repo/OracleLinux/OL8/codeready/builder/$basearch/ gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-oracle gpgcheck=1 enabled=1 [ol8_distro_builder] name=Oracle Linux 8 Distro Builder ($basearch) - Unsupported baseurl=https://yum.oracle.com/repo/OracleLinux/OL8/distro/builder/$basearch/ gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-oracle gpgcheck=1 enabled=1 [ol8_developer_EPEL] name=Oracle Linux $releasever EPEL Packages for Development ($basearch) baseurl=https://yum.oracle.com/repo/OracleLinux/OL8/developer/EPEL/$basearch/ gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-oracle gpgcheck=1 enabled=1 """
Replace /etc/mock/default.cfg
with the
following content, substituting x86_64
with
aarch64
if you intend to build packages for
Arm platforms:
include('templates/ol-8.tpl') config_opts['target_arch'] = 'x86_64' config_opts['legal_host_arches'] = ('x86_64',)
Before any user can use the mock utility, the
user must be added to the mock
group. You can
do this by running the following command:
sudo /usr/sbin/usermod -a -G mock $USER
Note that if the user is currently logged in, the user may need to log out and then log back in to the system for the change in group permissions to become active.
When the configuration is in place, you can start to build source packages by using the mock utility. For example, to simply build a package directly from a source RPM package:
mock --rebuild bash-4.4.19-12.el8.src.rpm
Packages are built in a chroot environment that is created for
the build root that is defined in the template. You can access
the file system used in the chroot in
/var/lib/mock
. For example, using the
configurations presented in this documentation would be similar
to the following:
ls /var/lib/mock/ol-8-x86_64/root/builddir/build/SRPMS/
bash-4.4.19-12.el8.src.rpm
ls -lh /var/lib/mock/ol-8-x86_64/root/builddir/build/RPMS/
total 4.9M -rw-r--r--. 1 root mock 1.6M Feb 3 02:10 bash-4.4.19-12.el8.x86_64.rpm -rw-r--r--. 1 root mock 1.2M Feb 3 02:10 bash-debuginfo-4.4.19-12.el8.x86_64.rpm -rw-r--r--. 1 root mock 841K Feb 3 02:10 bash-debugsource-4.4.19-12.el8.x86_64.rpm -rw-r--r--. 1 root mock 113K Feb 3 02:10 bash-devel-4.4.19-12.el8.x86_64.rpm -rw-r--r--. 1 root mock 1.3M Feb 3 02:10 bash-doc-4.4.19-12.el8.x86_64.rpm
If you need to work with build artifacts within the mock chroot, you can also do the following:
mock --shell
INFO: mock.py version 2.4 starting (python version = 3.6.8)... Start(bootstrap): init plugins INFO: selinux enabled Finish(bootstrap): init plugins Start: init plugins INFO: selinux enabled Finish: init plugins INFO: Signal handler active Start: run Start(bootstrap): chroot init INFO: calling preinit hooks INFO: enabled root cache INFO: enabled package manager cache Start(bootstrap): cleaning package manager metadata Finish(bootstrap): cleaning package manager metadata INFO: enabled HW Info plugin Finish(bootstrap): chroot init Start: chroot init INFO: calling preinit hooks INFO: enabled root cache INFO: enabled package manager cache Start: cleaning package manager metadata Finish: cleaning package manager metadata INFO: enabled HW Info plugin Finish: chroot init Start: shell
ls -lah /builddir/
total 20K drwx------. 1 root 1000 120 Feb 4 09:21 . dr-xr-xr-x. 1 root root 212 Feb 3 02:06 .. -rw-------. 1 root root 50 Feb 4 09:21 .bash_history -rw-r--r--. 1 root 1000 18 Aug 2 2020 .bash_logout -rw-r--r--. 1 root 1000 141 Aug 2 2020 .bash_profile -rw-r--r--. 1 root 1000 376 Aug 2 2020 .bashrc -rw-rw-r--. 1 root root 130 Feb 3 02:06 .rpmmacros drwxrwxr-x. 1 root 1000 88 Feb 3 02:06 build
You can find out more about mock in the MOCK(1) manual page or at https://github.com/rpm-software-management/mock/.