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
Creating an RPM Package of a Directory Structure
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