Use apt-get build-dep to install build dependencies

Or, how to build the latest tmux on Ubuntu

There are times you want to use a more up-to-date software than what comes with your Linux Distribution (distro). I had to do this when I was using Ubuntu 16.04. I wanted to use the latest tmux for its advanced mouse support but Ubuntu 16.04 came with an older version of tmux without the feature. Since the LTS versions rarely do a major-version upgrade, the only way to get the newer version was to build it from source.

Sometimes, building from source can be as easy as ./configure && make && sudo make install. More often than not though, it can be a real test of patience. What I do usually is to run the build script, read the error message, search the name of the missing component, rinse and repeat.

Here's an example of me trying to build tmux from scratch on Ubuntu (⛔ indicates a trial-and-error cycle):

# Get Git
$ sudo apt-get install -y git 
# Get the source
$ git clone https://github.com/tmux/tmux.git; cd tmux
# Well, this is the only executable, so let's go.
$ sh autogen.sh
...
aclocal: not found ⛔
# after googling 
$ sudo apt install -y automake
$ sh autogen.sh # ✅ works this time.
$ ./configure
...
configure: error: no acceptable C compiler found in $PATH ⛔
# I guess I should install gcc, since that's a popular compiler.
$ sudo apt install -y gcc
$ ./configure
...
configure: error: "libevent not found" ⛔
# Let's install the development package
$ sudo apt install -y libevent-dev
$ ./configure
...
configure: error: "curses not found" ⛔
# I just happen to know that the package is not called libcurses-dev 😏
$ apt install -y ncurses-dev
$ ./configure
...
config.status: error: Something went wrong bootstrapping makefile fragments 
for automatic dependency tracking.  If GNU make was not used, consider
re-running the configure script with MAKE="gmake" (or whatever is
necessary) ... ⛔
# What is totally not obvious is from the message above is that
# I am actually missing make entirely.
$ sudo apt install -y make
$ ./configure # succeeds ✅
$ make
... 
./etc/ylwrap: line 175: yacc: command not found ⛔
# Googles to find out that GNU bison provides yacc
$ sudo apt install -y bison
$ make 
# Finally succeeds ✅
Sidenote: the tmux documentation actually does have a list of dependencies. However, the actual mapping of those dependencies into the name of the packages is supposed to be the job of the distro maintainer, and therefore is missing. It is still your job to map those dependencies back to the name of the packages.)

This was just 6 tries, but with bigger packages, this trial-and-error approach can be extremely time consuming. Worse, even after building, you can still end up with random missing features because some of the optional features are included only when the library is found on the system.

Fortunately, on a Debian-based distro (like Ubuntu), there is a quick way to install the build dependencies for the software that already exists in the repo. This relatively obscure command apt-get build-dep will install all the build dependencies for you.

Additional Notes for Ubuntu

On Ubuntu, the first step to use apt-get build-dep is to add the source code repositories to the system source repositories. Source repositories contain the metadata necessary to find out the build-time dependencies for packages. We need to do this on Ubuntu once because recent versions of Ubuntu ships with the source repositories excluded by default. Presumably, this is to make apt-get update faster but I was never able to confirm. If anyone knows the answer, please let me know.

To enable the source code repositories, you can uncomment the lines starting with deb-src, or run the following command:

# The old sources.list will be backed up as /etc/apt/sources.list.bak
$ sudo sed -i.bak 's/^# *deb-src/deb-src/g' /etc/apt/sources.list && \
  sudo apt-get update
# restore with sudo mv /etc/apt/sources.list.bak  /etc/apt/sources.list

Real-life Example: Building tmux

With the source repository enabled, let's try building tmux again.

Install the build dependencies of tmux.

$ sudo apt-get build-dep -y tmux

Now we can start building.

cd tmux
sh autogen.sh && ./configure && make -j 4

For the latest tmux on Ubuntu 20.04, you will get an error like this (as of Feb 2022):

./etc/ylwrap: line 175: yacc: command not found

This is because this new version of tmux added a dependency to yacc. I confirmed this by reading the CHANGES file.

We can fix this by installing the yacc-compatible GNU bison: sudo apt-get install -y bison. Re-running the build should work. If everything went well, you should be able to run ./tmux to test it.

In the end, I still had to go through 1 trial-and-error cycle (yacc) but that's 5 less that the original.

Bonus 1: Safe Installation of Compiled Packages

Here's one more tip to manage the installation of source-compiled packages. Many guides at this point would tell you to run sudo make install but often there is a nasty surprise waiting for you after - You are at the mercy of package maintainer to be able to uninstall the package cleanly. Often the uninstall target just doesn't exist, in which case you can't easily uninstall the software. There are a couple ways to handle this (e.g., GNU stow - a topic for another blog). Here I will show how you can use checkinstall to easily create a reasonably well-behaved dpkg from the source. To use checkinstall, run the following command:

$ sudo apt-get install -y checkinstall 

Now you can run checkinstall to create a dpkg (Debian package) and install it.

It will ask you a bunch of questions, you can go with the default most of the time. As for the version string I just used 9999 (a convention that I borrowed from Gentoo) to express that I want my package to be the latest version.

# make a package - may have to answer some prompts
$ checkinstall --pkgname=tmux --pkgversion=9999 \
  --install=no --fstrans=yes
# install the package (replace amd64 with your architecture)
$ sudo dpkg -i tmux_9999-1_amd64.deb

Now you can see that your tmux is installed as /usr/local/bin/tmux (Technically it's in a wrong place for a dpkg package but it's not that important).

Now if you try to install tmux from apt, it will say you have the latest version.

$ sudo apt-get install -y tmux 
Reading package lists... Done
Building dependency tree       
Reading state information... Done
tmux is already the newest version (9999-1).
# And to uninstall this package,
# you can simply run apt-get remove -y tmux

Bonus 2: What if I just want to find the list of dependencies without installing them?

Found this answer on askubuntu.com:

# replace tmux with the package in question
apt-cache showsrc tmux | grep ^Build-Depends

Bonus 3: What if I am on Redhat/Fedora?

Use dnf builddep or yum-builddep.

Catergorized under: techtips / linux

Published: 2022-02-27T02:58:24.261401
Last modified: 2022-02-27T02:58:24.261493
Permalink