Ono je totiz rozdiel medzi "dependency hell" a "neriesitelne dependency hell". Len taky maly priklad do plena. Na zamyslenie. V systeme mam nainstalovane libncurses 4.3.0 a ziadne mc ani dialog:
# ls /usr/lib/libncurses* /usr/lib/libncurses.so.4 --> libncurses.so.4.3 /usr/lib/libncurses.so.4.3 --> libncurses.so.4.3.0 /usr/lib/libncurses.so.4.3.0
Chcem pouzivat napr mc-5.5.0 ktory vyzaduje libncurses.so.4.3.2 a popritom program dialog-1.2.3 ktory vyzaduje libncurses.so.4.3.1.
Po instalacii (bez riesenia zavyslosti):
# ldd `which mc` | grep ncurses libncurses.so.4 in /usr/lib/libncurses.so.4 --> /usr/lib/libncurses.so.4.3.0 # ldd `which dialog` | grep ncurses libncurses.so.4 in /usr/lib/libncurses.so.4 --> /usr/lib/libncurses.so.4.3.0 # mc Segmentation fault # dialog Segmentation fault
Ok takze potrebujem novu kniznicu. Je tu ale jeden problem! Binarky mc a dialog nehovoria ktoru presne verziu chcu ale tu s ktorou boli skompilovane. V sucasnych distrach su vacsinou simlinky na libncurses.so.4 co je simlinka na libncurses.so.4.3 co je linka na skutocnu kniznicu (v mojom pripade libncurses.so.4.3.0). Takto skompilovana binarka "si mysli" ze potrebuje 4 ale v skutocnosti chce 4.3.1 resp. 4.3.2.
Ak doinstalujem libncurses-4.3.1 aj libncurses-4.3.1 stav bude takyto:
# ls /usr/lib/libncurses* /usr/lib/libncurses.so.4 --> libncurses.so.4.3 /usr/lib/libncurses.so.4.3 --> libncurses.so.4.3.0 [*] /usr/lib/libncurses.so.4.3.0 /usr/lib/libncurses.so.4.3.1 /usr/lib/libncurses.so.4.3.2
[*] Tato simlinka moze ukazovat na 4.3.0, 4.3.1 alebo 4.3.2, zalezi to na sposobe akym instalujem, kazdopadne len na jeden z nich. Cize ak mi pojde mc, nepojde mi dialog a naopak.
Toto vsetko za predpokladu ze 4.3.1 a 4.3.2 niesu vzajomne kompatibilne. Cize tento problem nastane vtedy, ak sa v distribuciach pouzivaju symlinky ktore zahrnuju kniznice ktore niesu vzajomne kompatibilne. Inak povedane ak symlinka 4.3 bude pokryvat vsetky verzie 4.3.x a tieto verzie 4.3.x budu vzajomne kompatibilne tak nieje problem.
Moja skusenost je ale taka ze pomerne casto sa najdu rovnake kniznice verzie A.B.C a A.B.D pouzivajuce spolocnu symlinku A.B ale .C a .D niesu vzajomne kompatibilne. Takto vznikaju "neriesitelne dependency hell". Ide o to ze neexistuje taky "guru" ktory by povedal ktore verzie kniznic mozno zastresit spolocnou symlinkou. Mozete to otestovat ale zabudnete pretestovat nejaku polozku v menu v MC a s nespravnou kniznicou to potom u uzivatela hodi segfault.
No a to sa da vyriesit jedine tak ze sa nebudu pouzivat symlinky kniznic ale programy sa budu kompilovat oproti skutocnej kniznici, nie symlinke. Problem je ten ze ked chcete upgradovat jeden program tak musite upgradovat vsetky, alebo si tento program musi so sebou priniest svoje verzie kniznic.
Ocakavam vase podnety, nazory, pripomienky, mozno som totiz prehliadol nejake jednoduche, elegantne a priamociare riesenie tohoto problemu.
Problém je v tom, že knihovny libxxx-A.B.C a libxxx-A.B.D by měly být kompatibilní; (nekompatibilní změny se označují změnou čisla "B", případně "A"). No, ne vždy se zadaří :-(, může to být chyba tvůrců knihovny, nebo chyba aplikace, která využívá/zneužívá nějakou chybu knihovny, a po její opravě přestává ta aplikace fungovat.
Co s tím?
Pokud si program kompilujete, můžete ho slinkovat proti libxxx-A.B.C. Nevýhoda tohoto přístupu je v tom, že až vznikne bezpečnostní update knihovny na libxxx-A.B.D, tak budete muset všechny takové programy překompilovat (anebo "lhát" o verzi knihovny symlink ABC->ABD).
Pokud máte 2 aplikace vyžadující (podle jména) stejnou knihovnu, ale ve skutečnosti běhá každá jen se "svou" konkrétní verzí, můžete poprosit dyn. linker, aby nahrál "tu správnou" knihovnu pro tu správnou aplikaci. Ve vašem příkladu:
(nejnovější standardně instalovaná)
/usr/lib/libncurses.so.4.3 --> libncurses.so.4.3.2
(starši pro dialog)
/usr/lib/oldncurses/libncurses.so.4.3 --> ../libncurses.so.4.3.1
a dialog spouštět (např. skriptem)
LD_LIBRARY_PATH=/usr/lib/oldncurses dialog