An Internationalized Software Project With Auto Tools
Prev Adding a Module Next

Adding a Module

Here a module is added. Modules here are just sub-directories of 'src' which help to structure the source code. Each sub-directory will compile its sources into a static library. These static libraries are then linked together to form the executable.

First the sub-directory is created together with the necessary files: a source, a header and a Makefile.am file:
# mkdir src/testmodule
# touch src/testmodule/testfunc.cpp
# touch src/testmodule/testfunc.h
# touch src/testmodule/Makefile.am

src/testmodule/testfunc.h

void printMessage();


src/testmodule/testfunf.cpp

#include <stdio.h>
#include "testfunc.h"

void printMessage()
{
	printf("hello world!\n");
}

The module just has a function, which prints 'hello world'.

Integrating the Module into Auto Tools

src/testmodule/Makefile.am

noinst_LIBRARIES = libtestmodule.a
noinst_HEADERS = testfunc.h
libtestmodule_a_SOURCES = testfunc.cpp
src/testmodule/Makefile.am is similar to src/Makefile.am. 'noinst_LIBRARIES' lists all libraries, which will be created in this directory. 'noinst' indicates, that they will not be installed, but may be used in other directories for static linking.

'noinst_HEADERS' lists as in src/Makefile.am the header files. These are not directly compiled and not installed but are part of the source tarball.

Like 'testproj_SOURCES' in src/Makefile.am 'libtestmodule_a_SOURCES' lists all source file, which have to be compiled into the library. These sources make it into the source tarball, but will not be installed.

In order to use this function, src/main.cpp has to be modified:

src/main.cpp

#include <stdio.h>
#include "testproj.h"
#include "testmodule/testfunc.h"

int main(int)
{
	printMessage();
}

src/testproj.h is now useless, but will be kept. src/Makefile.am also needs a change:

src/Makefile.am

SUBDIRS = testmodule

bin_PROGRAMS = testproj
testproj_SOURCES = main.cpp
noinst_HEADERS = testproj.h
testproj_LDADD = $(top_srcdir)/src/testmodule/libtestmodule.a
'SUBDIRS' now points to a sub-directory which has to be processed. 'testproj_LDADD' list libraries, which have to be linked to testproj. As the sub-directories are build before 'src', the library will exist, when testproj is linked.

Finally 'configure.ac' needs a change, too:

configure.ac

...
AM_INIT_AUTOMAKE
AC_PROG_RANLIB

# Checks for programs.

...

# Checks for library functions.
AC_CONFIG_FILES([Makefile src/Makefile src/testmodule/Makefile])
AC_OUTPUT
'AC_PROG_RANLIB' enables the handling of static libraries. libtool will replace it lateron. More important: 'src/testmodule/Makefile' has to be added to AC_OUTPUT, so that 'configure' will create this Makefile as well.

Building the Project

With all this changes, 'make' can be started again. Note that it will detect the changed configure.ac and Makefile.am's and will automatically launch aclocal, automake, autoconf and autoheader, before 'configure' and finally 'make' is started!
# gmake
cd . && aclocal19

...

 cd . && automake19 --gnu
cd . && autoconf259
/usr/local/bin/bash ./config.status --recheck
running /usr/local/bin/bash ./configure   --no-create --no-recursion

...

config.status: executing depfiles commands
cd . && autoheader259
rm -f stamp-h1
touch config.h.in
cd . && /bin/sh ./config.status config.h
config.status: creating config.h
config.status: config.h is unchanged
gmake  all-recursive
gmake[1]: Entering directory `/usr/home/he/develop/testproj'
Making all in src
gmake[2]: Entering directory `/usr/home/he/develop/testproj/src'
Making all in testmodule
gmake[3]: Entering directory `/usr/home/he/develop/testproj/src/testmodule'
if g++ -DHAVE_CONFIG_H -I. -I. -I../..     -g -O2 -MT testfunc.o -MD -MP -MF ".deps/testfunc.Tpo" 
	-c -o testfunc.o testfunc.cpp; \
then mv -f ".deps/testfunc.Tpo" ".deps/testfunc.Po"; else rm -f ".deps/testfunc.Tpo"; exit 1; fi
rm -f libtestmodule.a
ar cru libtestmodule.a testfunc.o
ranlib libtestmodule.a
gmake[3]: Leaving directory `/usr/home/he/develop/testproj/src/testmodule'
gmake[3]: Entering directory `/usr/home/he/develop/testproj/src'
if g++ -DHAVE_CONFIG_H -I. -I. -I..     -g -O2 -MT main.o -MD -MP -MF ".deps/main.Tpo" -c -o 
	main.o main.cpp; \
then mv -f ".deps/main.Tpo" ".deps/main.Po"; else rm -f ".deps/main.Tpo"; exit 1; fi
g++  -g -O2   -o testproj  main.o ../src/testmodule/libtestmodule.a
gmake[3]: Leaving directory `/usr/home/he/develop/testproj/src'
gmake[2]: Leaving directory `/usr/home/he/develop/testproj/src'
gmake[2]: Entering directory `/usr/home/he/develop/testproj'
gmake[2]: Leaving directory `/usr/home/he/develop/testproj'
gmake[1]: Leaving directory `/usr/home/he/develop/testproj'
What a magic! Now testproj is compiled. 'make install' will just copy the executable, not the library:
# gmake install
Making install in src
gmake[1]: Entering directory `/usr/home/he/develop/testproj/src'
Making install in testmodule
gmake[2]: Entering directory `/usr/home/he/develop/testproj/src/testmodule'
gmake[3]: Entering directory `/usr/home/he/develop/testproj/src/testmodule'
gmake[3]: Nothing to be done for `install-exec-am'.
gmake[3]: Nothing to be done for `install-data-am'.
gmake[3]: Leaving directory `/usr/home/he/develop/testproj/src/testmodule'
gmake[2]: Leaving directory `/usr/home/he/develop/testproj/src/testmodule'
gmake[2]: Entering directory `/usr/home/he/develop/testproj/src'
gmake[3]: Entering directory `/usr/home/he/develop/testproj/src'
test -z "/usr/local/bin" || /usr/home/he/develop/testproj/install-sh -d "/usr/local/bin"
  /usr/bin/install -c 'testproj' '/usr/local/bin/testproj'

...
The program still does, what it should:
# testproj
hello world!
The result source code can be downloaded here.

Next libtool support will be added.
Prev Home Next
Revision Control Adding libtool Support