Make is the oldest build tool still in daily use: a Makefile lists targets, their prerequisites and the shell commands that produce them. GNU Autotools (Autoconf + Automake) sits on top of Make to generate portable configure scripts and Makefiles. Much of the Linux and open-source world (and many embedded and legacy enterprise codebases) still builds this way, so DevOps engineers meet it regularly.
In CI, each stage of the generic build pipeline maps to a Make / Autotools command, plugin or scanner. Press play, or step through it:
Source + configure.ac: A commit triggers CI. configure.ac and Makefile.am describe the build; autoreconf -fi generates configure and Makefile.in.
Dependencies: System libraries come from the OS package manager (apt-get in CI) and are found by pkg-config during configure.
Configure: ./configure CFLAGS="-O2 -Wall -Wextra -Werror" checks the toolchain and writes Makefile and config.h; warnings become errors.
Build: make builds in parallel; bear -- make records compile_commands.json so clang-tidy can analyse the code.
Test and coverage: make check runs the Automake test harness; a --coverage build plus gcovr --fail-under-line 80 enforces coverage.
Security scans in parallel: scan-build --status-bugs and cppcheck check our code, Syft and Grype scan the resulting packages or image, and Gitleaks scans for secrets.
Quality gate: make check and the analyzers must pass, and releases are gated on make distcheck.
Fail the build (fail): A failed check stops the pipeline at the gate, so nothing is packaged, signed or published.
Release tarball (pass): make distcheck builds the release tarball, unpacks it, then builds and tests it out of tree.
SBOM and signing (pass): Syft generates the SBOM for the tarball or packages, and Sigstore cosign signs them.
Store the tarball (pass): CI keeps the tarball with actions/upload-artifact; distributions repackage it as .deb or .rpm.
Make rebuilds a target when any prerequisite is newer than the target (timestamp-based). Recipes are shell commands and must be indented with a tab.
Autotools is a generator: maintainers run autoreconf to produce configure; users and CI run ./configure && make. Release tarballs ship the generated configure so users do not need Autotools installed.
make distcheck builds the tarball, unpacks it, builds and tests it out of tree, and installs it to a temporary prefix; it is the best release gate for Autotools projects.
Build files
File
Purpose
Commit?
Makefile
Targets, prerequisites and recipes (plain Make projects)
Yes
*.mk
Included Makefile fragments
Yes
configure.ac
Autoconf input: checks for compilers, headers, libraries
Yes
Makefile.am
Automake input: programs, sources, tests
Yes
autogen.sh
Convenience wrapper for autoreconf -fi
Yes
m4/
Custom Autoconf macros
Yes
configure, Makefile.in, aclocal.m4, config.h.in
Generated by Autotools
No in git, yes in release tarballs
config.log, config.status, Makefile (generated)
Results of ./configure
No
Commands by category
1
2
3
4
5
6
7
8
9
autoreconf -fi&& ./configure CFLAGS="-O2 -Wall -Wextra -Werror"# generate + configure
make -j"$(nproc)"# build
bear -- make -j"$(nproc)"# build and record compile_commands.json
clang-tidy -p. src/*.c # lint (needs compile_commands.json)
scan-build --status-bugs make -j"$(nproc)"# SAST (Clang Static Analyzer)
cppcheck --enable=warning,portability --error-exitcode=1 src/ # SAST
make check # tests
make CFLAGS="--coverage -O0" check && gcovr -r.--fail-under-line 80 # coverage gate
make distcheck # release tarball + full verification
Minimal project
A plain Makefile with automatic header dependency tracking (recipes use tabs):