ReleaseEngineering/PuppetAgain/HowTo/Build RPMs: Difference between revisions

 
(20 intermediate revisions by 6 users not shown)
Line 2: Line 2:
=How to Build RPMs=
=How to Build RPMs=


==Install Mach==
==Build a .src.rpm==


Start with a minimal install of CentOS 6.2.
Use a machine configured to build RPMs, with the toplevel::server::pkgbuilder class, which nowadays is just rpmpackager1. In moco, see [[ReleaseEngineering/How_To/Start_RPM_Ubuntu_Packager_Instances]] and do:


<pre>
# May need to be turned on first.
$ yum install wget createrepo
ssh rpmpackager1.srv.releng.use1.mozilla.com
$ wget http://thomas.apestaart.org/download/mach/mach-1.0.2.tar.gz
$ tar xzf ./mach-1.0.2.tar.gz
$ cd mach-1.0.2
$ ./configure --disable-selinux
$ make
$ make install
$ chmod u+s /usr/local/sbin/mach-helper
$ groupadd mach
$ useradd -g mach -m mach
$ passwd mach
</pre>


Due to a permissions bug I hit with mach (during a file copy), we'll continue as root.
The build infrastructure uses two types of rpm's: vanilla and customized for mozilla.
Let's clarify the terminology: a "vanilla package" is a package which is publicly available and is used by mozilla without applying any customization. An example of this is the jdk package used for Android builds. A "mozilla custom" package is a package rebuilt with some mozilla-related customization in the spec file defining how it is built. An example of this is the mercurial package deployed on slaves across the infrastructure.
Vanilla packages just need to be made available in our repositories, while mozilla-custom ones need to be rebuilt. The procedure described here applies to mozilla-custom packages.


Create /root/.machrc:
If you're upgrading or modifying an existing mozilla-custom package, you will need the following spec files:  
* old vanilla spec file: this is the spec file used to build the old version of the package before applying mozilla customizations
* new vanilla spec file: this is the spec file used to build the new version of the package before applying mozilla customizations
* old mozilla-custom spec file: the spec file used to build the previous mozilla-custom version of the package


<pre>
.spec files can be obtained from source rpm's as described below.
config['centos-6-x86_64-os']['macros']['dist'] = '.el6'
config['centos-6-i386-os']['macros']['dist'] = '.el6'
</pre>


==Prepare the Package==
=== How to extract .spec files from source rpm's ===


For this example, I want to build a new mozilla-python27 package based on 2.7.3 instead of 2.7.2.  I'm going to fetch the original .src.rpm and extract it into a subdirectory:
download the source RPM of the old version of the custom package you'd like to build from puppetagain.pub.build.mozilla.org/data/repos/yum/releng/public and unpack it:


<pre>
$ mkdir foopkg && cd foopkg
$ wget http://repos/repos/yum/releng/public/CentOS/6/x86_64/mozilla-python27-mercurial-2.1.1-4.el6.src.rpm
$ rpm2cpio $srpm | cpio -ivd
$ mkdir mozilla-python27 && cd mozilla-python27
$ rpm2cpio ../mozilla-python27-mercurial-2.1.1-4.el6.src.rpm | cpio -ivd
</pre>


Then edit these .spec file lines to update the Python version and package release number:
You should see a .spec file appear.


<pre>
=== What to do with these spec files? ===
%define pyrel 3
Release:        0%{?dist}
</pre>


==Build the Package==
Now that you have the old vanilla, new vanilla, and old custom, you should create a new spec file (to be used to build the new version of the package), by merging the diff between old vanilla and old custom (.i.e.: the mozilla customization) into the new vanilla spec file.


Now we want to rebuild the package using our updated .spec file.
Spec files used to build packages used in the infrastructure should be identical to the ones in https://github.com/mozilla/build-puppet under modules/packages/manifests/mozilla.  If not, figure out what the differences are, and which corresponds to the running version of the package.


