Linux server motherboard.

How to Create and Use Patch Files for RPM Packages

Source Code, Patches, and RPM Packages

Let's say that you have an archive of source code for a software package and you want to build an RPM package file. That's a good idea, the RPM Package Manager system handles package dependencies and is the core of your Linux configuration management. But let's say you want to make some changes or additions to the software, changing where it keeps its configuration or writes its logs, adding some documentation or data, or otherwise making an extension or change.

You can do this! There are three major steps:

First, obtain an archive file containing the original source code. The source code will consist of several files in a tree hierarchy of directories.

Second, modify a copy of that archive and create a patch file defining the changes and additions in going from the original to your version.

Third, modify or create a spec file describing how to start with the original archive and one or more patch files and build either a binary RPM package file that can be installed, or a source RPM package file containing the original code plus your modifications and the spec file, or both source and binary RPM files.

Modifying the Source Code and Creating a Patch File

Let's say you are building a package of the something program, and you have a tar archive of version 1.2.3. This will probably be a file named something-1.2.3.tar, likely compressed with gzip, bzip2, or xz.

A tar file extracts into the current directory, so a carefully created one will create a subdirectory and put all files and subdirectories into that. The alternative would be to clutter the current directory itself with a large number of files and directories, possibly overwriting existing files and at least making a mess of things.

Extract the source code archive and make a copy. The -a option, for archive, recursively copies down the directory tree while preserving permissions and timestamps and copying symbolic links as symbolic links. For this example we would expect the subdirectory to be named something-1.2.3:

$ cd /tmp
$ tar xf ~/something-1.2.3.tar
$ cp -a something-1.2.3 something-1.2.3-orig 

Make your changes. Now go into the something-1.2.3 directory tree and make your changes and additions.

Create a patch file with the diff command. You need to use at least these options:

-r for recursive down the directory trees

-u for unified blocks with 3 lines of context

-N to treat new files as if they were present but empty in the original

Some people recommend adding these:

-B to ignore changes consisting of added and deleted blank lines

-b to ignore changes in blank space within lines

-d to work harder to minimize the description of the set of changes within lines

Specify the two hierarchies with the original first and your modified version second:

$ diff -urN something-1.2.3-orig something-1.2.3 > mychanges.patch 

The result will contain something like the following. A new line with the individual diff command is followed by a description of how to change the original, indicated by "-" characters, into the new, indicated by "+" characters. As we see here, tar archives may specify nonsensical time stamps.

diff -urN something-1.2.3-orig/path/to/file1 something-1.2.3/path/to/file1
--- something-1.2.3-orig/path/to/file1	Fri Jul 31 00:28:34 2015
+++ something-1.2.3/path/to/file1	Mon Aug 10 21:27:46 2015
@@ -9,6 +9,9 @@
 This line is in both versions.
 So is this line,
 and this line.
+This line was added in going from first to second.
-This line was removed.
 This line is in both versions.
 So is this line,
 and this line
diff -urN something-1.2.3-orig/path/to/file2 something-1.2.3/path/to/file2
--- something-1.2.3-orig/path/to/file2	Wed Dec 31 19:00:00 1969
+++ something-1.2.3/path/to/file2	Mon Aug 10 21:27:08 2015
@@ -0,0 +1,3 @@
+
+This 4-line file was not present at all in the
+original version.
+ 

Using a Patch File with RPM

You will have a hierarchy at ~/rpmbuild in which you build RPM packages. Here is one where we are ready to build the xosview system monitoring tool. The SRPMS directory is intended for storing source RPM files. When the user "installs" the source RPM, the installation process extracts the source code components into SOURCES and the spec file into SPECS. Or, if starting from source code and patches only, you create the spec file by hand and then use it to build the binary and source RPM files.

