Rpm packages test building easy shortcuts

DISCLAIMER: This is a post oriented to Fedora, Centos and RedHat  distributions, although, most of the info is valid for any RPM distribution, with some minor differences

Most of the time, there’s confuse pages, too simple info or damn huge tutorials on how to create an RPM, been any distribution you are.

For some time, i’ve been using personal “shortcuts” to deal with rpm creation in a local machine creating scratch packages near final, avoiding take the burden to send to an external build machine and wait, sometimes, the good behavior of the internet. Even with some already provided tools on distros, i was unable to find a simple and effective way to do what i need. Hence i will place some of my scripts and hope someone think they are useful as well.

So, what are some of the common pitfalls when you are doing and rpm package ?

  • List of files –  How many times you got angry when your build failed in the file list stage ? And sometimes after long minutes or hours of compilation ?
  • Build root – How many times you need to setup a local buildroot place, and sites told you that you need to create some build root on your home dir, and need be built on that place only, worst, tell you that need be as superuser ?
  • Test the package – Ok, you made it, you built it, and then you discover that there are dependencies, soname changes, and anything that prevent you of install in your environment, so what to do ?

So, i tried to minimize all this things with a series of bash scripts, very rude ones, but functional enough to deal with a flat git structure like Fedora and RedHat do in your git package. Let’s start to the obvious basics.

I will not tell how to write an rpm spec, i will tell how to build and deal with the packaging. That’s the real pain actually.
All the script shortcuts are done as aliases or bash functions.

The directory structure

Forget about the “create the builddir blablabla”. The best approach i found on years was create a per package directory, and inside it create a simple git repository ( if not exists ) with proper ignores, and then, all builds go inside. Ex.

     | .gitgnore
     | SPECS
     | SOURCES
     | RPMS
     | SRPMS
     | BUILD
     | package.spec
     | source1.tar.xz
     | some.patch

As you can see, all spec and sources and patches are kept in flat directory, and the buildroot is their own package. Then you will ask, how can it works. Well, the whole idea is using internal symlinks, on the subdirectories, then never need to deal with enter in another subdirectory, all work can be done in a single place. For Fedora and RedHat gits this is quite useful as they have this structure by default

So, here’s the first shortcut bash function script, the structure creation dir and git creation, and the auto symlinking. For this i recommend that you have the git and rpmdevtools installed. First populated a directory with the name of your package with the spec and any source/patches you have, then run the script below:

specdir () {
    [ -z $1 ] && return # Name of the package directory
    [ ! -d ${PACKAGE} ] && return
    cd ${PACKAGE}
    git init
    for name in SPECS SOURCES SRPMS RPMS; do
        mkdir -p ${name}
        echo $name >> .gitignore
    git add .gitignore
    ( cd SPECS && ln -sf ../${PACKAGE}.spec . )
    pushd SOURCES
        for name in $(spectool -A ../${PACKAGE}.spec | cut -d ' ' -f2); do
            ln -sf ../${name} .
    echo "Local rpm root done for build"

So, now we have a proper flat package dir with git enabled and ready to build.  Of course, any extra sources/patches you add it, remember to add the proper symlink inside SOURCES

Now i will show the quick aliases i use to build.

The Jump Aliases

Not everyone knows, but there are a handful package called shortrpm that can improve the rpm skip steps, and with some combination, this enable to build in the new structure. Here the aliases and a quick explanation below

alias rpmb="rpmbuild -ba --define \"_topdir \$PWD\""
alias rpmbi="shortrpm -bi --short-circuit --define \"_topdir \$PWD\""
alias rpmbl="shortrpm -bl --short-circuit --define \"_topdir \$PWD\""
alias rpmbb="shortrpm -bb --short-circuit --define \"_topdir \$PWD\""
alias rpmbs="shortrpm -bs --short-circuit --define \"_topdir \$PWD\""

The usage is the same for all aliases: rpmalias package.spec

So what this aliases do ?

rpmb – Build the rpm on the structure, all stages.

rpmbi – Your package build fine, but failed in install stage. This restart  the build in the install stage, no need to wait building

rpmbl – Your package installed fine, but the list is incomplete or wrong. This jumps to that stage.

rpmbb – Everything is fine, i want just the binary rpms

rpmbs – Generates only the SRPM

So, why shortrpm is better than thr rpmbuild -b* functions ? Is just because rpmbuild just do THAT single stage in shortcut mode, shortrpm allows to continu FROM that stage shortcuted, and this is a handy thing, after you compiled a package like webkit for 2 hours, and discover that you made a typo ( a do a LOT ) on the list files.

Since i have everything done, it’s time to locally test the build and install. So, for Fedora, Centos and RedHat, there’s mock, a tool that most of the times looks more complex than it should be. Is basically a chroot like env to build your package for the target you want.

Before you argue, with some reason, that a virtual machine would be better suited for this, the reasonable approach is that you don’t have in house enough memory resources to run your system and a vm to compile some memory eater software like firefox, or webengine, so mock is the best short term solution resource wise. Let’s see the last shortcut for achieve this.

Mocking the beast

So, what i do usually is create a local repository where i can decide use it on apache webserver or even locally. For this we will need  some other two tools, mock and  createrepo. Is all that we need, as soon we have some srpm available.

Mock is a extreme powerfull tool, and has even a short circuit method for rpms, still, i found more useful the previous approach.

For simple usage, just install mock, add yourself in the mock group and try the last shortcut script

mockbuildsrpm() {
    [ -z $RELEASE ] && RELEASE="fedora-22-x86_64"
    REPO="/var/tmp/repos/$(echo $RELEASE | tr '-' '/')" # Assuming that using standard mock configs
    mkdir -p ${REPO}
    mock --dnf --no-cleanup-after -r ${RELEASE} --resultdir ${REPO} --rebuild $*
    [ $? == 0 ] && createrepo -v --compress-type=bz2 -p ${REPO}

Basically you can pass your configuration release, or let the default one ( mine is Fedora 22 now ) and it will build the srpm and create a repository ready to be consumed the way you want.
Usage is quite simple: mockbuildsrpm package-1.0.src.rpm

For fedora packagers with fedpkg, a simple test case using libao:

fedpkg clone libao
specdir libao
fedpkg sources
rpmbs *.spec
mockbuildrpm SRPMS/*
echo "Done :-)"

Hope this help you in new ideas to make the life easier on package building and fine tuning.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.