<pre>
If you're starting a fresh package, make yourself a new .spec file and download any source files archive to the current directory. E.g., in order to build mercurial 3.1.2, mercurial-3.1.2.tar.gz needs to be in $PWD.
$ rm -rf /usr/local/var/tmp/mach/*
$ mach='mach --debug -r centos-6-x86_64-os'
$ $mach clean
$ $mach build mozilla-python27/python27.spec
</pre>


Note: adjust the target to 'centos-6-i386-os' to generate a 32-bit package.
Edit the spec file to your heart's content.  To actually build the .src.rpm:


In this case, though, I wanted to use mock (not mach) to build the final package since my mach build machine does not have access to the Mozilla yum repos. We can use the .src.rpm generated above and feed that to mock.
$ mock -r puppetagain-centos6.5-64 --buildsrpm --sources $PWD --spec /path/to/spec


Note that this is a simple examplemach has an advantage over mock in that it figures out dependencies when building multiple packages and automatically pulls in source files (normally a manual operation).  This can save a lot of time and hassle.
The script output will tell you where the SRPM is.  Copy it somewhere else, or mock will delete it in the next step.


==Configure Mock==
==Build the Package==


* Install mock
Now we want to rebuild the package using our .src.rpm created above.
* Copy the [http://hg.mozilla.org/users/john.hopkins_mozillamessaging.com/misc/file/default/mock mock-config] folder to your home directory (this example uses /home/cltbld/mock-config).


==Build Using Mock==
* If necessary, fetch the .src.rpm you built earlier.
 
* Execute these steps to build for both 32 and 64 bit packages:
* Fetch the .src.rpm you built earlier.
* Execute these steps to build:
<pre>
<pre>
$ mock='mock --configdir=/home/cltbld/mock-config -r epel-6-x86_64 -v'
$ # 64 bit:
$ $mock --rebuild mozilla-python27-2.7.3-0.el6.src.rpm
$ rm -rf /var/cache/mock/epel-6.5-x86_64/ccache
$ mock --rebuild -r puppetagain-centos6.5-64 mozilla-python27-2.7.3-0.el6.src.rpm
$
$ # 32 bit:
$ rm -rf /var/cache/mock/epel-6.5-i386/ccache/
$ mock --rebuild -r puppetagain-centos6.5-32 mozilla-python27-2.7.3-0.el6.src.rpm
</pre>
</pre>
* The script will tell you where the results are available.
The script will tell you where the results are available.
* Use 'epel-6-i386' to build a 32-bit package.


==Build an .src.rpm Using Mock==
If your build fails with something like "configure: error: cannot compute suffix of object files: cannot compile" in /var/lib/mock/epel-6.5-x86_64/result/build.log, or error messages complaining of a permission denied for /tmp/ccache/0/0 folder, it probably means that the last person to build an rpm didn't do the 'rm -rf' cleanup step. You'll need to do it as root:


Find a suitable machine with 'mock' installed.  It's best to do this on a target machine, since its /etc/mock/default.cfg will already be set up correctly.
<pre>
 
$ su -
Download the srpm from puppetagain.pub.build.mozilla.org/data/repos/yum/releng/public and unpack it:
(slave root password)
 
# rm -rf /var/cache/mock/epel-6.5-i386/ccache/
mkdir foopkg && cd foopkg
# rm -rf /var/cache/mock/epel-6.5-x86_64/ccache
rpm2cpio $srpm | cpio -ivd
</pre>
 
You should see a .spec file appear.  Check that it is identical to the one in http://hg.mozilla.org/build/puppet under modules/packages/manifests/mozilla e.g., with an md5 hash.  If not, figure out what the differences are, and which corresponds to the running version of the package.
 
Edit the spec file to your heart's content.  To build an RPM, you'll need to stop off at an SRPM:
mock --buildsrpm --spec /path/to/spec --sources $PWD
The script output will tell you where the SRPM is. Copy it somewhere else, or mock will delete it.  Then build the SRPM into an RPM:
mock --rebuild /path/to/srpm


== Other Dependencies ==
== Other Dependencies ==


If your package depends on other mozilla-specific packages, I'm not sure what the best way to build is.  The less-than-awesome technique I used was to hack /etc/mock/epel-6-x86_64.cfg to include pointers to the public mirrors of the puppetagain repos.
If your package depends on other packages, it's best to build and land those first.  The mock configs point to the local puppetagain repositories, so once the dependency is landed, it will be available in your mock build environment.


= Testing =
= Testing =
For testing purposes, it's best to install the RPM locally, rather than dropping it into the puppetagain data directory and risking affecting production.  You can do that too, if you're confident it won't affect anything.
For testing purposes, it's best to install the RPM locally on a test host (NOT on the pkgbuilder host!), rather than dropping it into the puppetagain data directory and risking affecting production.  You can do that too, if you're confident it won't affect anything.


= Review =
= Review =

Latest revision as of 19:26, 4 June 2018

How to Build RPMs

Build a .src.rpm

Use a machine configured to build RPMs, with the toplevel::server::pkgbuilder class, which nowadays is just rpmpackager1. In moco, see ReleaseEngineering/How_To/Start_RPM_Ubuntu_Packager_Instances and do:

# May need to be turned on first.
ssh rpmpackager1.srv.releng.use1.mozilla.com

The build infrastructure uses two types of rpm's: vanilla and customized for mozilla. Let's clarify the terminology: a "vanilla package" is a package which is publicly available and is used by mozilla without applying any customization. An example of this is the jdk package used for Android builds. A "mozilla custom" package is a package rebuilt with some mozilla-related customization in the spec file defining how it is built. An example of this is the mercurial package deployed on slaves across the infrastructure. Vanilla packages just need to be made available in our repositories, while mozilla-custom ones need to be rebuilt. The procedure described here applies to mozilla-custom packages.

If you're upgrading or modifying an existing mozilla-custom package, you will need the following spec files:

  • old vanilla spec file: this is the spec file used to build the old version of the package before applying mozilla customizations
  • new vanilla spec file: this is the spec file used to build the new version of the package before applying mozilla customizations
  • old mozilla-custom spec file: the spec file used to build the previous mozilla-custom version of the package

.spec files can be obtained from source rpm's as described below.

How to extract .spec files from source rpm's

download the source RPM of the old version of the custom package you'd like to build from puppetagain.pub.build.mozilla.org/data/repos/yum/releng/public and unpack it:

$ mkdir foopkg && cd foopkg
$ rpm2cpio $srpm | cpio -ivd

You should see a .spec file appear.

What to do with these spec files?

Now that you have the old vanilla, new vanilla, and old custom, you should create a new spec file (to be used to build the new version of the package), by merging the diff between old vanilla and old custom (.i.e.: the mozilla customization) into the new vanilla spec file.

Spec files used to build packages used in the infrastructure should be identical to the ones in https://github.com/mozilla/build-puppet under modules/packages/manifests/mozilla. If not, figure out what the differences are, and which corresponds to the running version of the package.

If you're starting a fresh package, make yourself a new .spec file and download any source files archive to the current directory. E.g., in order to build mercurial 3.1.2, mercurial-3.1.2.tar.gz needs to be in $PWD.

Edit the spec file to your heart's content. To actually build the .src.rpm:

$ mock -r puppetagain-centos6.5-64 --buildsrpm --sources $PWD --spec /path/to/spec

The script output will tell you where the SRPM is. Copy it somewhere else, or mock will delete it in the next step.

Build the Package

Now we want to rebuild the package using our .src.rpm created above.

  • If necessary, fetch the .src.rpm you built earlier.
  • Execute these steps to build for both 32 and 64 bit packages:
$ # 64 bit:
$ rm -rf /var/cache/mock/epel-6.5-x86_64/ccache
$ mock --rebuild -r puppetagain-centos6.5-64 mozilla-python27-2.7.3-0.el6.src.rpm
$
$ # 32 bit:
$ rm -rf /var/cache/mock/epel-6.5-i386/ccache/
$ mock --rebuild -r puppetagain-centos6.5-32 mozilla-python27-2.7.3-0.el6.src.rpm

The script will tell you where the results are available.

If your build fails with something like "configure: error: cannot compute suffix of object files: cannot compile" in /var/lib/mock/epel-6.5-x86_64/result/build.log, or error messages complaining of a permission denied for /tmp/ccache/0/0 folder, it probably means that the last person to build an rpm didn't do the 'rm -rf' cleanup step. You'll need to do it as root:

$ su -
(slave root password)
# rm -rf /var/cache/mock/epel-6.5-i386/ccache/
# rm -rf /var/cache/mock/epel-6.5-x86_64/ccache

Other Dependencies

If your package depends on other packages, it's best to build and land those first. The mock configs point to the local puppetagain repositories, so once the dependency is landed, it will be available in your mock build environment.

Testing

For testing purposes, it's best to install the RPM locally on a test host (NOT on the pkgbuilder host!), rather than dropping it into the puppetagain data directory and risking affecting production. You can do that too, if you're confident it won't affect anything.

Review

For review, include the modified .spec in your r? for changes to the puppet repository.

Remember, if the package can't be 100% re-created from data in the PuppetAgain Mercurial repository, you're doing it wrong!

Landing

See ReleaseEngineering/PuppetAgain/Packages for details on landing the change.