Skip to content

GNU Autoconf cheatsheet from a first configure script to portable checks, optional features, cross compilation, and reusable macros.

GNU Autoconf creates a portable configure shell script from configure.ac. The generated script detects compilers, headers, functions, libraries, and user-selected options, then creates configured build files such as Makefile and config.h.

configure.ac --autoconf/autoheader--> configure + config.h.in
Makefile.in --./configure----------> Makefile
config.h.in --./configure----------> config.h
source files --make-----------------> program
Tool or FilePurpose
configure.acSource file written by the project maintainer using Autoconf macros
autoconfGenerates configure from configure.ac
autoheaderGenerates config.h.in when AC_CONFIG_HEADERS is used
autoreconfRuns the required Autotools commands to refresh generated files
configurePortable script run by someone building the package
config.statusRecreates configured output files after configure has run
Makefile.inTemplate converted into Makefile by configure
config.h.inTemplate converted into config.h by configure

Autoconf configures a project; it does not compile it. make, a compiler, or another build tool performs the actual build after configuration.

On Windows, Autoconf and generated configure scripts normally run in a POSIX-like environment such as MSYS2, Cygwin, or WSL.


When downloading source that already contains a configure script, you usually do not need Autoconf installed:

Terminal window
tar -xf hello-1.0.tar.gz
cd hello-1.0
./configure
make
make check # If the project provides tests
sudo make install # Optional; consider a user-writable --prefix instead

Common user options:

Terminal window
./configure --help
./configure --prefix="$HOME/.local"
./configure CC=clang CFLAGS="-O2 -g"
make -j4
make install
OptionMeaning
--helpList standard and project-specific configuration options
--prefix=DIRInstall architecture-independent and architecture-dependent files under DIR
--bindir=DIROverride the executable installation directory
--includedir=DIROverride the header installation directory
--libdir=DIROverride the library installation directory
CC=clangSelect a C compiler for configure tests and the build
CPPFLAGS="-I..."Add preprocessor/include options
CFLAGS="-O2 -g"Add C compiler options
LDFLAGS="-L..."Add link-editor options
LIBS="-lm"Add libraries to the link command

When editing configure.ac, regenerate the configuration machinery before testing it:

Terminal window
autoreconf --install
./configure
make

During active maintenance, a useful cycle is:

Terminal window
autoreconf --force --install
mkdir -p build
cd build
../configure CFLAGS="-Wall -Wextra -g"
make

An out-of-tree build keeps generated build output separate from the source directory.


hello-autoconf/
|-- configure.ac
|-- Makefile.in
`-- src/
`-- main.c
AC_PREREQ([2.69])
AC_INIT([hello-autoconf], [1.0.0], [bugs@example.org])
AC_CONFIG_SRCDIR([src/main.c])
AC_CONFIG_HEADERS([config.h])
AC_PROG_CC
AC_CHECK_HEADERS([stdlib.h string.h])
AC_CHECK_FUNCS([strdup])
AC_CONFIG_FILES([Makefile])
AC_OUTPUT
MacroWhat It Does
AC_PREREQ([2.69])Requires at least the given Autoconf version when generating configure
AC_INIT(...)Defines package name, version, and bug-report address
AC_CONFIG_SRCDIR([...])Ensures configure is being run for the expected source tree
AC_CONFIG_HEADERS([config.h])Requests a generated C header containing feature definitions
AC_PROG_CCFinds and tests a working C compiler
AC_CHECK_HEADERS([...])Defines HAVE_..._H for available headers
AC_CHECK_FUNCS([...])Defines HAVE_... for available functions
AC_CONFIG_FILES([Makefile])Configures Makefile from Makefile.in
AC_OUTPUTCreates config.status and produces configured output files
#include <config.h>
#include <stdio.h>
int main(void) {
printf("Hello from %s!\n", PACKAGE_STRING);
return 0;
}

Include config.h before system headers when the configuration definitions may affect declarations exposed by those headers.

Recipe lines beneath targets must start with a tab.

srcdir = @srcdir@
CC = @CC@
CPPFLAGS = @CPPFLAGS@ -I.
CFLAGS = @CFLAGS@
LDFLAGS = @LDFLAGS@
LIBS = @LIBS@
PROGRAM = hello
SOURCES = $(srcdir)/src/main.c
.PHONY: all clean distclean
all: $(PROGRAM)
$(PROGRAM): $(SOURCES) config.h
$(CC) $(CPPFLAGS) $(CFLAGS) -o $@ $(SOURCES) $(LDFLAGS) $(LIBS)
clean:
rm -f $(PROGRAM)
distclean: clean
rm -f Makefile config.h config.log config.status

