Red Antigua Logo
Yet another piece of web.
Ads by Goooooogle
Search this site (by Google)
Tools    (top)
Your IP
Check a site for broken links
(W3C)

Perl modules    (top)
Tree::Numbered::Tools
(CPAN)
Perl tutorials    (top)
Perl modules
HTML::Template
CGI::Application
Mail::POP3Client
Mail::Send
MIME::Tools
Cookies with CGI::Application
Upload files with CGI::Application
Download files with CGI::Application
Redirect with CGI::Application
CPAN shell
Install DBD::mysql from the CPAN shell
Perl trim function
Validate an IP with Perl
Run suid Perl scripts under Apache
Perl taint mode
Perl date functions with Date::Calc

In Spanish
Curso de Perl

C tutorials    (top)
C - Introduction
C - Absolute beginner's Emacs
C - Examples for beginners
C - Makefile examples
C - Autotools examples
Server configurations    (top)
DNS
Apache
Apache Authentication and Access Control
mod_perl on FreeBSD
MySQL
MySQL add account
phpMyAdmin
Squid
DHCP

UNIX on Windows    (top)
Apache setup on Windows
MySQL setup on Windows
PHP setup on Windows
Perl setup on Windows
Emacs setup on Windows
UnxUtils
PuTTY
WinSCP
GIMP on Windows
MinGW - gcc on Windows
MSYS - UNIX-styled shell on Windows
msysDTK - autotools on Windows
GDB for MinGW on Windows

Misc. FreeBSD/UNIX    (top)
CD and DVD creation on FreeBSD using 'k3b' on FreeBSD
'portupgrade' on FreeBSD
'ipf' on FreeBSD
'pf' on FreeBSD
'su' on FreeBSD
Mount an ISO image under FreeBSD
Load the correct sound driver under FreeBSD without knowing what sound card you are using
Simultaneous sound channels on FreeBSD
FreeBSD network stuff
DOS-to-UNIX file conversion
favicon.ico on UNIX
Emacs tips
Sendmail tips
GKrellm
Command Line Calculator
Save multimedia streams with 'mplayer'
xargs - solution to 'Argument list too long'
Process multiple images from the command line using 'ImageMagick'
Turn the system bell off under X Windows
Process each line in an input file from the command line (or in a shell script)
How to keep a program running in the background using 'nohup'
How to remove symbolic links in the current directory using 'find' and 'rm'
How to remove Emacs backup files in the current directory and all subdirectories using 'find' and 'rm'
How to execute .profile without logging in
Configure X to handle non-English characters
How to move /var to /usr/var

Redirect a web page    (top)
Redirect to another web page
Apache redirect
C redirect
Perl redirect
PHP redirect
HTML redirect
JavaScript redirect

Javascript    (top)
Trim function
Login form
Register form
Popup window

Virus list    (top)
Latest 10 viruses - Sophos

Off topic    (top)
Personal home links

Makefile for Autotools
Makefile for Autotools
IndexPreviousNext
This is a Makefile named AutoMakefile for executing the Autotools toolchain.
It is based on the documentation Overview of GNU Autotools - Building Your Application
Check out the Autotools tutorial on this site to learn more about Automake, Autoconf, libtools, etc.
Briefly, the Autotools toolchain creates Makefiles automatically for your source code.

You can browse and download all files listed here (as well as others not listed).

BEFORE (not "Autotools-aware"):
Assume we have an existing project called mysleep, with the following tree layout:

mysleep/ (tree root)

src/

source code

doc/

documentation

man/

man pages

etc.


In this example, we will only use the src/ subdirectory.
Create the mysleep directory, create the subdirectory src/, and put the following files in src/:

src/mysleep.h:
#include <stdio.h>
#ifdef WIN32
#include <windows.h>         /* Needed for Windows Sleep() */
#define sleep(x) (Sleep(x * 1000))
#else
#include <unistd.h>          /* Needed for BSD sleep() */
#endif

src/mysleep.c:
#include "mysleep.h"

#define SECONDS_TO_SLEEP 3

int
main()
{
    unsigned int sleep_left = 0;
    /* sleep() for SECONDS_TO_SLEEP seconds, then print a message. */
    sleep(SECONDS_TO_SLEEP);
    printf("I woke up after %d seconds.\n", SECONDS_TO_SLEEP);
    return 0;
}

In the src/ directory you should now be able to compile and run the application:
cc mysleep.c -o mysleep
./mysleep
The output should be:
I woke up after 3 seconds.

