SCONS - Nástroj pro sestavování software - 4

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 6198×

SCONS - nástroj pro sestavování software - 4

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:

  1. 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.

  2. 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.

  3. root přístup pro instalaci programů

Dynamická knihovna

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'])
na začátek souboru lock.h dát #define FSP_NOLOCKING a dílo je hotovo k překladu.
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>

Coding Style

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, in 
scons: `.' is up to date.
freebsd7:~/fsplib>

Instalace programu

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, in 
scons: 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.

Online verze článku: http://www.linuxsoft.cz/article.php?id_article=1702