$linuxjunkies
>

How to Build Software from Source on Linux

Build Linux software from source using configure, make, and make install — with dependency tips, CMake and Meson coverage, and clean-install strategies.

IntermediateUbuntuDebianFedoraArch9 min readUpdated June 7, 2026

Before you start

  • sudo or root access to install packages and files system-wide
  • Basic terminal familiarity: navigating directories, reading error output
  • Sufficient disk space (source + build artifacts can exceed 1 GB for large projects)
  • Internet access to download source tarballs and missing dependencies

Binary packages are convenient, but they are built for the lowest common denominator. Building from source lets you target your specific CPU, enable or disable features, and run software versions that your distribution simply does not ship. The workflow is almost always the same: fetch the source, satisfy dependencies, configure, compile, and install. The details are where most people trip up.

Before You Start: Required Build Tools

You need a C/C++ toolchain, make, and supporting utilities. Most projects also need pkg-config to locate libraries.

Debian / Ubuntu

sudo apt update
sudo apt install build-essential pkg-config git wget

Fedora / RHEL / Rocky

sudo dnf groupinstall "Development Tools"
sudo dnf install pkg-config git wget

Arch Linux

sudo pacman -S base-devel git wget

Step 1: Fetch the Source

Always prefer a tagged release tarball over a random commit. Tarballs from a project's releases page are tested and do not require autotools to regenerate the build system.

wget https://example.com/project/project-2.4.1.tar.gz
tar -xzf project-2.4.1.tar.gz
cd project-2.4.1

If you need the bleeding edge or want to contribute, clone via Git:

git clone --depth=1 --branch v2.4.1 https://github.com/example/project.git
cd project

When cloning a repository that ships configure.ac but no pre-generated configure script, you must run the bootstrap step first:

./autogen.sh
# or, if no autogen.sh exists:
autoreconf -fiv

Step 2: Read the Build Instructions

Before running anything, read README, INSTALL, or docs/building.md. Projects increasingly switch from Autotools to CMake or Meson. The configure commands differ, and attempting an Autotools workflow on a Meson project will fail immediately.

  • Autotools: has a configure script at the root
  • CMake: has a CMakeLists.txt at the root
  • Meson: has a meson.build at the root

This guide covers all three, starting with Autotools since it remains the most common in older and C-focused projects.

Step 3: Resolve Dependencies

Run ./configure (or the equivalent) once. It will fail loudly on any missing library and tell you exactly what is missing. Do not ignore these messages. Search your package manager for the development package, which includes headers.

Finding development packages

Debian / Ubuntu

apt search libfoo-dev
sudo apt install libfoo-dev

Fedora / RHEL / Rocky

dnf search libfoo-devel
sudo dnf install libfoo-devel

Arch Linux

pacman -Ss libfoo
sudo pacman -S libfoo

Repeat until ./configure finishes without errors. The last line of successful Autotools configure output looks like:

config.status: creating Makefile

Step 4: Configure the Build

The configure step is where you set the install prefix and toggle features. The single most important flag is --prefix, which controls where files land. Using /usr/local keeps your hand-built software separate from the system package manager.

Autotools

./configure --prefix=/usr/local \
            --enable-optimizations \
            --disable-debug

Run ./configure --help to see every available flag for that project.

cmake -B build \
      -DCMAKE_BUILD_TYPE=Release \
      -DCMAKE_INSTALL_PREFIX=/usr/local

Meson

meson setup build \
      --prefix=/usr/local \
      --buildtype=release

Meson requires its own package. Install it with pip install meson ninja or from your distro's repositories if you need a recent version.

Step 5: Compile

Use all available CPU cores. nproc returns the logical core count on every major distro.

Autotools / plain Makefile

make -j$(nproc)

CMake

cmake --build build -j$(nproc)

Meson / Ninja

ninja -C build -j$(nproc)

A successful compile ends with a linker step and no error lines. Warnings are usually not fatal. Errors reference a specific source file and line number — use that to search the project's issue tracker before assuming something is wrong with your system.

Step 6: Install — and Stay Tidy

The naive approach is sudo make install. It works, but it scatters files across /usr/local with no record of what was installed, making clean removal painful later. Use checkinstall or DESTDIR staging instead.

Option A: checkinstall (creates a native package)

sudo apt install checkinstall   # Debian/Ubuntu
sudo checkinstall               # replaces 'make install'

checkinstall runs make install internally, captures every file it writes, and wraps the result in a .deb (or .rpm on RPM systems). You can then uninstall cleanly with sudo apt remove project. This is the recommended method on Debian/Ubuntu systems. On Fedora, it is less maintained; use DESTDIR staging instead.

Option B: DESTDIR staging (universal)

make install DESTDIR=/tmp/project-root
ls /tmp/project-root/usr/local/bin   # verify layout

You can then use rsync to push the staged tree into place, or hand it to fpm to create a proper package. This works with CMake (cmake --install build --prefix /tmp/project-root) and Meson (DESTDIR=/tmp/project-root ninja -C build install) too.

Option C: Plain install (acceptable for isolated tools)

sudo make install

If you are installing a single binary to a custom prefix like $HOME/.local or /opt/project, plain install is fine because the prefix is already isolated.

Step 7: Verify the Installation

Confirm the binary is reachable and reports the expected version:

which project
project --version

If which returns nothing, your prefix's bin directory is not in PATH. Add it for your shell:

echo 'export PATH="/usr/local/bin:$PATH"' >> ~/.bashrc
source ~/.bashrc

If the binary links against shared libraries you built, also update the linker cache:

echo "/usr/local/lib" | sudo tee /etc/ld.so.conf.d/local.conf
sudo ldconfig

Troubleshooting

configure: error: C compiler cannot create executables

Your toolchain installation is incomplete. Verify with gcc --version and reinstall the build-essential / Development Tools group.

cannot find -lfoo during linking

A required library is present but the linker cannot find it. Check that its -dev/-devel package is installed, then run sudo ldconfig. If it is in a non-standard location, export LDFLAGS="-L/path/to/lib" before running configure.

make: Nothing to be done for 'all'

Object files from a previous build are still present. Run make clean or make distclean (Autotools), rm -rf build (CMake/Meson), then configure and compile again.

Installed binary crashes with version mismatch

The running binary found a different shared library version than the one it was built against. Run ldd $(which project) to see which libraries are resolved and compare against what you expected. DESTDIR staging makes this easier to audit before system-wide installation.

tested on:Ubuntu 24.04Debian 12Fedora 40Arch rolling

Frequently asked questions

Why use --prefix=/usr/local instead of /usr?
/usr is owned by the package manager on most distros. Installing to /usr/local keeps hand-built software in a separate tree, preventing conflicts and making it easier to remove later.
How do I uninstall software built from source?
If you used checkinstall, uninstall via your package manager. If you used plain make install and still have the source tree, run sudo make uninstall. Otherwise use DESTDIR staging next time and track files with a native package.
Is it safe to run make with -j$(nproc) on every project?
Almost always yes. Occasionally a project has broken Makefile dependencies that only manifest during parallel builds. If you get strange errors, try make -j1 to reproduce them serially before filing a bug.
Can I build as a regular user without sudo?
Yes. Set --prefix=$HOME/.local and the entire build and install happens without elevated privileges. Make sure $HOME/.local/bin is in your PATH.
What is the difference between make clean and make distclean?
make clean removes compiled object files and binaries. make distclean also removes the generated Makefile and configure output, returning the tree to roughly its tarball state. Use distclean when you want to reconfigure with different options.

Related guides