GNU Build System
V této kapitole vám představím všechny důležité části GNU Build System (autotools). Programy, skritpy a konfigurační soubory, které se spolupodílejí na vytvoření skriptu configure, hlavičkového souboru config.h a Makefile souborů. Toto je stěžejní kapitola celého seriálu o autotools.
O GNU Build Systému
Autotools je sada programů, která nějaké soubory čte a nějaké vytváří. V této části vám popíši, jaké programy jsou součástí autotools a s jakými konfiguračními soubory pracuje.
Soubor configure.ac, program autoconf, skripty configure a config.status a soubor config.log
Tím nejdůležitějším vstupním souborem je configure.ac (dříve
pojmenovaný configure.in). Do tohoto souboru se zapisují makra
jazyka m4. Program m4
je preprocessor, podobně
jako CPP. Tj. nahrazuje nějaké kusy textu za jiné kusy
textu. Oproti CPP je o něco složitejší, tj. umí toho mnohem více. Například
v něm můžete napsat něco jako funkci, používat switche, atd.
Kapitola o m4 se věnuje základům tohoto jazyka.
Nejjednodušší configure.ac může vypadat takto:
AC_INIT([psani-profi], [3.5.00], [sallyx@example.org],
[], [http://www.sallyx.org/sally/psani-vsemi-deseti/])
AC_OUTPUT
Toto jsou jediná dvě povinná makra v configure.ac. První makro,
AC_INIT
, má 5 argumentů (z toho jen první dva jsou povinné).
Hranaté závorky se používají jako uvozovky textu/kusu
kódu. m4 totiž umožňuje uvozovky
vnořovat, proto musí být počáteční „uvozovka“ jiná, než
ukončovací. (Nepleťte si to tedy s definicí pole z jazyka C.)
Druhé makro, AC_OUTPUT
, se postará o zapsaní všech
předchozích maker do skriptu configure.
Cokoliv zapíšete za makro AC_OUTPUT bude ignorováno.
Mezi názvem makra a závorkou (
nesmí být mezera!
Nejvíce práce při učení se autotools spočívá v poznávání podobných maker. Budete se učit, jaká makra existují, k čemu jsou, jaké požadují argumenty atp. Není to nic složitého. Všechna jsou dobře zadokumentována. Ale je jich takové množství, že se v tom začátečník snadno utopí. Proto čtěte dále, vybral jsem pro vás ty nejdůležitější :-).
Program autoconf přečte soubor configure.ac (z aktuálního adresáře) a vytvoří skript configure. Kromě toho se ještě vytvoří adresář autom4te.cache, kam si automake ukládá výsledky nějakých svých operací pro rychlejší znovuspuštění. (Tento adresář můžete klidně kdykoliv smazat.)
Můžete si to zkusit s předchozím configure.ac:
$ cat configure.ac AC_INIT([psani-profi], [3.5.00], [sallyx@example.org], [], [http://www.sallyx.org/sally/psani-vsemi-deseti/]) AC_OUTPUT $ autoconf $ ./configure -h `configure' configures psani-profi 3.5.00 to adapt to many kinds of systems. Usage: ./configure [OPTION]... [VAR=VALUE]... ... Report bugs to <sallyx@example.org>. psani-profi home page: <http://www.sallyx.org/sally/psani-vsemi-deseti/>. $ ./configure configure: loading site script /usr/share/site/x86_64-unknown-linux-gnu configure: creating ./config.status
Zatím toho moc configure neumí, ale nápovědu má velkou :-). Něco však přeci jen dělá. Vytváří soubor config.status. To je také bash skript, který dělá spoustu práce za configure. Především vytváří soubory na základě template souborů (config.h na základě config.h.in atp., viz dále).
Můžete se podívat na jeho nápovědu (./config.status -h
). Protože
ale zatím v configure.ac není o vytváření žádných souborů požádáno, tak
config.status zatím také nic nedělá. Kdyby něco dělal, vytvořil by adresář
config.cache, ve kterém si ukládá výsledky některých testů,
aby jeho opětovné spuštění mohlo být rychlejší. Tento adresář můžete
kdykoliv bez obav smazat.
Skript config.status je obvykle spouštěn skriptem configure, takže se o něj ani moc zajímat nemusíte. (Občas může být rychlejší spouštět přímo config.status, když víte co děláte …).
Tip: Když spustíte config.status s volbou --recheck
, tak spustí
skript configure se stejnými volbami, se kterými byl configure původně
spuštěn.
Po spuštění configure se ještě vytvoří soubor config.log. V něm najdete podrobně popsáno, co configure dělá. Pokud vám z nějakého důvodu configure selže, tak na konci tohoto logu najdete to, co dělal naposledy. Moc užitečné pro ladění.
Soubor aclocal.m4 a adresář m4/
Makra používaná v configure.ac musí být někde definována. Mnoho jich přináší
balíček ze kterého autotools instalujete. Jsou nainstalována do nějakých
souborů, které si autoconf najde. Pokud potřebujete, můžete si napsat vlastní
makra (v jazku m4). Pak musí být definována před makrem AC_INIT, nebo
v souboru aclocal.m4
. (Nic jiného než definice maker (a
komentáře) by před AC_INIT nemělo být!)
Další možností je zavolat makro AC_CONFIG_MACRO_DIR([m4])
(až za
AC_INIT). Pak se budou načítat makra ze souborů v adresáři
m4. Jméno tohoto adresáře může být jakékoliv, ale zvykem je
používat m4
.
Kromě standardních maker instalovaných s autotools existuje autoconf archive, který
obsahuje celou řadu dalších užitečných maker napsaných uživateli autotools.
(Takže potřeba psát vlastní makra je velice vzácná.)
Pokud nějaké z nich potřebujete použít, uložte jej do adresáře m4
(nezapomeňte zapsat AC_CONFIG_MACRO_DIR([m4])
do configure.h).
Například ax_lib_postgresql.m4 definuje makro AX_LIB_POSTGRESQL, které vám zjistí, zda je nainstalovaná postgres knihovna a jaké jsou potřeba přepínače pro překladač a preprocessor. Jak se používá vysvětlím na příkladu v některé z dalších kapitol.
Všechny makra z archivu můžete stáhnout pomocí gitu: git clone
git://git.sv.gnu.org/autoconf-archive.git
. V OpenSuSE distribuci
existuje balíček autoconf-archive
. Raději ale vždy stahuji
aktuální verzi maker, (jen ta, která potřebuji), z webu do svého projektu
(adresáře m4).
Program autoheader, skript configure.scan a soubor config.h.in
Program autoheader si přečte obsah souboru configure.ac a na jeho základě vytvoří soubor config.h.in.
Přesněji řečeno, vytvoří vstupní soubor pro první hlavičkový soubor, který určíte makrem AC_CONFIG_HEADERS. Tomuto makru se předává jako argument název souborů, které chcete nechat vygenerovat skriptem configure (který k tomu použije skript config.status). Názvy souborů jsou odděleny mezerou. Je zvykem první hlavičkový soubor nazývat config.h. (Ale můžete jej pojmenovat libovolně, třeba i včteně adresáre: src/config.h).
AC_INIT([psani-profi], [3.5.00], [sallyx@example.org],
[], [http://www.sallyx.org/sally/psani-vsemi-deseti/])
AC_CONFIG_HEADERS([config.h test.h])
AC_OUTPUT
S takovýmto configure.ac souborem vám autoheader vytvoří následující config.h.in:
/* Define to the address where bug reports for this package should be sent. */
#undef PACKAGE_BUGREPORT
/* Define to the full name of this package. */
#undef PACKAGE_NAME
/* Define to the full name and version of this package. */
#undef PACKAGE_STRING
/* Define to the one symbol short name of this package. */
#undef PACKAGE_TARNAME
/* Define to the home page for this package. */
#undef PACKAGE_URL
/* Define to the version of this package. */
#undef PACKAGE_VERSION
Program autoheader přečte makra použitá v configure.ac a zjistí, jaké proměnné
tyto makra definují. Pro ty pak vytvoří #undef
řádky v config.h.in.
Zatím je v configure.ac jen jedno makro definující nějaké proměnné, a to
AC_INIT (proměnné jsou definované v těle makra AC_INIT, v jazyce m4.)
$ autoconf $ autoheader $ ls autom4te.cache config.h.in configure configure.ac $ ./configure configure: creating ./config.status config.status: creating config.h config.status: error: cannot find input file: `test.h.in'
Formát pro *.h.in soubory se může zdát na první pohled zvláštní. Kromě
komentářů tam jsou jen řádky s #undef
. O tom, jestli bude dané
makro definováno, rozhodne až test na cílovém systému. Skript configure může ke
svému běhu využívat jen standardní unixové nástroje. K vytvoření config.h z
config.h.in používá config.status program sed, kterým nahrazuje existující řádky za něco
jiného (dle výsledků testu se buď řádek s #undef
zakomentuje,
nebo se nahradí řádkem #define
s hodnotou, kterou během
testování zjistil). Proto takový divný formát.
Vygenerovaný config.h (skriptem config.status) vypadá takto:
/* config.h.in. Generated from configure.ac by autoheader. */
/* Define to the address where bug reports for this package should be sent. */
#define PACKAGE_BUGREPORT "sallyx@example.org"
/* Define to the full name of this package. */
#define PACKAGE_NAME "psani-profi"
/* Define to the full name and version of this package. */
#define PACKAGE_STRING "psani-profi 3.5.00"
/* Define to the one symbol short name of this package. */
#define PACKAGE_TARNAME "psani-profi"
/* Define to the home page for this package. */
#define PACKAGE_URL "http://www.sallyx.org/sally/psani-vsemi-deseti/"
/* Define to the version of this package. */
#define PACKAGE_VERSION "3.5.00"
Jiný .in.h soubor než config.h obvykle potřebovat nebudete, takže pro další příklad test.h z configure.ac smažu. Ukáži vám ale ještě jedno nové m4 makro, které se používá pro definování proměnných, které se používají při generování hlavičkových souborů.
Tím makrem je AC_DEFINE
. Má tři (povinné) argumenty. Prvním je
jméno proměnné (používají se velká písmena), druhým je hodnota proměnné a
posledním je libovolný popis.
AC_INIT([psani-profi], [3.5.00], [sallyx@example.org],
[], [http://www.sallyx.org/sally/psani-vsemi-deseti/])
AC_DEFINE([HELLO_WORLD], ["Ahoj svete!"], [Definice pozdravu])
AC_CONFIG_HEADERS([config.h])
AC_OUTPUT
Všiměte si, že preprocessor m4 používá jako uvozovky hranaté závorky,
ale pro cpp ve vygenerovaném config.h je potřeba použít dvojité uvozovky.
Proto je druhý argument jak v hranatých závorkách, tak s uvozovkami.
Pravda ale je, že AC_DEFINE
je dost chytré,
takže i když dvojité uvozovky nepoužijete, v config.h budou stejně.
$ autoheader $ autoconf $ ./configure configure: creating ./config.status config.status: creating config.h
Výsledný config.h vypadá takto:
/* config.h.in. Generated from configure.ac by autoheader. */
/* Definice pozdravu */
#define HELLO_WORLD "Ahoj svete!"
/* Define to the address where bug reports for this package should be sent. */
#define PACKAGE_BUGREPORT "sallyx@example.org"
/* Define to the full name of this package. */
#define PACKAGE_NAME "psani-profi"
/* Define to the full name and version of this package. */
#define PACKAGE_STRING "psani-profi 3.5.00"
/* Define to the one symbol short name of this package. */
#define PACKAGE_TARNAME "psani-profi"
/* Define to the home page for this package. */
#define PACKAGE_URL "http://www.sallyx.org/sally/psani-vsemi-deseti/"
/* Define to the version of this package. */
#define PACKAGE_VERSION "3.5.00"
Makro AC_INIT interně používá právě makro AC_DEFINE k tomu, aby definovalo PACKAGE_* proměnné. Jiná makra definují proměnné na základě výsledků testů systému, takže jejich výsledná hodnota nebude vždy jasně daná, jako v tomto příkladu.
Program autoscan a soubor configure.scan
Program autoscan projde rekurzivně celý adresář, prohledá všechny zdrojové kódy (.c,.cpp,.h,…) a vytvoří šablonu pro configure.ac se jménem configure.scan.
Soubor configure.scan obsahuje vše, co si autoscan myslí, že by měl obsahovat configure.ac. To zní na první pohled super, bohužel možnosti autoscan programu jsou omezené a tak je vždy potřeba configure.scan ještě trochu doplnit a poopravit.
Program autoscan vytváří soubor se jménem configure.scan a ne configure.ac proto, aby nepřepsal vaše úpravy v configure.ac (pokud už by existoval).
Pro následující ukázku jsem vytvořil tento jednoduchý zdrojový kód:
Pro samotné autotools je potřeba hodně souborů a adresářů, proto se
obvykle zdrojové kódy ukládjí do podadresáře src.
Název src/
sice není povinný, ale je to
„nepsaný standard“.
$ autoscan $ tree . ├── autoscan.log ├── configure.scan └── src └── hello.c 1 directory, 3 files
Výsledkem je configure.scan s tímto obsahem:
# Process this file with autoconf to produce a configure script.
AC_PREREQ([2.69])
AC_INIT([FULL-PACKAGE-NAME], [VERSION], [BUG-REPORT-ADDRESS])
AC_CONFIG_SRCDIR([src/hello.c])
AC_CONFIG_HEADERS([config.h])
# 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_OUTPUT
Makro AC_PREG určuje minimálni požadovanou verzi autoconf, která by měla vygenerované konfiguraci rozumět. Je možné, že budete mít novější verzi než je 2.69 a tak tam budete mít jiné číslo.
AC_INIT už znáte. Program autoscan nemůže znát název vašeho programu, ani jeho verzi nebo vaší emailovou adresu, takže do AC_INIT dosadil nějaké zástupné hodnoty, které byste měli přepsat.
Jedna z voleb programu configure umožňuje tento skript spustit nad
adresářem, který určíte. Makro AC_CONFIG_SRCDIR
je tu jen jako
pojistka, která se ujistí, že vybraný adresář obsahuje soubor, který má jako
argument. Argument by tedy měl být co nejunikátnější název zdrojového souboru,
aby byl uživatel varován, pokud omylem určí špatný adresář. Program autoscan si
dosadí náhodně vybraný soubor, vy si jej přepište dle libosti.
Poslední nové makro je AC_PROG_CC
. To je první reálný test systému.
Toto makro se snaží najít nějaký překladač jazyka C. Pokud je váš program
psaný v C++, použijte makro AC_PROG_CXX
.
Makro AC_PROG_CC
hledá překladač v proměnné prostředí, pak se dívá po
gcc, cc a dalších. Viz Volby pro configure.
V configure.scan najdete ještě několik komentářů oddělující sekce, kde by měly být další testy. Popořadě by se nejdříve měla kontrolovat existence programů, které jsou potřeba pro překlad či běh vašeho programu, dále existence knihoven, hlavičkových souborů, různých standardních struktur a typů a nakonec existence funkcí z knihoven.
Makra jsou na sobě obvykle nezávislá a nezáleží tak na jejich pořadí (čest vyjímkám, jako je AC_INIT a AC_OUTPUT). Přesto je asi logičtější nejdříve hledat existenci knihovny, než to, jestli daná knihovna obsahuje konkrétní funkci …
Program autoscan nenašel v našem malém zdrojáku nic, co by bylo potřeba kontrolovat. Obvykle je úspěšnější, ale čas od času je potřeba mu pomoci a dopsat další testy, které neodhalil. O makrech, které by se k tomu měli používat bude některá z dalších kapitol.
Dalším krokem je přejmenovat configure.scan na configure.ac a upravit jej podle potřeby:
# Process this file with autoconf to produce a configure script.
AC_PREREQ([2.69])
AC_INIT([hello-world], [0.4], [hello-world@example.org])
AC_CONFIG_SRCDIR([src/hello.c])
AC_CONFIG_HEADERS([config.h])
AC_DEFINE([HELLO_WORLD], ["Ahoj svete!"], [Definice pozdravu])
# 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_OUTPUT
Všiměte si, že jsem doplnil AC_DEFINE. Berte to jen jako učebnicový příklad, v praxi je samozřejmě lepší vytvořit si nějaký .h soubor a definice napsat přímo do něj. Do configure.ac má smysl dávat jen definice, které se obvykle mění např. se změnou verze programu, nebo je možné je změnit pomocí nějaké konfigurační volby skriptu configure. Jak se to dělá, tak o tom zase někdy jindy.
Další postup už znáte:
$ mv configure.scan configure.ac # upravit configure.ac $ autoconf $ autoheader $ ./configure checking for gcc... gcc checking whether the C compiler works... yes checking for C compiler default output file name... a.out checking for suffix of executables... checking whether we are cross compiling... no checking for suffix of object files... o checking whether we are using the GNU C compiler... yes checking whether gcc accepts -g... yes checking for gcc option to accept ISO C89... none needed configure: creating ./config.status config.status: creating config.h
Hurá! Konfigurační skrypt už konečně něco checkuje! Schválně, co se stane, když se pokusím podstrčit neexistující překladač:
$ CC=xaxa ./configure checking for gcc... xaxa checking whether the C compiler works... no configure: error: in `.../02GNUBuildSystem/example4': configure: error: C compiler cannot create executables See `config.log' for more details
Je skvélé, že už máme skript, který kontroluje existenci překladače, teď ještě tak mít Makefile, který tento překladač použije.
Soubory Makefile.in
Pro vytvoření Makefile souborů musíte vytvořit předlohy v podobě souborů Makefile.in. K předchozímu příkladu přidám Makefile.in do rootu projektu, který pouze předá cíle druhému Makefile.in v adresáři src/. (Jejich obsah vizte dále.)
Takto vypadá počáteční souborová struktura (example5):
$ tree . ├── Makefile.in └── src ├── hello.c └── Makefile.in 1 directory, 3 files
Po spuštění autoscan přibylo do configure.scan nové makro:
AC_INIT([FULL-PACKAGE-NAME], [VERSION], [BUG-REPORT-ADDRESS])
...
AC_CONFIG_FILES([Makefile
src/Makefile])
AC_OUTPUT
Toto makro určuje, jaké soubory se mají vygenerovat dle jejich *.in předloh. Toto makro tedy přidám do configure.ac.
Podívejte se nejdříve na obsah Makefile.in. Vygenerovaný Makefile má za úkol
pouze předat cíle all
a clean
do adresáře src/:
all clean:
$(MAKE) -C @builddir@/src $@
To, co je mezi dvěmi zavynáči (@) se nahradí proměnnou, definovanou
makrem AC_SUBST. Existuje několik
předdefinovaných
proměnných, mezi něž patří @configure_input@
i @builddir@
.
Další proměnné mohou být definovány makry, jako je např.
AC_INIT.
V dokumentaci k tomuto makru se dočtete, že definuje následujicí output variables:
PACKAGE_NAME, PACKAGE_TARNAME, PACKAGE_VERSION, PACKAGE_STRING, PACKAGE_BUGREPORT, PACKAGE_URL.
@configure_input@
se nahradí textem
Makefile. Generated from Makefile.in by configure.
@builddir@
se nahradí adresářem, kam se budou generovat výstupní
soubory (Makefile, *.o soubory a výsledný program) – tedy tečkou
reprezentující aktuální adresář. Vzpomeňte, že configure se může spouštět z
jiného adresáře, než kde jsou uloženy zdrojové kódy (ty mohou být na read-only
médiu). Opomenutí použití @builddir@
a podobných proměnných je
jeden z častých důvodů, proč neprojde make distcheck
.
Soubor src/Makefile.in je o malinko zajímavější, ale také využívá jen output variables předdefinované, nebo definované makrem AC_INIT:
all:
$(CC) @CPPFLAGS@ @CFLAGS@ @DEFS@ -o @top_builddir@@PACKAGE_NAME@ @top_srcdir@/hello.c @LDFLAGS@ @LIBS@
clean:
$(RM) @PACKAGE_NAME@
Krátce se zmíním o @DEFS@. Pokud byste nepoužili makro AC_CONFIG_HEADERS,
pak by proměnná @DEFS@ obsahovala spousty -D
přepínačů s makry,
které jsou jinak definavené v config.h.
Při použití AC_CONFIG_HEADERS
obsahuje @DEFS@ jen -DHAVE_CONFIG_H
.
Další proměnné jsou definovány autotools, nebo je najdete ve vašem vygenerovaném config.h souboru (například @PACKAGE_NAME@).
Proměnná @top_builddir@
obsahuje kořen adresáře, kde dochází k
překladu. Výsledný program bude tedy uložen na stejné úrovni, jako je adresář,
ze kterého se spouští configure. Proměnná @top_srcdir@
obsahuje
absolutní cestu k adresáři, kde je příslušný Makefile.in.
Můžete si to jednoduše vyzkoušet. Spusťte configure například z /tmp adresáře:
$ cd /tmp/ $ /home/p.../02GNUBuildSystem/example5/configure checking for gcc... gcc checking whether the C compiler works... yes checking for C compiler default output file name... a.out checking for suffix of executables... checking whether we are cross compiling... no checking for suffix of object files... o checking whether we are using the GNU C compiler... yes checking whether gcc accepts -g... yes checking for gcc option to accept ISO C89... none needed configure: creating ./config.status config.status: creating Makefile vconfig.status: creating src/Makefile config.status: creating config.h config.status: config.h is unchanged $ cat src/Makefile # src/Makefile. Generated from Makefile.in by configure. all: $(CC) -g -O2 -DHAVE_CONFIG_H -o ../hello-world /home/p.../02GNUBuildSystem/example5/src/hello.c clean: $(RM) hello-world $ make make -C ./src all make[1]: Vstupuje se do adresáře „/tmp/src“ cc -g -O2 -DHAVE_CONFIG_H -o ../hello-world /home/p.../02GNUBuildSystem/example5/src/hello.c make[1]: Opouští se adresář „/tmp/src“
O naplnění ostatních proměnných se postarají makra, která v configure.ac použijete. (Respektive vygenerovaný configure.scan skript.) Některé hodnoty jsou „jen“ defaultní. Např. $(CC) můžete nadále změnit až při spuštění programu make…
Programy automake, aclocal, soubory aclocal.m4, Makefile.am a adresář build-aux
Sliboval jsem vám, že vám autotools pomohou vytvořit Makefile se standardními cíli. K tomu slouží program automake, jenž vygeneruje Makefile.in na základě Makefile.am šablony (jo jo, šablona pro vygenerování šablony :-).
Automake se přidal k autotools o něco později, takže autoconf na automake nezávisí, ale automake na autotools ano.
Program automake také čte confiugre.ac, aby zjistil, jaké soubory má generovat. Nehledá Makefile.am v souborovém systému, ale hledá makro AC_CONFIG_FILES. Krom toho musíte do configure.ac přidat nějaká další makra, která ovlivňují chování automake.
Tyto makra nejsou součástí autoconfigu, ale automake naštěstí přichází s pomocným programem aclocal, který vytvoří soubor aclocal.m4 s potřebnými makry. Ale pozor! Obsah aclocal.m4 je závislý na tom, jaká automake makra použijete v configure.ac. Tudíž je potřeba čas od času zavolat program aclocal znovu.
Automake vytvoří Makefile.in na základě Makefile.am. Z takto vygenerovaného Makefile.in pak skript configure vytvoří Makefile, který bude umět všechny standardní cíle GNU, který je přenositelný na všechny podporované systémy.
automake(<-Makefile.am) => Makefile.in autoconf(<-configure.ac) => configure ./configure(<-Makefile.in config.h.in) => Makefile config.h
To má ale jeden drobný háček. Třeba co se týče instaslace, tak ta se provádní na různých systémech různě. Během instalace je potřeba přesunout soubory na správná místa, nastavit správně přístupová práva, občas zavolat nějaký configurační program. A protože se tyto věci systém od systému liší, automake přichází s několika podpůrnými skripty. Protože váš výsledný configure skript i Makefile soubory mají fungovat i na systémech bez nainstalovaných autotools, je nutné tyto skripty přibalit k vašemu balíčku. Makro AC_CONFIG_AUX_DIR určuje adresář, kam se tyto pomocné skripty nahrají.
Tolik k teorii a teď zpět k praxi. Soubor configure.ac z předchozího příkladu doplním takto:
- # -*- Autoconf -*-
- # Process this file with autoconf to produce a configure script.
- AC_PREREQ([2.69])
- AC_INIT([hello-world], [0.6], [hello-world@example.org])
- AC_CONFIG_SRCDIR([src/hello.c])
- AC_CONFIG_HEADERS([config.h])
- AC_DEFINE([HELLO_WORLD], ["Ahoj svete!"], [Definice pozdravu])
- AC_CONFIG_AUX_DIR([build-aux])
- AM_INIT_AUTOMAKE([gnu -Wall -Werror])
- # 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
Makro AM_INIT_AUTOMAKE inicializuje automake. Prvním
argumentem tohoto makra jsou nějaké volby, které ovlivňují chování automake. Co
se první volby týče, máte 3 možnosti: gnits
, gnu
a
foreign
. Volba gnu
je defaultní. S touto volbou
vyžaduje automake existenci souborů NEWS, README, AUTHORS, ChangeLog, případně
ještě INSTALL a COPYING (soubory mohou být prázdné). Co má být obsahem těchto
souborů a jaký má být jejich formát se dočtete v GNU
Coding standardu. Pokud soubor COPYING nevytvoříte, automake ho vytvoří a
zapíše do něj GNU licenci. Podobně to platí pro INSTALL, do kterého zapíše
postup instalace.
Pokud tyto soubory vytvářet nechcete, použijte místo gnu
volbu
foreign
. Ta nic nevyžaduje. Volba gnit
je nějaký
nový, ještě nedokončený standard, takže si jí zatím nemusíte všímat.
Další volba pro
automake, -Wall
říká, že se mají vyhazovat všechny varování.
Pozor, jedná se o varování programu automake, nemá to nic společného s
-Wall
pro překladač gcc!
Volba -Werror
způsobí, že se varování změní na chyby, které ukončí
běh automake. To je super pro vývoj, protože tak žádné varování nepřehlédnete.
Ale je to smrtící pro distribuci, protože některá varování se týkají použití
zastaralých maker. Takže pokud by váš balíček někdo použil s novější verzí
automake, ve které by některé vaše makro bylo deprecated, varování by
(zbytečně) znemožnilo automake úspěšně dokončit tvorbu Makefile.in.
Proto nikdy nenechávejte volbu -Werror v balíčku,
který chcete vypusti do světa!
Automake vyžaduje AC_CONFIG_FILES
, aby poznalo, jaké Makefile.in
má generovat. Bez toho se tedy také neobejdete.
Teď už je téměř vše přichystáno. Ještě je potřeba vytvořit soubory Makefile.am a src/Makefile.am. Prozatím mohou zůstat prázdné.
$ tree . ├── configure.ac └── src └── hello.c 1 directory, 2 files $ mkdir build-aux $ touch NEWS README AUTHORS ChangeLog Makefile.am src/Makefile.am $ autoheader $ aclocal $ automake configure.ac:16: error: required file 'build-aux/compile' not found configure.ac:16: 'automake --add-missing' can install 'compile' configure.ac:13: error: required file 'build-aux/install-sh' not found configure.ac:13: 'automake --add-missing' can install 'install-sh' configure.ac:13: error: required file 'build-aux/missing' not found configure.ac:13: 'automake --add-missing' can install 'missing' Makefile.am: error: required file './INSTALL' not found Makefile.am: 'automake --add-missing' can install 'INSTALL' Makefile.am: error: required file './COPYING' not found Makefile.am: 'automake --add-missing' can install 'COPYING'
Jak vidíte, automake si stěžuje, že neexistují soubory INSTALL, COPYING
a další pomocné soubory, které bude výsledný Makefile potřebovat.
Zároveň také nabízí řešení: zavolat automake --add-missing
.
$ automake --add-missing configure.ac:16: installing 'build-aux/compile' configure.ac:13: installing 'build-aux/install-sh' configure.ac:13: installing 'build-aux/missing' Makefile.am: installing './INSTALL' Makefile.am: installing './COPYING' using GNU General Public License v3 file Makefile.am: Consider adding the COPYING file to the version control system Makefile.am: for your code, to avoid questions about which license your project uses $ autoconf $ tree . ├── aclocal.m4 ├── AUTHORS ├── autom4te.cache │ ... ├── build-aux │ ├── compile -> /usr/share/automake-1.15/compile │ ├── install-sh -> /usr/share/automake-1.15/install-sh │ └── missing -> /usr/share/automake-1.15/missing ├── config.h.in ├── configure ├── configure.ac ├── COPYING -> /usr/share/automake-1.15/COPYING ├── ChangeLog ├── INSTALL -> /usr/share/automake-1.15/INSTALL ├── Makefile.am ├── Makefile.in ├── NEWS ├── README └── src ├── hello.c ├── Makefile.am └── Makefile.in 3 directories, 25 files
Projekt se trošičku rozrostl, na to, že se stará jen o hello.c zdroják, že? :-)
Soubory vytvořené příkazem automake --add-missing
jsou symbolické linky. Takto to samozřejmně nelze uživatelům distribuovat,
ale příkaz make dist
naštěstí nahradí symlinky za
obyčejné soubory. (Výhoda symlinků je, že při aktualizaci autotools
bude ve vašem projektu dostupná aktuální verze těchto souborů).
Kdyby vás to z nějakého důvodu jó hodně štvalo, můžete použít přepínač
-c
, se kterým automake místo symlinků vytvoří obyčejné
soubory: automake -a -c
.
V tuto chvíli už můžete spustit ./configure
a nechat si
vygenerovat Makefile soubory. Takové Makefile už dokonce budou mít své cíle,
jako je make all
, make distcheck
atp.
Aby ale něco skutečně dělaly, musí se něco zapsat do Makefile.am souborů. Formátu těchto souborů věnuji celou kapitolu, protože je to, bohužel, rozsáhlá látka. To, co vám teď ukáži, je jen nezbytné minimum.
První soubor Makefile má za úkol jen spustit cíle v adresáři src/, takže obsah Makefile.am je jednoduchý:
SUBDIRS = src
V souboru src/Makefile.am se určí jen název výsledného binárního programu a seznam zdrojových kódu, které jsou pro sestavení programu potřeba:
bin_PROGRAMS=hello
hello_SOURCES = hello.c
Teď je potřeba znovu spustit automake, který z Makefile.am vytvoří Makefile.in. Automake si všimne, že chcete sestavovat binární soubor, tak začne vyžadovat další pomocný skript …
$ automake src/Makefile.am: error: required file 'build-aux/depcomp' not found src/Makefile.am: 'automake --add-missing' can install 'depcomp' $ automake -a src/Makefile.am: installing 'build-aux/depcomp' $ autoconf
Tím je dílo ukončeno. Nyní můžete spustit ./configure; make
distcheck
, což vám vytvoří balíček hello-world-0.6.tar.gz, který můžete
poslat do světa.
$ ./configure -q $ make --no-print-directory V=0 make all-recursive Making all in src CC hello.o CCLD hello $ ./src/hello Ahoj svete! z hello-world verze 0.6 $ make distcheck ... ================================================= hello-world-0.6 archives ready for distribution: hello-world-0.6.tar.gz =================================================
No není to fantastické? V podstatě vám stačí jen dvě řádky v Makefile.am a váš Makefile soubor je schopen překladu, instalace, vytvoření distribučního balčíku a to na všech možných, autotoolem podporovaných, systémech!
Program autoreconf
Teď už máte k dispozici celou řádku programů, které je potřeba spustit. Proto autotools přišel s ještě jedním navíc: autoreconf. Ten spustí všechny potřebné programy, spustí je ve správném pořadí a spustí je jen tehdy, když je to potřeba (když se změnil nějaký soubor, na kterém jsou dané programy závislé).
Místo autoheader;aclocal;automake;autoconf
stačí spustit
autoreconf
. A on spustí jen to, co je potřeba.
Od teď používejte jen autoreconf
;-).
Program autoreconf má, mimo jiné, jednu zajímavou volbu: -i
.
S touto volbou autoreconf zavolá automake --add-missing
, pokud je to potřeba.
Závěr
Toto byly všechny důležité programy a konfigurační subory z autotools. Vím, že jich je hodně, ale z programů potřebujete znát je autoreconf a když se znovu podíváte na poslední configure.ac soubor, jsem si jistý, že makra v něm zapsaná vám jsou již jasná. Není na nich nic složitého. Až uděláte s autotools dva, nebo tři projekty, zjistíte, že jen přidáváte makra do configure.ac (s čímž vám hodně pomůže autoscan) a tvoříte Makefile.am soubory.
V následujících kapitolách se budu věnovat především dalším důležitým autotools makrům a konfiguraci automake. To první je v zásadě jednoduché, to druhé až zas tak moc ne.