FreshSourcing. Čerstvé nápady. Kreatívne riešenia.

» Domov » Auto Tools » 14. časť

14. časť: Cache

V tejto časti si ukážeme, ako môžeme časovo relatívne náročné testy prítomnosti rôznych knižníc uchovávať pre prípadné ďalšie použitie, a šetriť tak čas pri opakovanom spustení programu configure.

Ak spustíte configure, začne zisťovať, aká je vaša systémová konfigurácia, či máte nainštalované potrebné knižnice atď. Tieto vlastnosti už vieme získať aj my a môžeme s nimi ľubovoľne narábať až do skončenia behu programu. Ak by sme potrebovali znova spustiť configure, opäť by musel zdĺhavo zisťovať všetky vlastnosti systému, pričom je dosť málo pravdepodobné, že sa medzitým niečo zmenilo. Preto sa niektoré nastavenia zvyknú ukladať do cache. Ďalšie spustenie potom prebehne značne rýchlejšie, nastavenia systému sa už iba načítajú zo špeciálneho súboru. Tým súborom je config.cache. Ak ste si príklady z predchádzajúcich častí pozorne preštudovali, určite ste si ho všimli. Vytvorí sa aj vtedy, ak by ste ho vy ako vývojár nevyužili - používajú ho niektoré makrá programu configure. V jednoduchších programoch môže vyzerať napríklad takto:

ac_cv_path_LD=${ac_cv_path_LD=/usr/bin/ld}
ac_cv_path_NM=${ac_cv_path_NM='/usr/bin/nm -B'}
ac_cv_path_install=${ac_cv_path_install='/usr/bin/install -c'}
ac_cv_prog_CC=${ac_cv_prog_CC=gcc}
ac_cv_prog_LN_S=${ac_cv_prog_LN_S='ln -s'}
ac_cv_prog_RANLIB=${ac_cv_prog_RANLIB=ranlib}
ac_cv_prog_cc_cross=${ac_cv_prog_cc_cross=no}
ac_cv_prog_cc_g=${ac_cv_prog_cc_g=yes}
ac_cv_prog_cc_works=${ac_cv_prog_cc_works=yes}
ac_cv_prog_gcc=${ac_cv_prog_gcc=yes}
ac_cv_prog_gnu_ld=${ac_cv_prog_gnu_ld=yes}
ac_cv_prog_make_make_set=${ac_cv_prog_make_make_set=yes}

Vidíme, že sú to obyčajné shell príkazy. Ak pustíme configure, vyzerá podobne:

$ ./configure
loading cache ./config.cache
checking for ...

Ak zmažeme cache súbor, výpis sa bude začínať trochu ináč:

$ rm ./config.cache
$ ./configure
creating cache ./config.cache
checking for ...

Je to napokon celkom logické - keďže cache nemôže nájsť, vytvorí si ju a počas behu si do nej bude zapisovať zistené vlastnosti systému - ale nie všetky. Ako zistíme, ktoré vlastnosti sa ukladajú a ktoré nie? Jednoducho: spustíme configure ešte raz po tom, čo sa vytvorí cache súbor. Niektoré riadky budú vyzerať podobne ako tento:

...
checking for ranlib... (cached) ranlib
checking for gcc... (cached) gcc
...

Skúste skompilovať nejaký program, ktorý používa napríklad knižnicu QT. Prvýkrát bude na riadku

checking for Qt...

stáť oveľa dlhšie ako druhýkrát, čo je iste veľmi praktické. Teraz si ukážeme, ako môžeme podobné triky robiť aj my.

AC_CACHE_VAL

Toto je prvý spôsob kešovania. Makro má takúto syntax:

AC_CACHE_VAL(premenná, príkazy)

Ako každé makro, môžeme ho zapísať napríklad do súboru configure.in. Vytvorme si teda jednoduchý program, pozostávajúci z týchto súborov:

Makefile.am
bootstrap
configure.in
hello.c
hello.h
main.c

Ostatné súbory sa buď vytvoria automaticky, alebo sa sem nakopírujú (napríklad install-sh, ...). My si teraz ukážeme súbor, ktorý nás najviac zaujíma - configure.in:

dnl Process this file with autoconf to produce a configure script.
AC_INIT(main.c)
AM_INIT_AUTOMAKE(hello, 1.0)

eval $ac_cv_my_val
echo $my_val
AC_CACHE_VAL(my_val, [
echo "nothing cached, default = foo"
my_val="foo"
])
ac_cv_my_val="my_val=$my_val"

AC_PROG_CC
AC_OUTPUT(Makefile)

Prvé tri a posledné dva riadky sú zrejmé. Ostáva nám vysvetliť si riadky uprostred. Najprv si skúste ukážku spustiť:

$ ./bootstrap
$ ./configure
creating cache ./config.cache
checking for a BSD compatible install... /usr//bin/install -c
checking whether build environment is sane... yes
checking whether make sets ${MAKE}... yes
checking for working aclocal-1.4... found
checking for working autoconf... found
checking for working automake-1.4... found
checking for working autoheader... found
checking for working makeinfo... found

