Every package manager covered in this section (APT, DNF, pacman) is ultimately installing software that someone already compiled from source and packaged. When nothing has done that for the software you need, you do it yourself.

Install build tools first

Compiling from source requires a compiler and standard build tools, which aren't installed by default on most systems:

sudo apt install build-essential      # Debian/Ubuntu
sudo dnf group install "Development Tools"  # Fedora/RHEL
sudo pacman -S base-devel             # Arch

The classic pattern: configure, make, install

Most C/C++ projects distributed as a source tarball follow the same three steps:

tar xzf project-1.4.0.tar.gz
cd project-1.4.0
./configure
make
sudo make install
  • ./configure - a generated script that checks your system for required libraries and tools, and produces a Makefile tailored to what it found. If it fails, the error almost always names a missing dependency (a -dev/-devel package, since headers needed for compiling are usually packaged separately from the runtime library) - install that and re-run.
  • make - actually compiles the source, using the generated Makefile. Run with -j$(nproc) to parallelize across all CPU cores and speed this step up meaningfully on anything nontrivial.
  • sudo make install - copies the built binaries, libraries, and man pages into place, by convention under /usr/local/ rather than /usr/.

Why /usr/local, specifically

This isn't arbitrary - it's the Filesystem Hierarchy Standard's designated space for software installed outside the distribution's own package manager (see The Filesystem Hierarchy). Keeping manually-built software out of /usr means it can never collide with or get silently overwritten by a package manager update, and which / $PATH ordering typically checks /usr/local/bin first, letting a manual build take precedence without touching anything package-managed.

The problem this creates: no easy uninstall or upgrade

A package manager tracks exactly which files belong to which package, so removal and upgrades are clean. make install does not - there's no built-in record of what got copied where, so removing a source-built program later usually means either keeping the original build directory around to run sudo make uninstall (only works if the project's Makefile defines that target, which not all do) or hunting down files manually.

checkinstall is a common workaround: it runs the install step inside a wrapper that captures what changed, then builds an actual .deb or .rpm from that, giving you a normal, trackable, removable package instead of an untracked scattering of files:

sudo checkinstall   # instead of `sudo make install`

Building from a git repository instead of a tarball

Cloning a project's repository directly sometimes skips the configure step (since it wasn't generated for a release) - an autoreconf or ./autogen.sh step typically has to run first to generate it:

git clone https://example.com/project.git
cd project
./autogen.sh
./configure
make
sudo make install

CMake as an alternative to configure/make

Many newer C/C++ projects use CMake instead of the traditional Autotools pattern above - same underlying idea (detect the environment, generate build files, compile), different commands:

mkdir build && cd build
cmake ..
make
sudo make install

Check a project's own README or INSTALL file for which of these two patterns it expects - there's no universal way to tell from the source tree alone which build system a given project uses.