2022-02-01
Let's see how to set up GNU Autotools for building a new project!
Today we're starting a new project written in the C language.
The project will have a dependency to make it more interesting. We really can use any library, and for this example we'll pick the SDL library.
Last but not least, our project needs a name. Since libSDL is usually powering games, we could imagine our project is a game. Why not call it "Aventura"?
Prerequisites
Before starting, if you're not familiar with Autotools, take some time and go through the Autotools tutorial, an excellent slideshow by Alexandre Duret-Lutz.
Then we need to install all the packages we need.
Let's make sure we have Autotools. For Debian, that can be done with:
sudo apt install autoconf automake libtool gettext
Also, since we picked SDL as a project dependency, let's install the SDL development package:
sudo apt install libsdl2-dev
The implementation
-
Prepare the directory structure.
We need a
srcdirectory for the source code, where we begin with a single file,main.c.. └── src └── main.c -
Edit
src/main.cand add the following code, which attempts to initialize the video subsystem of SDL and then cleans up and exits. It's like "Hello, World!" for SDL.#include "SDL.h" #include <stdio.h> int main (void) { if (SDL_Init (SDL_INIT_VIDEO) < 0) { fprintf (stderr, "SDL could not be initialized. SDL_Error: %s\n", SDL_GetError ()); return 1; } atexit (SDL_Quit); return 0; }
How would we compile this without Autotools?
A first attempt might be:
gcc -o src/aventura src/main.c
However that would not be enough, because
SDL.his most likely not located directly in a standard include directory (such as/usr/include). It's probably under/usr/include/SDL2.You could specify the include path with
-I:gcc -I/usr/include/SDL2 -o src/aventura src/main.c
It would compile, but after that you'd get linker errors. You would need to explicitly link against SDL2 with
-lSDL2:gcc -I/usr/include/SDL2 -o src/aventura src/main.c -lSDL2
An easier and more portable way of getting the build flags in place would be to use pkg-config.
First we would call
pkg-config --list-alland look for "sdl" in its output:pkg-config --list-all | grep -i sdl
The above would tell us that the name of the package for SDL is
sdl2, and we could use that name to get the build flags:pkg-config --cflags --libs sdl2
Then we could use the output of
pkg-configin the call togcc:gcc -o main $(pkg-config --cflags --libs sdl2) src/main.c
That's better, but at this point it's already too complicated to compile directly (and we just started). Better leave this to the build system.
-
Let's add one Makefile template (named
Makefile.am) in the root directory and another one insrc.touch {.,src}/Makefile.am
Now the project tree should look like this:
. ├── Makefile.am └── src ├── main.c └── Makefile.am -
Edit the top level
Makefile.amand add the following line, which tells Automake which subdirectories to build (in our case,src).SUBDIRS = src -
Edit
src/Makefile.amand add the following two lines, which tell Automake the names of the binaries we want to build (in our case,aventura) and the lists of source files to compile for each of these binaries (main.cfor now).bin_PROGRAMS = aventura aventura_SOURCES = main.c - Run
autoscan.This will produce
configure.scan, which is can be used as a starting point forconfigure.ac:# -*- Autoconf -*- # Process this file with autoconf to produce a configure script. AC_PREREQ([2.71]) AC_INIT([FULL-PACKAGE-NAME], [VERSION], [BUG-REPORT-ADDRESS]) AC_CONFIG_SRCDIR([src/main.c]) AC_CONFIG_HEADERS([config.h]) # Checks for programs. AC_PROG_CC # Checks for libraries. # Checks for header files. # Checks for typedefs, structures, and compiler characteristics. # Checks for library functions. AC_CHECK_FUNCS([atexit]) AC_CONFIG_FILES([Makefile src/Makefile]) AC_OUTPUT - Rename
configure.scantoconfigure.ac. - Edit
configure.ac:- Fill the values for the project name, the version and the bug report address
- Call
AM_INIT_AUTOMAKE -
Call
PKG_CHECK_MODULESto define the dependency. This macro is an interface between autoconf andpkg-config. We already know the name of the package issdl2.
5c5,6 < AC_INIT([FULL-PACKAGE-NAME], [VERSION], [BUG-REPORT-ADDRESS]) --- > AC_INIT([aventura], [0.1], [someone@example.com]) > AM_INIT_AUTOMAKE([foreign -Wall -Werror]) 12a14,20 > PKG_CHECK_MODULES( > [SDL2], > [sdl2 > 2.0.3], > [CFLAGS="$CFLAGS $SDL2_CFLAGS" > LIBS="$SDL2_LIBS $LIBS"], > AC_MSG_WARN($SDL2_PKG_ERRORS) > )
- Run
autoreconf --install
Now everything is ready.
You can run ./configure
followed by make.
The executable is ./src/aventura.