Autoconf replaces substitutions such as @CC@, @CFLAGS@, and @LIBS@ when it creates Makefile.

Terminal window
autoreconf --install
./configure CFLAGS="-Wall -Wextra -g"
make
./hello

Typical generated files:

configure # Distribute this so builders do not need Autoconf
config.h.in # Distribute this if config.h is generated
config.log # Local diagnostics from running configure
config.status # Local regeneration helper
config.h # Local configured header
Makefile # Local configured build rules

AC_PREREQ([2.69])
AC_INIT([package-name], [version], [bugs@example.org], [tar-name], [homepage])
AC_CONFIG_SRCDIR([src/main.c])
AC_CONFIG_HEADERS([config.h])
# Tool discovery
AC_PROG_CC
AC_PROG_INSTALL
# Options selected by the builder
AC_ARG_ENABLE(...)
AC_ARG_WITH(...)
# System feature checks
AC_CHECK_HEADERS(...)
AC_CHECK_FUNCS(...)
AC_SEARCH_LIBS(...)
# Generated outputs
AC_CONFIG_FILES([Makefile src/Makefile])
AC_OUTPUT

Autoconf input is processed by M4. Bracket-quote literal macro arguments consistently:

AC_INIT([calculator], [2.1.0], [bugs@example.org])
AC_CHECK_HEADERS([stdint.h unistd.h])
AC_CHECK_FUNCS([getline snprintf])

Do not write shell tests as if this were C:

# Good: portable shell used inside generated configure
if test "x$enable_debug" = xyes; then
AC_DEFINE([ENABLE_DEBUG], [1], [Define to enable debug logging.])
fi
CommandPurpose
autoconfRegenerate only configure
autoheaderRegenerate only config.h.in
autoreconf --installRegenerate required files and install auxiliary support files if needed
autoreconf --force --installForce regeneration after changing macros or included M4 files
autoupdateRewrite obsolete Autoconf macro spellings where possible
autoscanInspect a source tree and propose starting checks in configure.scan
ifnamesList C preprocessor conditionals used by source files

Autoconf communicates configuration results in two common ways:

MechanismBest ForUsed In
AC_SUBST and @NAME@Build commands, directories, compiler flags, filenamesMakefile.in, scripts, .pc.in files
AC_DEFINE and config.hC/C++ conditional compilationSource and header files
AC_ARG_WITH([greeting],
[AS_HELP_STRING([--with-greeting=TEXT], [message printed by the program])],
[GREETING=$withval],
[GREETING=Hello])
AC_SUBST([GREETING])
GREETING = @GREETING@
AC_DEFINE([ENABLE_LOGGING], [1], [Define to compile logging support.])

Generated config.h contains a definition resembling:

#define ENABLE_LOGGING 1

For a shell-derived value, use AC_DEFINE_UNQUOTED carefully:

AC_DEFINE_UNQUOTED([APP_DEFAULT_PORT], [$default_port],
[Default TCP port used by the application.])
#include <config.h>
#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif
#ifdef ENABLE_LOGGING
# include <stdio.h>
# define LOG(message) fprintf(stderr, "%s\n", (message))
#else
# define LOG(message) ((void) 0)
#endif

5. Detecting Compilers, Headers, Types, and Functions

Section titled “5. Detecting Compilers, Headers, Types, and Functions”

Portable software should test for the feature it needs instead of guessing from an operating-system name.

