Skip to main content

Linux C Build Automation with GNU Autotools

·613 words·3 mins
Autotools Makefile Linux C
Table of Contents

🧭 Introduction
#

GNU Autotools is a collection of build tools designed to generate portable, standards-compliant build systems for C and C++ projects on Unix-like platforms. It is part of the GNU Project and produces Makefiles that conform to GNU coding standards.

Anyone who has worked with open-source C/C++ projects is familiar with the classic three-step build workflow:

./configure
make
make install

This workflow eliminates the need to manually maintain complex Makefiles for different environments. Once configured, a single make command can automatically build an entire project, greatly improving development efficiency.

For small projects, handwritten Makefiles may suffice. However, as project size and complexity grow, maintaining them becomes difficult and error-prone. In such cases, tools like GNU Autotools or CMake are used to automatically generate Makefiles. This article focuses on using Autotools to automate C project builds.

🧩 Components of GNU Autotools
#

Before starting, install the required tools. On CentOS:

yum install autoconf automake libtool

Autotools consists of several utilities:

  • aclocal: Collects macro definitions into aclocal.m4
  • autoscan: Scans source code and generates configure.scan
  • autoheader: Generates config.h.in
  • autoconf: Produces the configure script from configure.ac
  • automake: Generates Makefile.in from Makefile.am
  • libtool: Builds portable static and shared libraries

🔄 Standard Build Workflow
#

The typical Autotools workflow is:

  1. Run autoscan to generate configure.scan
  2. Rename and edit it as configure.ac
  3. Run aclocal, autoconf, and autoheader
  4. Create Makefile.am files
  5. Run automake --add-missing to generate Makefile.in
  6. Run ./configure to generate final Makefile
  7. Run make and optionally make install

🛠 Project Setup
#

Create a sample project layout:

mkdir -p /tmp/myproject/{src,include}

Source Files
#

main.c

#include <stdio.h>
#include "include/math.h"

int main(void)
{
    int a = 10, b = 20;
    printf("max=%d\n", max(a, b));
    printf("min=%d\n", min(a, b));
    return 0;
}

math.h

#pragma once
int max(int x, int y);
int min(int x, int y);

math.c

int max(int x, int y) { return x > y ? x : y; }
int min(int x, int y) { return x < y ? x : y; }

⚙️ Building a Simple Executable
#

Step 1: Generate configure.ac
#

Run:

autoscan
mv configure.scan configure.ac

Edit configure.ac:

AC_PREREQ([2.69])
AC_INIT(main, 1.0)
AM_INIT_AUTOMAKE
AC_CONFIG_SRCDIR([src/main.c])
AC_CONFIG_HEADERS([config.h])
AC_PROG_CC
AC_CONFIG_FILES([Makefile])
AC_OUTPUT

Step 2: Generate Build Scripts
#

aclocal
autoconf
autoheader

Step 3: Create Makefile.am
#

AUTOMAKE_OPTIONS = foreign
bin_PROGRAMS = main
main_SOURCES = src/main.c src/math.c
include_HEADERS = include/math.h

Generate Makefile templates:

automake --add-missing

Step 4: Configure and Build
#

./configure
make

Run the program:

./main

📦 Building with a Static Library
#

Directory Layout
#

myproject/
├── include/
├── lib/
│   └── math.c
└── src/
    └── main.c

configure.ac
#

AC_PREREQ([2.69])
AC_INIT(main, 1.0)
AM_INIT_AUTOMAKE
AC_CONFIG_SRCDIR([src/main.c])
AC_CONFIG_HEADERS([config.h])
AC_PROG_CC
AC_PROG_RANLIB
AC_OUTPUT([Makefile src/Makefile lib/Makefile])

Top-level Makefile.am
#

AUTOMAKE_OPTIONS = foreign
SUBDIRS = lib src

lib/Makefile.am
#

noinst_LIBRARIES = libmath.a
libmath_a_SOURCES = math.c
AM_CPPFLAGS = -I$(top_srcdir)/include

src/Makefile.am
#

bin_PROGRAMS = main
main_SOURCES = main.c
main_LDADD = $(top_srcdir)/lib/libmath.a
AM_CPPFLAGS = -I$(top_srcdir)/include

Build and install:

./configure
make
make install

🔗 Building with a Shared Library (Libtool)
#

configure.ac
#

AC_PREREQ([2.69])
AC_INIT(main, 1.0)
AM_INIT_AUTOMAKE
AC_CONFIG_SRCDIR([src/main.c])
AC_CONFIG_HEADERS([config.h])
AC_PROG_CC
AC_PROG_LIBTOOL
AC_OUTPUT([Makefile src/Makefile lib/Makefile])

Run:

aclocal
autoheader
autoconf
libtoolize -f -c
automake --add-missing

lib/Makefile.am
#

lib_LTLIBRARIES = libmath.la
libmath_la_SOURCES = math.c
AM_CPPFLAGS = -I$(top_srcdir)/include

src/Makefile.am
#

bin_PROGRAMS = main
main_SOURCES = main.c
main_LDADD = $(top_srcdir)/lib/libmath.la
AM_CPPFLAGS = -I$(top_srcdir)/include

Build and install:

./configure
make
make install

After installation, the executable can be run system-wide, and shared libraries will be placed under /usr/local/lib.

✅ Summary
#

GNU Autotools provides a powerful and portable way to automate C project builds on Linux. By combining autoconf, automake, and libtool, you can support:

  • Simple executables
  • Multi-directory projects
  • Static libraries
  • Shared libraries
  • Cross-platform portability

Although the learning curve is steeper than handwritten Makefiles, Autotools scales far better for real-world projects and remains widely used in mature open-source ecosystems.

Related

Configure a TFTP Server on Linux
·400 words·2 mins
Linux TFTP Networking
Linux SSH Password-Free Login and Automation in 2026
·559 words·3 mins
Linux SSH Security Automation DevOps
Linux nc (Netcat) Command Explained: Practical Networking Examples
·496 words·3 mins
Linux Networking Netcat