XavierLamien/PackagingDrafts/PatchBestPractice

= Patch Best Practice Guideline =

First approach
A patch is just a file that make you able to fix trouble (such as a makefile which contains a variable which doesn't match with fedora environment) which could happen during the build of your package(s).

The goal of this guideline is to show you how you can do that easly.

So, i think the better way to learn and have nice skill in patching, it's to give you most examples as possible that you can practice to improve your knowledge.

How to create a patch
To be able to create a patch, you have for first to know (indeed) what files(s) you have to modify to fix errors. We will see this in examples use case below.

For now i will just show you action to realize to create your patch.

When you found out what file(s) (including its location) must be fix, The best way to procede is as follow:

1. Create a patch on one file.

Make a copy of file which must be fix.

$ cp bar.am bar.am.false We will now edit the original file, the .false file will be the base changing usage that the generated patch command will use to make the difference. You can use your favorite text editor to procede or use vim as follow. $ vi bar.am When it's done, use :wq command to save and exit.

Now we can procede and generate the patch as follow. $ diff -u bar.am.false bar.am > ~/rpmbuild/SOURCES/foo-%{version}-error_name_fixed.patch

2. Create a patch on multiple files.

Same thing, make a copy of each files you have to fix with extension like .false (in my example).

Then, use this follow to generate one patch file for more than one file-to-fix. $ gendiff /top/directory .false >> ~/rpmbuild/SOURCES/foo-%{version}-error_name_fixed.patch

How to apply a patch
Using a patch is very simple as drink a beer :-).

Patch usage in SPEC file: [...] Patch0:   %{name}-%{version}-featuretofix.patch Patch1:   %{name}-%{version}-toolstofix.patch [...] %setup -q -n %{name}-%{version}

%patch -p1 0 ###where 0 is Patch0, the patch number previously set. %patch -p1 1 [...]

or/and in some case

[...] %setup -q -n %{name}-%{version}

%patch -p1 -b .featurestofix %patch -p1 -b .toolstofix [...]

When does a patch is really usefull ?
This question is really important. Indeed you should know when a patch is really usefull cause, in some case the use of patch can be avoid by using sed expression in SPEC file(s). I mean that for minor fix the use of Sed is more appropriate than patch, such as fix a wrong default installation path written in Makefile file.

1. A case where a patch can be avoid

You have to build a package for both arch i386 and x86_64, which contains some libraries files which should be install in following path i386:/usr/lib and x86_64:/usr/lib64 and where configure and makefile files doesn't provided the flags options --libdir to install these libraries in /usr/lib64 for x86_64 package but in /usr/lib.It's not that we want. So to fix this the use of Sed is more appropriate and easy as follow: [...] %prep -q -n %{name}-%{version}

sed -e 's|/usr/lib/*.so|%{_libdir}/*.so|g -i /path/to/file/to/fix [...} ]

2. A case where a patch have to be set

For some build package, you have many files which contain many expression which must be fix in diferrent files (to make the build able to work) in the source tarball. In this case, the use of patch is totally more appropriate than using Sed.

We will see that in examples use case below.

First Use Case: Easy patching
We'll take for this example the package bar where you can get from its related website here:

!### TO DO ####

Second Use Case: Advanced patching
For this advanced patching i will take an application that i packaged and hardly patched to be able to work on Fedora envornment.

This pakcage is keytouch (fr), for now the rpm files are only available on my personnal repository (i plan to add them to the fedora repository). you can get the source on its website here

1. Understand the build error.

To understand the build error you have to be a lil' smart and be able to interprate the error.