AFTER ("Autotools-aware"):
These steps are required:
  1. Include config.h in your code.
    (Note that config.h does not exist yet, but will be created by Autotools.)
  2. Create configure.ac in mysleep/.
  3. Create Makefile.am in mysleep/.
  4. Create src/Makefile.am.

1. src/mysleep.h (modified):
#include <config.h>
#include <stdio.h>
#ifdef WIN32
#include <windows.h>         /* Needed for Windows Sleep() */
#define sleep(x) (Sleep(x * 1000))
#else
#include <unistd.h>          /* Needed for BSD sleep() */
#endif

2. configure.ac (you may run autoscan in the mysleep/ directory to create a template for this file):
#                                               -*- Autoconf -*-
# Process this file with autoconf to produce a configure script.

AC_PREREQ(2.56)
AC_INIT([mysleep], [0.0.1], [kuuse@redantigua.com])
# 1. Deprecated form of AM_INIT_AUTOMAKE: 
# http://www.gnu.org/software/automake/manual/html_node/Public-macros.html
# AM_INIT_AUTOMAKE(sleep, 0.0.1)
# 2. Recommended form of AM_INIT_AUTOMAKE, but is not supported by older versions of automake
# AM_INIT_AUTOMAKE([-Wall -Werror foreign])
# 3. Tested to work with automake 1.4-p6
# AM_INIT_AUTOMAKE([-Wall])
# 4. Without options: Should work with any version, but does it tell you about all automake warnings?
AM_INIT_AUTOMAKE
AC_CONFIG_SRCDIR([src/mysleep.c])
AM_CONFIG_HEADER(config.h)
AC_COPYRIGHT([Copyright 2007, Johan Kuuse])

# Checks for programs.
AC_PROG_CC
AC_PROG_MAKE_SET
# If you add the macro AC_PROG_LIBTOOL here, you must run "libtoolize" before "automake", 
# or you will get an error:
# required file `./ltmain.sh' not found
###AC_PROG_LIBTOOL

# Checks for libraries.

# Checks for header files.
AC_CHECK_HEADERS([unistd.h])

# Checks for typedefs, structures, and compiler characteristics.

# Checks for library functions.

AC_CONFIG_FILES([Makefile
                 src/Makefile])
AC_OUTPUT

3.Makefile.am:
SUBDIRS = src
# datarootdir: required for autoconf >= 2.60
datarootdir = $(prefix)/share

4.src/Makefile.am:
bin_PROGRAMS = mysleep
# datarootdir: required for autoconf >= 2.60
datarootdir = $(prefix)/share

As we will see, both configure.ac and Makefile.am are small files, not too tricky to configure.
The tricky part consists in executing the 10 steps in the toolchain in the correct order.
This is where AutoMakefile comes to help.
It can execute all the toolchain steps, or one by one.
If one step is executed, all dependencies (read "previous steps") are executed first, to create all files in the correct order.

README.AutoMakefile was used as a specification for AutoMakefile to figure out dependencies:
# README.AutoMakefile - heavily based on
# http://developer.novell.com/wiki/index.php/Overview_of_GNU_Autotools#Building_Your_Application

Step 1:
Action:         Create NEWS, README, AUTHORS, and ChangeLog if they do not exist already.
How:            touch NEWS README AUTHORS ChangeLog
Input:          None
Ouput:          NEWS, README, AUTHORS, ChangeLog
Used in step:   7

Step 2:
Action:         Create configure.ac automatically using autoscan if it does not exist.
                Edit configure.ac by hand if it exists.
                Check if configure.ac has been modified by hand.
How:            Non-existing configure.ac: autoscan && mv configure.scan configure.ac
                Existing configure.ac: awk check-for-modified configure.ac
Input:          None
Ouput:          configure.ac
Used in step:   4, 6, 8

Step 3:         
Action:         Create Makefile.am by hand if it does not exist.
                Check if Makefile.am has been modified by hand.
How:            awk check-for-modified Makefile.am
Input:          None
Output:         Makefile.am
Used in step:   7

Step 4:
Action:         Create aclocal.m4
How:            aclocal
Input:          configure.ac    (step 2)
Output:         aclocal.m4      
Used in steps:  5, 8

Step 5:
Action:         Create config.h.in by invoking autoheader.
How:            autoheader
Input:          aclocal.m4      (step 4)
Output:         config.h.in     
Used in step:   9

