V dnešním díle se doučíme základní operace s frameworkem pro sestavování software SCons. Probereme si výrobu dynamických knihoven včetně linkování programů proti nim a instalaci přeložených knihoven a programů.
7.5.2010 12:00 | Radim Kolář | přečteno 6540×
V minulém dílu jsme si přeložili knihovnu fsplib a vytvořili z ní statickou knihovnu, kterou jsme pak přilinkovali k testovacímu programu.
Pro dnešní příklady budeme potřebovat:
Scons 1.3.0. Postačí nám i starší verze, použijte tu co máte v distribuci. Zpětná kompabilita SCons je výborná, ale doporučoval bych používat alespoň 0.98, protože se mírně změnilo u předchozích verzí API. V dnešních jednoduchých příkladech to ale nebude vadit, protože u takto základních věcí se API neměnilo. V Ubuntu 8.04.4LTS je kupříkladu obsaženo postarší scons 0.97.
fsplib knihovnu. Jednak je velmi jednoduchá na sestavení a jednak používá SCons build systém, takže si v ní můžete pro inspiraci prohlédnout dodané SCons* soubory.
root přístup pro instalaci programů
Prvním příkladem, který si dnes ukážeme bude vytvoření dynamické knihovny. Je to velmi jednoduché, podobně jako v případě statické knihovny co jsme si ukazovali minule. Stačí dát do SConstruct
SharedLibrary('fsp', source=['fsplib.c','lock.c'])
freebsd7:~/fsplib> scons -Q gcc -o fsplib.os -c -fPIC fsplib.c gcc -o lock.os -c -fPIC lock.c gcc -o libfsp.so -shared fsplib.os lock.os freebsd7:~/fsplib>
Podobně jako při vytváření statické knihovny je k názvu výsledného objektu přidán prefix lib. Všimněte si také že při vytváření dynamické knihovny jsou použity jiné kompilační volby a jiné výstupní soubory než při vytváření statické knihovny. Díky tomu můžeme vytvářet obě dvě verze knihovny současně aniž by vzájemně kolidovaly.
SharedLibrary('fsp', source=['fsplib.c','lock.c']) StaticLibrary('fsp', source=['fsplib.c','lock.c'])
freebsd7:~/fsplib> scons -Q gcc -o fsplib.o -c fsplib.c gcc -o lock.o -c lock.c ar rc libfsp.a fsplib.o lock.o ranlib libfsp.a freebsd7:~/fsplib>
Tímto dostaneme obě dvě verze knihovny fsplib. Dynamická se nekompilovala, protože byla sestavená z minula. SCons používá kvalitní detekci změny zdrojových souborů pomocí hash funkce obsahu souboru a proto jej pouhá změna data neošálí.
freebsd7:~/fsplib> touch fsplib.c lock.c freebsd7:~/fsplib> scons -Q scons: `.' is up to date. freebsd7:~/fsplib>
V předchozích dílech jsem vysvětlil coding style používaný v SCons - Globální definice v SConstruct, definice per adresář v SConscript. Aktualizujeme tedy náš projekt podle těchto pravidel:
freebsd7:~/fsplib> mv SConstruct SConscript freebsd7:~/fsplib> echo "SConscript(dirs=['.'])" > SConstruct freebsd7:~/fsplib> scons -Q scons: `.' is up to date. freebsd7:~/fsplib>
To nám také odpoví na otázku jak sestavovat projekt který má více adresářů. Buďto rozšíříte seznam dirs, který je předán funkci SConscript nebo ji uvedete ještě jednou s jiným parametrem. Použiji druhou možnost, ukazuje to více inteligenci SCons frameworku. Z důvodu čitelnosti doporučuji ve vašich projektech používat raději tu první možnost.
freebsd7:~/fsplib> echo "SConscript(dirs=['test'])" >> SConstruct freebsd7:~/fsplib> scons -Q TypeError: File /usr/home/hsn/fsplib/test found where directory expected.: File "/usr/home/hsn/fsplib/SConstruct", line 2: SConscript(dirs=['test'])
Pokud jste před začátkem našich experimentů s SCons překompilovali fsplib pomocí dodaných SCons souborů, tak dostanete tuto zajímavou chybu. Pokud soubor test smažeme a SCons bude na jeho místě očekávat adresář který nenajde tak dostaneme jen warning.
freebsd7:~/fsplib> rm test freebsd7:~/fsplib> scons -Q scons: warning: Ignoring missing SConscript 'test/SConscript' File "/usr/home/hsn/fsplib/SConstruct", line 2, inscons: `.' is up to date. freebsd7:~/fsplib>
V předchozím díle jsme si ukázali jak slinkovat program staticky. Dnes si ještě ukážeme asi nejběžnější případ z praxe - slinkujeme program oproti dynamické knihovně. Netřeba podrobněji vysvětlovat, je to obnobné jako statické linkování co jsme prováděli minule.
fsplib=SharedLibrary('fsp', source=['fsplib.c','lock.c']) Program(target = 'test', source = ['test.c', fsplib])
freebsd7:~/fsplib> echo "SConscript(dirs=['.'])" > SConstruct freebsd7:~/fsplib> scons -Q gcc -o test.o -c test.c gcc -o test test.o libfsp.so freebsd7:~/fsplib>
Dynamicky slinkovaný program test nefunguje, protože dynamický loader nenajde námi přeloženou knihovnu.
freebsd7:~/fsplib> ./test /libexec/ld-elf.so.1: Shared object "libfsp.so" not found, required by "test" freebsd7:~/fsplib> ldd ./test ./test: libfsp.so => not found (0x0) libc.so.7 => /lib/libc.so.7 (0x2807f000) freebsd7:~/fsplib>
Program i knihovnu proto nainstalujeme do standardních adresářů. K tomu slouží funkce Install s dvěma parametry kam a co. Program test přejmenujeme na fsptest aby nám nekolidoval s již existujícím systémovým příkazem a mírně proto upravíme SConscript na:
fsplib=SharedLibrary('fsp', source=['fsplib.c','lock.c']) testprog=Program(target = 'fsptest', source = ['test.c', fsplib]) Install('/usr/local/bin',testprog) Install('/usr/local/lib',fsplib)
a spustíme:
freebsd7:~/fsplib> scons scons: Reading SConscript files ... scons: done reading SConscript files. scons: Building targets ... gcc -o fsptest test.o libfsp.so scons: done building targets. freebsd7:~/fsplib> fsptest fsptest: Command not found. freebsd7:~/fsplib>
Vidíme, že sice došlo k linkování programu fsptest, ale již nikoliv k jeho instalaci nebo k instalaci dynamické knihovny. SCons standardně sestaví vše v adresáři a podadresářích ze kterých je spuštěn. V našem případě je spuštěn z ~/fsplib nikoliv z /usr/local. Když ho spustíme z /usr/local přirozeně pak nenajde soubor SConstruct aby vědel co má překládat.
freebsd7:~/fsplib> scons -C /usr/local scons: Entering directory `/usr/local' scons: *** No SConstruct file found.
V helpu zjistíme že můžeme scons předat umístění souboru SConstruct jako parametr na příkazové řádce.
freebsd7:~/fsplib> scons -C /usr/local -f ~/fsplib/SConstruct scons: Entering directory `/usr/local' scons: Reading SConscript files ... scons: warning: Ignoring missing SConscript 'SConscript' File "/home/hsn/fsplib/SConstruct", line 1, inscons: done reading SConscript files. scons: Building targets ... scons: *** [SConscript] .sconsign.dblite: Permission denied scons: building terminated because of errors. freebsd7:~/fsplib>
To taky nevypadá příliš nadějně. Ze Souboru SConstruct totiž načítáme soubor SConscript, který se nachází ve stejném adresáři jako SConstruct, což nefunguje když je scons spouštěn z jiného adresáře. Volba -f totiž nezpůsobí přepnutí se do adresáře v kterém se nachází zadaný soubor a navíc se pomocí -C přepneme úmyslně jinam.
Další konzultací manuálu zjistíme, že scons můžeme předat to co má sestavit na příkazové řádce. To je to ono. Instalace totiž v scons není nic jiného než další objekt, který se má sestavit. Předáme mu proto k sestavení /usr/local. Není potřeba dokonce předávat konkrétní adresasáře nebo soubory které se mají nainstalovat.
freebsd7:~/fsplib> sudo scons -Q /usr/local Install file: "fsptest" as "/usr/local/bin/fsptest" Install file: "libfsp.so" as "/usr/local/lib/libfsp.so"
Jak již jsem zmínil v předchozích dílech, SCons generuje automaticky clean akci, která odstraní to co bylo přeloženo, případně nainstalováno. Chcete odinstalovat program? Nic snažšího.
freebsd7:~/fsplib> sudo scons -c -Q /usr/local Removed test.o Removed fsplib.os Removed lock.os Removed libfsp.so Removed fsptest Removed /usr/local/bin/fsptest Removed /usr/local/lib/libfsp.so freebsd7:~/fsplib>
Z použití utility make jsme zvyklí na instalaci pomocí make install. Není problém toto zařídit i v SCons. Použijeme alias, kdy scons naučíme že když mu řekneme vyrob install tak tím vlastně myslíme vyrob soubory v /usr/local
freebsd7:~/fsplib> echo "Alias('install', '/usr/local')" >> SConscript freebsd7:~/fsplib> sudo scons -Q install gcc -o test.o -c test.c gcc -o fsplib.os -c -fPIC fsplib.c gcc -o lock.os -c -fPIC lock.c gcc -o libfsp.so -shared fsplib.os lock.os gcc -o fsptest test.o libfsp.so Install file: "fsptest" as "/usr/local/bin/fsptest" Install file: "libfsp.so" as "/usr/local/lib/libfsp.so"
Po dnešku již budete umět použít SCons pro sestavení, nainstalování a odinstalování jednoduchého software. V dalším díle se podíváme na ovlivňování kompilačních voleb.