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:
- Install any dependencies, packages that must be installed before the binary can be built.
- Install the source code.
- Examine and possibly modify the build specification — compilation options, embedded package information, change log, and so on.
- Build the binary package.
- Clean up.
- 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 /usr/lib/libusb-1.0.so.0 /usr/lib/libusb-1.0.so.0.1.0 /usr/share/doc/libusb1.0_0 /usr/share/doc/libusb1.0_0/AUTHORS /usr/share/doc/libusb1.0_0/COPYING /usr/share/doc/libusb1.0_0/ChangeLog /usr/share/doc/libusb1.0_0/NEWS /usr/share/doc/libusb1.0_0/README
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 /usr/include/libusb-1.0 /usr/include/libusb-1.0/libusb.h /usr/lib/libusb-1.0.so /usr/lib/pkgconfig/libusb-1.0.pc
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