Step 6 (optional, only with libtool):
Action:         Create config.guess, config.sub, and ltmain.sh.
How:            libtoolize
Input:          configure.ac    (step 2)
                aclocal.m4      (step 4)
Output:         config.guess, config.sub, ltmain.sh
Used in step:   7
NOTE:           The web page
                http://developer.novell.com/wiki/index.php/Overview_of_GNU_Autotools
                does mention configure.ac but not aclocal.m4 (created in step 4) as
                required input file for 'libtoolize'.
                Anyhow, if aclocal.m4 is missing, 'libtoolize' complains with the following message:
                "You should add the contents of `/usr/share/aclocal/libtool.m4' to `aclocal.m4'."
                The fix: Required input files: configure.ac, aclocal.m4

Step 7:
Action:         Create Makefile.in, install-sh, missing, INSTALL, COPYING, and depcomp
                                                   by invoking automake.
How:            automake --add-missing
Input:          NEWS, README, AUTHORS, ChangeLog        (step 1)
                Makefile.am                             (step 3)
                config.guess, config.sub, ltmain.sh     (step 6, optional, only with libtool)
Output:         Makefile.in, install-sh, missing, INSTALL, COPYING, depcomp     
Used in step:   9

Step 8:
Action:         Create configure by invoking autoconf.
How:            autoconf
Input:          aclocal.m4      (step 4) 
                configure.ac    (step 2)
Output:         configure
Used in step:   9

Step 9:
Action:         Create Makefile by invoking configure
How:            ./configure
Input:          configure       (step 8) 
                config.h.in     (step 5)
                Makefile.in     (step 7)
Output:         Makefile
Used in step:   10

Step 10:
Action:         Create executable by executing make
How:            make
Input:          Makefile        (step 9)
Output:         executable

The Makefile is named AutoMakefile to not cause a name conflict with the automatically generated Makefile.
To use AutoMakefile as input to make, type:
make -f AutoMakefile
AutoMakefile:
# AutoMakefile - Makefile for autotools.
# NOTE: This file is for developers only!
# Read README, where the construction of this makefile is explained.
#
# If you just want to install and use the program/library, type:
# ./configure && make && make install
# Read INSTALL for details. 

# Change this section to fit your needs.
# ---------------------------------------
# LIB1 = 
PROGRAM1 = mysleep
FULL-PACKAGE-NAME = mysleep
VERSION = 0.0.1
BUG-REPORT-ADDRESS = kuuse@redantigua.com
# ---------------------------------------
# There should be no need to change anything below this line.

# Variables for multiple targets. 
TOUCH_TARGETS      = AUTHORS ChangeLog NEWS README
LIBTOOLIZE_TARGETS = config.guess config.sub ltmain.sh
AUTOMAKE_TARGETS   = Makefile.in install-sh missing INSTALL COPYING

.PHONY: help
help:
        @echo Type \'make -f AutoMakefile all\' to generate a Makefile \
for this project using autotools.
        @echo Type \'make -f AutoMakefile libtool\' to generate a Makefile \
for this project using autotools \(including libtool\).
        @echo Type \'make -f AutoMakefile stepN\' \(N = 1-10\) to go through \
the autotool chain step by step.
        @echo Type \'make -f AutoMakefile readme\' about a detailed explaination \
for each step.
        @echo Type \'make -f AutoMakefile\' or \'make -f AutoMakefile help\' to show \
this message again.

.PHONY: readme
readme:
        @if test -r README.AutoMakefile; then less README.AutoMakefile; else \
echo Sorry, but \'README.AutoMakefile\' is missing.; fi

# autotools process, step by step, as described in README.AutoMakefile
.PHONY: all
all:                      step1 step2 step3 step4 step5       step7        step8 step9 step10

.PHONY: libtool
libtool: libtool_precheck step1 step2 step3 step4 step5 step6 step7libtool step8 step9 step10

.PHONY: libtool_precheck
libtool_precheck:
        @if ! test -r configure.ac; then echo configure.ac does not exist.; \
echo Please create it by hand and be sure to include the AC_PROG_LIBTOOL \
macro if you plan to run libtoolize.; exit 1; fi
        @awk 'BEGIN {rc=1} {if ($$0 ~ /^AC_PROG_LIBTOOL/) {rc=0}} END {exit(rc)}' configure.ac || \
