Hlavní navigace

Kompilujeme ze zdrojového kódu - opravujeme kód

16. 9. 2002
Doba čtení: 5 minut

Sdílet

Ne vždy jsou programy napsané správně a přenositelně. Pokud se domníváte, že k opravě budete potřebovat dokonalou znalost programování, jste na omylu. Nejčastějšími zdroji problémů totiž bývají nekompatibility mezi jednotlivými systémy.

Jejich zdrojem jsou odlišné cesty, knihovny a jejich závislosti a rozdíly mezi hlavičkovými soubory na různých platformách.

Úpravy configure.in a dalších souborů

Přímá úprava těchto souborů je jedinou cestou pro korektní opravy konfigurace. K tomu však potřebujeme znát základy m4 a navíc ještě pravidla pro psaní těchto skriptů. Vše lze nastudovat

z dokumentace automake, autoconf a m4, která bývá, jak u GNU nástrojů bývá zvykem,

přibalena ke každému balíku ve formátu texinfo a formátech z něj generovaných.

Abych vám usnadnil experimentování, připravil jsem minimální balík hallo.tar.gz. Je zabalen bez jakýchkoliv generovaných souborů. Po spuštění autogen.sh se vygenerují. Jde o nejmenší množinu souborů, pro kterou již bude fungovatmake distcheck.

Zde můžete experimentovat s jednoduchými testy.

AC_CHECK_LIB([kni­hovna], [funkce])