nothing cached, default = foo
checking for gcc... gcc
checking whether the C compiler (gcc ) works... yes
checking whether the C compiler (gcc ) is a cross-compiler... no
checking whether we are using GNU C... yes
checking whether gcc accepts -g... yes
updating cache ./config.cache
creating ./config.status
creating Makefile

Takisto si skúste otvoriť súbor config.cache. Názov premennej ac_cv_my_val by sme mohli dekódovať ako AutoConf Cached Value my_val. Všimnite si jej obsah (tretí riadok odspodu v súbore configure.in). Táto premenná je zapísaná do súboru config.cache. Prvý riadok vykoná príkaz, ktorý táto premenná v sebe "obsahuje", teda premennej my_val priradí jej hodnotu (opäť si všimnite posledný riadok toho bloku). V druhom riadku bloku vypíšeme obsah premennej - preto ten prázdny riadok vo výpise vyššie. Makro AC_CACHE_VAL vykoná svoje príkazy (teda druhý parameter) iba v prípade, že premenná my_val neexistuje. Skúste namiesto riadku

echo $my_val

riadok

unset $my_val

Potom sa text nothing cached... vypíše vždy (samozrejme, vykoná sa aj nasledujúce priradenie). Skúsme spustiť configure ešte raz (bez tejto poslednej zmeny). Dostaneme toto:

loading cache ./config.cache
checking for a BSD compatible install... (cached) /usr//bin/install -c
checking whether build environment is sane... yes
checking whether make sets ${MAKE}... (cached) yes
checking for working aclocal-1.4... found
checking for working autoconf... found
checking for working automake-1.4... found
checking for working autoheader... found
checking for working makeinfo... found
foo
(cached) checking for gcc... (cached) gcc
checking whether the C compiler (gcc ) works... yes
checking whether the C compiler (gcc ) is a cross-compiler... no
checking whether we are using GNU C... (cached) yes
checking whether gcc accepts -g... (cached) yes
creating ./config.status
creating Makefile

Všimnite si hlavne prvý riadok. Ďalej si všimnite, ako nám configure oznámil, že premenná my_val bola načítaná z cache. Za textom (cached) si musíme prechod na nový riadok pridať sami. Práve preto existuje aj druhé, jednoduchšie makro - AC_CACHE_CHECK.

AC_CACHE_CHECK

Makro má syntax:

AC_CACHEC_CHECK(správa, premenná, príkazy)

Správa sa vypíše medzi checking a ..., teda stačí dopísať napríklad for Qt. Zvyšné dva parametre fungujú rovnako ako pri predchádzajúcom makre. Predošlý príklad by sme si mohli upraviť takto:

dnl Process this file with autoconf to produce a configure script.
AC_INIT(main.c)
AM_INIT_AUTOMAKE(hello, 1.0)
dnl AM_CONFIG_HEADER(config.h)

eval $ac_cv_my_val
AC_CACHE_CHECK([for my_val], my_val,
[
my_val="foo"
])
ac_cv_my_val="my_val=$my_val"

AC_PROG_CC
AC_OUTPUT(Makefile)

Toto makro vám môže podstatne zjednodušiť prácu, ale iba vtedy, ak potrebujete aj výpisy. Inak použijete prvé makro.

Na záver tohto pokračovania si ukážeme príklad, ktorý využije vedomosti nadobudnuté v posledných častiach - výpisy, voliteľné argumenty a kešovanie údajov.

dnl Process this file with autoconf to produce a configure script.
AC_INIT(main.c)
AM_INIT_AUTOMAKE(hello, 1.0)
dnl AM_CONFIG_HEADER(config.h)

AC_ARG_WITH(foo,
[  --with-foo=FOO          foo is FOO],
[
  if [test "$withval" = "yes"] || [test -z $withval]; then
    withval=default_foo
  fi

  AC_MSG_CHECKING([for foo])
  foo=$withval

  AC_MSG_RESULT($foo)
],
[
  eval $ac_cv_foo
  AC_CACHE_CHECK([for foo], foo,
    [ foo="default_foo" ])
])

ac_cv_foo="foo=$foo"

AC_PROG_CC
AC_OUTPUT(Makefile)

Týmto kódom sme pridali nový voliteľný parameter --with-foo=..., ktorého hodnota sa priradí premennej foo. Ak parameter uvedieme bez hodnoty, teda --with-foo, alebo s prázdnou hodnotou (--with-foo=), použije sa default_foo. Ak parameter nepoužijeme vôbec, údaj sa načíta z cache. Ak parameter nepoužijeme a konfigurujeme program po prvýkrát, údaj sa nemá odkiaľ načítať (cache sa vytvorí až po prvom behu configure). Preto sa použije default hodnota default_foo. Takto sme pripravený prakticky na všetky možné prípady. Tento príklad môžete použiť ako základ pre vlastné configure.in súbory. Pomerne jednoducho ho môžete rozšíriť o automatickú lokalozáciu knižníc doplnenú o možnosť "ručného" zadania presnej cesty s kešovaním posledne zadanej hodnoty. Inšpirovať sa môžete aj predchádzajúcou časťou.


Oto Komiňák


Článok bol uverejnený v magazíne PC Revue 03/2003.