Für ein kleines Projekt ist ein Buildsystem mit wenig Aufwand möglich.
Grundlage ist ein configure.in und ein oder mehrere Makefile.am. Ich handhabe es so, dass ein Modul in einem Unterverzeichnis landet und ein eigenes Makefile.am bekommt. Die restlichen Dateien werden alle aus diesen Dateien generiert. Darum müssen sie nicht unbedingt im CVS landen. Wenn ein Entwickler keine oder alter Versionen von autoconf und automake hat oder Anwender auf das CVS zugreifen, dann sollten die Dateien trotzden dort aufgenommen werden. Zum kompilieren sind dann autoconf und automake nicht mehr notwendig.
Source
Nehmen wir an unser Projekt enthält folgende Dateien:
Code:
talk.h:
extern void sayHello();
talk.c:
#include <stdio.h>
#include "talk.h"
void sayHello() { printf("Hello"); }
main.c:
#include <stdio.h>
#include "talk.h"
int main() { sayHello(); printf(" World\n"); return 0; }
Das Buildsystem liegt im Projekt-root-Verzeichnis und der Source im Unterverzeichnis "src".
automake
Für automake sind später noch ein paar Einträge in der configure.in zu erledigen, vorerst kümmern wir uns um die Makefile.am.
Wir haben zwei Source-Files und einen Header. Daraus werden zwei Objekt-Files die zusammengelinkt das Program "helloworld" ergeben sollen. Das dazugehörige Makefile.am im Verzeichnis "src" sieht dann so aus:
Code:
## Process this file with automake to produce Makefile.in
# Program binary name
bin_PROGRAMS = helloworld
# sources
helloworld_SOURCES = main.c talk.c
# mark headers to include also in package
EXTRA_DIST = talk.h
Für das Projekt-root-Verzeichnis brauchen wir ebenfalls ein Makefile.am, das nichts anderes macht, als das Makefile im Verzeichnis src aufzurufen und Automake mitteilt, dass keine GNU-Dateien (README, COPYING etc.) vorhanden sein müssen.
Code:
## Process this file with automake to produce Makefile.in
SUBDIRS = src
AUTOMAKE_OPTIONS = foreign
autoconf
In diesem einfachen Fall ist die configure.in sehr einfach zu erstellen:
Code:
$ autoscan
$ mv configure.scan configure.in
Autoscan erstellt die Grundstruktur und durchsucht die Sourcen nach problematischen Stellen und fügt dafür Makros ein. Das ist natürlich nicht vollständig, aber für uns reicht das.
Die configure.in, die wir so erhalten haben muss noch editiert werden. Einerseits um Angaben zum Projekt-Namen zu machen und andererseits um Automake zu integieren. Die Test in der Mitte können so stehen gelassen werden. Der Header wird jedoch umgestellt und es wird der Pfad zu den Makefiles angegeben. Schlussendlich sieht configure.in so aus:
Code:
# Process this file with autoconf to produce a configure script.
AC_INIT([hworld], [0.1.0], [user@host.de])
AC_CONFIG_SRCDIR([config.h.in])
AM_CONFIG_HEADER([config.h])
AM_INIT_AUTOMAKE
# 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_CONFIG_FILES([Makefile
src/Makefile])
AC_OUTPUT
Man beachte AM_CONFIG_HEADER statt AC_CONFIG_HEADER und die Angabe der resultierenden Makefiles.
Buildsystem bauen lassen
Im Folgenden werden ein paar Tools aufgerufen, welche Dateien in das Projekt-Verzeichnis kopieren und neue Dateien generieren. Das ist immer Dann notwendig, wenn sich was am Buildsystem ändert, z.B. wenn neue Dateien in den Makefile.am hinzugefügt werden oder configure.in editiert wurde. Um diesen Vorgang zu automatisieren gibt es zwar autogen, ich persönlich bevorzuge ein kleines Shellscript Namens bootstrap das die Aufrufe enthält.
Folgende Schritte sind notwendig:
Code:
# aclocal.m4 erstellen:
aclocal
# config.h.in aus configure.in erstellen
autoheader
# aus Makefiles.am Makefile.in generieren und einige
# zusätzliche Tools in das Verzeichnis kopieren
# ("--add-missing --copy" bewirkt letzeres)
automake --add-missing --copy
# schlussendlich aus configure.in das configure-Script erstellen
autoconf
Damit sind wir schon soweit, dass jeder jetzt die folgenden Schritte bereits kennt. Kompilieren wir die Sourcen:
Code:
$ ./configure && make
$ ./src/helloworld
Hello World
$ make dist
$ ls
Makefile aclocal.m4 config.h.in configure hworld-0.1.0.tar.gz mkinstalldirs
Makefile.am autom4te.cache config.log configure.in install-sh src
Makefile.in config.h config.status depcomp missing stamp-h1
$ tar tzf hworld-0.1.0.tar.gz
Wie man sieht, sind weitere nützliche Targets vorhanden, wie "make dist" das ein Tarball erstellt, der den Benutzern verteilt werden kann.
Lesezeichen