From Atomicorp Wiki
Jump to: navigation, search


[edit] Abstract

A src.rpm is completely self contained, it has everything internal to it to archive, patch, build, and install a piece of software. It also contains macros to run actions before, and after the package is installed, and trigger macros to run before/after its installed when it detects other packages. The action of building an RPM will never involve you installing the package as a requirement to build it.

[edit] PSA App Vault RPMS

What makes app vault rpms unique is that you are in effect packaging something for another package management system. That involves more steps, and more changes that have nothing to do with the RPM system. IE, they have their own XML file used to describe the application, and its dependencies.

[edit] So here are some tips on building a package that is maintainable:

1) dont ever modify the application tarball directly. Use patches instead, even if it takes you an extra hour to do it right. When you update your rpm in a few months, its going to save you a lot of time.

2) leverage the %install macro if you've got to move files around. This is especially handy since the PSA app vault packages rebundle the web app as httpdocs.tar. Dont waste time doing that up front, when you do it in %install it will make your life a lot easier on the next update.

3) Try to avoid using the Epoch: tag (this overrides the version #). I went Epoch crazy early on, and its coming back to haunt me now. Only use the Epoch tag when all other options have been exhausted.

4) When you're building binary RPMs (not app vault), check out mock. It builds a chrooted OS for whatever platform you need to build packages for. This is useful in that it keeps your build tree away from your production OS.

5) Dont make rpms interactive. Avoid any output, special commands, documentation, that get displayed during the installation. If its being run through yum, a web interface, etc. Odds are noone will see it anyway, and worst case, it could break those apps.

[edit] building rpms with rpmbuild

1) Build as yourself. Not root, you'll need to do some work first. Start with your ~/.rpmmacros file

 vim ~/.rpmmacros

2) Add path to build dirs

 %_topdir               /home/sshinn/src/redhat/

3) Create your builddirs

 mkdir -p ~/src/redhat
 cd ~/src/redhat
 cd RPMS
 mkdir i386 i686 x86_64

4) Build stuff, example:

 rpmbuild --rebuild whatever-1.0-1.src.rpm

[edit] building rpms with mock

 mock -r <DISTRO> whatever.src.rpm

On my system, Ive called my /etc/mock/ configs el4-i386.cfg, el5-x86_64.cfg, so the way I run it is:

 mock -r el4-i386 whatever.src.rpm

I also wrote a wrapper around Mock to rapidly build packages for multiple platforms called "art-build". Its loosely based on Dag Wieers DAR package (pre-mock builder), so instead of building from the src.rpm, I build from the .spec file. You can see art-build here: http://www.atomicorp.com/Tutorials/Building%20RPMS/

[edit] Modifying RPMS

[edit] SPEC: Conditional Statements

Example 1: an if someversion, else (new way)

%if 0%{?el3}%{?el4}
BuildRequires: somepackage
BuildRequires: someotherpackage

Example 2: Specific version (old way)

%{?fc4:BuildRequires: libpcap }

[edit] SPEC: automatically add in the date to a changelog

%define date    %(echo `LC_ALL="C" date +"%a %b %d %Y"`)
* %{date} PLD Team  <feedback@pld-linux.org>

[edit] Requires/BuildRequires:

Some interesting ways to implement a Requires:

BuildRequires:  %{_includedir}/pcap.h

This would get around a problem where two distros are calling a package different things. In this example it would get around libpcap being called "libpcap" on el4, and "libpcap-devel" on fc9.

[edit] SPEC: Post/Postun Notes

# only rpm -i (not rpm {-U|-F}) except if this is a first time install
if [ $1 = 1 ]; then
 echo whatever
# only rpm {-U|-F}
if [ $1 = 2 ]; then
  echo whatever

# only on rpm {-U|-F}

if [ $1 = 2 ]; then
  echo "pre code 2, upgrade event"
# only rpm -e (not rpm {-U|-F})
if [ $1 = 0 ]; then
  echo whatever

# only rpm -e (not rpm {-U|-F})
if [ $1 = 0 ]; then
   echo whatever
# only rpm {-U|-F} (not rpm -e)
if [ $1 = 1 ]; then
   /sbin/service syslog-ng condrestart
Personal tools