ReleaseEngineering/How To/Create a new RPM

From MozillaWiki
Jump to: navigation, search


Guess what? We have an rpm-sources repo. Keep the specs in there, and comment them heavily. That means updating the ChangeLog, and more importantly it means describing verbosely where various tarballs come from.

Spec Files

This section will not go over all the ins and outs of RPM spec file creation, but will talk about which machines it should be done on and show a couple examples. In general, there's two different ways we package things in an RPM. Firstly, there's the more "normal" build & installation in a spec file. Whenever possible, it's best to use this method of deployment. It makes RPM rebuilding simpler and often allows the same spec file to be used across multiple platforms. A simple example of this is the zope.interface package. Its spec file is as follows:

Name: zope.interface
Summary: Zope.Interface
Version: 3.3.0
Release: 0moz1
License: ???
Group: Python
Source: %{name}-%{version}.tar.gz
BuildRoot: %{_tmppath}/zope-interface-%{version}-root
Requires: python25

%define _python /tools/python-2.5.1/bin/python
%define _prefix /tools/zope-interface-%{version}
%define _localstatedir %{_prefix}/var
%define _mandir %{_prefix}/man
%define _infodir %{_prefix}/info


%setup -q

%{_python} build_ext

%{_python} install --root=$RPM_BUILD_ROOT --prefix=%{_prefix}


%defattr(-, root, root)

Note that the package installs itself into $RPM_BUILD_ROOT and still sets an installation prefix. This ends up translate to $tmpdir/tools/zope-interface-3.3.0, in this case.

When creating a spec file for packages like this you can generally put whatever you would use to install it manually into the appropriate sections (%prep, %build, %install) with the caveat of making sure they install into $RPM_BUILD_ROOT. The %files section instructs rpmbuild to add any files listed in it to the RPM.

For packages that cannot be created through these means, a more brute force technique is used. Rather than installing the package from its original source in the spec file, the install is done outside of the spec file and packaged up. The spec file then takes that package and puts it into an RPM. Some things (most notably Scratchbox and Android SDKs) make it difficult or impossible to reliably reproduce the installations. Here's an example of this technique:

Name: gcc433
Summary: An interpreted, interactive, object-oriented programming language.
Version: 4.3.3
Release: 0moz1
License: ???
Group: C
# This isn't the original source package but rather a Mozilla built tarball.
# The original source package requires downloading additional pieces from
# the Internet, which is difficult to do in RPM, and makes reproducability
# impossible.
Source0: gcc433-4.3.3.tgz
BuildRoot: %{_tmppath}/%{name}-%{version}-root
AutoReqProv: no

%define __strip /bin/true
%define __os_install_post %{nil}

%define toplevel_dir gcc-4.3.3
%define install_dir %{toplevel_dir}


rm -rf $RPM_BUILD_DIR/%{toplevel_dir}
tar -zxf %{SOURCE0} >/dev/null

# none

install -d -m 755 $RPM_BUILD_ROOT

mkdir -p $RPM_BUILD_ROOT/tools/%{install_dir}
rsync -av %{toplevel_dir}/ $RPM_BUILD_ROOT/tools/%{install_dir}


%defattr(-, root, root)

Note that the build section is empty here, and the %install section simply creates the destination directory and uses rsync to populate it. Also of note here is the disabling of some RPM features: AutoReqProv: no, %define __strip /bin/true, and %define __os_post_install %{nil} disable the built-in dependency checking, and some optimizations that rpmbuild normally performs. These are usually required when deploying packages this way.

Building RPMs

Once you have a spec file ready and the source in hand building RPMs is pretty simple. Generally, we use staging-master (32-bit CentOS), moz2-linux64-slave07 (64-bit CentOS), and talos-r3-fed{64,}-slave01 (Fedora 32/64) as build machines for RPMs. Each of them has an 'rpmbuild' directory inside of cltbld's home directory. The directory structure inside looks as follows:


Source files referenced in spec files go in SOURCES and end-result RPMs go in RPMS/$arch.

To build an RPM, head to the SPECS directory and type the following:

rpmbuild -ba --target=$arch specfile

Where $arch is 'i686' for 32-bit machines and 'x86_64' for 64-bit ones. If all goes well, you'll soon have an RPM.