Package buildsystem
activeHow I build and publish my personal slackware64-current package repository.
My personal Slackware packages for slackware64-current are built by a small pipeline of tools running inside one dedicated QEMU virtual machine. Nothing here is a single program: it is a repository that gets reassembled, a dependency layer that gets patched, a builder that turns SlackBuilds into packages, and a publishing step that puts them online at packages.danix.xyz. This page walks the whole flow in the order a build actually happens.
The VM
The buildsystem lives in a QEMU virtual machine running slackware64-current,
kept up to date with slackpkg against a local mirror of Slackware’s own system
packages. It has 8 CPU cores and around 8 GB of RAM, enough to build all but the
heaviest packages comfortably, and I reach it over SSH. Keeping it in its own VM
means a build, a broken dependency, or a full repository regeneration never
touches my daily driver: the box exists to be hammered and, if needed, thrown
away and rebuilt.
Assembling the repository
Once a week the SlackBuilds tree is regenerated from scratch. It starts as a
clone of Ponce’s slackbuilds checked out
on the current branch, the community tree that tracks SlackBuilds.org against
slackware-current. On top of that I overlay my own two collections as squashed
git subtrees: my-slackbuilds for
general personal packages and
Slackware-Pentesting-Suite
for security tooling.
Where a personal package shares a name with an upstream one, the upstream copy is shadowed: its directory is removed so my version wins. The result is a single local tree that is standard SBo plus my additions, ready to build. That whole assembly is one script, which will get its own page here later.
The -current dependency problem
SBo SlackBuilds target Slackware stable, so some of their build-time
dependencies are unnecessary on -current, which already ships them as system
packages or newer versions. rust-opt and google-go-lang are typical: needed
on stable, pointless on -current. These “phantom” dependencies would otherwise
force needless rebuilds.
slackrepo strips a dependency from a package with a per-package hint file carrying
DELREQUIRES, but writing one by hand for every affected package after each
weekly regeneration is exactly the tedium a script should own. That job belongs to
mkhint: its -F sweep reads a list of phantom deps and, for
every package whose requirements hit one, writes or merges the right
DELREQUIRES across the freshly rebuilt tree in a single pass.
Curious how the phantom-dep sweep actually works? The whole thing is one Bash script.
Read the mkhint sourceBuilding
The actual building is done by
slackrepo, an automated SlackBuild
builder for Slackware, now maintained by Andrew Clemons. It compiles each package and its dependencies in a clean
chroot, tracks upstream git revisions to work out what has changed and needs
rebuilding, and produces a repository that plugs straight into slackpkg+. I run
it with a start hook that first rebases my SlackBuilds tree onto upstream, so
every build starts from a current tree, and it handles the dependency ordering so
a single command rebuilds everything that moved.
Publishing
When a build finishes, a chain of slackrepo finish hooks takes over. They
regenerate the slackpkg+ repository metadata, build the styled HTML frontend for
the package site, sync the result out to the live server, and send a notification
that the run is done. The frontend wraps Apache’s plain directory autoindex in a
themed header and footer so packages.danix.xyz reads
as a proper repository rather than a bare file listing. That frontend is its own
small project and will get a page here later too.
It is mostly a shell hook that walks the package tree and writes the header and footer HTML. Have a look under the hood.
See the frontend generatorTesting against 15.0 stable
Some of the packages I write are meant to be submitted upstream to SlackBuilds.org, which targets Slackware stable, not -current. Since my whole buildsystem is -current, a package building fine here proves nothing about 15.0. Before I submit one, I test it with a separate, independent tool built for exactly that: it resolves the SlackBuild’s dependency tree locally, then builds and installs every package in a fresh disposable overlay chroot layered over a clean, read-only Slackware 15.0 base. That catches the current-versus-15.0 drift a -current build hides.
It does not touch or drive slackrepo, and its built packages are throwaway: the only question it answers is “does this still build clean on 15.0”. One limit worth naming: it shares the host kernel, so packages that build kernel modules still want a real 15.0 VM. This tool will also get its own page here in time.
The overlay-chroot and dependency-resolution logic live here if you want to read how the 15.0 test is built.
Browse sbo-batch-testerThe weekly rhythm
Put together, the week is one repeatable cycle: regenerate the SlackBuilds tree,
sweep the phantom-dependency hints with mkhint -F, build and publish with
slackrepo and its hooks, and, for anything headed to SlackBuilds.org, spot-test it
against a clean 15.0 base first. Four small tools, each doing one job well, and a
disposable VM to run them in. Very Slackware.
I hope you found this walk through my buildsystem interesting. If you end up running something similar, or you have questions, ideas, or suggestions about any piece of it, drop me a line and I will gladly get in touch.
See you next time.
Everything the buildsystem produces lands here. If you run slackware64-current, you can point slackpkg+ at it and pull my packages straight in.
Browse the package repository