(echo Macro AC_PROG_LIBTOOL was not found in configure.ac.; \
echo Please add this macro to configure.ac if you plan to run libtoolize.; exit 1)


# Step 1:
# Create NEWS, README, AUTHORS, and ChangeLog, if missing.
.PHONY: step1
step1: $(TOUCH_TARGETS)
$(TOUCH_TARGETS):
        touch $@

# Step 2:
# Check if configure.ac exists.
# If not, create a template, configure.scan, using autoscan, rename configure.scan to configure.ac.
# Display "created, requires edit" message, exit.
# If configure.ac already exists, check if the AC_INIT macro has been edited has been edited.
# If not, display "requires edit" message, exit.
# NOTE: This target is .PHONY, as we always want to do this check.
have_configure_ac := $(wildcard configure.ac) 
.PHONY: step2
ifeq ($(strip $(have_configure_ac)),) 
step2: configure.ac_was_created_from_template_and_requires_edit
.PHONY: configure.ac_was_created_from_template_and_requires_edit
configure.ac_was_created_from_template_and_requires_edit:
        @echo "configure.ac does not exist, let us create a configure.scan template using autoscan..." 
        rm -rf autom4te.cache configure.scan && autoscan
        mv configure.scan configure.ac
        @echo "Now edit configure.ac by hand, then try again." 
        exit 1
else
step2: configure.ac_exists_but_requires_edit
.PHONY: configure.ac_exists_but_requires_edit
configure.ac_exists_but_requires_edit:
        @awk 'BEGIN {rc=1} {if ($$0 ~ /^AC_INIT/) {rc=0}} END {exit(rc)}' configure.ac || \
(echo The required macro AC_INIT is missing in configure.ac.; \
echo Please edit configure.ac and try again.; exit 1)
        @awk '{if ($$0 ~ /^AC_INIT\(FULL-PACKAGE-NAME, VERSION, BUG-REPORT-ADDRESS\)/) {printf "\
It seems like you have created a template for configure.ac, but you need to edit it.\n\
You should at least modify the following macro:\n\
AC_INIT\(FULL-PACKAGE-NAME, VERSION, BUG-REPORT-ADDRESS\)\n\
Try something like:\n\
AC_INIT\($(FULL-PACKAGE-NAME), $(VERSION), $(BUG-REPORT-ADDRESS)\)\n\
Please edit configure.ac and try again.\n\
"; exit 1} }' configure.ac
endif

# Step 3:
# Check if Makefile.am exists.
# If not, display "create" message, exit.
# If Makefile.am already exists, check if the variable 'datarootdir' is present.
# If not, display "requires edit" message, exit.
# NOTE: This target is .PHONY, as we always want to do this check.
have_makefile_am := $(wildcard Makefile.am) 
.PHONY: step3
ifeq ($(strip $(have_makefile_am)),) 
step3: Makefile.am_does_not_exist
.PHONY: Makefile.am_does_not_exist
Makefile.am_does_not_exist:
        @echo "Makefile.am does not exist, please create it by hand, then try again." 
        exit 1
else
step3: Makefile.am_exists_but_requires_edit
.PHONY: Makefile.am_exists_but_requires_edit
Makefile.am_exists_but_requires_edit:
        @awk 'BEGIN {rc=1} {if ($$0 ~ /datarootdir/) {rc=0}} END {exit(rc)}' Makefile.am || \
(echo You have created Makefile.am, but you need to edit it.; \
echo You should at least define the following variable:; \
echo datarootdir = $$\(prefix\)/share; \
echo Please edit Makefile.am and try again.; exit 1)
endif

# Step 4:
# Create aclocal.m4
.PHONY: step4
step4: step2 aclocal.m4
aclocal.m4:
        aclocal

# Step 5:
# Create config.h.in by invoking autoheader.
.PHONY: step5
step5: step4 config.h.in
config.h.in:
        autoheader

# Step 6 (optional, for libtool only):
# Create config.guess, config.sub, and ltmain.sh by invoking libtoolize.
# TODO: Automatic check for AC_PROG_LIBTOOL macro in configure.ac.
# Do not use libtool if AC_PROG_LIBTOOL is missing.
.PHONY: step6
step6: configure.ac_requires_edit_for_libtool $(LIBTOOLIZE_TARGETS)
.PHONY: configure.ac_requires_edit_for_libtool
configure.ac_requires_edit_for_libtool: configure.ac step4
$(LIBTOOLIZE_TARGETS):
        @awk 'BEGIN {rc=1} {if ($$0 ~ /^AC_PROG_LIBTOOL/) {rc=0}} END {exit(rc)}' configure.ac || \