Let's show the error that we get after launched the build of this package and interprate it. Executing(%install): /bin/sh -e /var/tmp/rpm-tmp.22536 + umask 022 + cd /home/sth/rpmbuild/BUILD + cd keytouch-2.3.0 + LANG=C + export LANG + unset DISPLAY + rm -rf /var/tmp/keytouch-2.3.0-beta-5-1.fc6.lxtnow-root-sth + mkdir -p /var/tmp/keytouch-2.3.0-beta-5-1.fc6.lxtnow-root-sth//etc/X11/xinit/Xclients.d + mkdir -p /var/tmp/keytouch-2.3.0-beta-5-1.fc6.lxtnow-root-sth//etc/init.d/ + mkdir -p /var/tmp/keytouch-2.3.0-beta-5-1.fc6.lxtnow-root-sth//etc/pam.d/ + mkdir -p /var/tmp/keytouch-2.3.0-beta-5-1.fc6.lxtnow-root-sth//etc/security/console.apps/ + make install DESTDIR=/var/tmp/keytouch-2.3.0-beta-5-1.fc6.lxtnow-root-sth Making install in mxml make[1] : Entering directory " != "$XSESSION_KEYTOUCHD_LINE" ] ; then \ XSESSION_TMP= ; \ echo "$XSESSION_KEYTOUCHD_LINE" > $XSESSION_FILE; \ echo "$XSESSION_TMP" >> $XSESSION_FILE; \ fi \ fi grep: /etc/X11/Xsession: No such file or directory cat: /etc/X11/Xsession: No such file or directory /bin/sh: line 10: /etc/X11/Xsession: Permission denied /bin/sh: line 11: /etc/X11/Xsession: Permission denied make[2] : *** [install-data-local]  Error 1 make[2] : Leaving directory  " != "$$XSESSION_KEYTOUCHD_LINE" ] ; then \ XSESSION_TMP= ; \ echo "$$XSESSION_KEYTOUCHD_LINE" > $$XSESSION_FILE; \ --- keytouch-2.3.0-beta-4/keytouchd/Makefile.in.false1	2007-01-11 16:23:07.000000000 +0100 +++ keytouch-2.3.0-beta-4/keytouchd/Makefile.in	2007-01-11 16:27:14.000000000 +0100 @@ -333,13 +333,13 @@ install-data-local: @$(NORMAL_INSTALL) XSESSION_KEYTOUCHD_LINE="keytouchd &"; \ -	XSESSION_DIR="$(DESTDIR)/etc/X11/Xsession.d"; \ +	XSESSION_DIR="$(DESTDIR)/etc/X11/xinit/Xclients.d"; \ if [ -d $$XSESSION_DIR ] ; then \ echo '# $$Id: 92keytouchd_launch' > $$XSESSION_DIR/92keytouchd_launch; \ echo "$$XSESSION_KEYTOUCHD_LINE" >> $$XSESSION_DIR/92keytouchd_launch; \ chmod 644 $$XSESSION_DIR/92keytouchd_launch; \ else \ -		XSESSION_FILE="/etc/X11/Xsession"; \ +		XSESSION_FILE="/etc/X11/xinit/Xsession"; \ if [ " " != "$$XSESSION_KEYTOUCHD_LINE" ] ; then \ XSESSION_TMP= ; \ echo "$$XSESSION_KEYTOUCHD_LINE" > $$XSESSION_FILE; \ --- keytouch-2.3.0-beta-4/keytouch-init/Makefile.am.false1	2007-01-11 16:17:10.000000000 +0100 +++ keytouch-2.3.0-beta-4/keytouch-init/Makefile.am	2007-01-11 16:19:04.000000000 +0100 @@ -19,11 +19,10 @@ install-data-local: @$(NORMAL_INSTALL)

-	if [  ] ; then \ +	if [ /sbin/chkconfig ] ; then \ echo "$(bindir)/keytouch-init" > $(DESTDIR)/etc/init.d/keytouch-init.sh; \ chmod +x $(DESTDIR)/etc/init.d/keytouch-init.sh; \ --- keytouch-2.3.0-beta-4/keytouch-init/Makefile.in.false1	2007-01-11 16:17:10.000000000 +0100 +++ keytouch-2.3.0-beta-4/keytouch-init/Makefile.in	2007-01-11 16:18:28.000000000 +0100 @@ -332,11 +332,10 @@ install-data-local: @$(NORMAL_INSTALL)

-	if [  ] ; then \ +	if [ /sbin/chkconfig ] ; then \ sed 's,\(^keytouchinit=\)\(.*\),\1$(bindir)/keytouch-init,' keytouch-init.sh \ > $(DESTDIR)/etc/init.d/keytouch-init.sh; \ chmod +x $(DESTDIR)/etc/init.d/keytouch-init.sh; \ -		chkconfig --add keytouch-init.sh; \ elif [  ] ; then \ echo "$(bindir)/keytouch-init" > $(DESTDIR)/etc/init.d/keytouch-init.sh; \ chmod +x $(DESTDIR)/etc/init.d/keytouch-init.sh; \ --- keytouch-2.3.0-beta-4/keytouch-acpid/Makefile.am.false1	2007-01-11 16:13:41.000000000 +0100 +++ keytouch-2.3.0-beta-4/keytouch-acpid/Makefile.am	2007-01-11 16:15:37.000000000 +0100 @@ -19,11 +19,10 @@ install-data-local: @$(NORMAL_INSTALL)

