UNIX / Linux keyboard.

Building Binary Packages from Source

Building Packages on Linux

Before you begin, beware that RPM-based Linux distributions used to put the package building infrastructure somewhere like /usr/src/rpm or maybe something similar to /usr/src/distroname. Now, however, it defaults to ~/rpmbuild. If you were to build packages as root, especially when you build large packages like the kernel, you could quickly fill your root partition and run out of space. However, you don't want to use the root account while building packages. Do the package build as your ordinary user, then just install the packages as root. Something like this on a apt-get/dpkg distribution such as Debian, Mint, Ubuntu, etc:

$ sudo dpkg -i path/to/my-new-package.deb

Or on a yum/rpm distribution such as RHEL, Oracle, etc:

$ su
# rpm -Uvh path/to/my-new-package.rpm

The following assumes doing all the work except the final installation step as an unprivileged user, so the package is built under /home and there will be plenty of room.

The overall sequence will be:

  1. Install any dependencies, packages that must be installed before the binary can be built.
  2. Install the source code.
  3. Examine and possibly modify the build specification — compilation options, embedded package information, change log, and so on.
  4. Build the binary package.
  5. Clean up.
  6. Install the resulting binary package.

Why the anxiety about building a package as root? The package source will contain makefiles which could cause the builder to run arbitrary commands.

But can't packages contain pre- and post-installation scripts so there's still a way for someone to leave a logic bomb for root?

Yes. Make certain to only download and build trusted packages from trusted providers. It's enormously difficult to really do that reliably. Be careful.

Here we go, one major step at a time:

Install dependencies

Some other packages may need to be installed before you can build the package you're interested in. For example, my system has a package named libusb1.0_0 containing shared libraries which applications use to access USB devices. The package contains:

$ rpm -ql libusb1.0_0

Another package, its "-devel" companion, contains shared libraries and header files needed to compile new applications that will use the package.

$ rpm -ql libusb1.0-devel

On an RPM-based system, there is no easy way to determine in advance the complete list of all the required packages. Just forge on, when you run into a dependency you will be told what's missing and you can simply add it then.

On an apt-get/dpkg system, you can specify adding those packages that will be needed to build your new one. From here forward, we will assume that you want to build newpackage.

$ sudo apt-get build-dep newpackage

Install the source code

You could download the source package with a browser or with command-line FTP. However, if you have configured a repository containing the source package, you could use the package management tools to download the source code.

On an RPM-based system, do something like the following:

$ yum install newpackage.src
$ cd ~/rpmbuild/SRPMS
$ rpm -Uvh newpackage-version.src.rpm

On an apt-get/dpkg system, you can download the source to wherever you want to do the build:

$ cd /path/to/your/build/area
$ apt-get source newpackage

Examine and possibly modify the build specification

You can change the compilation opens and modify the embedded package information and change log. Usually there is no need to do this, but if you want to, now's the time.

On an RPM-based system:

$ cd ~/rpmbuild/SPECS
$ vi newpackage.spec

On an apt-get/dpkg system:

$ cd newpackage-release
$ vi debian/rules debian/changelog
$ debchange

Build the binary package

This is where the real work is done! Depending on what you're building, you may see quite a bit of compiler work here.

On an RPM-based system run the following command, where -bb means to do the full build of the binary package described in the spec file:

$ rpmbuild -bb newpackage.spec

On an apt-get/dpkg system run the following command, where -uc specifies an unsigned .changes and -b specifies building a binary package:

$ dpkg-buildpackage -uc -b

Check to see if the build went well, and if so, clean up

On an RPM-based system:

$ tree ~/rpmbuild/RPMS
$ rpmbuild --clean newpackage.spec

On an apt-get/dpkg system:

$ ls ../*deb
$ ./debian/rules clean

Install the resulting binary package

See my page on package management for more details on these commands and where to go next.

On an RPM-based system change into the appropriate architecture-specific location where the binary package was created, then install it:

$ cd ~/rpmbuild/RPMS/arch
$ su root -c 'rpm -Uvh newpackage-version.arch.rpm'

On an apt-get/dpkg system go up one level out of the rules subdirectory, then install the package:

$ cd ..
$ sudo dpkg -i newpackage*.deb