Здравейте,
На който бог на Ц не му се четат дрънканици, да иде направо на последното изречение. Goto END; (любимият ми оператор)
=*=
Напоследък не съм наминавал, но то е и защото освен експерименти с bash, си правя такива с Ц. Трябва да кажа, че опити с Ц и Ц++ си правя от мно-о-ого години с го-о-о-олеми прекъсвания. Все още много неща ми звучат като черна магия.
Днешният казус. Просто ме гложди.
Ако искам да ползвам някаква библиотека трябва да вкарам заглавката ѝ. Например:
GeSHi (C):
#include <X11/Xlib.h>
Т'ва например е за Xlib. Обаче Ц не знае де трябва да го търси. При цомпилиране трябва да кажем. Например:
GeSHi (Bash):
gcc -g -Wall -o intro intro.c $(pkg-config --libs --cflags x11)
Всъщност изхода от подкомандата е „-lX11“. Който и pc да отворите отдолу пише само -l*.
Разглеждал съм и много заглавки (*.h), но вътре са описани само, какви неща са изнесени от библиотеката за ползване. Не пише, къде да се търсят.
Добре де, въпроса е как точно вече транслираната програма знае, къде точно се намира споделената библиотека? Аз например знам къде е, защото съм я инсталирал от пакет или от изходен код. Знам, къде, какво е сложено.
Така, аз през годините съм разбрал (май първо от Гейт го чух) за митична програма наречена linker. Това име се споменава и в много други езици. Аз не съм го срещал като понятие в динамично-типизираните езици (на които пиша предимно), но изглежда е много важно нещо за неща като Ц и Жаба. Така нареченият linker в *nix за Ц изглежда се нарича ld. Много често ми е гърмял.
Изглежда също, че той е отговорната програма, която казва на нашата програма, къде се намира съответното so, което да ползва за правилното си изпълнение. Обаче никой, никъде не му е задал нещо различно от „-l*“, в нашият пример „-lX11“.
Е добре де, как под ягодите се разбира точното име на споделената библиотека и къде се намира?
Второто е до някъде много ясно. Има променливи на средата, които оказват това. Най-използвана е LD_LIBRARY_PATH, но има всякакви други откачени, например LD_RUN_PATH, LTDL_LIBRARY_PATH. Както и да е. Ако в ГНУ/Линукс няма поне по три неща правещи едно и също едновременно, няма да е ГНУ/Линукс. Такива променливи не всеки път са зададени, пък все пак програмите си намират библиотеките. Например в Дебиан 8 те са на много олигофренично място (подкаталози на /usr/lib/i386-linux-gnu/). А ld някак си ги намира¹.
Някъде съм срещал да се „изяснява“, че ако искам да знам, какво точно *.so се ползва и къде е то, трябвало да се допитам до libtool. Четох му документацията на това нещо, дори изходният код (някакъв bash), за да разбера, че това е някакво нещо, правещо нещо си, което не се отнася до мен и изобщо за нищо не служи, освен да обслужва само себе си.
Та успях ли да попитам ясно?
=*=
END:
Обобщавам: В Ц е пълно с черна магия. Сигурно скоро пак ще попитам за нещо, но в момента изгарям от любопитство да разбера как при транслиране на една програма, тя после разбира как се казват нейните споделени библиотеки, като това никъде и по никакъв начин не е оказано??? Програмата някак си пита ld за това, но и на самото ld, никой, никога и никак не му е казвал подобно нещо и все пак, той го знае?!?
Благодаря!
¹Според разни изходи от транслиране, чете някакъв малоумен /etc/ld.so.conf. Не знам за другите дистрибуции, но в Дебиан 8 е ужасен. Поне в 5 до 7 помня, че не беше нацепен на частички в /etc/ld.so.conf.d/, а си беше цял. Както и да е, като насъбере пътищата от всички места описани там, почва да намира библиотеките. Но техните имена все още ги няма.