MacroPurpose
AC_PROG_CCFind a C compiler and configure C language tests
AC_PROG_CXXFind a C++ compiler
AC_LANG([C])Select C for following checks
AC_LANG([C++])Select C++ for following checks
AC_LANG_PUSH([C++]) / AC_LANG_POP([C++])Temporarily perform checks as C++
AC_PROG_CC
AC_PROG_CXX
AC_LANG_PUSH([C++])
AC_COMPILE_IFELSE(
[AC_LANG_PROGRAM([[#include <vector>]], [[std::vector<int> v; v.push_back(1);]])],
[AC_MSG_NOTICE([C++ vector support is available])],
[AC_MSG_ERROR([a usable C++ standard library is required])])
AC_LANG_POP([C++])
AC_CHECK_HEADERS([stdint.h stdlib.h string.h unistd.h])
AC_CHECK_HEADERS([sys/socket.h netinet/in.h arpa/inet.h])

These checks commonly create definitions such as:

#define HAVE_STDINT_H 1
#define HAVE_SYS_SOCKET_H 1

When one header needs another header first, supply prerequisite includes:

AC_CHECK_HEADERS([sys/socket.h])
AC_CHECK_HEADERS([netinet/in.h], [], [],
[AC_INCLUDES_DEFAULT[
#ifdef HAVE_SYS_SOCKET_H
# include <sys/socket.h>
#endif
]])
AC_CHECK_FUNCS([getline memmove snprintf strdup strnlen])

Check one function with explicit failure behavior:

AC_CHECK_FUNC([clock_gettime],
[AC_DEFINE([HAVE_CLOCK_GETTIME], [1],
[Define if clock_gettime is available.])],
[AC_MSG_WARN([clock_gettime unavailable; using fallback timing])])
AC_CHECK_TYPES([ssize_t, uint32_t])
AC_CHECK_MEMBERS([struct stat.st_mtim])
AC_CHECK_SIZEOF([long])
AC_TYPE_SIZE_T
AC_TYPE_PID_T
CheckPossible Definition or Result
AC_CHECK_TYPES([uint32_t])HAVE_UINT32_T
AC_CHECK_MEMBERS([struct stat.st_mtim])HAVE_STRUCT_STAT_ST_MTIM
AC_CHECK_SIZEOF([long])SIZEOF_LONG
AC_TYPE_PID_TProvides a usable pid_t fallback when needed

Use AC_SEARCH_LIBS when a function may already be in the C library on some platforms but require an extra library on others:

AC_SEARCH_LIBS([clock_gettime], [rt],
[],
[AC_MSG_ERROR([clock_gettime is required])])
AC_SEARCH_LIBS([socket], [socket],
[],
[AC_MSG_ERROR([socket support is required])])

If a library is required unconditionally and its API function is unique to it:

AC_CHECK_LIB([m], [sin],
[],
[AC_MSG_ERROR([the math library is required])])

Successful library checks update LIBS, so preserve @LIBS@ at the end of link commands in Makefile.in:

$(CC) $(CPPFLAGS) $(CFLAGS) -o app $(OBJECTS) $(LDFLAGS) $(LIBS)
AC_CHECK_HEADERS([zlib.h], [],
[AC_MSG_ERROR([zlib headers are required])])
AC_CHECK_LIB([z], [inflate], [],
[AC_MSG_ERROR([zlib library is required])])

Projects that provide .pc metadata can be checked through the PKG_CHECK_MODULES macro supplied by pkg-config:

PKG_PROG_PKG_CONFIG
PKG_CHECK_MODULES([LIBXML], [libxml-2.0 >= 2.9])
AC_SUBST([LIBXML_CFLAGS])
AC_SUBST([LIBXML_LIBS])
CPPFLAGS = @CPPFLAGS@ @LIBXML_CFLAGS@
LIBS = @LIBXML_LIBS@ @LIBS@

This requires the pkg.m4 macro to be available when generating configure, often through aclocal or a local m4/ directory.


7. User Options: Optional Features and Dependencies

Section titled “7. User Options: Optional Features and Dependencies”

Use AC_ARG_ENABLE for behavior built into your package:

AC_ARG_ENABLE([debug],
[AS_HELP_STRING([--enable-debug], [compile debug logging support])],
[],
[enable_debug=no])
AS_CASE([$enable_debug],
[yes], [AC_DEFINE([ENABLE_DEBUG], [1],
[Define to compile debug logging support.])],
[no], [],
[AC_MSG_ERROR([--enable-debug accepts only yes or no])])
Terminal window
./configure --enable-debug
./configure --disable-debug

Use AC_ARG_WITH for external software or a selected path:

AC_ARG_WITH([ssl],
[AS_HELP_STRING([--with-ssl=PREFIX],
[use TLS support installed below PREFIX])],
[ssl_prefix=$withval],
[ssl_prefix=no])
AS_IF([test "x$ssl_prefix" != xno], [
AS_IF([test "x$ssl_prefix" != xyes], [
CPPFLAGS="$CPPFLAGS -I$ssl_prefix/include"
LDFLAGS="$LDFLAGS -L$ssl_prefix/lib"
])
AC_CHECK_HEADERS([openssl/ssl.h], [],
[AC_MSG_ERROR([OpenSSL headers not found])])
AC_CHECK_LIB([ssl], [SSL_new], [],
[AC_MSG_ERROR([OpenSSL library not found])])
AC_DEFINE([WITH_SSL], [1], [Define to build TLS support.])
])
Terminal window
./configure --with-ssl
./configure --with-ssl=/opt/openssl
AC_MSG_NOTICE([checking optional networking support])
AC_MSG_WARN([documentation will not be generated])
AC_MSG_ERROR([libfoo >= 2.0 is required])
AC_MSG_CHECKING([whether experimental mode is enabled])
AC_MSG_RESULT([$enable_experimental])

Use an error when a missing capability makes the requested build impossible; use a warning when a safe reduced build remains usable.


Prefer built-in macros first. When they cannot express a required API or compiler behavior, use a focused test.

AC_COMPILE_IFELSE(
[AC_LANG_PROGRAM(
[[#include <stdatomic.h>]],
[[_Atomic int counter = 0; return (int) counter;]])],
[AC_DEFINE([HAVE_C11_ATOMICS], [1],
[Define if C11 atomics are available.])],
[AC_MSG_WARN([C11 atomics unavailable; using mutex fallback])])
save_LIBS=$LIBS
LIBS="$LIBS -lpthread"
AC_LINK_IFELSE(
[AC_LANG_PROGRAM(
[[#include <pthread.h>]],
[[pthread_t t; return pthread_create(&t, 0, 0, 0);]])],
[AC_DEFINE([HAVE_PTHREAD_CREATE], [1],
[Define if POSIX threads are linkable.])],
[AC_MSG_ERROR([POSIX threads are required])])
LIBS=$save_LIBS

For normal thread support, an established macro from a macro archive or project convention may handle platform-specific flags more fully than a small hand-written probe.

AC_RUN_IFELSE(
[AC_LANG_PROGRAM([], [[return 0;]])],
[AC_MSG_NOTICE([test program ran successfully])],
[AC_MSG_ERROR([test program failed])],
[AC_MSG_NOTICE([cross compiling: skipping run-time probe])])

Always provide a cross-compiling result or a policy for AC_RUN_IFELSE: a cross build cannot normally execute target binaries on the build machine.


9. Out-of-Tree Builds, Installation, and Reconfiguration

Section titled “9. Out-of-Tree Builds, Installation, and Reconfiguration”
Terminal window
mkdir build-debug
cd build-debug
../configure --prefix="$HOME/.local" CFLAGS="-O0 -g"
make
make install

For this to work cleanly:

PracticeReason
Use @srcdir@ in hand-written Makefile.in templatesSource files remain reachable from the build directory
Add -I. when including generated config.hThe header lives in the build directory
Avoid generating files into source directories during makeMultiple build directories remain independent
Terminal window
./config.status # Recreate configured files
./config.status Makefile # Recreate one configured output
./config.status --recheck # Rerun configure using its saved arguments

Use Autoconf directory substitutions rather than hard-coded install paths:

prefix = @prefix@
exec_prefix = @exec_prefix@
bindir = @bindir@
includedir = @includedir@
libdir = @libdir@
install:
mkdir -p "$(DESTDIR)$(bindir)"
cp hello "$(DESTDIR)$(bindir)/hello"
Terminal window
./configure --prefix=/usr/local
make
make DESTDIR="$PWD/stage" install

DESTDIR is commonly used to stage package contents without changing the configured prefix.


TermMeaning
BuildMachine on which configure and compiler commands run
HostMachine on which the built program or library will run
TargetMachine for which a compiler or debugger produced by the package will generate code

Most ordinary applications care about --host; compiler/toolchain projects may also care about --target.

AC_CANONICAL_BUILD
AC_CANONICAL_HOST
AC_PROG_CC
Terminal window
./configure --build=x86_64-pc-linux-gnu \
--host=aarch64-linux-gnu \
CC=aarch64-linux-gnu-gcc
make

For a cross build, allow the builder to provide a cached answer:

AC_CACHE_CHECK([whether the target has working frobnicate],
[ac_cv_have_working_frobnicate], [
AC_RUN_IFELSE(
[AC_LANG_PROGRAM([[#include <frobnicate.h>]],
[[return frobnicate() ? 0 : 1;]])],
[ac_cv_have_working_frobnicate=yes],
[ac_cv_have_working_frobnicate=no],
[AC_MSG_ERROR([set ac_cv_have_working_frobnicate for cross compilation])])
])
AS_IF([test "x$ac_cv_have_working_frobnicate" = xyes], [
AC_DEFINE([HAVE_WORKING_FROBNICATE], [1],
[Define if frobnicate works on the host system.])
])

The cross builder can then explicitly provide the result:

Terminal window
./configure --host=aarch64-linux-gnu \
ac_cv_have_working_frobnicate=yes
Terminal window
./configure --cache-file=config.cache
rm -f config.cache # Discard stale cached test answers

Cache files can make repeated configurations faster, but do not reuse results after changing compilers, sysroots, or target systems.


Autoconf can configure hand-written Makefile.in files. Automake is a separate companion tool that creates Makefile.in from shorter Makefile.am declarations.

hello-automake/
|-- configure.ac
|-- Makefile.am
`-- src/
|-- Makefile.am
`-- main.c
AC_PREREQ([2.69])
AC_INIT([hello-automake], [1.0.0], [bugs@example.org])
AM_INIT_AUTOMAKE([foreign subdir-objects])
AC_CONFIG_SRCDIR([src/main.c])
AC_CONFIG_HEADERS([config.h])
AC_PROG_CC
AC_CONFIG_FILES([Makefile src/Makefile])
AC_OUTPUT
SUBDIRS = src
bin_PROGRAMS = hello
hello_SOURCES = main.c
hello_CPPFLAGS = -I$(top_builddir)
Terminal window
autoreconf --install
./configure
make
make check
make distcheck
Automake FeaturePurpose
bin_PROGRAMSPrograms installed in bindir
noinst_PROGRAMSPrograms built but not installed
*_SOURCESSource files for a named program or library
check_PROGRAMSTest programs built for make check
TESTSTest executables or scripts run by make check
make distProduce a source distribution archive
make distcheckTest distribution, build, install, uninstall, and cleanup workflows

12. Advanced: Local Macros and Macro Directories

Section titled “12. Advanced: Local Macros and Macro Directories”

As configuration logic grows, move reusable probes from configure.ac into M4 macro files.

AC_DEFUN([AX_CHECK_WIDGET], [
AC_CHECK_HEADERS([widget.h], [],
[AC_MSG_ERROR([widget.h is required])])
AC_SEARCH_LIBS([widget_init], [widget], [],
[AC_MSG_ERROR([libwidget is required])])
])
AC_CONFIG_MACRO_DIRS([m4])
AX_CHECK_WIDGET

With Automake, also declare the macro directory:

ACLOCAL_AMFLAGS = -I m4

Then regenerate:

Terminal window
autoreconf --force --install

AC_CONFIG_MACRO_DIRS is available in current Autoconf releases. Projects that intentionally support older Autoconf can use the older singular form, AC_CONFIG_MACRO_DIR([m4]).

PracticeBenefit
Prefix project or third-party macros, such as AX_ or MYPROJECT_Avoid naming collisions
Use AC_REQUIRE([AC_PROG_CC]) inside a macro that needs a C compilerEnsure prerequisites run once and in the proper order
Save and restore CPPFLAGS, LDFLAGS, or LIBS around temporary testsAvoid leaking unwanted settings into later checks
Use AC_CACHE_CHECK for expensive or user-overridable probesMake results visible and usable for cross builds
Keep probes small and feature-orientedReduce false failures across platforms
AC_DEFUN([MYPROJECT_CHECK_FAST_INT], [
AC_REQUIRE([AC_PROG_CC])
AC_CHECK_SIZEOF([long])
AS_IF([test "$ac_cv_sizeof_long" -ge 8], [
AC_DEFINE([HAVE_64BIT_LONG], [1],
[Define if long is at least 64 bits wide.])
])
])

File or CommandUse It For
config.logCompiler commands, error messages, and failed test programs
./configure --helpSupported options and directory variables
./config.status --recheckRepeat configuration with saved arguments
autoreconf -vfiVerbose regeneration of generated files
autoconf -WallWarnings while generating configure
SymptomLikely CauseFix
configure: error: cannot find required auxiliary filesA tool such as Automake requires helper scriptsRun autoreconf --install
config.h.in is missingAC_CONFIG_HEADERS exists but autoheader was not runRun autoreconf --install or autoheader
Macro appears as literal text in generated outputMacro is unavailable to aclocal/M4Install its provider or configure m4/ macro lookup
A library is installed but check failsMissing include path, library path, dependency, or wrong architectureInspect config.log; set CPPFLAGS and LDFLAGS correctly
Works in source tree but not build/Templates assume source and build directories are identicalUse @srcdir@, @top_srcdir@, and build-directory include paths
Cross compile fails at a run testConfigure tries to execute target codeAdd a cross result path or supply a cache answer
Changing CFLAGS seems ignoredStale cache or reusing generated build filesConfigure a fresh build directory or remove config.cache
Terminal window
./configure CPPFLAGS="-I/opt/foo/include" LDFLAGS="-L/opt/foo/lib"
less config.log

Look for the failing compiler invocation and its small test program. It usually reveals a missing header, unresolved symbol, wrong compiler, or unsupported flag.


PracticeReason
Distribute configure, config.h.in, and needed Makefile.in files in release archivesUsers building a release should not need Autotools
Regenerate generated files from maintained inputs instead of hand-editing themChanges remain reproducible
Test at least one clean out-of-tree buildCatches source/build path mistakes
Test useful combinations of --enable-* and --with-* optionsFinds conditional-build breakage
Let users override CC, CPPFLAGS, CFLAGS, LDFLAGS, and LIBSSupports alternate compilers, packaging, and cross builds
Test features rather than OS namesPlatforms and library availability do not map cleanly to names
Put detailed failed-probe evidence in config.logMakes reports diagnosable
Terminal window
autoreconf --force --install
rm -rf build-check
mkdir build-check
cd build-check
../configure --prefix="$PWD/install" CFLAGS="-Wall -Wextra -O2"
make
make check
make install

When using Automake:

Terminal window
make distcheck

MacroPurpose
AC_PREREQ([version])Require a maintainer-side Autoconf version
AC_INIT([pkg], [version], [bugs])Initialize package metadata
AC_CONFIG_SRCDIR([file])Verify source directory location
AC_CONFIG_HEADERS([config.h])Generate a configuration header
AC_CONFIG_FILES([Makefile])Generate files from .in templates
AC_CONFIG_MACRO_DIRS([m4])Declare local macro directories
AC_OUTPUTProduce configured outputs
MacroPurpose
AC_PROG_CCFind C compiler
AC_PROG_CXXFind C++ compiler
AC_PROG_INSTALLFind a BSD-compatible install program
AC_CHECK_PROGFind one program
AC_CHECK_PROGSFind the first available program from a list
MacroPurpose
AC_CHECK_HEADERSTest for headers
AC_CHECK_FUNCSTest for functions
AC_CHECK_DECLSTest for declared symbols
AC_CHECK_TYPESTest for types
AC_CHECK_MEMBERSTest for structure members
AC_CHECK_SIZEOFDetermine size of a type
AC_SEARCH_LIBSFind a library needed for a function
AC_CHECK_LIBCheck a specific library for a function
MacroPurpose
AC_ARG_ENABLEAdd --enable-* / --disable-* feature options
AC_ARG_WITHAdd --with-* / --without-* dependency options
AC_SUBSTSubstitute a variable into output templates
AC_DEFINEDefine a preprocessor symbol
AS_HELP_STRINGFormat option help text
AS_IF / AS_CASEUse portable generated-shell conditionals
AC_MSG_NOTICEPrint information
AC_MSG_WARNPrint a warning
AC_MSG_ERRORStop configuration with an error
MacroPurpose
AC_COMPILE_IFELSECheck whether a source fragment compiles
AC_LINK_IFELSECheck whether a source fragment links
AC_RUN_IFELSECheck run-time behavior; needs cross-compile handling
AC_CACHE_CHECKCache and report a configuration test result
AC_DEFUNDefine a reusable M4 macro
AC_REQUIREEnsure another macro has expanded first

  1. Configure and build an existing released package with ./configure --help, ./configure, and make.
  2. Create a one-file C project using configure.ac, Makefile.in, AC_PROG_CC, and AC_CONFIG_FILES.
  3. Add config.h with header and function checks, then use #ifdef HAVE_... in C.
  4. Add --enable-debug and an optional dependency using AC_ARG_ENABLE and AC_ARG_WITH.
  5. Test an out-of-tree build and a custom installation prefix.
  6. Study config.log after intentionally requesting a missing header or library.
  7. Try an Automake project and run make distcheck.
  8. Extract a repeated dependency test into a local M4 macro.
  9. Design configuration tests that still work during cross compilation.

Terminal window
# User building a release
./configure --prefix="$HOME/.local"
make
make check
make install
# Maintainer after editing configure.ac or M4 macros
autoreconf --force --install
# Clean separate build directory
mkdir build && cd build
../configure CC=clang CFLAGS="-Wall -Wextra -g"
make
# Regenerate configured output files
./config.status
./config.status --recheck
# Cross compile example
./configure --host=aarch64-linux-gnu CC=aarch64-linux-gnu-gcc
# Diagnose a failure
less config.log