Packagecloud logo

Working with Source RPMs

What are source RPMs?

A package is a collection of binaries, scripts, and associated data that is installed by your package manager.

Packages are typically generated from source code and a set of a metadata written by the package maintainer. Occasionally, the source may by patched by the package maintainer at build time.

A source RPM captures the source code and patches as they were at RPM build time.

On RPM-based systems (CentOS, Red Hat Enterprise Linux, Oracle Linux, and many more) source RPMs are RPM files that contain a tarball of source code, patches, auxiliary files that are used during the build process, and a .spec file for generating the RPM.

Why are source RPMs useful?

Source RPMs are extremely useful for:

  • Regenerating binary packages
  • Debugging issues with applications and libraries
  • Modifying existing applications to add additional logging
  • Confirming whether or not a particular security fix has been applied to the source

We strongly recommend that people and organizations running applications in production on RPM-based systems become familiar with RPM source packages so that when a bug appears, system operators and developers will have the tools to quickly and easily obtain the source and debug the issue.

 

Working with source RPMs

If you intend to rebuild or modify a source RPM, it is strongly recommended that you install the yum-utils and rpm-build packages which contains many useful tools for working with yum and RPMs:

$ sudo yum install yum-utils rpm-build

Getting Source RPMs

Getting the source for an RPM package is not as straight-forward as obtaining source packages for other systems.

Start by using yumdownloader which is part of the yum-utils package. This program will download the source RPM for the named package.

For example, to get the source RPM for redis run:

$ yumdownloader --source redis

This will download the redis source RPM file in the current working directory.

Next, you must install the source RPM. When a source RPM is installed, the source tarballs, patches, and auxilliary files will be installed under a top level directory. This directory is called topdir. You can get the current value of topdir by checking the output of rpm --showrc | grep topdir. On many systems, the default value is rpmbuild in the current user’s home directory.

You can set your own topdir by creating a file named .rpmmacros in your home directory like this:

%_topdir      %(echo $HOME)/my-rpm-build-dir

This sample .rpmmacros file will cause source RPMs installed by you to be written to my-rpm-build-dir in your home directory.

You can now install the source RPM:

$ rpm -ivh ./redis-2.8.19-1.el7.src.rpm

This will write the source tarballs, patches, and other files to the SOURCES directory under your specified topdir. The RPM spec file will be written to SPECS.

 

Install Source RPM build dependencies

You should now install the source RPM’s build dependencies by using yum-builddep:

$ sudo yum-builddep redis

 

Preparing the source

Now, that you’ve installed the source RPM and build dependencies, you can prepare the source so that all patches are applied. This brings the source into the state it was in when the RPM was built.

Begin by switching to the SPECS directory under your topdir:

$ cd rpmbuild/SPECS

Next, prepare the source using the rpmbuild program, passing the -bp flag, and specifying the spec filename:

$ rpmbuild -bp redis.spec

Now, you can examine the source. It is found in the BUILD directory under topdir:

$ ls ~/rpmbuild/BUILD
redis-2.8.19

Now, you can look through the source code for Redis precisely as it was when Redis was compiled and put into the package that you have installed on your system.

 

Modifying the source and applying patches

Patches are applied to source code during the RPM build process by listing patches in the RPM spec file, and then applied during the build process.

For example, in redis.spec, a patch is specified like this:

Patch0001:            0001-redis-2.8.18-redis-conf.patch

The actual application happens before the %build step:

%patch0001 -p1

 

Updating the RPM package version number

Updating the RPM package version number is done by modifying the Release field found in the RPM spec file.

Typically, the Version field is set to the version of the source itself whereas the Release field is incremented for each RPM packaging related change.

 

Rebuilding the package

Now, you are ready to rebuild the RPM package!

You can do this by running the following command in the SPECS directory:

$ rpmbuild -ba redis.spec

This will build and write a source RPM and a binary RPM in the SRPMS and RPMS directories, respectively.

 

Upload Source RPMs to packagecloud.io

You can now upload your source RPMs to packagecloud.

You simply push the source RPM just as you would any other RPM with the package_cloud CLI.

For example, to upload a source RPM to CentOS 7:

$ package_cloud push user/repo/el/7 redis-2.8.19-1.el7.src.rpm

Looking for repository at user/repo... success!
Pushing redis-2.8.19-1.el7.src.rpm... success!

The packagecloud command line client uses the package create API to upload the source RPM file.

 

Conclusion

The RPM package toolchain enables users to quickly and easily recreate the source tree for a package as it was at build time. This is incredibly useful for debugging strange application behavior and for adding additional logging output to applications that aren’t telling you what you need to know when they run.

Becoming familiar with the workflow of obtaining source code via the package manager is essential for debugging and administering infrastructure of any size.

You might also like other posts...