Användarverktyg

Webbverktyg


teknik:projekt_med_gnu_autoconf_och_make

Projekt med GNU Autoconf och Make

Tänkte sätta mig ner och skriva en guide för hur man gör ett komplett projekt med hjälp av GNU verktygen Autoconf och Make.

Detta är väldigt grundläggande men med kunskapen så kommer ni kunna använda autoconf och make för att kompilera just ert projekt skrivet i C, C++ eller Fortran. Jag har valt att ta ett ganska enkelt program, en fil bara, skrivet i C och omvandla det till ett projekt med autoconf och make för att demonstrera.

Vi börjar med en enda fil, ni kan hitta den så som den såg ut innan projektet här. Senare kan ni ladda ner arkivfilen av projektet och se hur det utvecklats.

GNU Autoconf

Gnu Make finns nog redan på de flesta system så förmodligen saknar ni endast autoconf paketet, det är enkelt hämtat och installerat från gnu.org. När ni installerar det så kör ni tre kommandon som är ganska grundläggande för alla användare av POSIX system som Linux och UNIX.

./configure
make
make install

Alla nördar har kört detta vid något tillfälle och sett massa text susa förbi på skärmen, ser imponerande ut men inte många vet vad som pågår. Förutom vi som programmerar med POSIX standarden då, vi har vid något tillfälle insett att vårt projekt är för stort att kompilera för hand och velat ha något enklare.

För mig personligen var inlärningskurvan till autoconf och make otroligt brant, jag kämpade faktiskt länge med att ge upp och försöka på nytt att förstå mig på hur jag skulle skriva ordentliga Makefile-filer och configure-script. Därför kan det vara bra med en guide som den här.

Autoconf är ett makroverktyg, det tar som indata en fil full av makron och skalkod som den sedan omvandlar till ett script för Bourne Shell. Att spotta ut all den där texten på skärmen är faktiskt mycket enklare än vad de flesta tror.

Vi börjar med grunderna, Hejsan Världen, eller Hello World på ett helt annat språk.

AC_INIT(hejsan, version-0.1)
AC_MSG_NOTICE([Hejsan Världen])

En enkel makrofil med två rader, en initialisering av autoconf systemet med AC_INIT och ett meddelande utskrivet på skärmen med AC_MSG_NOTICE. Meddelandet citeras här med [ ] tecken istället för ” “. Det är bäst om ni undviker att skriva ut [ ] men det är inte omöjligt (det går t.ex. att ändra de tecken som används för citering), dock går vi inte in på djupet i den här guiden.

I första raden, AC_INIT, kan ni se att vi definierar namnet av vårt program och versionsnummret, ganska oviktigt för oss nybörjare just nu.

Andra raden är en sorts notis och kan användas när som helst under konfigurationsprocessen för att skriva ut meddelanden.

Kör vi nu kommandot autoconf configure.ac > configure så läses configure.ac filen in och ut spottas ett bourne shell script. Ändra rättigheterna på scriptet till chmod +x och kör det med ./configure så har vi redan skapat en ny katalog och två nya filer vi inte hade förut.

Katalogen är cache för autoconf och kan raderas när som helst.

Filerna är så klart configure scriptet, men även en loggfil som vi kanske minns från olika öppenkällkodsprojekt. Jag brukar t.ex. leta bland annat efter config.log filen för att se hur jag konfigurerade paketet vid senaste kompileringen. Den är även väldigt användbar om något går fel i configure scriptet och måste rättas till.

Nu ska vi vidare och göra något användbart.

Autoconf är ju bara makron, vi skriver ett makro och det exekveras i autoconf som en åtgärd för att t.ex. kolla om en C kompilator finns på systemet, eller C++, Fortran, eller söka efter ett bibliotek och testa att kompilera mot det.

I detta fallet ska vi använda oss av makrot AC_PROG_CC för att kolla om en fungerande miljö för att kompilera C-filer existerar. Ni har också makron som AC_PROG_CXX och AC_PROG_F77 som kollar efter C++ respektive Fortran.

Andra makron som AC_CHECK_HEADERS kan snabbt leta upp inkluderade header-filer åt er och AC_CHECK_LIB för att kolla så att önskade bibliotek finns på systemet.

Vårt program länkar mot libpcap för att sniffa paket, så därför är det ett krav att ha pcap.h och libpcap. Så här kan vår configure.ac fil se ut nu.

AC_INIT(snifstat, version-0.2)
AC_MSG_NOTICE([Configuring snifstat])
AC_PROG_CC
AC_CHECK_HEADERS([pcap.h])
AC_CHECK_LIB(pcap, pcap_create)

Kör autoconf configure.ac och spotta ut datan i configure scriptfilen så kan vi nu köra ./configure för att se om libpcap finns på systemet.

Vad som händer nu när vi kör configure är att ett väldigt litet C-program kompileras med funktionen pcap_create() i main() och länkas mot libpcap, eller -lpcap. Autoconf behöver inte veta vilka argument pcap_create funktionen tar eftersom den bara kompilerar för att se om funktionen finns närvarande i biblioteket. Därför är detta makro väldigt dynamiskt och fungerar för allt.

I den resulterande configure.ac filen har jag lagt till lite extra rader som ni inte ser här men eftersom citeringen av kod är så dålig i wordpress kan ni ladda ner paketet mot slutet av artikeln istället för att se resultatet.

