Setting up autoconf and automake for Phoenix2D

If there is one thing I hate doing with fervor, pure hatred, and cold sweat running through my spine, is makefiles. The first makefile I did was for a simple library, app, and testing project, it took me an entire day of reading best practices, which are kind of non existent, the makefile manual, and a lot of diet coke.

What I feel, and what I'm saying, it is not something new. Someone, or some people to be exact have suffered through this just like I have. Don't believe me?

The proof is in Autoconf and Automake. Amazing tools to help you eat code and crap lightning makefiles. Now I did used once cmake and considered using scons [for a build system] but I feel like I have to sell the idea to myself and then to others, so for now let's go all standard on the project.

.
+-- base                    // home folder
|   +-- phoenix2d-{version} // the lib
|   |   +-- phoenix2d       // master folder      
|   +-- player              // app example

That is the structure of the project, in the libs master folder we'll be placing different modules, right now the content looks like this.

.
+-- phoenix2d           // master folder
|   +-- autom4te.cache  // autoconf m4 files
|   +-- build   // for testing the build system
|   +-- communications  // a module  
|   |   +-- *.h         // CODE
|   |   +-- *.cpp       // CODE
|   |   +-- Makefile.am // Make rules
|   |   +-- Makefile.in // Make rules
|   +-- config          // app example
|   +-- doc             // doxygen settings
|   +-- m4              // autoconf m4 files
|   +-- aclocal.m4
|   +-- AUTHORS
|   +-- autogen.sh
|   +-- ChangeLog
|   +-- communications.hpp      // important
|   +-- communications.hpp.in
|   +-- communications.hpp.in~
|   +-- configure
|   +-- configure.ac            // important
|   +-- configure.scan
|   +-- COPYING
|   +-- INSTALL
|   +-- Makefile.am             // important
|   +-- Makefile.in
|   +-- NEWS
|   +-- README

Now that I'm writing this, I feel some changes will be necessary, since this could easily populate with a lot of folders maybe I should add everything to a lib folder just like the boost guys.

The communications module

This is the first module and the first feature we have to maintain, which is the parsing and sending data to the server. I don't know, maybe I should split it to a parsing module and the communications leave it for sockets.

This module as of March 2014 has a lot of code that doesn't belong there, such as the pde_engine which will most likely be another module.

The official site for the repository is here but I maintain a personal copy here mostly for development purposes.

Some changes will be necessary on the code to add better threading support, since as of right now accessing shared variables is not multi threaded supported.

Expect big changes.

How to setup your own autoconf

Essentially I had to build 3 files using autoscan and autoreconf. The autogen.sh is just a tool for running autoreconf.

#!/bin/sh
autoreconf --force --install -I m4  

The configure.ac file

I added a communications.hpp file that includes all the files in the module. This system will likely get replicated for the subsequent modules.

Most of what's here is generated by autoscan, I just added some include and src files.

#                                               -*- Autoconf -*-
# Process this file with autoconf to produce a configure script.

AC_PREREQ([2.69])  
AC_INIT(Phoenix2D Library, 0.1, claudio.rdgz@gmail.com)  
AC_CONFIG_AUX_DIR(config)  
AC_CONFIG_HEADERS([communications.hpp])  
AC_CONFIG_MACRO_DIR([m4])  
m4_pattern_allow([AM_PROG_AR])  
AM_PROG_AR  
AC_CONFIG_SRCDIR(communications/Actions.cpp)

# Give me ALL the warnings!
AM_INIT_AUTOMAKE([-Wall])

# Checks for programs.
AC_LANG(C++)  
AC_PROG_CXX  
AC_PROG_CC

# Checks for libraries.
LT_INIT

# Check for Boost libraries
# We need the regex headers
AC_LANG_PUSH([C++])  
AC_CHECK_HEADERS([boost/regex.hpp], [],  
    [AC_MSG_ERROR(You need the Boost libraries.)])
AC_LANG_POP([C++])

AC_SUBST([PHOENIX_API_VERSION], [0.1])

# Checks for header files.
AC_CHECK_HEADERS([arpa/inet.h netdb.h string.h sys/socket.h unistd.h])

# Checks for typedefs, structures, and compiler characteristics.
AC_CHECK_HEADER_STDBOOL  
AC_TYPE_SIZE_T

# Checks for library functions.
AC_FUNC_ERROR_AT_LINE  
AC_CHECK_FUNCS([bzero gethostbyname inet_ntoa pow socket sqrt])

AC_OUTPUT(Makefile communications/Makefile)  

And of course you'll be needing the Makefiles.

the module Makefile.am:

SUBDIRS = communications  
EXTRA_DIST = autogen.sh  
ACLOCAL_AMFLAGS = -I m4 ${ACLOCAL_FLAGS}  

the Makefile.am for building each file:

This is the Makefile rules for generating the communications static library.

lib_LIBRARIES = libphoenix2d_communications.a  
libphoenix2d_communications_a_SOURCES = Actions.cpp \  
                         Ball.cpp \
                         BeforeKickOff.cpp \
                         Command.cpp \
                         Commands.cpp \
                         Config.cpp \
                         Connect.cpp \
                         Controller.cpp \
                         CornerKickL.cpp \
                         CornerKickR.cpp \
                         Flag.cpp \
                         FreeKickL.cpp \
                         FreeKickR.cpp \
                         Game.cpp \
                         GoalKickL.cpp \
                         GoalKickR.cpp \
                         KickInL.cpp \
                         KickInR.cpp \
                         KickOffL.cpp \
                         KickOffR.cpp \
                         Line.cpp \
                         Logger.cpp \
                         Normal.cpp \
                         Parser.cpp \
                         Player.cpp \
                         PlayMode.cpp \
                         PlayOn.cpp \
                         Position.cpp \
                         Reader.cpp \
                         Self.cpp \
                         Server.cpp \
                         Trainer.cpp \
                         Vector2D.cpp \
                         World.cpp \
                         WorldModel.cpp