$ tree -F ~/rpmbuild
/home/cromwell/rpmbuild
|-- BUILD/
|-- BUILDROOT/
|-- RPMS/
|   |-- noarch/
|   `-- x86_64/
|-- SOURCES/
|   |-- XOsview.png
|   |-- xosview-1.11-app-def.patch
|   |-- xosview-1.16.tar.gz
|   `-- xosview-aarch64.patch
|-- SPECS/
|   `-- xosview.spec
`-- SRPMS/
    `-- xosview-1.16-4.fc22.src.rpm

8 directories, 6 files 

Add two lines to the spec file for each patch file. The first, just below the Source: line(s), names the patch file. The second, at the end of the %prep area, tells how to use it with the patch command. You will need either -p0 or -p1 specifying how many levels to strip off the path names, depending on how you built the patch file compared to how the tar file is contructed.

Example Spec File Using Multiple Patches

Here is an annotated spec file showing how the patches are specified:

######################################################################
# Every spec file must start with an unlabeled block defining:
# Summary       = One-line summary, details go in %description
# Name          = Package name
# Version       = As numbered by original authors
# Release       = Our release, maybe we change our mind and rebuild with
#                 a larger number.  When we build the binary package it
#                 will be in a file name-version-release-architecture.rpm.
#                 and "rpm -q" will report "name-version-release".
# Group         = One of the categories in /usr/share/doc/rpm/GROUPS
# License       = GPL, GPL+, BSD, MIT, etc
# URL           = Home page of project, will be reported in "rpm -qi"
# Source*       = Where to get the reference copy of the source code.
#                 The file name component of the URL must agree with the
#                 tar file stored in SOURCES.  Simply "Source" is there
#                 is just one, "Source0", "Source1", etc if there are more.
# Patch*        = Our patch files.  Again just "Patch" if there is one,
#                 "Patch0", "Patch1", etc if there are more.
# BuildRequires = Packages, typically *-devel, needed to compile
# Requires      = Packages needed before installing
######################################################################
Summary:       An X Window System utility for monitoring system resources
Name:          xosview
Version:       1.16
Release:       4%{?dist}
Group:         Applications/System
License:       GPL+
URL:           http://www.pogo.org.uk/~mark/xosview/
Source0:       http://www.pogo.org.uk/~mark/xosview/releases/xosview-%{version}.tar.gz
Source1:       http://roxos.sunsite.dk/dev-contrib/guido/XOsview.png
Patch0:        xosview-1.11-app-def.patch
Patch1:        xosview-aarch64.patch
BuildRequires: libXpm-devel
BuildRequires: libX11-devel 
BuildRequires: desktop-file-utils
Requires:      xorg-x11-fonts-misc
######################################################################
# %description section is free-form text with the package details.
######################################################################
%description
The xosview utility displays a set of bar graphs which show the
current system state, including memory usage, CPU usage, system load,
etc. Xosview runs under the X Window System.

######################################################################
# %prep section tells how to prepare beyond extracting the tar files.
# The following says to apply the patch file defined above as Patch0
# with "patch -p1", then apply the above Patch1 with "patch -p1".
######################################################################
%prep
%setup -q
%patch0 -p1
%patch1 -p1

######################################################################
# %build section tells how to do the compilation.
######################################################################
%build
%{__make} %{?_smp_mflags} OPTFLAGS="%{optflags}" 
cat > %{name}.desktop <<EOF
[Desktop Entry]
Encoding=UTF-8
Name=OS Resource Viewer
Comment=
Exec=xosview
Terminal=false
Type=Application
Icon=xosview
Categories=Utility;System;
EOF

######################################################################
# %install section tells how to install the package components.
######################################################################
%install
%{__install} -d %{buildroot}%{_bindir}   \
    %{buildroot}%{_mandir}/man1          \
    %{buildroot}%{_datadir}/icons        \
    %{buildroot}%{_datadir}/applications

%{__make} install PREFIX=%{buildroot}%{_prefix} INSTALL="%{__install} -p"
%{__install} -p -m 0644 %{SOURCE1} %{buildroot}%{_datadir}/icons/%{name}.png
%{__install} -p -m 0644 -D Xdefaults %{buildroot}%{_datadir}/X11/app-defaults/XOsview
desktop-file-install --dir %{buildroot}%{_datadir}/applications %{name}.desktop

######################################################################
# %files section lists the package components.
######################################################################
%files
%doc CHANGES COPYING COPYING.GPL README README.linux TODO Xdefaults
%{_bindir}/%{name}
%{_mandir}/man1/%{name}.1*
%{_datadir}/icons/%{name}.png
%{_datadir}/applications/%{name}.desktop
%{_datadir}/X11/app-defaults/XOsview

######################################################################
# %changelog section describes the package history.
######################################################################
%changelog
* Mon Aug 18 2014 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 1.16-4
- Rebuilt for https://fedoraproject.org/wiki/Fedora_21_22_Mass_Rebuild

[... long list of changes deleted ...] 

For more details of the spec file and its macros see the RPM Building HOWTO

Building the Source and Binary RPMs

Build a Source RPM from spec file and source:

$ rpmbuild -bs ~/rpmbuild/SPECS/something-1.2.3.spec 

Input: ~/rpmbuild/SPECS/something-1.2.3.spec
Input: ~/rpmbuild/SOURCES/something-*
Output: ~/rpmbuild/SRPMS/something-1.2.3.src.rpm

Build a Binary RPM from SRPM:

$ rpmbuild --rebuild ~/rpmbuild/SRPMS/something-1.2.3.src.rpm 

Input: ~/rpmbuild/SRPMS/something-1.2.3.src.rpm
Output: ~/rpmbuild/RPMS/arch/something-1.2.3.arch.rpm

Build a Binary RPM from the Spec File and Source:

$ rpmbuild -bb ~/rpmbuild/SPECS/something-1.2.3.spec 

Input: ~/rpmbuild/SPECS/something-1.2.3.spec
Input: ~/rpmbuild/SOURCES/something-*
Output: ~/rpmbuild/RPMS/arch/something-1.2.3.arch.rpm

Build a Source RPM and Binary RPM from the Spec File and Source:

$ rpmbuild -ba ~/rpmbuild/SPECS/something-1.2.3.spec 

Input: ~/rpmbuild/SPECS/something-1.2.3.spec
Input: ~/rpmbuild/SOURCES/something-*
Output: ~/rpmbuild/SRPMS/something-1.2.3.src.rpm
Output: ~/rpmbuild/RPMS/arch/something-1.2.3.arch.rpm

Other Linux topics