4. Automake 1.3

Když jsem poprvé objevil make a Makefile soubory, blahořečil jsem jeho vynálezcům - soubory Makefile se svými pravidly velmi usnadňují práci a překlad i těch nejmenších projektů. Ovšem po delší době věnované správě vetšího projektu začne člověka bolet hlava z hordy pravidel, které naň vystrkují své růžky kamkoliv se pohne. Spousty vynikajících vlastností a možností, jenž jsme nejdříve vynášeli do nebe nás unavují a v slabších chvilkách zatoužíme po jednoduché a z co největší části automatizované správě pravidel a cílů překladu (která by nám ovšem ponechala možnost sem tam udělat něco "po staru"). Myslím, že z názvu kapitoly nebylo těžké usoudit: budu hovořit o nástroji Automake.

4.1 Kterak Automake funguje

Automake je nástroj, který Vám usnadní přípravu šablon Makefile.in pro Váš configure skript. Autoři vybrali Perl pro implementaci automake - ovšem obdobně jako v případu Autoconf/M4 musí být Perl přítomný na Vašem systému pouze tehdy, když chcete soubory Makefile.in vytvářet. V distribučním archivu budou tyto soubory obsaženy a počítač koncového uživatele nemusel o Perlu vůbec nikdy slyšet (ke své škodě :)

Kromě automatického počítání závislostí (dependencies) Automake na základě Vámi poskytnutých informací připraví soubor Makefile, ve kterém se nacházejí i následující cíle:

make install, make uninstall
Slouží k instalování programů, dat i dokumentace (info, man)
make clean, make mostlyclean, make maintainer-clean
Vyčistí adresáře od nechtěných souborů vytvořených během konfigurace či překladu (*.o, config.log, ...)
make dist
Vyrobí distribuční balíček, který bude připraven pro koncového uživatele
make tags
Ve spolupráci s programem etags vytvoří v každém adresáři tzv TAGS soubory. V TAGS souborech jsou uchovány informace o všech definicích a deklaracích ve Vašich zdrojových souborech. V některých editorech (Emacs, vi) se můžete pomocí těchto souborů velmi efektivně "procházet" po svých zdrojácích a kdykoliv lehce vyhledat definici daného symbolu.

Ve skutečnosti samozřejmě Automake připraví pouze Makefile.in - připomeňme si však, že tento soubor je velmi blízký výslednému souboru Makefile. Pouze místo skutečných hodnot v něm budou figurovat řetězce @PROMĚNNÁ@ (například @CFLAGS@ místo při konfiguraci zvoleného "-g -Wall").

  Makefile.am  --(automake)--> Makefile.in --(configure)--> Makefile

Je přibližné schema vytvoření Makefile souboru. V každém podadresáři Vašeho projektu vytvoříte soubor Makefile.am. Příkazem automake se z každého Makefile.am vytvoří Makefile.in, který se při konfiguraci použije jako šablona pro Makefile.

4.2 configure.in

Automake nejen předpokládá, že ve svém projektu používáte autoconf, navíc klade na configure.in několik požadavků:

Měli byste použít makro AM_INIT_AUTOMAKE(jméno_balíčku, verse) (což je nejjednodušší) nebo explicitně vykonat akce, které toto makro provádí (definovat proměnné PACKAGE, VERSION a vyvolat některé testy).

V případě, že používáte C (C++, lex, yacc,..) musíte se v configure.in vyvolat příslušné testy.

Samozřejmě nesmíte nakonec zapomenout uvést všechny Makefile soubory mezi parametry AC_OUTPUT.

Jelikož Automake rozšiřuje Autoconf o nová makra, je nutné, aby o nich věděl i program autoconf. Proto je zde program 'aclocal', který všechna nezbytná makra zapíše do souboru aclocal.m4 . Celý proces vytvoření Makefile souboru tedy bude:

    grass@meadow:~/kopretina$ autoheader
    grass@meadow:~/kopretina$ aclocal
    grass@meadow:~/kopretina$ automake
    grass@meadow:~/kopretina$ autoconf

    grass@meadow:~/kopretina$ configure

Nemusíte se však obávat, že místo slíbené jednoduchosti automake přináší pouze další nadbytečné komplikace. Jednak koncový uživatel použije z těchto příkazů jen poslední, jednak i Vy sami většinou použijete první čtyři příkazy pouze jednou - příště se o ně postarají dependencies v Makefile, které zaručí, že se potřebné příkazy spustí, jakmile se některé z důležitých souborů (Makefile.am, configure.in) změní.

4.3 Druhy balíčků

Automake rozlišuje několik druhů balíčků, jednak dle členění adresářové struktury....

Flat
Všechny soubory jsou v jediném adresáři
Deep
Všechny zdrojové soubory se nacházejí v podadresářích, v nejvyšším adresáři jsou pouze konfigurační soubory.
Shallow
Většina souborů se nachází v nejvyšším adresáři, zatímco některé části (knihovny) jsou v podadresářích

