How To Build RPM Packages In A Chroot Environment Using mach
How To Build RPM Packages In A Chroot Environment Using machNote: this article was tested using CentOS 5.1, but it should also work with other RPM-based distros (e.g. Fedora, SuSE)
A description of the problemOK, so you want to build a binary RPM package for deployment on your servers. You have a .spec file or .src.rpm that you got from one of the many repositories such as freshrpms.net or dag.wieers.com, or that you wrote yourself. Why not just build it using rpmbuild? There are several problems you may come across.
If you want an example of how bad the problem is, try building the package perl-SOAP-Lite from its spec file. You will quickly find yourself in dependency hell, with 16 other packages needing to be installed or built, all in the correct order.
The solution: machMach (for "make a chroot") solves all these problems. It installs a minimal subset of your target distribution under /var/lib/mach/roots/distro. When it's time to build a package, given a spec file it turns it into a .src.rpm by downloading the necessary sources automatically (or you can just give it a .src.rpm in the first place). Mach then switches into this cleanroom environment using chroot. It builds the package jailed into this environment, pulling in any dependencies automatically by yum. The finished binary package is left in a local yum repository, in case it is needed by any future package builds. Finally, the environment is cleaned up to its pristine state by removing all surplus packages. As a bonus, building in a chroot environment ensures that all your "BuildRequires:" dependencies are correctly declared in the spec file, because the package won't build without them.
Installing machI will walk through an installation from scratch on a CentOS 5.1 system, but setting it up to build packages for CentOS 4. Installing mach itself is a one-time bootstrapping operation. Once you've done this, all your future RPM packages can be built within mach itself. There are some binary packages available on the download site, but I prefer to build it myself from source:
$ wget http://thomas.apestaart.org/download/mach/mach-0.9.3.tar.bz2
After installation, check that you have the documentation in /usr/share/doc/mach-0.9.3/README and that there is a group called mach in /etc/group.
Optional: point to a local yum mirrorFor deterministic results, you might want to choose a local yum mirror explicitly rather than relying on automatic redirects. This is done in /etc/mach/location. For example, if you are in the UK, you might want to change centos = 'http://mirror.centos.org/centos' to centos = 'http://www.mirrorservice.org/sites/mirror.centos.org'
Setting up usersAny user who is going to use the mach environment needs to be a member of the supplementary group mach. You can do this by adding their username to the end of the line in /etc/group: mach:x:102:user1,user2,user3... Do this for your own non-root account, then logout and login again. NOTE: because mach relies on shared group permissions, your umask value must be 0002 (allowing group write on all files and directories you create). Check it like this, and change it if necessary: $ umask 0002 # this is OK $ umask 0022 # this is wrong $ umask 0002 $ umask 0002 # now it's correct Your umask is reset at the start of each session, so if it doesn't default to 0002 then you'll need to update your .profile or change it manually each time you login. Finally, each user needs to create a file ~/.machrc like the following: config['installer'] = 'yum'
config['files'] = {
'/etc/hosts': '''
127.0.0.1 builder.example.com builder localhost
''',
'/etc/resolv.conf': '''
nameserver 1.1.1.1
nameserver 2.2.2.2
search example.com
'''
}
config['defaultroot'] = 'centos-4-i386-extras'
config['macros'] = {
'vendor': 'My Company Name',
}
(Or: set these globally in /etc/mach.conf) This gives some parameters which will be needed within the chroot environment. In the /etc/hosts line, the first hostname is the one which you want to appear in the package as the build host, and the second one should be the actual output of 'hostname' on this machine (if different) Check out the files under /etc/mach/dist.d/ for the various choices of chroot environments. The above example builds packages for a CentOS 4 system which has the 'extras' repository available to it, in addition to the basic ones. See README for more detailed info.
Preparing the build environmentMake sure you have lots of free disk space available under /var (at least 2GB) then proceed as follows: $ umask 0002 # Confirm this is 0002 !! $ mach setup build Preparing root
This is slow the first time you run it, because it downloads (using yum) an entire set of packages for the distro you want to build under. However these packages are cached. So in future, even if you blast away the entire chroot environment, it won't download all the packages again when rebuilding it. Speaking of which, should you ever wish to completely toast the build environment and recreate it from scratch, here's how: $ mach clean
Your new root is at /var/lib/mach/roots/distro/ and you can browse it like this: $ mach chroot Entering /var/lib/mach/roots/centos-4-i386-extras, type exit to leave.
-bash-3.1# ls / bin dev home media opt root selinux sys usr
-bash-3.1# exit logout
Building packagesThis is where the fun starts. You simply give one or more .spec files or .src.rpm files to mach build: $ mach build foo.spec bar.spec ... or $ mach rebuild foo.src.rpm bar.src.rpm ... Mach does all the rest for you automatically, and dumps the shiny finished packages under /var/tmp/mach/distro/.
A worked example: perl-SOAP-LiteLet's try out the "hard" RPM package I mentioned before. $ umask 0002 # just checking! $ wget http://svn.rpmforge.net/svn/trunk/rpms/perl-SOAP-Lite/perl-SOAP-Lite.spec
Building .src.rpm from perl-SOAP-Lite.spec
That's it. The "Results:" line tells you the directory which contains the RPM packages(s) which were built: $ ls -l /var/tmp/mach/centos-4-i386-extras/perl-SOAP-Lite-0.710.05-1 total 764
If all goes well, then smile.
TroubleshootingMissing dependenciesSometimes a package will fail to build because it depends on another package which isn't available in the vendor's binary repository. For example, with older versions of CentOS, the perl-SOAP-Lite package wouldn't build because it depended on perl-Compress-Zlib which wasn't present. No problem: just find a .spec file for it, and tell mach to build that package as well. $ wget http://svn.rpmforge.net/svn/trunk/rpms/perl-Compress-Zlib/perl-Compress-Zlib.spec
It doesn't even matter which order your specify the .spec files on the command line. Mach sorts them so that the dependencies are built before the packages which depend on them.
Other problemsIf you're still having trouble, add the '-d' flag to enable verbose debugging output, like this: $ mach -d build foo.spec bar.spec If mach complains that the repository is locked, and you're sure that no other user is using it (e.g. a previous build was forcibly aborted), then you can unlock it using mach unlock. Occasionally, a package may have a BuildRequires: dependency on a package which isn't in a yum repository, and also can't be built from source (an example would be a package which depends on the oracle-instantclient-devel binary RPM). You can fix this by manually copying the RPM file(s) to /var/lib/mach/roots/distro/usr/src/rpm/RPMS.mach-local/.
Multiple rootsYou can have multiple distro chroots installed at once. Just use mach -r distro ... to select the one you're interested in at any one time, or change defaultroot in ~/.machrc As a result, a single build machine can build totally clean packages for a variety of different target systems. All you need is a bit of disk space and bandwidth.
RPM Links
|







Recent comments
17 hours 15 min ago
17 hours 19 min ago
21 hours 21 min ago
1 day 7 hours ago
1 day 10 hours ago
1 day 18 hours ago
2 days 18 hours ago
2 days 20 hours ago
3 days 27 min ago
4 days 5 hours ago