Nejčastější test je test na knihovnu, připadně funkci v ní (pokud nám jde pouze o přítomnost knihovny, testujeme funkci main. AC_CHECK_LIB může mít až pět argumentů, definujících jeho chování. Implicitní je, že pokud je knihovna nalezena, přilinkuje se ke všem aplikacím i dalším prováděným testům. Proto u nich velmi záleží na pořadí.

Vrátíme se k příkladu z minulého dílu a napíšeme:

AC_CHECK_LIB([crypt], [main])
AC_CHECK_LIB([shadow], [main])

Na mém počítači je knihovna libshadow závislá na knihovně libcrypt. Druhý test však již bude proveden s přilinkováním knihovny libcrypt, a tedy bude úspěšný. Mohlo by to být zcela čistým řešením našeho problému, kdyby to nezpůsobilo linkování knihovny libcrypt i na platformách, kde je to zbytečné.

AC_CHECK_HEADER([hla­vičkový_soubor­.h])

Další běžnou funkcí je kontrola hlavičkového souboru. Má až tři argumenty. Kontrola testuje, zda vložení hlavičkového souboru nehlásí žádná varování. K opravě často stačí zmírnění hodnoty CPPFLAGS – nastavení -Wall či dokonce -Werror je spolehlivou cestou k problémům.

Přítomnost hlavičkových souborů můžeme testovat v kódu programu na základě funkcí HAVE_HLAVIČKO­VÝ_SOUBOR_H.

Různé verze auto nástrojů

Dalším chytákem, zvlášť při kompilaci z CVS, jsou nekompatibility jednotlivých verzí všech těch auto nástrojů. Tým GNU totiž od roku 1999 prakticky nevydával nové verze. Když po dvou letech vyšla nově přepracovaná verze těchto nástrojů, vývojáři tvrdili, že jsou kompatibilní se starými verzemi. To je ovšem pravda pouze zčásti, a to pro korektně napsané konfigurační skripty. A ty jsou spíš vzácností než pravidlem. Stačí jediná chybějící závorka a už dojde k expanzi tam, kde nemá.

Proto jsem si na svůj počítač nainstaloval i starší verze konfiguračních nástrojů: automake-1.4-p5, autoconf-2.13, gettext-0.10.35, gettext-0.10.40, libtool-1.3.5. Mám je uloženy

s v adresáři /opt/balík, takže jsou standardně pro systém neviditelné (ovšem pozor na knihovnu libltdl,

k té té musí mít přístup dynamický linker). Pokud je chci použít, nastavím:
export PATH=/opt/balík:bin:$PATH
export ACLOCAL_FLAGS=
  "-I/usr/share/aclocal $ACLOCAL_FLAGS"
# pozor, ne všechny balíky mají
# podporu ACLOCAL_FLAGS

Některé aplikace (glib2 z CVS) již vyžadují přímo určité verze těchto nástrojů dostupné jako automake-verze apod.

Lze dokonce narazit na nekompatibilitu některých verzí Perlu (5.6.1) s některými verzemi Automake (2.53).

Pokud tedy narazíte na podivné chyby, zamyslete se nad tím, co je jednodušší – hledat chybu v přesnosti syntaxe, nebo experimentovat s různými verzemi auto nástrojů.

Chyby při kompilaci

Nenalezený hlavičkový soubor a nenalezená knihovna jsou poměrně časté problémy a jsou většinou snadno řešitelné správným nastaveníCPPFLAGS, LDFLAGS, případně CFLAGS, jak jsme se již zmínili.

Zdaleka nejčastější chybou při kompilaci je použití funkce z nevloženého hlavičkového souboru. Protože standardy i knihovny se vyvíjejí, občas se stane, že určité funkce jsou definované v jiných hlavičkových souborech, než autor čekal. Poznáme to nejčastěji podle chybové hlášky o neznámé funkci či proměnné. Naším úkolem je najít ten správný soubor a připsat ho do zdrojového kódu:

#include <hlavičkový_soubor.h>

Který to má být, nám může napovědět jméno proměnné či funkce – bývá zvykem, že prvních pár písmen názvu se odvíjí od jména knihovny. Pokud nenapoví, nezbývá, než použít například grep a prohledat celý adresář hlavičkových souborů.

Další záludností je nutnost definice speciální proměnné, která aktivuje určitá rozšíření. U základního systému to bývá _GNU_SOURCE a _BSD_SOURCE. Kompletní seznam povolených rozšíření najdete v souboru /usr/include/fe­atures.h.

Obdobně vypadající chybou, avšak tentokrát při linkování, je chybějící funkce. Příčinou opět bývá přesunutí funkce do jiné knihovny, nebo častěji závislost knihovny na jiné knihovně.

Řešením je přilinkování knihovny k aplikaci. Nechceme-li program linkovat ručně, musíme jméno knihovny dostat do souboru Makefile. Můžeme to udělat nečistými triky podle minulého dílu, nebo čistěji tak, jak je uvedeno výše. Ještě čistější je výběrové použití knihoven a jejich skupin, ale takový postup je pracnější a měl by jej provést spíš správce balíku.

Obrácenou chybou je vlastní definice proměnné z hlavičkového souboru. Týká se to hlavně aplikací ze starších UNIXů a proměnné errno. Ta totiž v hlavičkových souborech některých UNIXů zcela chyběla. Náprava je jednoduchá – smazat problematický řá­dek.

Záludnou chybou je některá z konstrukcí #if ve

funkci, která je definovaná jako makro (např. strcpy), nebo vůbec jakákoliv nečekaná expanze

některého řetězce, a to zejména proto, že chybové hlášení je naprosto matoucí. Chybu nelze nalézt jinak, než že si prohlédneme výstup preprocesoru:
gcc soubor.c -E -C -dD | less

Je to nezáživné čtení, ale jediná cesta k opravě těchto chyb.

Další chyby

Existuje ještě několik „prefabrikovaných modelů“ chyb

v programech, které lze řešit bez znalosti kódu. Z ostatních

CS24_early

chyb ještě zmíním chyby v C++. Gcc má několik voleb, které můžeme

přidat do CXXFLAGS. Ty specifikují dialekt C++. Obecně je

však gcc stále striktnější a nečisté konstrukce odmítá. K něčemu jej však lze ještě přinutit pomocí -fpermissive. Stojí za to vyzkoušet jej dříve, než začneme kód studovat.

Byl pro vás článek přínosný?

Autor článku