... jednak dle požadavků, které na balíček klade...

automake --foreign
Na takový balíček nebudou kladeny téměř žádné nároky
automake --gnu (implicitní)
musíte dodržet GNU standard pro distribuční balíčky - například v nejvyšším adresáři se musí vyskytovat soubory NEWS, AUTHORS, COPYING (GPL), ChangeLog a další. automake --add-missing za Vás některé z těchto souborů vytvoří.
automake --gnits
gnits je poněkud přísnější (ještě nespecifikovaný :) standard. Navíc k souborům vyžadovaným v gnu zde musí být například soubor THANKS...

4.4 Makefile.am

4.4.1 Komentáře

Jako obvykle začnu svůj výklad věcí ze všech nejdůležitější: komentáře. Při psaní Makefile.am můžete použít celkem dva druhy komentářů - běžné "#" a dále komentáře "##", které nebudou do výsledku zapsány. Je opět dobrým zvykem začínat Makefile.am následujícím řádkem:

## Process this file with automake to produce Makefile.in

4.4.2 Proměnné

Jistě by jste se rádi dozvěděli, co jiného můžete zapsat do souboru Makefile.am kromě komentářů a explicitních pravidel, kterými lze nahradit pravidla zařazené do Makefile automake. Celé kouzlo automake je založeno na speciálních proměnných - například proměnnou SUBDIRS řeknete v Makefile.am, které podadresáře do Vašeho projektu patří:

 SUBDIRS = docs src data

Všechny zde uvedené adresáře budou zařazeny do distribuce a pokud neurčíte jinak, při každém příkazu make se provede též cd subdir && make. Nemusím jistě připomínat, že v každém podadresáři musí být připraven soubor Makefile.am a Makefile v tomto adresáři musí být zařazen jako parametr do AC_OUTPUT v configure.in. Jelikož automake sám připraví i Makefile.in v podadresářích, není třeba automake explicitně v každém adresáři spouštět.

Na proměnou SUBDIRS se vztahuje pouze jedno omezení - mohou zde být uvedeny pouze podadresáře, které jsou přímými potomky adresáře (o nic však nepřicházíte, protože v každém podadresáři je opět Makefile.am, který může opět obsahovat proměnou SUBDIRS).

4.4.3 Primární proměnné

Jestliže se v našem balíčku lučních květinek vyskytují programy pampeliška a jitrocel (mhm, poněkud morbidní příklad... Myslím, že začnu uvažovat o příhodnějších příkladech, více odlidštěných, přetechnizovaných,...), sdělíme to automake výčtem těchto programů v proměnné bin_PROGRAMS:

## kontrolní otázka - (Vy přetechnizovaní) poznáte jitrocel? 
bin_PROGRAMS = jitrocel pampeliska

bin_ je prefix a jím určíte, kam je třeba dané programy nainstalovat (jitrocel a pampeliska budou zasazeny do adresáře $bindir, který uživatel vybral pomocí parametru --prefix nebo přímo --bindir). Dále automake zná například prefix sbin_, libexec_, pkglib_ a noinst_ (neinstaluj).

Kromě PROGRAMS - tzv primární proměnné (nebo též makro - jak libo) - automake zná i jiné: LIBRARIES(lib, pkglib), LISP(list), SCRIPTS(bin, sbin, libexecm, pkgdata), DATA(data, sysconf, sharedstate, localstate, pkgdata), HEADERS(include, oldinclude, pkginclude) a další (MANS, TEXINFOS, JAVA,... ). Myslím, že jejich jména říkají vše. Každé primární proměnné odpovídají příslušné prefixy uvedené v závorkách (proč také instalovat DATA do $bindir, že?)

Poté, co jsme do posledního všechny definovali programy, data a dokumentaci, zbývá nám k dokončení Makefile.am pouze několik krůčků. V prvním kroku se v Makefile.am svěříme, z kterých zdrojových souborů je ten který program sestaven

spolecne = kytka.h kvet.h kytka.c kvet.c koreny.c

pampeliska_SOURCES =  $(spolecne) pampeliska.c
jitrocel_SOURCES   =  $(spolecne) jitrocel.c

Přestože příklad nepatří mezi nejlepší (kromě již diskutovaných jmen by měli být společné části v knihovnách), domnívám se, že je více než demonstrativní. Jména všech souborů programu uvedeného v PROGRAMS jsou nasypána na jedné hromadě v proměnné prog_SOURCES. V seznamu můžeme používat proměnné, programy mohou sdílet zdrojové soubory, na jejichž pořadí nezáleží. Dále je třeba zde uvést též jména hlavičkových souborů.

