Richardfearn (talk | contribs) (add link to RPM HOWTO) |
Richardfearn (talk | contribs) (add info about building just the binary package (-bb) or just the source package (-bs)) |
||
Line 383: | Line 383: | ||
When you run it you will see that loading and saving files now uses the new-style file dialog box. | When you run it you will see that loading and saving files now uses the new-style file dialog box. | ||
{{message|<code>rpmbuild -ba</code> builds the binary and source packages. You can also build just the binary package (with <code>-bb</code>), or just the source package (with <code>-bs</code>).}} | |||
=== Case Study: OpenEXR === | === Case Study: OpenEXR === |
Revision as of 00:39, 2 April 2010
Documentation Summary:
Purpose: Document to explain how to build and modify packages.
Audience: Experienced users interested in building RPM packages, either for the Fedora Project or their own use.
Assumptions: Reader has root access to a Fedora system.
Related Documents: Maximum RPM; RPM HOWTO
Lead Writer: Ignacio Vazquez-Abrams
RahulSundaram Note to Writer:
There seems to be a related guide available. You might want to combine the work being done
http://koti.welho.com/vskytta/packagers-handbook/packagers-handbook.html
VilleSkyttä notes: packagers-handbook is in docs CVS, see http://cvs.fedora.redhat.com/viewcvs/packagers-handbook/?root=docs
Building Packages in Fedora
Changelog
2005.08.22: 0.0: Initial proposal (Ignacio Vazquez-Abrams)
2005.08.30: 0.1: Moved to wiki (Ignacio Vazquez-Abrams)
2005.09.10: 0.2: Filled in intro to "Creating a New Package" and "Case Study: leafpad" (Ignacio Vazquez-Abrams)
2005.10.31: 0.3: Filled in mock appendix (Ignacio Vazquez-Abrams)
2005.12.30: 0.4: Adjusted the creating a non-root rpmbuild Buildroot (James Lawrence)
2006.03.16: 0.5: Filled in the library section (Ignacio Vazquez-Abrams)
2009.03.30: 0.6: Pruned empty sections (Ignacio Vazquez-Abrams)
Introduction
RPM (RPM Package Manager) is at the heart of Fedora. It is responsible for installing new software, as well as tracking files so that the same software can be uninstalled with a minimum of fuss. But RPM on its own doesn't actually do anything. It's up to the packager to specify how a package is built, as well as explaining what sort of files the package contains, and what other packages it relies upon for proper operation.
Goals
This guide explains how to create packages under Fedora as opposed to other RPM-based Linux distributions. It is not intended to be an exhaustive guide to all possible spec file and rpmbuild options. For those you are invited to look at the latest snapshot of Maximum RPM .
Intended Audience
This guide is written for people who want to build packages in Fedora, either for themselves or for others.
Structure of a Package
- Header
This contains things such as the name, version, release, epoch, and architecture the package was built for, as well as what this package requires from other packages and what it provides to other packages.
- Files
This contains all files, directories, symlinks, etc. contained in the package, as well as the size, permissions, ownership, and SELinux file context.
- Scripts
This contains the scripts to be run during package install and uninstall, as well as the script run during an RPM verify.
Creating a New Package
Tarballs are convenient. They can hold almost anything and they can be opened on almost any operating system. The problem is that files installed from a tarball are almost impossible to track. For this reason it's useful to be able to turn a tarball into a package. This chapter shows you examples of this.
Creating a non-root Buildroot
Most software source code comes in the form of tarballs (a tar archive compressed with either gzip or bzip2). It's possible to inadvertently have code in a makefile or script in a tarball that could damage your system. For this reason it's best to build packages as a user that doesn't have full access to the system.
Creating a non-root buildroot is easy:
- As root, install the
rpmdevtools
package:yum install rpmdevtools
- As a normal user, run
rpmdev-setuptree
. This creates a~/rpmbuild
directory where packages are built as well as adding vital options to the~/.rpmmacros
file. - Open
~/.rpmmacros
in a text editor and add a few more useful options at the end of the file:- "%packager Your Name Here <Your E-mail Address>"
- This allows other people to find you should they have questions if your package ever gets released into the public.
- "%vendor Your Callsign Here"
- This provides an easy way to separate your packages from packages of the same software made by other sources.
- "%packager Your Name Here <Your E-mail Address>"
Case Study: leafpad
Leafpad is a simple application. For installation, it only requires the binary, the icon, the menu entry, and gettext translations. This makes it a good project to examine for packaging. The homepage for leafpad itself is at http://tarot.freeshell.org/leafpad.
The first step is to go into the buildroot and create a new spec file for your package. In a terminal run the following commands:
cd ~/rpmbuild/SPECS rpmdev-newspec leafpad
This creates a new spec file called leafpad.spec
.
Open the spec file in a text editor.
Name: leafpad Version: Release: 1 Summary: Group: License: URL: Source0: BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n) BuildRequires: Requires: %description %prep %setup -q %build %configure make %{?_smp_mflags} %install rm -rf $RPM_BUILD_ROOT make install DESTDIR=$RPM_BUILD_ROOT %clean rm -rf $RPM_BUILD_ROOT %files %defattr(-,root,root,-) %doc %changelog
Since this is an unofficial package, the first thing you do is set the release to something lower than 1. Also, put a "tag" in the release to help show where the package comes from. Then follow it with the actual release in the sequence of packages that you may eventually release.
Next you fill in the version (as of writing this, 0.8.3) as well as add a summary pulled from the website.
Version: 0.8.3 Release: 0.docs.1 Summary: A GTK+ based simple text editor
Now you need to categorize the package into an appropriate group. The groups are listed in /usr/share/doc/rpm-*/GROUPS
or in RPMGroups . In this case the appropriate group is Applications/Editors since leafpad is a text editor.
For the license field, leafpad uses the GPL. From the leafpad website, get the URL for downloading leafpad 0.8.3.
Use this information to fill out the next section:
Group: Applications/Editors License: GPL URL: http://tarot.freeshell.org/leafpad/ Source0: http://savannah.nongnu.org/download/leafpad/leafpad-0.8.3.tar.gz
Next you must deal with BuildRequires and Requires. According to the leafpad webpage, it needs GTK+ >= 2.0.0 in order to build or run. You can let RPM figure out what libraries it needs to run, so fill in BuildRequires and comment out Requires for now.
BuildRequires: gtk2-devel >= 2.0.0 #Requires:
Add a description for the package. The lines of text in %description should be at most 79 charaters long.
%description Leafpad is a GTK+ based simple text editor. The user interface is similar to Notepad. It aims to be lighter than GEdit and KWrite, and to be as useful as them.
For now we'll skip most of the sections and just worry about %changelog at this time. Fill it in with the date (the command LC_TIME=en_US date +"%a %b %e %Y"
will give you the exact text you should put), your name, your e-mail address, the version and release of the package, and a short description of what's changed in the package. Since this is the first package we'll just say that instead.
%changelog * Gud Fez 74 6395 Foobly Barowitz <foobly@barowitz.tld> 0.8.3-0.docs.1 - Initial RPM release
So now the spec file should look like this (except with today's date and your name and e-mail address in %changelog):
Name: leafpad Version: 0.8.3 Release: 0.docs.1 Summary: A GTK+ based simple text editor Group: Applications/Editors License: GPL URL: http://tarot.freeshell.org/leafpad/ Source0: http://savannah.nongnu.org/download/leafpad/leafpad-0.8.3.tar.gz BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n) BuildRequires: gtk2-devel >= 2.0.0 #Requires: %description Leafpad is a GTK+ based simple text editor. The user interface is similar to Notepad. It aims to be lighter than GEdit and KWrite, and to be as useful as them. %prep %setup -q %build %configure make %{?_smp_mflags} %install rm -rf $RPM_BUILD_ROOT make install DESTDIR=$RPM_BUILD_ROOT %clean rm -rf $RPM_BUILD_ROOT %files %defattr(-,root,root,-) %doc %changelog * Gud Fez 74 6395 Foobly Barowitz <foobly@barowitz.tld> 0.8.3-0.docs.1 - Initial RPM release
Now you need to actually download the source for leafpad and put it in the right place. Go ahead and download the tarball with your browser, wget, curl, or some other tool, then move it to ~/rpmbuild/SOURCES.
So now that you have the spec file and the sources, you need to actually go through the motions of building the package, which involves going through to the end of %build. Type the following commands in a terminal:
cd ~/rpmbuild/SPECS rpmbuild -bc leafpad.spec
At this point you will most likely end up with an error message, especially if you've never built any software on your machine before. Let's work through them one at a time.
bash: /usr/bin/rpmbuild: No such file or directory
This indicates that you need to install the rpm-build package, however you should already have it installed since it's a dependency of rpmdevtools which you had to install in order to previously create the non-root buildroot.
error: Failed build dependencies:
gtk2-devel >= 2.0.0 is needed by leafpad-0.8.3-0.docs.1.i386
This message tells you that you need to install files or packages in order to build the package. You can use yum to install the files or packages that it indicates. In this case you would use yum install gtk2-devel
in order to do so.
Once you get a clean build the last line of output will be + exit 0
. You can then go ahead and test %install like so:
rpmbuild -bi leafpad.spec
At this point you definitely will see errors:
RPM build errors: Installed (but unpackaged) file(s) found: /usr/bin/leafpad /usr/share/applications/leafpad.desktop /usr/share/locale/bg/LC_MESSAGES/leafpad.mo /usr/share/locale/ca/LC_MESSAGES/leafpad.mo /usr/share/locale/cs/LC_MESSAGES/leafpad.mo /usr/share/locale/de/LC_MESSAGES/leafpad.mo /usr/share/locale/es/LC_MESSAGES/leafpad.mo /usr/share/locale/fr/LC_MESSAGES/leafpad.mo /usr/share/locale/hu/LC_MESSAGES/leafpad.mo /usr/share/locale/it/LC_MESSAGES/leafpad.mo /usr/share/locale/ja/LC_MESSAGES/leafpad.mo /usr/share/locale/lt/LC_MESSAGES/leafpad.mo /usr/share/locale/pl/LC_MESSAGES/leafpad.mo /usr/share/locale/pt/LC_MESSAGES/leafpad.mo /usr/share/locale/ru/LC_MESSAGES/leafpad.mo /usr/share/locale/sk/LC_MESSAGES/leafpad.mo /usr/share/locale/sv/LC_MESSAGES/leafpad.mo /usr/share/locale/ta/LC_MESSAGES/leafpad.mo /usr/share/locale/vi/LC_MESSAGES/leafpad.mo /usr/share/locale/zh_CN/LC_MESSAGES/leafpad.mo /usr/share/locale/zh_TW/LC_MESSAGES/leafpad.mo /usr/share/pixmaps/leafpad.png
The next step is to take all those files and put them in %files. But just copying and pasting them would be the wrong thing to do.
RPM has a number of macros that can be used to shorten the spec file or add needed flexibility. You can see some of the directory-based macros in RPMMacros . You can get a complete list by running rpm --showrc
.
So go ahead and add all of the files except the ones under /usr/share/locale to %files, substituting macros where appropriate.
%files %defattr(-,root,root,-) %doc %{_bindir}/leafpad %{_datadir}/applications/leafpad.desktop %{_datadir}/pixmaps/leafpad.png
Now you just need to handle the files under /usr/share/locale. Fortunately Fedora provides the %find_lang
macro for that. It looks for all files under /usr/share/locale that match the argument you pass it and puts them in a file of the same name appended with ".lang". The macro is called at the end of %install. Since the name of the package is "leafpad" we can just use the appropriate macro instead.
%install rm -rf $RPM_BUILD_ROOT make install DESTDIR=$RPM_BUILD_ROOT %find_lang %{name}
And you also need to tell %files to include the files listed in the generated file.
%files -f %{name}.lang %defattr(-,root,root,-) %doc %{_bindir}/leafpad %{_datadir}/applications/leafpad.desktop %{_datadir}/pixmaps/leafpad.png
At this point the package will build, but there is another step to take before you're ready.
You need to fill in the %doc specifier in %files with any documentation for the app. Go to ~/rpmbuild/BUILD/leafpad-0.8.3
and look at the files there. Most of them are only needed to build the app, but some are useful to include. The specific files you're interested in are AUTHORS, ChangeLog, COPYING, NEWS, and README, so go ahead and add them to %doc in %files.
%files -f %{name}.lang %defattr(-,root,root,-) %doc AUTHORS ChangeLog COPYING NEWS README %{_bindir}/leafpad %{_datadir}/applications/leafpad.desktop %{_datadir}/pixmaps/leafpad.png
Now you can go ahead and test the package again.
rpmbuild -bi leafpad.spec
Success! You can now go ahead and build the binary and source packages.
rpmbuild -ba leafpad.spec
Close to the end of the process you'll see three files being written. The first one is the source package, the second is the binary package, and the third is the debug information for the binary package. If you already have leafpad installed from Fedora go ahead and remove it now, and install the new binary package as root.
rpm -e leafpad rpm -Uvh /path/to/leafpad-0.8.3-0.docs.1.$(uname -i).rpm
After installing it a menu entry named Leafpad should appear under Accessories. Go ahead and run it, and try it out a bit.
You may notice that leafpad currently uses the old-style GTK+ file dialog box for opening and saving files. In order to make it use the new-style file dialog box you need to pass an option to configure. Normally you would run ./configure --help
to show us the different options, but the act of producing a proper package wipes the necessary files. In a terminal run the following:
cd ~/rpmbuild/SPECS rpmbuild -bp leafpad.spec
This goes through just the %prep section of the spec file (unpacks the tarball and applies any patches). Now you can do the following to see the options:
cd ~/rpmbuild/BUILD/leafpad-0.8.3 ./configure --help
In this case the option you're looking for is --enable-chooser
. Go ahead and modify %build appropriately.
%build %configure --enable-chooser make %{?_smp_mflags}
Now you need to increment the release and add the %changelog entry.
Version: 0.8.3 Release: 0.docs.2 Summary: A GTK+ based simple text editor
%changelog * Wed Jan 30 2008 Foobly Barowitz <foobly@barowitz.tld> 0.8.3-0.docs.2 - Enabled new-style GTK+ file dialog * Mon Jan 21 2008 Foobly Barowitz <foobly@barowitz.tld> 0.8.3-0.docs.1 - Initial RPM release
So now rebuild the package.
rpmbuild -ba leafpad.spec
Since the release of the new package is higher than the old package you can just upgrade it directly as root.
rpm -Uvh /path/to/leafpad-0.8.3-0.docs.2.$(uname -i).rpm
When you run it you will see that loading and saving files now uses the new-style file dialog box.
Case Study: OpenEXR
OpenEXR is a library created by Industrial Light & Magic for creating and using high dynamic range images. Create and fill in a spec file for OpenEXR in the same manner as you did for leafpad.
Name: OpenEXR Version: 1.2.2 Release: 0.docs.1 Summary: A high dynamic-range (HDR) image file format Group: System Environment/Libraries License: BSD URL: http://www.openexr.com/ Source0: http://savannah.nongnu.org/download/openexr/OpenEXR-1.2.2.tar.gz BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n) BuildRequires: #Requires: %description OpenEXR is a high dynamic-range (HDR) image file format developed by Industrial Light & Magic for use in computer imaging applications. %prep %setup -q %build %configure make %{?_smp_mflags} %install rm -rf $RPM_BUILD_ROOT make install DESTDIR=$RPM_BUILD_ROOT %clean rm -rf $RPM_BUILD_ROOT %files %defattr(-,root,root,-) %doc %changelog * Gud Fez 74 6395 Foobly Barowitz <foobly@barowitz.tld> 1.2.2-0.docs.1 - Initial RPM release
Unfortunately the OpenEXR website is far less forthcoming regarding what packages are required to build the library. Comment out the BuildRequires line for now, download the source tarball, and run the prep stage.
#BuildRequires: #Requires:
rpmbuild -bp OpenEXR.spec
Go into the BUILD/OpenEXR-1.2.2 directory and open the INSTALL file there. Most packages have build instructions in this file. Some even include a list of build requirements. Unfortunately OpenEXR does not.So then close this file and open README instead. About halfway through the file it reads "exrdisplay requires FLTK 1.1 or greater" so go ahead and add this to BuildRequires, remembering to uncomment it.
BuildRequires: fltk-devel >= 1.1 #Requires:
Now try to compile the package:
rpmbuild -bc OpenEXR.spec
error: Failed build dependencies: fltk-devel >= 1.1 is needed by OpenEXR-1.2.2-0.docs.1.i386
Of course, you need to actually install the fltk-devel
package in order to build OpenEXR, so do so now with yum. Once that is done, try compiling the package again.
checking for strerror... yes checking for compress in -lz... no configure: error: *** OpenEXR requires a recent version of zlib, which you don't appear to *** have. *** *** This could be because the run-time linker is not finding zlib, or it *** is finding the wrong version. In this case, you'll need to set your *** LD_LIBRARY_PATH environment variable, or edit /etc/ld.so.conf to point *** to the proper version. Also, make sure you have run ldconfig if *** that is required on your system. error: Bad exit status from /var/tmp/rpm-tmp.XXXXX (%build) RPM build errors: Bad exit status from /var/tmp/rpm-tmp.XXXXX (%build)
It seems that FLTK isn't the only package required to build OpenEXR. Go ahead and add zlib-devel to BuildRequires and install it via yum.
BuildRequires: fltk-devel >= 1.1 zlib-devel #Requires:
Now compile once more.
[more messages above] makeTiled.cpp: In function 'void<unnamed>::reduceY(const TypedImageChannel<T>&, TypedImageChannel<T>&, bool, Extrapolation, bool) [with T = unsigned int] ': makeTiled.cpp:447: instantiated from here makeTiled.cpp:318: error: 'class TypedImageChannel<unsigned int>' has no member named 'image' makeTiled.cpp:319: error: 'const class TypedImageChannel<unsigned int>' has no member named 'image' makeTiled.cpp:320: error: 'class TypedImageChannel<unsigned int>' has no member named 'image' make[1] : *** [makeTiled.o] Error 1 make: *** [all-recursive] Error 1 error: Bad exit status from /var/tmp/rpm-tmp.XXXXX (%build) RPM build errors: Bad exit status from /var/tmp/rpm-tmp.XXXXX (%build)
Isn't this an interesting predicament. What has happened here is that the compiler has detected a problem in the source and is failing because the compiler cannot make sense of it. If you scroll back to the first few error messages you can get a clue about what is causing the error.
./Image.h:59: error: expected <code>)' before '&' token ./Image.h:64: error: ISO C++ forbids declaration of 'Image' with no type ./Image.h:64: error: expected ';' before '&' token
In this case the second line is saying that the source is using a datatype before it knows that the datatype exists. From the line we see that the problem is in a file called Image.h
. Scroll up a bit further to find out where this file is located.
Making all in exrmaketiled make[1] : Entering directory <code>~/rpmbuild/BUILD/OpenEXR-1.2.2/exrmaketiled'
Go to this directory, open Image.h
, and go to line 59.
class ImageChannel { public: friend class Image; ImageChannel (Image &Image); virtual ~ImageChannel(); virtual Imf::Slice slice () const = 0; Image & image () {return _image;} const Image & image () const {return _image;}
What you have here is the beginning of the declaration for the ImageChannel
class. When you examine the problems in the error messages listed above in relation to the source code you will notice that they all refer to Image
. The C++ standard dictates that you cannot use a type until the compiler knows about it, however the friend
declaration on line 57 is not enough to do so. You must add a line telling the compiler about the Image
class. But before you do so, copy the file to Image.h.friend
:
cp Image.h Image.h.friend
Now put a forward declaration of the Image
class before the declaration of the ImageChannel
class. You are supposed to edit the original file, not the new Image.h.friend
.
class Image; class ImageChannel {
Since RPM uses pristine tarballs to build packages, you now need to make a patch containing the difference between the original file and the modified file. RPM provides a convenient tool for this called gendiff
. When run against a directory and passed a suffix it will compare all files with that suffix to the corresponding files without that suffix and generate a patch with the changes:
cd ~/rpmbuild/BUILD gendiff OpenEXR-1.2.2 .friend > ../SOURCES/OpenEXR-1.2.2-friend.patch
The generated patch should look similar to this:
--- OpenEXR-1.2.2/exrmaketiled/Image.h.friend YYYY-MM-DD hh:mm:ss.xxxxxxxxx -ZZZZ +++ OpenEXR-1.2.2/exrmaketiled/Image.h YYYY-MM-DD hh:mm:ss.xxxxxxxxx -ZZZZ @@ -49,6 +49,7 @@ +class Image; class ImageChannel {
Now add the patch to the spec file so that rpmbuild uses it during the build.
Source0: http://savannah.nongnu.org/download/openexr/OpenEXR-1.2.2.tar.gz Patch0: OpenEXR-1.2.2-friend.patch BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
%prep %setup -q %patch0 -p1 -b .friend %build
Compile the package once again.
make[1] : Leaving directory <code>/home/ignacio/work/rpmbuild/BUILD/OpenEXR-1.2.2/exrenvmap' make[1] : Entering directory <code>/home/ignacio/work/rpmbuild/BUILD/OpenEXR-1.2.2' make[1] : Nothing to be done for <code>all-am'. make[1] : Leaving directory <code>/home/ignacio/work/rpmbuild/BUILD/OpenEXR-1.2.2' + exit 0
Much better. Now initiate the install phase:
rpmbuild -bi OpenEXR.spec
RPM build errors: Installed (but unpackaged) file(s) found: /usr/bin/exrdisplay /usr/bin/exrenvmap /usr/bin/exrheader /usr/bin/exrmakepreview /usr/bin/exrmaketiled /usr/bin/exrstdattr /usr/include/OpenEXR/Iex.h /usr/include/OpenEXR/IexBaseExc.h ... /usr/include/OpenEXR/halfFunction.h /usr/include/OpenEXR/halfLimits.h /usr/lib/libHalf.a /usr/lib/libHalf.la /usr/lib/libHalf.so /usr/lib/libHalf.so.2 /usr/lib/libHalf.so.2.0.2 /usr/lib/libIex.a /usr/lib/libIex.la /usr/lib/libIex.so /usr/lib/libIex.so.2 /usr/lib/libIex.so.2.0.2 /usr/lib/libIlmImf.a /usr/lib/libIlmImf.la /usr/lib/libIlmImf.so /usr/lib/libIlmImf.so.2 /usr/lib/libIlmImf.so.2.0.2 /usr/lib/libImath.a /usr/lib/libImath.la /usr/lib/libImath.so /usr/lib/libImath.so.2 /usr/lib/libImath.so.2.0.2 /usr/lib/pkgconfig/OpenEXR.pc /usr/share/aclocal/openexr.m4 /usr/share/doc/OpenEXR-1.2.2/examples/drawImage.cpp /usr/share/doc/OpenEXR-1.2.2/examples/drawImage.h ... /usr/share/doc/OpenEXR-1.2.2/examples/rgbaInterfaceTiledExamples.cpp /usr/share/doc/OpenEXR-1.2.2/examples/rgbaInterfaceTiledExamples.h
That's quite a large number of files. Fortunately you don't need to specify every single file; specifying a directory will include every file and directory under it. But before you add them, notice that many of the files are libraries and C/C++ headers. You will need to create a devel
subpackage to contain the files required for building packages against OpenEXR.
%description OpenEXR is a high dynamic-range (HDR) image file format developed by Industrial Light & Magic for use in computer imaging applications. %package devel Summary: Headers and libraries for building apps that use OpenEXR Group: Development/Libraries Requires: %{name} = %{version}-%{release} %description devel This package contains headers and libraries required to build applications that use the OpenEXR format. %prep
%files %defattr(-,root,root,-) %doc %files devel %defattr(-,root,root,-) %doc %changelog
The tarball also rudely places examples in the documentation directory of the main package when it would make more sense to have them in the devel subpackage.
%install rm -rf $RPM_BUILD_ROOT make install DESTDIR=$RPM_BUILD_ROOT rm -rf $RPM_BUILD_ROOT%{_defaultdocdir}/%{name}-%{version}/examples
All executables and *.so.* files should be placed in the main package.
%files %defattr(-,root,root,-) %doc %{_bindir}/* %{_libdir}/*.so.*
All headers, static libraries, libtool archives, *.so files, autotools, and pkgconfig files go in the -devel subpackage.
%files devel %defattr(-,root,root,-) %doc %{_includedir}/%{name} %{_libdir}/*.a %{_libdir}/*.la %{_libdir}/*.so %{_libdir}/pkgconfig/%{name}.pc %{_datadir}/aclocal/*.m4
We should add the examples to the documentation in the -devel subpackage. Normally we would use
%doc examples
to do this, but unfortunately there are 2 problems. The first is that the directory isn't called "examples". By looking at the various files under BUILD/OpenEXR-1.2.2 we find that the directory is actually called "IlmImfExamples". The second problem is that the directory will contain several files that we don't want included in the final package. What should be done is to copy it in %prep to the proper name and remove to undesired files, and then add it to %doc in -devel, and any appropriate files to %doc in the main package.
%prep %setup -q %patch0 -p1 -b .friend cp -a IlmImfExamples examples rm examples/Makefile*
%files %defattr(-,root,root,-) %doc AUTHORS ChangeLog LICENSE NEWS README %{_bindir}/* %{_libdir}/*.so.* %files devel %defattr(-,root,root,-) %doc examples %{_includedir}/%{name} %{_libdir}/*.a %{_libdir}/*.la %{_libdir}/*.so %{_libdir}/pkgconfig/%{name}.pc %{_datadir}/aclocal/*.m4
Since the package places shared libraries into normal directories /sbin/ldconfig will have to be invoked after the package has been installed or removed as described in ScriptletSnippets.
%clean rm -rf $RPM_BUILD_ROOT %post -p /sbin/ldconfig %postun -p /sbin/ldconfig %files
So now if you rebuild it you will find that it builds cleanly. Go ahead and build and then install the binary packages.
rpmbuild -bb OpenEXR.spec rpm -Uvh /path/to/OpenEXR-1.2.2-0.docs.1.arch.rpm /path/to/OpenEXR-devel-1.2.2-0.docs.1.arch.rpm
Appendix: mock: Chroot Buildtool
Turning a spec file, a tarball, and patches into an actual package is a complex process. Installed development packages can poison the package with unexpected capabilities, which will cause users of the package to complain when their builds lack those capabilities. Additionally, it is very easy to miss BuildRequires that need to be added to the spec file.
Unix-class operating systems provide a facility known as chroot which causes a subdirectory to become the new root directory temporarily. mock
is a tool which takes advantage of this facility to provide a "cleanroom" build of a source package. Only a basic set of packages plus the packages listed in BuildRequires are installed into the chroot and then mock builds the package under the chroot. This creates a clean, reproducible build of the package.
mock
takes the following command line arguments:
-r <root>
: This gives the root you want to use. It should match one of the configuration files in/etc/mock
.--resultdir=<directory>
: This tells mock where you want the logs and built packages to be placed.<source package>
: This is the source RPM you want to rebuild.
E.g., mock -r fedora-4-i386-core --resultdir=mock-leafpad-0.8.3 leafpad-0.8.3-0.docs.2.src.rpm
The configuration file is actually a Python script that creates a dictionary (config_opts
) that contains all the values used by mock
for generating the chroot and building source packages. The keys in the dictionary include:
root
: The directory under/var/lib/mock
in which to generate the chroot.target_arch
: The processor architecture the chroot handles.yum.conf
: The yum configuration file content used by the chroot.macros
: A set of RPM macros to be initialized bymock
.