-# Building RPM packages for OpenAFS
+[[!toc levels=2]]
-The OpenAFS source tree contains an RPM spec file for building RPM packages.
-Recent versions of OpenAFS have makefile targets to build the source
-distribution tarballs and a source RPM package (srpm). After creating these
-files, run the `rpmbuild` tool to create create the binary RPM packages.
+# Introduction
-The following commands show how to build RPM packages from a git checkout. The
-tools will create RPM packages from annotated git tags. Checkout a tag for the
-desired version, then generated the source rpm, then run rpmbuild to build the
-binaries RPM package files.
+This guide shows how to build OpenAFS RPM packages for Red Hat Enterprise
+Linux, CentOS, and Fedora, using the contributed RPM spec file provided with
+the OpenAFS source code.
+
+## Prerequisites
+
+Upgrade your kernel to the most recent version:
+
+ $ sudo yum update kernel
+ $ sudo reboot # if updated
+
+Install the packages required to build the OpenAFS source RPM (SRPM):
+
+ $ sudo yum install rpm-build yum-utils make perl libtool bzip2 wget
+
+Additional build dependencies will be installed after the spec file is
+generated.
+
+# Building OpenAFS RPMs
+
+This section describes how to build RPMs for OpenAFS release or pre-release.
+See "Advanced topics" below to build packages based on the `master` branch for
+development and testing.
+
+## Method 1: Building from source code distribution
+
+The OpenAFS Release Team provides software releases as source code
+distributions. A source RPM (SRPM) file can easily be built from a source
+distribution release with the `makesrpm.pl` script provided in the source tree.
+
+Download the source distribution files from [openafs.org][3]. Four files are
+provided in a release; a source tarball, a documentation tarball, release
+notes, and a change log. Extract the `makesrpm.pl` script from the source
+tarball and then run `makesrpm.pl` to build the source RPM (SRPM). The
+resulting SRPM will be placed in the current directory. Install the build
+dependencies with `yum-builddeps`, plus the kernel module build dependencies
+(which will not be installed with `yum-builddeps` due to some quirks of the
+OpenAFS spec file.) Finally, run `rpmbuild` to build the binary RPMs. The
+resulting RPMs will be placed in `~/rpmbuild/RPMS`.
+
+ # Download source release.
+ $ wget https://www.openafs.org/dl/openafs/1.8.5/openafs-1.8.5-src.tar.bz2
+ $ wget https://www.openafs.org/dl/openafs/1.8.5/openafs-1.8.5-doc.tar.bz2
+ $ wget https://www.openafs.org/dl/openafs/1.8.5/RELNOTES-1.8.5
+ $ wget https://www.openafs.org/dl/openafs/1.8.5/ChangeLog
+
+ # Build the source RPM.
+ $ tar xf openafs-1.8.5-src.tar.bz2 --strip-components=4 '*/makesrpm.pl'
+ $ perl makesrpm.pl openafs-1.8.5-src.tar.bz2 openafs-1.8.5-doc.tar.bz2 RELNOTES-1.8.5 ChangeLog
+
+ # Install build dependencies.
+ $ sudo yum-builddep openafs-1.8.5-1.src.rpm
+ $ sudo yum install "kernel-devel-uname-r == $(uname -r)"
+ $ sudo yum install elfutils-devel # if RHEL/CentOS 8
+
+ # Build RPMs.
+ $ rpmbuild --rebuild openafs-1.8.5-1.src.rpm
+
+## Method 2: Building from a git checkout
+
+The OpenAFS makefile has a target (`make srpm`) to build a source RPM (SRPM) from a git
+checkout of a release or pre-release tag. A downside to this method is the
+release notes and change log provided in the OpenAFS source distribution
+releases are not included in the generated SRPM. This method can also be used
+to build RPMs from a local branch based on an OpenAFS stable branch, such as
+`openafs-stable-1_8_x`. See "Advanced topics" below to see how to build packages for testing
+based on the `master` branch.
+
+To build packages from a git checkout, clone the repository, then checkout the
+release or pre-release tag, or a commit based on a stable branch. Run the
+`regen.sh` tool to generate the `configure` script, then run `configure` to
+generate the makefile. (The `configure` options given in this step are not used
+to generate the binaries; those are defined in the spec file.) The resulting
+source RPM will be placed in the `./packages` directory. Install the build
+dependencies with `yum-builddep` and then build the binary RPMs with
+`rpmbuild`.
+
+ $ sudo yum install git make krb5-devel
$ git clone git://git.openafs.org/openafs.git
$ cd openafs
- $ git checkout openafs-stable-<version> # NOTE: replace dots with underscores in version number
- $ ./regen.sh
- $ ./configure
+ $ git checkout openafs-stable-1_8_5
+
+ $ ./regen.sh -q
+ $ ./configure --disable-kernel-module
$ make dist
$ make srpm
- $ rpmbuild --rebuild -ba --define "_topdir $(pwd)/rpmbuild" packages/openafs-<version>-1.src.rpm
-The packages will be created in the `rpmbuild/RPMS` directory. See the RPM
-spec file in src/packaging/RedHat for the OpenAFS `--define` options.
+ # Install build dependencies.
+ $ sudo yum-builddep packages/openafs-1.8.5-1.src.rpm
+ $ sudo yum install "kernel-devel-uname-r == $(uname -r)"
+ $ sudo yum install elfutils-devel # if RHEL/CentOS 8
+
+ # Build RPMs.
+ $ rpmbuild --rebuild packages/openafs-1.8.5-1.src.rpm
+
+## Build options
+
+The OpenAFS spec file provides several options to select which packages are to
+be built by `rpmbuild` and to enable certain build-time features in the
+binaries. These options are specified as `rpmbuild` command line arguments.
+
+The `build_userspace` and `build_modules` defines control when the the kernel
+module packages are to be built. Userspace packages includes all of the
+packages except the kernel module package, including the servers and the
+OpenAFS client Dynamic Kernel Module System (DKMS) package. By default,
+both the userspace and kernel modules are built.
+
+To build all of the packages except the OpenAFS kernel module:
+
+ $ rpmbuild \
+ --rebuild \
+ --define "build_userspace 1" \
+ --define "build_modules 0" \
+ openafs-<version>-<release>.src.rpm
+
+To build only the OpenAFS kernel module for the currently running kernel:
+
+ $ rpmbuild \
+ --rebuild \
+ --define "build_userspace 0" \
+ --define "build_modules 1" \
+ openafs-<version>-<release>.src.rpm
+
+Specify the `kervers` option to build kernel modules for specific kernel
+versions. Install `kernel-devel` packages for the versions you wish to build.
+You may need to configure and enable the CentOS Vault "update" repositories for
+older kernel versions.
+
+ # Install an older kernel-devel version.
+ $ sudo yum install kernel-devel-uname-r == "3.10.0-957.27.2.el7.x86_64"
+
+ $ rpm -qa kernel-devel
+ kernel-devel-3.10.0-957.27.2.el7.x86_64
+ kernel-devel-3.10.0-1062.12.1.el7.x86_64
+
+ $ rpm -i openafs-<version>-<release>.src.rpm
+
+ $ rpmbuild \
+ -bb \
+ --define "build_userspace 0" \
+ --define "build_modules 1" \
+ --define "kernvers 3.10.0-957.27.2.el7.x86_64" \
+ ~/rpmbuild/SPECS/openafs.spec
+
+ $ rpmbuild \
+ --bb \
+ --define "build_userspace 0" \
+ --define "build_modules 1" \
+ --define "kernvers 3.10.0-1062.12.1.el7.x86_64" \
+ ~/rpmbuild/SPECS/openafs.spec
+
+Additional `rpmbuild` options provided by the OpenAFS spec file are:
+
+* `--without authlibs` Disable authlibs package
+* `--without krb5` Disable krb5 support
+* `--with bitmap-later` Enable "bitmap later" support
+* `--with bos-restricted` Enable "bos restricted" mode
+* `--with supergroups` Enable "supergroups"
+* `--with kauth` Build the obsolete kaserver and related programs
+
+## Common errors
+
+Avoid kernel module build errors by ensuring you have a kernel-devel package
+installed which matches the running kernel.
+
+ $ uname -r
+ 4.18.0-147.5.1.el8_1.x86_64
+ $ rpm -qP kernel-devel | grep uname
+ kernel-devel-uname-r = 4.18.0-147.5.1.el8_1.x86_64
+
+Your build may fail with the error:
+
+ + /usr/lib/rpm/check-rpaths
+ ...
+ ERROR 0001: file '/usr/lib64/libafsauthent.so.2.0.0' contains a standard rpath '/usr/lib64' in [/usr/lib64]
+
+This check fails because the OpenAFS spec hardcoded the `/usr/lib64` standard
+paths for some binaries. The Linux dynamic loader automatically loads shared
+objects from this system default path, so the path specified in the spec file is
+redundant.
+
+To disable this `check-rpath` check, set the `QA_RPATHS` environment variable
+to `0x0001` before running rpmbuild.
+
+ $ export QA_RPATHS=0x0001
+ $ rpmbuild -bb ~/rpmbuild/SPECS/openafs.spec
+
+# Installing OpenAFS RPMs
+
+## Installing client RPMs with the Dynamic Kernel Module System (DKMS)
+
+The Dynamic Kernel Module System (DKMS) kernel modules take longer to install,
+but are automatically rebuilt after the kernel is upgraded. Unless you are
+maintaining, or have access to, a yum repository which tracks kernel updates
+and builds matching OpenAFS kernel modules for each update, you will want to
+use the DKMS method to install the OpenAFS kernel module.
+
+Add the EPEL yum repository, which provides the DKMS system. Install the
+Kerberos5 workstation package, which provides the `kinit` program. Install the
+OpenAFS DKMS and openafs Kerberos5 support packages with `yum`. This will take
+some time as the kernel-module is built from source. Be sure to install
+the openafs-client and dkms-openafs packages in a single `yum install`
+invocation.
+
+ $ cd ~/rpmbuild/RPMS/x86_64
+ $ sudo yum install epel-release
+ $ sudo yum install \
+ krb5-workstation \
+ openafs-1.8.5-1.el8.x86_64.rpm \
+ openafs-docs-1.8.5-1.el8.x86_64.rpm \
+ openafs-krb5-1.8.5-1.el8.x86_64.rpm \
+ openafs-client-1.8.5-1.el8.x86_64.rpm \
+ dkms-openafs-1.8.5-1.el8.x86_64.rpm
+
+## Installing client RPMs with a pre-built kernel module (kmod)
+
+Install the kmod which matches your currently running kernel version. Be sure
+to install the openafs-client and kmod-openafs packages in a single `yum
+install` invocation.
+
+ $ cd ~/rpmbuild/RPMS/x86_64
+ $ sudo yum install \
+ krb5-workstation \
+ openafs-1.8.5-1.el8.x86_64.rpm \
+ openafs-docs-1.8.5-1.el8.x86_64.rpm \
+ openafs-krb5-1.8.5-1.el8.x86_64.rpm \
+ openafs-client-1.8.5-1.el8.x86_64.rpm \
+ kmod-openafs-1.8.5-1.4.18.0_147.5.1.el8_1.x86_64.rpm
+
+## Installing server RPMs
+
+Install the server package with:
+
+ $ cd ~/rpmbuild/RPMS/x86_64
+ $ sudo yum install \
+ openafs-1.8.5-1.el8.x86_64.rpm \
+ openafs-docs-1.8.5-1.el8.x86_64.rpm \
+ openafs-server-1.8.5-1.el8.x86_64.rpm
+
+# Advanced topics
+
+## Building RPMs with mock
+
+[Mock][4] is a tool for building packages in a chroot. The mock chroot
+isolation makes it makes it easier to build a large number of kernel module
+versions on a single build host. In addition, mock provides a clean build
+environment for each build, and mock will automatically install the build
+requirements specified by the openafs.spec file in the temporary mock chroot.
+
+Mock also provides the ability to build RPMs for different distributions on one
+machine. For example, one could build RPMs targeted for CentOS 6, 7, and 8 on
+one CentOS 8 build host. Although it is possible to build RPMs for other
+distributions with mock, it not possible to build RPMs for other architectures,
+since mock does not support cross-compiling.
+
+Install mock and add yourself to the 'mock' group.
+
+ $ sudo yum install mock
+ $ sudo usermod -a -G mock $USER
+ $ newgrp - mock
+
+To build OpenAFS rpms with mock, first create the OpenAFS RPM as shown above.
+Then run the mock commands to build the packages using the mock system.
+
+ $ mock --rebuild openafs-1.8.5-1.src.rpm
+
+## Building RPMs with afsutil
+
+[afsutil][5] is a python tool to facilitate OpenAFS development. The `afsutil
+package` command is a front-end tool for building RPMs from a git checkout,
+with or without mock. The main advantages of using `afsutil package` to build
+packages is that it makes it easy to build a source RPM (SRPM) from a git
+commit based on the master branch (as well as stable branches). This can be
+helpful to build packages for testing or to make changes to the master branch
+version of the spec file.
+
+When used with mock, `afsutil` will, by default, build kernel modules for
+every kernel-devel version discovered in the enabled yum repositories within
+the mock chroot.
+
+OpenAFS packages require a copy of the CellServDB client configuration file.
+`afsutil package` will automatically download the CellServDB version specified
+in the spec file from grand.central.org. An alternate CellServDB file can be
+specified by url or local path with the `--csdb` option.
+
+RPM packages for `afsutil` are available. This is the preferred installation
+method on CentOS. Alternatively, `aftutil` may be installed with `pip`, or from
+source.
+
+### Method 1: Installing afsutil with yum
+
+ $ sudo yum install https://download.sinenomine.net/openafs/repo/sna-openafs-release-latest.noarch.rpm
+ $ sudo yum install afsutil
+
+### Method 2: Installing afsutil with pip
+
+ $ sudo yum install epel-release # if RHEL/CentOS
+ $ sudo yum install python2-pip # if RHEL/CentOS 8
+ $ sudo yum install python-pip # if RHEL/CentOS 7 or earlier
+ $ sudo pip install afsutil
+
+### Method 2: Installing afsutil from source
+
+ $ git clone https://github.com/openafs-contrib/afsutil
+ $ cd afsutil
+ $ python configure.py # or, python2 configure.py on RHEL/CentOS 8
+ $ sudo make install
+
+### Building RPMs with afsutil
+
+To build OpenAFS packages from a git checkout:
+
+ $ sudo afsutil getdeps # Install build dependencies
+ $ git clone git://git.openafs.org/openafs.git
+ $ cd openafs
+ $ afsutil package
+
+The `afsutil package` command will build packages for the userspace and kernel
+modules by default. See the `--build` option to build these separately.
+
+If you installed `mock` (see above), specify the `--mock` option to build the
+packages in the mock chroot. Mock will automatically install the build
+dependencies.
+
+Build the server, client, and kernel module for the local machine with:
+
+ $ afsutil package --mock --kernel="$(uname -r)"
+
+`afsutil package --mock` will query the yum repositories configured for the
+mock chroot to discover the kernel-devel kernel versions available. You can
+add local yum repositories to your mock configurations in `/etc/mock/` to
+provide kernel-devel packages for older kernel versions.
+
+To list kernel versions available in the mock chroot:
+
+ $ afsutil package --mock --list 2>/tmp/error
+ 3.10.0-1062.4.2.el7
+ 3.10.0-1062.4.3.el7
+ 3.10.0-1062.9.1.el7
+ 3.10.0-1062.12.1.el7
+ ...
+
+Specify the --kernel option to build a kmod for specific kernel version. This
+option may be given more than once to build multiple kernel modules.
+
+ $ afsutil package --mock --build=kmods --kernel=3.10.0-1062.4.3.el7
+
+To build all kernel module versions:
+
+ $ afsutil package --mock --build=kmods
+
+If the afsutil package command is interrupted and then restarted, builds for
+any already completed kmod-openafs RPMs will be skipped. Use the the --clobber
+option to override this and force all of the RPMs to be rebuilt.
+
+See `afsutil package --help` for the available options. Default values for
+options may be specified in the `.afsutil.cfg` configuration file. See
+the [afsutil README][5] for more information.
+
+# See also
+
+* [RPM Packaging Guide][6]
+
+
+[1]: https://github.com/openafs-contrib/afsutil
+[2]: https://pypi.org/project/afsutil/
+[3]: https://www.openafs.org/release/
+[4]: https://github.com/rpm-software-management/mock/wiki
+[5]: https://github.com/openafs-contrib/afsutil
+[6]: https://rpm-packaging-guide.github.io/