Hlavní navigace

Programování pod Linuxem pro všechny (6)

Jakub Matys

Dnešní díl naváže na minulý - bude se zabývat knihovnami. Nikoli však takovými věcmi, jako je rozdíl mezi dynamickými a statickými knihovnami, ale skočím rovnou na praktičtější otázky. Naučíte se vytvářet a spojovat knihovny se spustitelnými kódy pomocí nástroje libtool.

Libtool

Libtool je nástroj, který umožňuje snazší práci s knihovnami a programy. Dodává programátorům jednotné „prostředí“ pro téměř všechny operace při vytváření programů a odbourává nesourodost různých platforem. Kapitoly budou dále rozděleny podle postupu při vytváření programů. V tomto článku se budu zabývat pouze systémy podporujícími dynamické knihovny. Použití na systémech pouze se statickými knihovnami je obdobné, bližší informace můžete nalézt v howto.

Vytváření přemístitelných kódů

Nejdříve bych chtěl upozornit, že přemístitelné kódy používané Libtool mají příponu ‚.lo‘ místo ‚.o‘. Teď bude následovat příklad, vysvětlení přijde po něm:

# libtool --mode=compile gcc -g -O -c test.c
gcc -g -O -c -fPIC -DPIC test.c
mv -f test.o test.lo
gcc -g -O -c test.c > /dev/null 2>&1

Parametr –mode=compile říká programu, že má data zkompilovat. Řetězec následující za ním prozrazuje, jak by si toto přeložení programátor představoval. Jak jste si asi všimli, libtool přidává u platforem podporujících dynamické knihovny parametry -fPIC -DPIC. Co znamená PIC, si můžete přečíst v předminulém dílu. Dále si můžete všimnout, že libtool přejmenuje koncovku vytvořeného přemístitelného kódu. A nakonec vytvoří ještě jeden přemístitelný soubor (tentokrát s koncovkou .oa bez voleb -fPIC a -DPIC). Proto se nelekejte, pokud se nějakou dobu na obrazovce neobjeví žádný výstup. Je to zaviněno tím, že se při vytváření druhého přemístitelného kódu vypisují výstupy do /dev/null (viz man 4 null). Takto vytvořený přemístitelný kód (myslím ten s koncovkou .lo) je možné dále použít k slinkování knihovny.

Spojování knihoven

Libtool využívá ke své práci soubor s příponou ‚.la‘. Tento soubor obsahuje informace o knihovně, např. všechny její názvy, a to jak dynamické, tak statické verze. Tento soubor navíc při kompilování nahrazuje pravé jméno knihovny, to vše bude předvedeno.

# libtool --mode=link gcc -g -O -o libhello.la test.lo -rpath /usr/local/lib
rm -fr .libs/libhello.la .libs/libhello.* .libs/libhello.*
gcc -shared  test.lo   -Wl,-soname -Wl,libhello.so.0 -o .libs/libhello.so.0.0.0
(cd .libs && rm -f libhello.so.0 && ln -s libhello.so.0.0.0 libhello.so.0)
(cd .libs && rm -f libhello.so && ln -s libhello.so.0.0.0 libhello.so)
ar cru .libs/libhello.a  test.o
ranlib .libs/libhello.a
creating libhello.la
(cd .libs && rm -f libhello.la && ln -s ../libhello.la libhello.la) 

Samotné knihovny jsou v adresáři ./.libs, odkud jsou také volány, dokud nedojde k jejich instalaci. A obsah souboru libhello.la je:

# libhello.la - a libtool library file
# Generated by ltmain.sh - GNU libtool 1.4.2a (1.922.2.79 2001/11/28 21:50:31)
#
# Please DO NOT delete this file!
# It is necessary for linking the library.

# The name that we can dlopen(3).
dlname='libhello.so.0'

# Names of this library.
library_names='libhello.so.0.0.0 libhello.so.0 libhello.so'

# The name of the static archive.
old_library='libhello.a'

# Libraries that this one depends upon.
dependency_libs=''

# Version information for libhello.
current=0
age=0
revision=0

# Is this an already installed library?
installed=no

# Files to dlopen/dlpreopen
dlopen=''
dlpreopen=''

# Directory that this library needs to be installed in:
libdir='/usr/local/lib' 

Spojování spouštěcích souborů

Spojování spouštěcích souborů není o nic těžší než spojování knihoven. Výklad zase napíši až po příkladu.

# libtool --mode=link gcc -g -O -o hell main.o libhello.la
gcc -g -O -o .libs/hell main.o  ./.libs/libhello.so -Wl,--rpath -Wl,/usr/local/lib
creating hell 

Příkaz slinkuje přemístitelný kód main.o s knihov­noulibhello.so (všiměte si, že na příkazovém řádku byl zadán soubor libhello.la) a vytvoří skript(!) hell. Samotný spouštěcí soubor hell je v adresáři ./.libs. Skript slouží k spouštění programu, nejsou-li knihovny nainstalovány (jako v tomto případě); pokud se pokusíte spustit samotný program hell, systém vám nahlásí, že potřebná knihovna libhello.so.0 ne­byla nalezena. Skript je výhodný, pokud například zkoušíte program se svými knihovnami, ale nechcete je instalovat do systému. Při distribuci je samozřejmě nutné knihovny instalovat, ale o tom v dalším dílu.

Příští díl se bude stále zabývat libtool. Pokusím se vám vysvětlit ladění programů a instalování knihoven a programů.

Našli jste v článku chybu?
1. 3. 2004 12:19
Ava (neregistrovaný)

Clanek nebyl uplne spatny, ale na muj vkus prilis prakticky, neni mi treba vubec jasny jake ma pouziti libtool vyhody oproti klas. dynamickym knihovnam, v cem se vlastne lisi soubory *.o a *.lo a proc je vubec vyhodnejsi libtool pouzivat. Uvital bych nejake teoreticke pozadi, priklady "jak co udelat" si najdu v howto, v tomto clanku bych radsi nasel alespon odpoved na to proc bych si to howto mel vubec precist. K IA-64: Opravdu si uklada navratovou adresu do registru ? jak to dela pri vnorene…

28. 2. 2004 23:05
Jerry III (neregistrovaný)

Jenze treba na x86 existuje nekolik volacich konvenci, hlavni dve sou C, kde zasobnik uklizi volajici a Pascal, kde ho uklizi volany. Pokud je budu mezi sebou michat tak mi bude kod docela dobre padat. Ale pokud je tohle na *nixu zalezitosti systemu a kompilatory se tomu podrizujou tak jedine dobre, aspon se tim clovek opravdu nemusi zabyvat. Jinak ze je rozdil mezi x86 a x86-64 sem nevedel, co sem cetl tak treba x86-64 porad cpe treba navratovou adresu na zasobnik, jediny rozdily sou ve veli…