Jediný zádrhel, který nebyl z našeho příkladu zřejmý, je potíž s "podezřelými" znaky ve jménech programů. Znaky nepatřící do množiny [a-zA-Z0-9_] (alfanumerické znaky spolu s podtržítkem) je třeba nahradit "_" (podtržítkem). Zdrojové soubory programu "mam-rad-podivne.nazvy" budou zapsány v proměnné mam_rad_podivne_nazvy_SOURCES. Uff. (nemam_rad_dlouha_jmena).

V proměnných SOURCES se samozřejmě mohou vyskytnout soubory .cc, .y (yacc) nebo .l (lex) a automake pro ně vygeneruje příslušná pravidla. Nesmíte však zapomenout zařadit do configure.in příslušné testy.

Druhý krok, proměnné prog_LDADD a prog_LDFLAGS, je samozřejmě pouze volitelný. Zde specifikujete knihovny a parametry pro ld, které tento program vyžaduje (kromě LIBS - ty jsou zařazeny automaticky):

  pampeliska_LDADD = -lkytky  @KYTKY_LIBS@
  mam_rad_podivne_nazvy_LDADD = -losk -llivy -lnaz -lev -lze

4.4.4 Podmínky

Snad se laskavý čtenář nebude cítit ošizen, když nyní napíši, že po předchozím paragrafu již zná vše podstatné pro psaní Makefile.am souborů. Abych řekl pravdu - ona to totiž nejni žádná věda. Naše povídání o Makefile.am souborech ukončíme několika řádky o podmíněném překladu. Nyní však nemám na mysli #if konstrukce ve zdrojových souborech.

Do našeho projektu kopretina jsme zařadili grafický front-end pro X-windows. Jelikož se však jedná pouze o nadstavbu, nikoliv o klíčový program, je program sestaven pouze pokud si tak uživatel explicitně vyžádá (například parametrem --with-xkopretina, který jsme pro tento případ přidali do configure.in).

Jak tedy řešit situaci, kdy je třeba postavit pouze některé z programů? Bystřejší z čtenářů (tedy ti, kteří nejsou zmateni mými nemístnými komentáři v závorkách) si již jistě domysleli, že vhodným prostředkem bude proměnné a AC_SUBST configure.in a řetězce uvozené @ v Makefile.am (nezaměňujte prosím s primárními proměnnými či proměnnými, jak je zná Makefile):

configure.in

AC_ARG_WITH(xkopretina, [ --with-xkopretina      Postavit X front-end],
            XKOPRETINA=xkopretina)

AC_SUBST(XKOPRETINA)

Makefile.am

bin_PROGRAMS = kopretina @XKOPRETINA@
EXTRA_PROGRAMS = xkopretina

kopretina_SOURCES = ...
xkopretina_SOURCES = ...

Pokud uživatel spustí "./configure --with-xkopretina", je xkopretina přidána mezi překládané programy. Jelikož by se automake měl dozvědět o všech programech, přibyla do Makefile.am nová proměnná s předponou EXTRA_, ve které jsme vypsali všechny volitelné programy. Podobnou proměnnou použijeme i v případě zdrojových souborů:

spolecne = kytka.h kvet.h kytka.c kvet.c koreny.c

pampeliska_SOURCES =  $(spolecne) pampeliska.c
jitrocel_SOURCES   =  $(spolecne) jitrocel.c

slunecnice_SOURCES = $(spolecne) slunecnice.c slunecnice.h @SL_OPT@

# tak jako slunečnice každým dnem, otáčím se ...
EXTRA_slunecice_SOURCES = za_sluncem.c

Snad jsem neuvedl tápající více ve zmatek, když jsem použil na jednom řádku primární proměnnou, proměnnou a řetězec uvozený @, který je nahrazen configure skriptem. Pro úplnost pouze dodávám, že v proměnné EXTRA_SUBDIRS jsou uvedeny všechny (v SUBDIRS neuvedené či uvedené pouze podmíněně) adresáře.

4.5 Distribuční balíčky

make dist je, jak jsem již napsal, velmi užitečný cíl, který vytvoří .tar.gz soubor připravená k distribuci. Spolu se zdrojovými programy, dokumentací a daty budou do adresáře začleněny soubory uvedené v proměnné EXTRA_DIST a samozřejmě soubory, jež mají něco společného s konfigurací (configure, configure.in, Makefile.am, Makefile.in s předpočítanými dependencies,...). Dále automake zařadí též soubory README, TODO, NEWS, ChangeLog... - úplný přehled Vám podá automake --help.

4.6 Závěr, příklady

Abyste si doplnili svůj obrázek o tom, jaký může být .am soubor, začlenil jsem dva soubory (Makefile.am a src/Makefile.am) z již zmíněného balíčku GAG. Zvídavější z Vás se ještě mohou podívat, co se s těmito soubory stane (Makefile.in, src/Makefile.in, Makefile a src/Makefile)

Poslední kapitola mého referátu pojednává o nástroji libtool.


(c) 1998 0rfelyus