-	if [  ] ; then \ +	if [ /sbin/chkconfig ] ; then \ sed 's,\(^keytouchacpid=\)\(.*\),\1"$(bindir)/keytouch-acpid \&",' keytouch-acpid.sh \ > $(DESTDIR)/etc/init.d/keytouch-acpid.sh; \ chmod +x $(DESTDIR)/etc/init.d/keytouch-acpid.sh; \ -		chkconfig --add keytouch-acpid.sh; \ elif [  ] ; then \ echo "$(bindir)/keytouch-acpid &" > $(DESTDIR)/etc/init.d/keytouch-acpid.sh; \ chmod +x $(DESTDIR)/etc/init.d/keytouch-acpid.sh; \ --- keytouch-2.3.0-beta-4/keytouch-acpid/Makefile.in.false1	2007-01-11 16:13:41.000000000 +0100 +++ keytouch-2.3.0-beta-4/keytouch-acpid/Makefile.in	2007-01-11 16:15:11.000000000 +0100 @@ -332,11 +332,10 @@ install-data-local: @$(NORMAL_INSTALL)

-	if [  ] ; then \ +	if [ /sbin/chkconfig ] ; then \ sed 's,\(^keytouchacpid=\)\(.*\),\1"$(bindir)/keytouch-acpid \&",' keytouch-acpid.sh \ > $(DESTDIR)/etc/init.d/keytouch-acpid.sh; \ chmod +x $(DESTDIR)/etc/init.d/keytouch-acpid.sh; \ -		chkconfig --add keytouch-acpid.sh; \ elif [  ] ; then \ echo "$(bindir)/keytouch-acpid &" > $(DESTDIR)/etc/init.d/keytouch-acpid.sh; \ chmod +x $(DESTDIR)/etc/init.d/keytouch-acpid.sh; \

3. Re-launch the build.

third Use Case: Expert patching
!## TO DO ##

--- mdsplib-0.11/Makefile~	2007-06-08 11:31:18.000000000 +0200 +++ mdsplib-0.11/Makefile	2007-06-08 11:31:18.000000000 +0200 @@ -5,16 +5,15 @@ libdir = $(prefix)/lib includedir = $(prefix)/include
 * 2. Create the patch to fix

-library: libmetar.a +library: libmetar.so.0

all: dmetar library

-libmetar.a: src/antoi.o src/charcmp.o src/dcdmetar.o src/dcdmtrmk.o src/fracpart.o src/prtdmetr.o src/stspack2.o src/stspack3.o -	ar ruv libmetar.a src/antoi.o src/charcmp.o src/dcdmetar.o src/dcdmtrmk.o src/fracpart.o src/prtdmetr.o src/stspack2.o src/stspack3.o -	ranlib libmetar.a +libmetar.so.0: src/antoi.o src/charcmp.o src/dcdmetar.o src/dcdmtrmk.o src/fracpart.o src/prtdmetr.o src/stspack2.o src/stspack3.o +	gcc -shared -o libmetar.so.0 -Wl,-soname,libmetar.so.0 src/antoi.o src/charcmp.o src/dcdmetar.o src/dcdmtrmk.o src/fracpart.o src/prtdmetr.o src/stspack2.o src/stspack3.o

-dmetar: src/drvmetar.o libmetar.a -	$(CC) $(CFLAGS) -o dmetar src/drvmetar.o libmetar.a $(LIBS) +dmetar: src/drvmetar.o libmetar.so.0 +	$(CC) $(CFLAGS) -o dmetar src/drvmetar.o -L. -lmetar $(LIBS)

src/antoi.o: src/antoi.c src/local.h $(CC) $(CFLAGS) -c src/antoi.c -o src/antoi.o @@ -44,14 +43,13 @@ $(CC) $(CFLAGS) -c src/stspack3.c -o src/stspack3.o

clean: -	rm -f src/*.o dmetar libmetar.a +	rm -f src/*.o dmetar libmetar.so.0

install: library mkdir -p $(DESTDIR)$(includedir) cp metar.h $(DESTDIR)$(includedir)/ chmod 0644 $(DESTDIR)$(includedir)/metar.h mkdir -p $(DESTDIR)$(libdir) -	cp libmetar.a $(DESTDIR)$(libdir)/ -	chmod 0644 $(DESTDIR)$(libdir)/libmetar.a -	ranlib $(DESTDIR)$(libdir)/libmetar.a - +	cp libmetar.so.0 $(DESTDIR)$(libdir)/ +	chmod 0755 $(DESTDIR)$(libdir)/libmetar.so.0 +	ln -s libmetar.so.0 $(DESTDIR)$(libdir)/libmetar.so