GNU Make

Nu ska vi använda oss smått av GNU Make för att genom autoconf skapa en Makefile som kan kompilera vårt projekt.

Jag har egentligen BSD Make på mina system eftersom jag är en BSD-nisse, men för att vara konsisten har jag även GNU Make installerat som gmake på mitt system, därför kommer jag använda programnamnet gmake i fortsättningen men på många system heter det helt enkelt make.

Använder vi makrot AC_OUTPUT med ett filnamn som argument så kommer det filnamnet.in läsas in och behandlas för att sedan spottas ut som det angivna filnamnet.

Alltså, skriver vi AC_OUTPUT(Makefile) så kommer Makefile.in läsas in och spottas ut i form av Makefile.

Det görs även ett antal ersättningar i Makefile.in innan den spottas ut, dessa stoppar vi in genom att skriva @variabel@.

Till att börja med kan vår Makefile.in se ut så här till exempel.

PREFIX=@prefix@
CC=@CC@
LD=@LD@
CFLAGS=@DEFAULT_CFLAGS@
LDFLAGS=@DEFAULT_LDFLAGS@
SRC=@srcdir@

Redan nu kan vi börja skriva argument till vårt configurescript för att ersätta de olika @@-variablerna med valfri text. Skriver vi t.ex. ./configure –prefix=/usr/local så kommer PREFIX i Makefile att anges värdet /usr/local.

Samma sak med de andra värdena i filen. Dock vill vi ju inte skriva allt detta på kommandoraden med argument, därför återvänder vi till autoconf och vår configure.ac fil för att utforska makrot AC_SUBST.

För att det ska fungera måste vi definiera DEFAULT_CFLAGS och DEFAULT_LDFLAGS i configure.ac filen också, annars blir det problem med citeringen för någon anledning som jag inte riktigt förstår ännu.

De nya raderna i filen lägger vi helst ovanför AC_OUTPUT makrot och de kan se ut så här.

DEFAULT_CFLAGS="-I/usr -I/usr/local"
DEFAULT_LDFLAGS="-L/usr -L/usr/local -lc -lpcap"
 
AC_SUBST(CC, gcc)
AC_SUBST(LD, ld)
AC_SUBST([DEFAULT_CFLAGS])
AC_SUBST([DEFAULT_LDFLAGS])
AC_SUBST(srcdir, src)
AC_SUBST(prefix, /usr/local)

Vi ska även utveckla vår Makefile.in med lite extra rader som ska kompilera själva programmet.

I Makefile kan vi använda syntax som påminner om Bourne Shell, de få saker som är GNU Make specifika är klasserna där vi definierar olika åtgärder some make ska ta. T.ex. definierar vi här två stycken, en all: och en clean:.

export
 
all:
$(MAKE) -f $(SRC)/Makefile
@echo 'All done, now run snifstat.'
 
clean:
rm -f *.o snifstat

Simpelt sagt så är all: den som körs vid standard användning, alltså när du bara kör gmake. Den andra är clean: och fullständigt valfri, kör du gmake clean så kan man ha lite skalkommandon som rensar upp för en ny kompilering.

I detta fallet kan alla Bourne Shell scriptare se att jag valt att köra gmake kommandot på en annan Makefile i underkatalogen src. Kommandot som körs $(MAKE) -f $(SRC)/Makefile innehåller två variabler, en är definierad till namnet av det nuvarande make programmet, den andra definierar vi själva lite längre upp med SRC=@srcdir@, och detta i sin tur kommer från AC_SUBST kommandot i configure.ac filen där srcdir sätts till src.

Alltså, i vår huvudkatalog har vi en underkatalog som heter src, där har vi vår fil, snifstat.c. Vi kan lika gärna kompilera den direkt, varför jag valt att göra ännu en Makefile i en underkatalog är att jag helt enkelt vill visa hur det görs. Detta på grund av att de flesta större projekt kommer vilja att dela upp det på detta vis för en bättre struktur.

Slutsatsen blir ju, vad är i src/Makefile?

snifstat:
$(CC) $(LDFLAGS) $(CFLAGS) $(LIBS) $(INCLUDES) -o snifstat $(SRC)/snifstat.c

Endast två rader! Så, omedelbart inser man att alla variabler vi sätter i Makefile ärvs ner av kommandot till denna filen. Använd den lilla parsern i ert huvud och omvandla variablerna till deras rätta värde så ser ni snabbt att vi här kompilerar filen, weee, äntligen!

Likdant här i Makefile.in har jag lagt till extra rader som inte visas i artikeln men laddar ni ner slutpaketet kan ni gå igenom Makefile.in och se en install-klass också som hjälper er att installera paketet.

Nu är vi praktiskt taget färdiga och för det ni inte förstod från att läsa artikeln så har jag laddat upp det färdiga paketet här så ni kan undersöka filerna själva.

Nu är vi vid den punkten där ni kan ladda ner paketet, packa upp det och köra ./configure, gmake och gmake install precis som många andra paket.

Lycka till med ert framtida arbete i Autoconf och Make, här har ni lite länkar som kan hjälpa er på vägen.

* GNU Autoconf Macro Index * Autoconf manualen * Google.com

teknik/projekt_med_gnu_autoconf_och_make.txt · Senast uppdaterad: 2012-12-06 21:08 (extern redigering)