Getting Started with Automake and Autoconf
This little example will show you how to setup a project using the auto tools and also show you how to compile in a static library with your project. Creating shared libraries are for a different story. I'm assuming you're familiar with downloading an open source project and running ./configure and make. This basically shows how to automate setting up those commands.
First of all, we need to agree upon a source tree structure for this example. I usually do something like the following...
router/:
ChangeLog COPYING doc/ Makefile.am src/ autogen.sh* configure.in README
router/src:
dvrouter.h main.cpp dvrouter.cpp libjdhsocket/ Makefile.am
router/src/libjdhsocket:
clientsocket.cpp serversocket.cpp socketbase.cpp clientsocket.h
Makefile.am serversocket.h socketbase.h
Of course, you can use really any damn structure you like, but just bear with me here.
First thing to do is create a configure.in file (in new versions it's configure.ac) file. This file basically tells autoconf where stuff is and what to do. Here is a very basic configure.in file.AC_INIT(router,1.0) AM_INIT_AUTOMAKE AM_CONFIG_HEADER([src/config.h]) CFLAGS=" $CFLAGS -g" CXXFLAGS=" $CXXFLAGS -g -DDEBUG" LDFLAGS=" $LDFLAGS -g" # Checks for programs. AC_PROG_CXX AC_PROG_CC AC_PROG_INSTALL AC_PROG_AWK AC_PROG_RANLIB # Checks for header files. AC_HEADER_STDC AC_CHECK_HEADERS([arpa/inet.h fcntl.h limits.h malloc.h netdb.h \ netinet/in.h stddef.h stdlib.h string.h sys/ioctl.h sys/socket.h sys/time.h unistd.h]) # Checks for typedefs, structures, and compiler characteristics. AC_C_CONST AC_C_INLINE AC_TYPE_SIZE_T AC_HEADER_TIME AC_CHECK_TYPES([ptrdiff_t]) # Checks for library functions. AC_PROG_GCC_TRADITIONAL AC_FUNC_MEMCMP AC_CHECK_FUNCS([gethostbyname gettimeofday memmove memset pow select socket]) AC_PATH_PROG(routerpath, router) AC_OUTPUT([Makefile src/Makefile src/libjdhsocket/Makefile]) echo echo $PACKAGE $VERSION echo eval eval echo router will be installed in $bindir. if test "x$routerpath" != "x" ; then echo Warning: You have an old copy of router at $routerpath. fi echo echo configure complete, now type 'make' and then 'make install' echoAdd the following Makefile.am to the root directory. this is the same directory your configure.in is located.
SUBDIRS = srcThis Makefile.am is for the src directory. This basically defines the program and tells it to look into the subdir and compile the lib we are going to statically link in. Notice the cool syntax and other fun things.
bin_PROGRAMS = router router_SOURCES = main.cpp dvrouter.cpp dvrouter.h SUBDIRS = libjdhsocket router_LDADD = libjdhsocket/libjdhsocket.aThe last Makefile.am, the one for the socket library, is pretty simple and of course it goes in src/libjdhsocket/
noinst_LIBRARIES = libjdhsocket.a libjdhsocket_a_SOURCES= clientsocket.cpp clientsocket.h serversocket.cpp serversocket.h socketbase.cpp socketbase.h
Now we've got everything setup. However, automake and autoconf need a bunch of other shit to actually work. There are several command used to "initialize" your source tree so automake knows everything about it and what to do. So, I usually execute a file like this to initialize. Call it autogen.sh or something similar. This isn't really something that's distributed. It's just used for you while developing. If you change the configure.in file or doing anything drastic, it's probably a good idea to run this again.
#! /bin/sh autoheader -f touch NEWS README AUTHORS ChangeLog touch stamp-h aclocal autoconf -f automake --add-missing -c
That's it! Now you've got it setup and you can ./configure and make to setup and compile the project.
Now, I havn't gone into any depth or really explained all of the details, but that's where you come in. The auto tools are definately the way to go, especially for public open source projects that are going to be compiled on who knows what kind of machine.
1 Comment