Configure byl vytvořen proto, aby konfiguraci usnadnil a zautomatizoval. Pokud se tak nestane, většinou je to kvůli chybě v balíku, testech, nebo atypické konfiguraci počítače.
Často při tom narazíme na problémy, které musíme vyřešit, abychom získali funkční a plnohodnotný program. Dnes se budeme zabývat možnostmi, jak to udělat.
Protokol config.log
Configure při svém běhu generuje soubor config.log, který je mnohem detailnější než výpis configure na obrazovku. Najdeme v něm spoustu cenných informací, z nichž zjistíme, proč se test nevydařil. Nezdařený test může znamenat, že kompilátor knihovnu vůbec nenašel, že ji sice našel, ale požadovaná funkce v ní není, že požadovaná funkce tam sice je, ale výsledný program nelze slinkovat (protože vyžaduje ještě dodatečné knihovny). Z těchto informací odvozujeme další postup oprav.
Knihovna nebo hlavičkový soubor nebyly nalezeny
Zda knihovna nebo hlavičkový soubor v systému existuje, si lze snadno ověřit (máme locate, find, mc a jiné nástroje).
Pokud skutečně neexistuje, je řešení nejjednodušší – nainstalovat (pamatujte na to, že ve většině distribucí potřebujete ke kompilaci i balík s označením -devel).
Kompilátor standardně „vidí“ knihovny pouze v adresářích /lib, /usr/lib a/usr/local/lib a hlavičkové soubory v /usr/include a /usr/local/include. Pokud je knihovna či hlavičkový soubor jinde, musíme to skriptu configure říci (viz třetí díl).
Při testování hlavičkového souboru se občas stane, že preprocesor vydá varování. Configure však usoudí, že soubor je chybný a nepoužitelný, a my musíme hledat cestu k opravě.
Funkce nebyla v knihovně nalezena
Takovou věc lze ověřit i prohledáním knihovny. Pokud tam funkce není, může být v jiné knihovně (často to platí o knihovnách terminfo a termcap, libl alibfl, libdb a libdb2 a dalších), nebo můžeme mít starou verzi.
Pokud máme podezření, že na našem systému je funkce v jiné knihovně, můžeme prohledat třeba celý adresář knihoven. Kandidáty vybere rychlejší grep, pozitivní odpověď je vhodné zkontrolovat programem objdump (grep dá pozitivní odpověď i tehdy, figuruje-li v knihovně daný řetězec v jiném kontextu, než je exportovaný symbol). Pokud se podezření potvrdí, bude třeba v balíku provést úpravy, aby tuto knihovnu použil.
Soubor nebyl nalezen
Configure často hledá soubory na nevhodně vybraných cestách. Pokud je nenajde, vyhlásí chybu. Ne vždy však autor nabízí volbu –with-něco, která by umožnila přenastavení. Pak nezbyde, než opravit konfigurační skript.
Automatické přegenerování configure
Skript configure má další, dosud nezmíněnou volbu. Je jí –enable-maintainer-mode. Ta přidá do všech vygenerovaných souborů Makefile další závislosti, kterými kontroluje též konzistentnost a aktuálnost skriptu configure a souborů Makefile. Pokud tedy provedeme změnu v souborech configure.in, Makefile.am, Makefile.in a dalších, dojde k aktualizaci všech generovaných souborů. Systém však není všemocný a rozhodně si neporadí s komplikovanými změnami, jakou je například změna adresářové struktury. V takových situacích musíme soubory přegenerovat explicitně buď příkazem ./configure, nebo dokonce ./autogen.sh. Skript./autogen.sh často nastavuje tento přepínač automaticky (předpokládá se, že jej používají hlavně vývojáři, neboť nebývá dokonce ani ve zdrojovém kódu mimo CVS).
Nečisté metody
Vím, že není příliš pedagogické, začínat opravy konfiguračních skriptů právě takto, ale přesto… Pokud nejsme tvůrci distribuce, účelem vlastní kompilace bývá balík nainstalovat stůj co stůj. Na čistotu stylu přitom tolik nehledíme. Máme tedy otevřenou cestu k použití různých metod.
Existuje mnoho efektivních metod, jak co nejsnadněji zkompilovat zlobivý balík. Ne všechny lze označit jako čisté. Nyní si několik nečistých metod ukážeme a vysvětlíme si jejich nekorektnost.
Pokud některou z nečistých metod použijete, neposílejte ji autorovi balíku jako návrh na opravu. Na takové zařazení mají šanci jen čisté metody.
Editace generovaných souborů
Editace generovaných souborů způsobí, že je nelze přegenerovat. Při dalším generování by totiž oprava zmizela. Pro rychlou kompilaci však často splní svůj jednorázový účel.
Předvedeme si několik takových triků (k provedení triků používám skript sedfile, jednoduchou nadstavbu nad programem sed, kterou jsem popsal v Drobnostech ze shellového zápisníku II.).
Příklad: Při konfiguraci balíku kdebase jsem narazil na problém:
checking for getspent in -lshadow... no
Na svém počítači mám nainstalovanou dynamickou knihovnu shadow, zatímco na ostatních bývá statická. Dynamická verze však vyžaduje knihovnu crypt. Proto ji musíme do testu přidat.
sedfile "s/-lshadow/& -lcrypt/g" configure
Je to nečistý postup, ale projde. Podobně lze editovat i generované soubory Makefile. Čistou metodou je v tomto případě editace příslušného testu v m4 makru.
Ruční spuštění příkazu
Ruční dokončení je ještě surovější postup. Pokud některý kompilační příkaz selže, zkopírujeme si poslední příkaz, který make prováděl. Na příkazové řádce se postavíme do správného adresáře, příkaz vložíme, provedeme úpravu a příkaz spustíme. Potom znovu spustíme make. Máme-li štěstí, bude spokojen s ručně zkompilovaným souborem a již se jej nebude pokoušet vytvořit.
Záznam do keše
Keš config.cache má sloužit k ukládání výsledků konfigurace. Pokud configure bere hodnoty v ní uložené na vědomí, můžeme mu podstrčit požadovanou hodnotu.
Příklad: Při konfiguraci balíku wv configure neviděl knihovnu libMagick z balíku ImageMagick.
Nakonfiguroval jsem balík, prohlédl si keš a našel vhodnou proměnnou. Odpověď no jsem změnil na yes:
ac_cv_lib_Magick_GetImageInfo=\ ${ac_cv_lib_Magick_GetImageInfo=yes}
Balíky, které používají novou verzi auto nástrojů, mají keš standardně vypnutou a je třeba ji zapnout pomocí –config-cache v argumentech configure.
Přechodná změna v systému
Někdy kompilaci balíku brání nevhodné cesty k některým souborům, nebo ji naopak blokuje přítomnost určitých souborů na nevhodných místech. Typickým příkladem může být gnome-build. Jeho kompilaci na mém systému brání IDL soubory soubory z balíku bonobo z Gnome1. Vinou špatně nakonfigurovaných cest jim kompilátor dá přednost před správnými soubory z balíkulibbonobo z Gnome2 v jiném adresáři. Samozřejmě, že existuje čistá cesta, jak tomu předejít, ale pokud soubory krátkodobě odstraníme z cesty, kompilace se též zdaří.
mkdir /opt/gnome/share/idl/schovka mv /opt/gnome/share/idl/Bonobo*\ /opt/gnome/share/idl/schovka/
Nyní kompilátor na problémové soubory nevidí a kompilace projde. Po kompilaci vrátíme soubory na místo:
mv /opt/gnome/share/idl/schovka/*\ /opt/gnome/share/idl/ rmdir /opt/gnome/share/idl/schovka
Degradace požadavku
Autoři občas nadsazují požadavky svého programu – z opatrnosti požadují určitou verzi programu, i když by mohl fungovat i se staršími verzemi. Pokud si nechceme do systému instalovat nové knihovny, můžeme ve skriptu najít místo, kde se testuje číslo verze, a snížit tam hodnotu. Často se stane, že se nám program podaří zkompilovat, a poměrně často bude i funkční. Pokud ne, byl požadavek programátora na příslušnou verzi oprávněný…
Tvrdá změna názvu
Občas se stane, že knihovna nebo funkce, kterou hledáme, se jmenuje na našem počítači jinak. Podívejme se na knihovnu DB, která je častou příčinou těchto problémů. Existuje několik implementací a mnoho různých rozhraní (DB1, DB2, DB3, DB4, DBM, NDBM, GDBM…). Situaci dále komplikují různé emulace a různá umístění hlavičkových souborů. V našem případě půjde o emulaci rozhraní DB-1.85 pomocí Sleepycat DB4. Funkce dbopen() sice patří mezi emulované, ale pouze jako makro v hlavičkovém souboru. To interně volá knihovní funkci __db185_open(). Ve zdrojovém kódu to nepoznáme, ale testy v configure hlavičkové soubory nepoužívají.
Příklad: V balíku kdeadmin narazíme na přesně takový test – kontroluje přítomnost funkce dbopen() v knihovně db. Provedeme tedy změnu:
sedfile "s/dbopen/__db185_open/g" configure
Čistší cestou bude, použijeme-li úpravu na zdrojový configure.in a configure z něj přegenerujeme:
sedfile "s/dbopen/__db185_open/g" configure.in
Podobné problémy nás potkají i při kompilaci starší verze Pythonu:
sedfile 's/<db\.h>/<db_185.h>/'\ Modules/bsddbmodule.c
Trik však přesto zůstane nečistým i tehdy, neprovádíme-li změnu na generovaném souboru. Úpravou totiž spolehlivě zajistíme, že se program nezkompiluje na systému s původním názvem objektu. Na rozdíl od výše uvedených triků je však v nouzi použitelný třeba pro tvůrce distribuce – ten jistě ví, jak vypadají soubory v jeho distribuci, a jeho cílem je sladění balíku s distribucí.
Tento trik je užitečný například tehdy, chceme-li knihovny používající libtermcap kompilovat s libncurses (ta v sobě obsahuje všechna volání i pro termcap, ale použije při tom databázi terminfo).
Příště se již budeme věnovat čistým postupům oprav.