(echo Macro AC_PROG_LIBTOOL was not found in configure.ac.; \
echo Please add this macro to configure.ac if you plan to run libtoolize.; exit 1)
        libtoolize

# Step 7 (without libtool):
# Create Makefile.in, install-sh, missing, INSTALL, COPYING, and depcomp by invoking automake.
.PHONY: step7
step7: step1 step3 step5 $(AUTOMAKE_TARGETS)
# Step 7 (with libtool):
# Create Makefile.in, install-sh, missing, INSTALL, COPYING, and depcomp by invoking automake.
.PHONY: step7libtool
step8libtool: step1 step3 step5 step6 $(AUTOMAKE_TARGETS)
$(AUTOMAKE_TARGETS):
        automake --add-missing --copy

# Step 8:
# Create configure by invoking autoconf.
.PHONY: step8
step8: step2 step4 configure
configure:
        autoconf

# Step 9:
# Create Makefile by invoking configure.
.PHONY: step9
step9: step5 $(AUTOMAKE_TARGETS) step8 Makefile
.PHONY: step9libtool
step9libtool: step5 step6 $(AUTOMAKE_TARGETS) step8 Makefile
Makefile:
        ./configure

# Step 10:
# Create executable by executing make.
.PHONY: step10
step10: make
.PHONY: make
make: step9
        make
        @echo
        @echo Type \'src/$(PROGRAM1)\' to launch the application.
        @echo Type \'make install \' to install it \(requires root access\).


# Clean up.
.PHONY: clean
clean: emacsclean
        # First, clean up from possible files created by 'make'. 
        @if test -r Makefile; then make clean; rm -f Makefile; fi
        @if test -r src/Makefile; then cd src; make clean; rm -f Makefile; fi
        # Then, clean up from files created by 'make -f AutoMakefile all'. 
        rm -rf .deps src/.deps COPYING INSTALL Makefile.in src/Makefile.in \
aclocal* autoscan.log autom4te.cache \
configure configure.scan config.* \
libtool stamp-h* *.o  *.exe \
$(PROGRAM1) $(LIBTOOLIZE_TARGETS) $(AUTOMAKE_TARGETS) \
depcomp mkinstalldirs

# Clean up Emacs backup files in current directory and all subdirectories.
.PHONY: emacsclean
emacsclean:
        find . -name "*~" -exec rm {} \;

Comments:
Note that each step (1-10) is defined as a .PHONY target, which serves as an "alias" for the "real" target.
If the "real" target is a file (most of the cases), then the "real" target is NOT defined as .PHONY.
(We don't want to recreate an already existing file.)
Let's look at the rule for the target step1 as an example:
TOUCH_TARGETS = AUTHORS ChangeLog NEWS README

# Step 1:
# Create NEWS, README, AUTHORS, and ChangeLog, if missing.
.PHONY: step1
step1: $(TOUCH_TARGETS)
$(TOUCH_TARGETS):
        touch $@
The commands for the step1 target is always executed by force (it is a .PHONY target), but the touch command for each "real" target (NEWS, README, AUTHORS, and ChangeLog, respectively) is only executed if the file corrsponding to the target name does not exist.
As we see, step1 works an an "alias" for the four targets NEWS README AUTHORS ChangeLog.
The target step1 is .PHONY, but the resulting "real" targets are not.

On the other hand, if the target name doesn't correspond to a file name, this means that we want to force to execute tha target's commands.
Let's look at parts of the rule for the target step2 as an example (some lines omitted for clarity):
# Step 2:
# If configure.ac already exists, check if the AC_INIT macro has been edited has been edited.
# If not, display "requires edit" message, exit.
# NOTE: This target is .PHONY, as we always want to do this check.
step2: configure.ac_exists_but_requires_edit
.PHONY: configure.ac_exists_but_requires_edit
configure.ac_exists_but_requires_edit:
        check configure.ac contents with 'awk', exit with error code if not edited correctly
The commands for the step2 target is always executed by force (it is a .PHONY target).
It is an alias for the target configure.ac_exists_but_requires_edit, which isn't a real target, and is also defined as .PHONY.
This is because we always want to force a check of the contents of configure.ac, even if the file configure.ac exists.
IndexPreviousNext
Last modified: Thu Jan 03 16:45:01 Romance Standard Time 2008