^ 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 |