| Linux – Friheden til at programmere: Version 2.5.20050330 – 2020-12-31 | ||
|---|---|---|
| forrige | Kapitel 5. Programmørens værktøjskasse | 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 <stdio.h>
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 <config.h>
#endif// #include <stdio.h>
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 <stdio.h>
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 iAfsnit 5.10er 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 <config.h>
#endif
#include <stdio.h>
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)
