Date: 2021-10-28
It's lab time! We can take some of what we learned in the previous articles, and put it into practice. This is a practical guide to help you set up Mock, download a package's source, and build it!
Lightning Quick Review:
Remember that mock is the program we use to build RPMs. It sets up an isolated chroot environment, installs a minimal Rocky system inside, and installs only packages that are necessary for the build.
Also recall that our package sources are hosted at: https://git.rockylinux.org/staging/rpms , so we will definitely need git on our system to pull sources.
And if you remember from the sources article, archives for the source packages are located in Rocky's S3 storage: https://rocky-linux-sources-staging.a1.rockylinux.org/{SHA1SUM} , so we'll want the curl utility to download from there. (Or we can use wget, web browser, etc.)
Mock is packaged for most RPM-based distributions, and even works on Debian/Ubuntu(!) due to its chroot/container workflow. It doesn't matter too much what system you run it on, but I (of course) recommend Rocky 8, or some other RHEL 8 compatible system to try this. That way you're guaranteed to be compatible with the instructions I'm using here.
No! Most anything will do. I myself will be running these instructions on a Raspberry Pi 4 running the latest Rocky Linux 8. Any laptop, desktop, or VM that runs Rocky should be able to manage this. More memory and faster storage/processor will obviously speed your builds up though :-) .
This is pretty easy, everything we want is already packaged for us. Mock is in the EPEL repository, so we'll need to enable that (don't worry, all it takes is a package install!)
First, let's install git and curl (or make sure they're already installed):
dnf install git curl
Next, we can enable the EPEL repository and install mock:
dnf install epel-release
dnf install mock
You can run mock
builds as root and be fine, but generally we like to use an unprivileged user. To do that, simply add your user to the "mock" group (that was created when you installed the mock package):
sudo usermod -G mock -a MYUSER
(Where MYUSER is the name of your user. For example, mine is "skip")
Be sure to start up a new shell after this! Your group membership doesn't take effect until you launch a new shell.
Check your group membership with: id
, make sure mock is listed in your groups list.
Let's create some directories in our home folder to organize things: a place for code, and a place to build RPMs:
mkdir -p ~/rockysrc ~/rockybuild
Now our permissions are set, and we've got some build space organized!
Let's set up mock to build against Rocky Linux!
Take a look at the files under /etc/mock/: We see that there are tons of options, you can build packages for all KINDS of systems!
Notice that there is a default.cfg file, and it is a symbolic link to "epel-8.cfg". This default is for CentOS 8, building with EPEL repositories. But we want to change it to Rocky! Note that there's a rocky-8-x86_64.cfg file in there, let's point the default.cfg to that instead:
cd /etc/mock
sudo rm default.cfg
sudo ln -s rocky-8-x86_64.cfg default.cfg
Side note: This assumes x86_64 (Intel) processor. If you are using an ARM 64-bit processor (like a Raspberry Pi), please use the rocky-8-aarch64.cfg config file instead. Your builds much match your processor!
Now we have mock ready to build our packages in a Rocky Linux chroot/container environment! Let's build!
First package is a simple one: everyone's favorite shell! Ok, maybe not everyone's, but it's pretty darn popular. Bash is a straightforward package, so let's build it!
We know from the previous article on source control that Rocky's package sources are kept under https://git.rockylinux.org/staging/rpms/PACKAGENAME. So let's navigate to our rockysrc folder and clone bash. We can then cd into the folder and make sure we have the proper "r8" (Rocky 8) branch checked out:
cd ~/rockysrc
git clone https://git.rockylinux.org/staging/rpms/bash
cd bash
git branch
We have the bash spec file and patches, but we are missing the .tar.gz file - the actual bash source code! Again referring back to my article on source control, we know that the file name and hash are listed under a .bash.metadata file in the repository. Let's take a look:
# (assuming you are in the bash/ folder we cloned):
[skip@RpiRockyDev bash]$ cat .bash.metadata
8de012df1e4f3e91f571c3eb8ec45b43d7c747eb SOURCES/bash-4.4.tar.gz
We see the SHA hash of the file, and the name/location where it belongs. If you read the source article closely, you know that Rocky stores its sources on a web server with files labelled by SHA1 hash: https://rocky-linux-sources-staging.a1.rockylinux.org/{SHA1SUM}. So let's download this file into SOURCES/ and name it appropriately:
# (again, from inside the bash/ folder we cloned)
curl -o SOURCES/bash-4.4.tar.gz https://rocky-linux-sources-staging.a1.rockylinux.org/8de012df1e4f3e91f571c3eb8ec45b43d7c747eb
ls -larth SOURCES/
Now we have the RPM spec file and patches (from Git), and the source tarball (from the sources webserver). We're ready to build!
In order to compile our Bash package, we need to first build the Source RPM (SRPM). Fortunately, this is pretty straightforward.
We are going to keep all of our build output (logs and RPM files) organized in the ~/rockybuild folder we made earlier. You can organize things however you like, the way I'm doing it here is just a suggestion.
# create bash build output folder:
mkdir -p ~/rockybuild/bash
# Compile SRPM from our spec file and sources folder, and put it in the rockybuild/bash/ folder:
mock -v --resultdir=~/rockybuild/bash --buildsrpm --spec=~/rockysrc/bash/SPECS/bash.spec --sources=~/rockysrc/bash/SOURCES/
There's a bit to unpack with that mock command. We're telling it to:
When the dust clears, we should now have a source RPM file in the ~/rockybuild/bash/ folder, named by version. Mine is called: bash-4.4.19-14.el8.src.rpm , but your version may be different as new versions of bash are released.
Why use mock to create a simple SRPM? We could have just used rpmbuild to produce the source RPM without the overhead of Mock. In theory, there shouldn't be much difference. However, the advantage of doing it in Mock is the Rocky mock config that we are using guarantees all of our RPM macros/variables are defined correctly. Things like release tags (el8, el8_4, etc.) ought to be accurate. It usually doesn't matter when doing private builds, but it can make a difference!
Finally! Time to compile! This is simple, just point Mock at your package and let er' rip! Like this:
# (I like to use the "time" command to time my RPM compilations. You can completely remove it if you like)
time mock -v --resultdir=~/rockybuild/bash ~/rockybuild/bash/bash-4.4.19-14.el8.src.rpm
This should take a few minutes, depending on how fast your system is. When the command finishes, you should now have RPMs and log files in your --resultdir! Here is mine for reference:
[skip@RpiRockyDev bash]$ ls -1 ~/rockybuild/bash/
bash-4.4.19-14.el8.aarch64.rpm
bash-4.4.19-14.el8.src.rpm
bash-debuginfo-4.4.19-14.el8.aarch64.rpm
bash-debugsource-4.4.19-14.el8.aarch64.rpm
bash-devel-4.4.19-14.el8.aarch64.rpm
bash-doc-4.4.19-14.el8.aarch64.rpm
build.log
hw_info.log
installed_pkgs.log
root.log
state.log
If you have these files, then congrats! You've built a Rocky RPM, and you've done it, at its core, the same way our release team does. Only 3199 more to go.... ;-) .
Here is a quick review of the steps we just took to download the Bash source and compile it:
# 1: Clone from Git:
git clone https://git.rockylinux.org/staging/rpms/bash
# 2: Retrieve the source tar and name it correctly (from the .bash.metadata file in the Git repository):
curl -o SOURCES/bash-4.4.tar.gz https://rocky-linux-sources-staging.a1.rockylinux.org/8de012df1e4f3e91f571c3eb8ec45b43d7c747eb
# 3: Build an SRPM from our sources:
mock -v --resultdir=~/rockybuild/bash --buildsrpm --spec=~/rockysrc/bash/SPECS/bash.spec --sources=~/rockysrc/bash/SOURCES/
# 4: Build the package from the SRPM:
time mock -v --resultdir=~/rockybuild/bash ~/rockybuild/bash/bash-4.4.19-14.el8.src.rpm
For basic packages, that's all there is to it! Clone from git, grab the tarball, build SRPM, build binary package. 4 relatively straightforward steps.
This lab entry got a bit long, so I'm splitting it into 2 parts.
I'm releasing part 2 soon, where we'll compile bind, the famous DNS server!
It's a little tricky because there are some dependencies we'll need to dig through, unfortunately it doesn't just work like bash did.
Thank you for reading! Please feel free to ask questions in chat , or on reddit if you want to talk about building packages.
See you in the next article, build lab #2!
-Skip