Procesul de legare expus – Biblioteci statice vs. dinamice
Crearea unei biblioteci statice și dinamice
Pentru o bibliotecă statică, codul obiect din fișierele binare (extensia .o
) sunt combinate într-un singur fișier de arhivă cu extensia .a
. Această arhivă este similară cu o cutie de instrumente care conține toate instrumentele care ar putea fi utilizate în programele care apelează biblioteca respectivă în timpul legăturii. Instrumentele sunt inserate în locurile în care sunt necesare. În imaginea de mai jos, am o serie de fișiere .c
.
Din moment ce o bibliotecă este o arhivă de cod obiect, trebuie să convertesc toate aceste fișiere .c
în fișiere .o
folosind următoarea comandă:
gcc -Wall -Wextra -Werror -pedantic -c *.c
Opțiunea -c
oprește procesul de compilare chiar înainte de legare, după ce sunt generate fișierele de cod obiect. Acum am toate fișierele de cod obiect:
Dacă execut comanda ar -rc libholbertonschool.a *.o
, pot arhiva aceste fișiere într-un singur fișier de bibliotecă .a
. Comanda ar
este pentru arhivare, opțiunea -r
este pentru a muta membrii care au extensia .o
, iar opțiunea -c
este pentru a crea arhiva dacă aceasta nu există. Un fișier de bibliotecă începe cu prefixul lib
și are extensia .a
. Ultimul pas care este necesar pe unele sisteme este de a indexa conținutul arhivei pentru a grăbi crearea legăturii. Acest lucru se poate face cu ranlib libholbertonschool.a
. Acum am o bibliotecă ce conține codul obiect pentru toate funcțiile din imaginea de mai sus.
Utilizarea bibliotecii statice
Pentru a utiliza această bibliotecă cu un fișier de test oarecare, trebuie să compilez fișierul de test cu biblioteca folosind una din următoarele două comenzi:
gcc test.c ./libholbertonschool.a -o exename
gcc test.c -L. -lholbertonschool -o exename
Ambele fac același lucru, dar a doua este puțin mai criptică. Opțiunea -L.
caută bibliotecile din directorul curent, iar opțiunea -l
, care este legată de holbertonschool
, caută implicit fișierul de bibliotecă, unde se presupune un prefix lib
și un sufix .a
. Fără compilarea cu un fișier de bibliotecă, gcc
va arunca o eroare deoarece funcțiile pe care încearcă să le lege nu sunt furnizate. Prin furnizarea unei biblioteci la compilare, compilatorul poate acum să caute în bibliotecă funcțiile de care are nevoie și să le insereze acolo unde este nevoie.
Biblioteci dinamice
Crearea bibliotecilor dinamice este ușor diferită de bibliotecile statice, dar conceptele sunt în general aceleași. Am același număr de fișiere .c
și fișierul antet care definește prototipurile lor într-un fișier numit lists.h
.
Pentru a crea biblioteca dinamică, care are un .so
(care reprezintă obiectul partajat), se poate introduce următoarea comandă de compilare:
gcc -fPIC -Wall -Werror -Wextra -pedantic *.c -shared -o libholberton.so
Semnalizatorul -fPIC
reprezintă Codul independent de poziție, care este necesar pentru legarea dinamică. Semnificația acestuia este exact ceea ce pare – deoarece bibliotecile legate dinamic pot fi stocate oriunde în memorie unde se potrivesc, acest indicator permite ca fișierul de bibliotecă să fie utilizat indiferent de locul în care este stocat.
Indicatorul -shared
permite crearea unei arhive partajate, iar opțiunea -o
ne permite să redenumim fișierul de ieșire în libholberton.so
.
După ce am executat această comandă, acum am o bibliotecă partajată!
Utilizarea bibliotecii dinamice
Să spunem că am următorul cod:
#include "holberton.h"
#include <stdlib.h>
#include <stdio.h>/**
* main - check the code for Holberton School students.
*
* Return: Always EXIT_SUCCESS.
*/
int main(void)
{
printf("%d\n", _strlen("Holberton"));
return (EXIT_SUCCESS);
}
Pot compila programul cu următorul cod:
gcc -Wall -pedantic -Werror -Wextra -L. 0-main.c -lholberton -o len
La fel ca în cazul bibliotecilor statice, opțiunile -L.
caută în director fișierele de bibliotecă, iar -l
care este atașat la începutul lui holberton
este o căutare implicită a fișierelor de bibliotecă care au prefixul lib
, sufixul .so
și holberton
între cele două.
Pentru a utiliza fișierul de bibliotecă pe care tocmai l-am creat, trebuie să mă asigur că compilatorul este capabil să găsească toate fișierele de bibliotecă în memorie și că acestea sunt încărcate corect în memorie pentru început. Dacă execut ldd len
acum, pot vedea următoarele:
Linia libholberton.so => not found
îmi spune că dependența de biblioteca dinamică pe care tocmai am creat-o nu este îndeplinită. Pentru a remedia acest lucru, trebuie înțeleasă variabila de mediu $LD_LIBRARY_PATH
. În Linux, această variabilă este o listă de directoare, separate prin două puncte, în care sistemul caută fișiere de bibliotecă. În imaginea de mai sus, puteți vedea că ecoul acestei variabile la starea actuală arată că este goală și, astfel, încercarea mea de a rula programul (len
) nu funcționează deoarece biblioteca partajată nu poate fi încărcată.
Directorul meu curent arată astfel: