^ Linux – Friheden til at programmere: Version 2.5.20050330 – 2020-12-31 ^| | [[program:vaerktoej-make|forrige]] | Kapitel 5. Programmørens værktøjskasse | [[program:vaerktoej-anjuta|næste]] | ---- ==== 5.11. Autoconf og automake ==== Makefiles er en stor hjælp til selv små projekter. Et problem der hurtigt opstår er at projektet begynder at udvide sig og blive mere og mere komplekst. Det får så dinMakefiletil at blive voldsomt stor, fyldt med fejl og uoverskuelig. Mange af de operationer der er i enMakefile, er trivielle gentagelser fra projekt til projekt. Når der skal ske det samme så mange gange, ville det være en fordel at indbygge dette i **make** eller lave noget udenom **make** der kan håndtere dette. Resultatet blev **autoconf** . Formålet med **autoconf** er få oprettet en "make"-fil der passer til slutbrugerens linux-version og eventuelt med brugerens specielle ønsker. Hele **autoconf** -systemet er lidt af en rodebunke og ret komplekst. Der findes flere mindre gode instruktioner til **autoconf** , og dette er nok endnu et eksempel – vi forsøger alligevel. Følgende programpakker skal være installeret inden man kan gå i gang:make,autoconfogautomake. For at gøre det hele så simpelt som muligt, laver vi det klassiske "Hello, world!" eksempel og bygger videre på dette. I et tomt underkatalog har vi så det lille simple programhello.cmed følgende indhold. /* Filnavn: hello.c */ #include int main(void) { printf("Hello, world!\n"); return 0; } For at komme i gang med selve **autoconf** mangler viconfigure.ac(tidligereconfigure.in) ogMakefile.am.Makefile.amer en fil til programmet **automake** , og den vil så opretteMakefile.in.Makefile.amer ofte en lille fil og ser således ud i en minimal udgave for et C-program. ## Filnavn: Makefile.am AUTOMAKE_OPTIONS = foreign bin_PROGRAMS = hello hello_SOURCES = hello.c Næste fil erconfigure.achvilket er en fil der kan gå hen og blive ret stor. I sin minimale udgave ser den således ud: # Filnavn: configure.ac AC_INIT(hello.c) AM_INIT_AUTOMAKE( demo-hello, 1.0 ) AC_PROG_CC AC_STDC_HEADERS AC_OUTPUT(Makefile) Med filernehello.c,Makefile.amogconfigure.ackan vi gå i gang med at oprette de filer vi senere skal have distribueret til brugeren. aclocal.m4er en samling af alle de shell-macroer som bruges iconfigure.ac. Filenaclocal.m4dannes af programmet **aclocal** ved at **aclocal** skannerconfigure.acfor hvilke macroer der bliver brugt. Macroerne finder den i .m4-filer som dem i /usr/share/aclocal/ (Den kigger i nuværende bibliotek og /usr/share/aclocal/ automatisk, man kan angive yderligere biblioteker). **aclocal** skal køres hvis der anvendes nye makroer iconfigure.ac. Når man da kalder **autoconf** for at danne **configure** ud fraconfigure.ac, vil **autoconf** erstatte brug af macroer med koden fraaclocal.m4. hven%aclocal For at få oprettetMakefile.in– det er den der senere skal læses af **configure** – køres kommandoen **automake -a** . hven%automake -a Der manglede nogle filer til **automake** hvilket vi automatisk får med, med tilvalget "--add-missing" ("-a" på kort form). hven%autoconfhven%./configurehven%make Ved oversættelse ses at der er brugt tilvalget "-g" til **gcc** , det betyder at der kommer fejlsøgningsdata med i programmet. Det kan slås fra ved at sætte CFLAGS iconfigure.actil for eksempel "-O2". Dertil kommer at der er to oversætterdirektiver, PACKAGE og VERSION, med på kommandolinjen. Der kan komme flere direktiver, så det vil være smart hvis disse blev lagt i en fil for sig, så kommandolinjen ikke bliver for lang. Dette kan gøres ved at tilføje AM_CONFIG_HEADER(config.h) iconfigure.ac. # Filnavn: configure.ac AC_INIT(hello.c) AM_INIT_AUTOMAKE( demo-hello, 1.0 ) //AM_CONFIG_HEADER(config.h) CFLAGS="-O2"// AC_PROG_CC AC_STDC_HEADERS AC_OUTPUT(Makefile) Efter tilføjelse af AM_CONFIG_HEADER kan systemet drille lidt ved at komme med nogle sære fejlmeddelelser. Dette skyldes at der er nogle afhængigheder iaclocal.m4, så denne fil skal opdateres med kommandoen **aclocal** . For at få oprettet header-filenconfig.h.inkøres **autoheader** . **./configure** vil så oprette filenconfig.hsom evt. kan tilføjes ihello.c. Dernæst kan **./configure** køres igen, og der oprettes enMakefile. hven%aclocalhven%autoheader ; autoconfhven%./configurehven%make clean ; make Bemærk at der nu under oversættelse tilføjes //-DHAVE_CONFIG_H// på kommandolinjen. Vi kan nu teste ihello.com der er enconfig.hog inkludere denne. Dernæst tjekker vi om PACKAGE og VERSION er defineret, og udskriver disse værdier. Tag et kig påconfig.h, og se hvad den indeholder. /* Filnavn: hello.c */ //#ifdef HAVE_CONFIG_H #include #endif// #include int main(void) { //#ifdef PACKAGE #ifdef VERSION printf("Bygget med pakken: %s-%s\n\n", PACKAGE, VERSION); #endif #endif// printf("Hello, world!\n"); return 0; } Der er en del filer i et autoconf-system og som nybegynder kan det være noget svært at få et overblik. Listen herunder giver en beskrivelse af de mest almindelige filer. **Tabel 5-1. Filer i et autoconf system** ^ Filnavn ^^ Skrives af ^^ Læses af ^| | hello.c | *dig* | gcc | | Makefile.am | *dig* | automake | | configure.ac | *dig* | automake autoconf aclocal | | config.h.in | autoheader | automake configure | | aclocal.m4 | aclocal | autoconf | | Makefile.in | automake | configure | | missing | automake | make?? | | install-sh | automake | "make install" | | mkinstalldirs | automake | configure | | stamp-h.in | automake | configure | | configure | autoconf | *script* | | Makefile | configure | make | | config.h | configure | hello.c(gcc) | | stamp-h | configure | configure | | config.cache | configure | configure | | config.status | configure | configure | | config.log | configure | *dig* | I figuren herunder ses en skematisk tegning af de vigtigste filer i et autoconf system. **Figur 5-10. Autoconf road map** {linuxbog:autoconfs.png} Du har nu fået oprettet de to mest basale filerMakefile.amogconfigure.acsom fint kan danne basis for et projekt. Lad os lige stoppe op og kikke på hvad der er oprettet af filer og hvorfor.Makefile.amer den mest overordnede fil og også den mest avancerede m.h.t. til brug af makroer. Heldigvis for forståelsen er der ikke så mange kommandoer i denne fil, de er bare ret avancerede.Makefile.amindeholder informationer om hvordan projektet overordnet ser ud. Hvilke er selve programmerne, hvor skal disse installeres, hvilke kildefiler kræver disse programmer osv. EnMakefile.amskal oprettes i hvert underkatalog, så dem kan man nemt få nogle stykker af. DenMakefile.amder ligger i roden af projektet, har kommandoen **AUTOMAKE_OPTIONS** som overordnet bestemmer hvilken type af projekt man køre. Et tilvalg man kan bruge til frie programmer er for eksempelgnuder er aktiveret som standard. Medgnu-tilvalget opretter **automake** en del ekstra filer såsom COPYING og INSTALL. Dertil forventer **automake** at der er oprettet fire ekstra filer (NEWS README AUTHORS ChangeLog). Den nyeMakefile.amser således ud: ## Filnavn: Makefile.am AUTOMAKE_OPTIONS = //gnu// bin_PROGRAMS = hello hello_SOURCES = hello.c Inden **automake** køres igen, skal vi lige have tilføjet de ekstra filer som en gnu-installation kræver, og så kan **automake** køres. En nyMakefile.inoprettes, og den indeholder ny oplysninger om flere filer der skal med i en distribution når man senere kører kommandoen **make dist** . hven%touch NEWS README AUTHORS ChangeLoghven%automake Kommandoen **bin_PROGRAMS** er en noget mere avanceret makro der fortæller hvilke binære filer der skal oversættes, og hvor disse skal installeres. Flere programmer kan indeholdes i en pakke, og de skrives på samme linje med mellemrum imellem. //bin// betyder at programmerne installeres i det underkatalog der er defineret i variablen **bindir** . Slutbrugeren kan så senere under installation bestemme hvor binære filer skal installeres. Default vil programmer blive installeret i/usr/local/bin/, men for nogle programmer gælder at disse skal installeres i/bin/. Vi kan på forhånd selv bestemme **bindir** , hvilket vi kommer tilbage til. **bin_PROGRAMS** har en fætter der hedder **sbin_PROGRAMS** , og den har default/usr/local/sbin/. **hello_SOURCES** er en noget speciel variable der fortæller hvilke kildefiler der anvendes til et enkelt program. **automake** tager hvert program der er listet i fx. **bin_PROGRAMS** og leder efter variablen **???_SOURCES** . **automake** forventer altså at denne variabel er oprettet, og der kommer selvfølgelig en fejl hvis den ikke er. configure.acer filen der fortæller hvordan en opsætning skal foregå. Her kikkes der ikke på kildetekster etc., men alene på hvordan opsætningen skal forløbe for slutbrugeren. Til et projekt er der kun énconfigure.ac, og denne er placeret i roden af projektet. Der kan komme mange underlige fejl undervejs, hvilket kan afhjælpes ved at køre de forskellige programmer igen. For alle programmer gælder at det ikke skader at køre dem igen, og det tager heller ikke ret lang tid at gøre det. Så går noget galt, så kør denne stribe programmer igen: hven%aclocal; automake -a; autoheader; autoconf; ./configure Læs mere:[http://sources.redhat.com/automake/automake.html|http://sources.redhat.com/automake/automake.html],[http://sources.redhat.com/autoconf/autoconf_toc.html|http://sources.redhat.com/autoconf/autoconf_toc.html],[http://www.andamooka.org/reader.pl?section=autobook|http://www.andamooka.org/reader.pl?section=autobook]og "info automake" lokalt på dit system. Se også autoconf-filerne fra distribution fileutils. === 5.11.1. Autoconf, underkataloger === Til større projekter er det en fordel at lægge afgrænsede dele af projektet i underkataloger. Som tidligere nævnt består et autoconf-system af enconfigure.acog evt. flereMakefile.am. I roden af projektet lægges enMakefile.amder fortæller hvilke underkataloger der skal med, og i hvert katalog enMakefile.amder beskriver hvilke kildetekster der skal med i dette katalog. I dette eksempel er der et katalog med en C-fil og et katalog med en man-fil. Her er listen af filerne før vi går i gang med at køre autoconf-programmerne. ./Makefile.am ./configure.ac man/Makefile.am man/hello.1 src/Makefile.am src/hello.c De enkelte filer ser således ud: Filnavn: ./Makefile.am AUTOMAKE_OPTIONS = foreign SUBDIRS = man src Filnavn: ./configure.ac AC_INIT(src/hello.c) AM_INIT_AUTOMAKE( katalog-hello, 1.0 ) AC_PROG_CC AC_STDC_HEADERS AC_OUTPUT(Makefile man/Makefile src/Makefile) Filnavn: man/Makefile.am man_MANS = hello.1 man_aux = $(man_MANS:.1=.x) EXTRA_DIST = $(man_MANS) Filnavn: man/hello.1 .TH HELLO 1 "1 August 2001" "Hello" "Friheden til at programmere" .SH NAME hello \- en hilsen .SH SYNOPSIS hello .SH DESCRIPTION .B hello skriver "Hello, world!" til standard out. .SH USAGE hello .SH COPYRIGHT Copyright \(co 2001 Friheden til at programmere. .SH SEE ALSO goodbye(1) Filnavn: src/Makefile.am bin_PROGRAMS = hello hello_SOURCES = hello.c Filnavn: src/hello.c #include int main(void) { printf("Hello, world!\n"); return 0; } Med alle filer på plads er det blot at køre autoconf-programmerne: hven%aclocal; automake -a; autoconfhven%./configurehven%make Anvendelse af underkataloger kræver altså ikke meget mere end at have alle filer i samme katalog../Makefile.amhar **AUTOMAKE_OPTIONS** som så ikke er i de andreMakefile.am-filer, **SUBDIRS** angiver i hvilke underkataloger der ligger flereMakefile.am's. Specielt for./configure.acskal det bemærkes at alleMakefiler skal angives i **AC_OUTPUT()** . === 5.11.2. Autoconf/automake eksempel === I eksemplet i[[program:vaerktoej-make|Afsnit 5.10]]er vist hvordan man manuelt opbygger enMakefile. Skal samme eksempel laves med autoconf/automake, skal der skrives to filer: ## Filnavn: Makefile.am AUTOMAKE_OPTIONS = foreign bin_PROGRAMS = ceks2 ceks2_SOURCES = ceks2.c cfkt.c # Filnavn: configure.ac AC_INIT(ceks2.c) AM_INIT_AUTOMAKE( demo-ceks , 1.0 ) AC_PROG_CC AC_STDC_HEADERS AC_OUTPUT(Makefile) De to filer kan se meget anderledes ud, men dette er noget af det simpleste man kan have til et C-program. Herefter er det blot at køre nogle kommandoer: hven%automake -ahven%aclocalhven%autoconfhven%./configurehven%makehven%make installhven%make uninstallhven%make dist # o.s.v... Det er lidt mere besværligt end det oprindelige eksempel, men vi fik også en **make install** plus et par andre gode ting for besværet. === 5.11.3. Installation af andre filer === I de andre eksempler er vist hvordan C-programmer kan oversættes og installeres i/usr/local/binved at bruge makroen **bin_PROGRAMS** . Har man programmer der skal lægges i/usr/local/sbiner det makroen **sbin_PROGRAMS** man skal bruge. HTML-filer, kommandofortolker og Perl-programmer skal håndteres anderledes. Her er et lille eksempel på hvad der skal tilføjes for at klare disse fil-typer. ## Filnavn: Makefile.am ... bin_SCRIPTS = hello.pl hello.sh sbin_SCRIPTS = minbackup.sh sysconfdir_DATA = hello.conf htmldir = /var/www/html/hello html_DATA = index.html ... I ovennævnte eksempel er de første tre makroer prædefinerede. Til **bin_PROGRAMS** er allerede defineret **bindir** , hvilket kan ændres af den bruger der installere programmet. Hvis bin-filerne skal ned i/binvil brugeren skrive:hven%./configure --bindir=/bin Listen over prædefinerede kataloger fås nemmest med:hven%./configure --help | grep DIR I førnævnte eksempel er opfundet et nyt katalog med navnethtmldir. Skal brugeren selv have lov til at bestemme hvilket katalog det er, skal der lidt mere til, og vi skal over og rette iconfigure.ac. Der skal ske det at der kommer et nyt tilvalg som bliver vist af **./configure --help** , og en variabel der kan sættes. # Filnavn: configure.ac ... htmldir=/var/www/html/hello AC_MSG_CHECKING(htmldir) AC_ARG_WITH(htmldir, [ --with-htmldir=DIR Where to put html/php files], [ case "$withval" in yes|no) ;; * ) htmldir="$withval" ;; esac]) AC_SUBST(htmldir) AC_MSG_RESULT(${htmldir}) ... Prøv herefter følgende kommandoer: hven%./configure --helphven%./configure --htmldir=/home/wwwhven%make -n install | more Eksemplet medhtmldirer inspireret af automake-manualen ogconfigure.acfra Samba. === 5.11.4. Tjek at en funktion er til stede === En god ting at have med i sinconfigure.acer at tjekke om de funktioner man bruger i C-programmerne er til stede i det pågældende system hvor **./configure** køres. Ihello.cbruges kun **printf()** og den tjekkes således: # Filnavn: configure.ac ... AC_CHECK_FUNCS(printf) ... Kør **autoconf** og **./configure** for at se resultatet. Flere funktioner kan skrives som parameter med mellemrum imellem. Eksemplet er fundet i Sambasconfigure.ac. === 5.11.5. Variable i config.h === En spændende ting man kan lave medconfigure.ac, er at tilføje variable tilconfig.hmed dynamisk input på det tidspunkt **./configure** køres. For ikke at kommandolinjen skal blive for lang, er det bedst at have AM_CONFIG_HEADER sat iconfgiure.in. I følgende eksempel hentes den aktuelle dato og tid når **./configure** køres. Den kan herefter findes iconfig.hog bruges i for eksempelhello.c. # Filnavn: configure.ac ... CONFDATO=`date "+%Y-%m-%d %H:%M:%S"` AC_DEFINE_UNQUOTED(CONFDATO,"$CONFDATO",[Dato for kørsel af ./configure]) ... For at få hele systemet opdateret kræves at **autoheader** køres for at få opdateretconfig.h.in, **autoconf** skal køres for at få opdateretconfigure, og **./configure** skal køres for at opdatereconfig.h. Herefter kan man se resultatet iconfig.h. hven%autoheader ; autoconf ; ./configurehven%cat config.h Oversætterdirektivet kan nu ses iconfig.h, og det kan så bruges ihello.c. /* Filnavn: hello.c */ #ifdef HAVE_CONFIG_H #include #endif #include int main(void) { #ifdef CONFDATO printf("./configure er kørt d.: %s\n", CONFDATO ); #endif printf("Hello, world!\n"); return 0; } Herefter er det blot at køre **make** og **./hello** , så vises dato og tid for hvornår **./configure** er kørt. Alternativt til dato kunne være kommandoen **uname -a** for at få oplysninger om det system programmet blev oversat på, eller et tilvalg som brugeren der kører **./configure** , selv kan definere. Eksemplet er fundet i PHP'sconfigure.ac. === 5.11.6. Autoconf og andre sprog === Hidtil er sproget C blevet brugt i eksemplerne, men autoconf/automake kan også bruges til både C++ og Fortran. Det er blot et spørgmål om at AC_PROG_CC udskiftes med henholdsvis AC_PROG_CXX eller AC_PROG_F77. Se følgende eksempel: # Filnavn: configure.ac AC_INIT(hello.c++) AM_INIT_AUTOMAKE( demo-hello, 1.0 ) AC_PROG_CXX AC_OUTPUT(Makefile) ---- | [[program:vaerktoej-make|forrige]] | [[program:index|hjem]] | [[program:vaerktoej-anjuta|næste]] | | Brug af oversættelsesfiler ("makefiles") | [[program:vaerktoej|op]] | Anjuta |