Building Software From Source on Linux
Most software you need is available through your distribution’s package manager, and that is almost always the better choice: dependencies are resolved automatically, updates arrive through your normal update process, and removal is clean. Building from source becomes necessary when software is not packaged for your distribution at all, when you need a version newer than what your repositories carry, or when you need custom compile-time options a pre-built package does not offer.
The standard workflow
Most C and C++ projects using the traditional Autotools build system follow a consistent pattern:
tar -xzf software-1.0.tar.gz
cd software-1.0
./configure
make
sudo make install
Each step does something distinct, and understanding what separates them matters for troubleshooting when something goes wrong partway through.
./configure: checking dependencies and generating a Makefile
./configure --prefix=/usr/local
configure inspects your system for required compilers, libraries, and dependencies, and generates a Makefile customized for your specific environment based on what it finds. --prefix controls where the software will ultimately be installed; /usr/local is the conventional default for manually built software, kept separate from /usr, which your package manager considers its own territory.
If configure fails, the error almost always names a specific missing dependency directly, which is the next thing to install, rather than indicating a problem with the source code itself.
./configure
# checking for libssl... not found
# configure: error: OpenSSL development files are required
Installing build dependencies
Missing dependencies from a configure failure are usually development packages, which contain header files and build-time libraries not included in the regular runtime package:
# Debian/Ubuntu: development packages use a -dev suffix
sudo apt install libssl-dev libcurl4-openssl-dev build-essential
# Fedora/RHEL: development packages use a -devel suffix
sudo dnf install openssl-devel libcurl-devel
sudo dnf groupinstall "Development Tools"
# Arch
sudo pacman -S base-devel openssl
build-essential (Debian/Ubuntu) and the Development Tools group (Fedora/RHEL) install the core compiler toolchain (gcc, make, and related tools) needed for any build from source, and are worth installing once up front if you expect to build software from source more than occasionally.
This is often an iterative process: run configure, install whatever it names as missing, run it again, and repeat until every dependency is satisfied.
make: compiling the source
make
This actually compiles the source code into binaries, following the instructions in the Makefile that configure generated. It does not require sudo, since it only writes files inside the source directory itself, nothing on the system yet. Compilation can take anywhere from seconds to hours depending on the project’s size.
make -j4
-j4 runs up to 4 compilation jobs in parallel, which can meaningfully speed up the build on a multi-core system. -j$(nproc) automatically matches the parallel job count to the number of available CPU cores.
make install: placing files on the system
sudo make install
This copies the compiled binaries, libraries, and other files to their final locations, typically under the --prefix specified during configure. It normally requires sudo, since it writes outside the source tree to system directories an ordinary user cannot write to.
The problem: no clean uninstall by default
This is the real drawback of building from source directly. A package installed through apt or dnf is tracked, every file it placed is recorded, and it can always be cleanly removed. A plain make install leaves files scattered across the system with no record of exactly what was placed where.
sudo make uninstall
Some projects implement a make uninstall target that reverses exactly what make install did, but this only works if you still have the original, unmodified build directory available, and many projects do not implement it at all.
checkinstall: getting a real, removable package
checkinstall solves the uninstall problem by intercepting the install step and packaging the result into an actual .deb or .rpm, rather than copying files loosely onto the system:
sudo apt install checkinstall # Debian/Ubuntu
sudo dnf install checkinstall # Fedora/RHEL (may require EPEL)
./configure
make
sudo checkinstall
checkinstall walks through an interactive prompt to fill in package metadata (name, version, description), then generates and installs a real package your package manager recognizes, which can later be removed cleanly with a normal apt remove or dnf remove, exactly like any other installed software. For anyone who expects to build more than one piece of software from source over time, using checkinstall from the start avoids the slow accumulation of untracked files a plain make install leaves behind.
CMake-based projects
Not every project uses Autotools. CMake is a common alternative, with a similar but distinct workflow:
mkdir build && cd build
cmake ..
make
sudo make install
The core shape is the same, generate build files, compile, install, even though the specific tool generating those build files differs.
Frequently Asked Questions
Why would I need to build software from source instead of using my package manager?
Package managers are almost always the better option when available, since they handle dependencies, updates, and clean removal automatically. Building from source becomes necessary when a specific piece of software is not packaged for your distribution at all, when you specifically need a version newer than what your distribution’s repositories provide (distributions often intentionally lag behind upstream for stability), or when you need to build with custom compile-time options or optimizations that a pre-built package does not offer, such as enabling a specific hardware feature or disabling one for compatibility.
What does ./configure actually do?
configure is a script, typically generated by a build system called Autotools, that checks your system for required dependencies, compilers, and libraries, and generates a Makefile customized for your specific system based on what it finds. It commonly accepts options controlling where the software will be installed (—prefix=/usr/local, for example) and which optional features to enable or disable. If configure fails, the error message almost always names a specific missing dependency or development library, which is the next thing to install before trying again, rather than a problem with the source code itself.
What is the difference between make and make install?
make actually compiles the source code into binaries, using the instructions in the Makefile that configure (or an equivalent build system) generated, and this step does not require root privileges since it only writes files inside the source directory itself. make install copies the resulting compiled binaries, libraries, and other files to their final system locations, typically somewhere under /usr/local by convention, and this step normally does require sudo, since it writes to system directories outside the source tree that an ordinary user does not have write access to.
How do I find and install the dependencies a build needs?
The configure step (or the equivalent for whatever build system a project uses, such as CMake) will typically fail with a clear error naming the specific missing dependency, most often a development package, distinguished by a -dev suffix on Debian/Ubuntu (like libssl-dev) or a -devel suffix on Fedora/RHEL (like openssl-devel), which contains the header files and build-time libraries not included in the regular runtime package. Install the missing package with your normal package manager, then re-run configure; this is often an iterative process of running configure, installing whatever it complains is missing, and running it again, sometimes several times in a row until every dependency is satisfied.
How do I uninstall software that was built from source?
This is one of the real downsides of building from source: there is no package manager tracking what files were installed where, unlike software installed through apt or dnf, which can always be cleanly removed. Some projects support make uninstall, which removes exactly what make install placed, but only works if you still have the original build directory available and unmodified since the last install, and many projects do not implement this target at all. This is precisely why checkinstall exists: it wraps the build process and produces a real, trackable package (.deb or .rpm) that your package manager can then install and later cleanly remove like any other package, rather than leaving files scattered with no record of what was placed where.
What is checkinstall and why should I consider using it?
checkinstall is a tool that replaces the plain make install step, intercepting the files that would be installed and packaging them into an actual .deb or .rpm package instead of just copying them loosely onto the system. Once installed, this checkinstall-generated package behaves like any other package your package manager knows about, including clean removal later with a normal apt remove or dnf remove, which a plain, untracked make install does not support at all. For anyone who expects to build multiple pieces of software from source over time, using checkinstall from the start avoids the accumulation of untracked files that plain make install otherwise leaves scattered across the system with no easy way to clean them up later.