Static lib in linux

Блог радиста

Блог о Linux в частности и Open Source в общем, о программировании и немного о M$ Windows

Статические и динамические библиотеки в Linux

Статические и динамические библиотеки в Linux

Сегодня мы поговорим о библиотеках в Linux (подозреваю также, что многие описанные здесь вещи возможны и в других *nix-операционных системах, но это требует проверки 🙂 ).

1) Статические библиотеки (создание с помощью Assembler, C/C++; подключение и использование в программах на Assembler,C/C++);
2) Динамические библиотеки (создание с помощью Assembler, C/C++; подключение и использование в программах на C/C++l, Python).

1) Статическая библиотека — это такая библиотека, которая связывается (линкуется) с программой в момент компиляции оной. При этом объектный код библиотеки помещается в исполняемый файл программы. С этой точки зрения статическая библиотека похожа на исходный код программы, с которой она связывается, за исключением того, что библиотека компилируется «кем-то еще» и программист, использующий библиотеку, имеет дело исключительно только с результатом этой компиляции.

В Linux, как правило, файл-статическая_библиотека имеет расширение «.a»

2) Статические библиотеки на языке C.

Исходный код библиотеки:

Сохраните его в файле static.c

Ключевое слово extern необходимо для того, чтобы функция была видна в программе.

Теперь скомпилируем (! без линковки) библиотеку:

gcc -c static.c -o static.o
(на выходе имеем файл static.o, содержащий объектный код нашей библиотеки)

ar rc libMY_STATIC.a static.o

ar упаковывает несколько (! Это важно. Дело не ограничивается только одним объектным файлом) объектных файлов в одну статическую библиотеку. Статическая библиотека имеет расширение «.a», при этом ее название должно начинаться с «lib» (дань традиции).
Параметры ar:
r — предписывает заменять старые версии объектных файлов новыми — необходим для переупаковки библиотеки;
c — создать статическую библиотеку, если та еще не существует.

Проиндексируем функции внутри библиотеки для более быстрой линковки:

Итак, мы получили статическую библиотеку libMY_STATIC.a.

Теперь попытаемся использовать библиотеку в нашей программе:

Исходный текст программы (C):

Сохраните его в файле program1.c

Способы связывания библиотеки и программы:

— Скомпилируем и слинкуем (в том числе с нашей библиотекой) нашу программу:

gcc program1.c libMY_STATIC.a

(предполагается, что в качестве аргумента gcc будут переданы полные пути (!) к вашим библиотекам)

На выходе получим:

Hello world! I’m static library
Return code: 0

— Скомпилируйте с помощью команды:

gcc program1.c -L. -lMY_STATIC -o a1.out

— путь к каталогу, содержащему наши библиотек (используйте «-L

— название нашей библиотеки (это важно — название (!), а не имя файла — собственно, если библиотека имеет своим именем «libBLABLABLA.a», то ее названием будет «BLABLABLA» — т.е. имя без приставки «lib» и расширения «.a») (для нескольких библиотек используйте «-l -l . «)

Запустите файл a1.out на выполнение и удостовертесь, что результаты те же, что и в предыдущем пункте.

— Видоизменим предыдущий способ — уберем аргументы «-L»:

В начале проверим значение переменной LD_LIBRARY_PATH и содержимое файла /etc/ld.so.conf:

echo $LD_LIBRARY_PATH ; cat /etc/ld.so.conf

На экране появился некоторый список каталогов — это те каталоги, в которых система ищет библиотеки при их линковке с программой (еще к таким каталогам относятся:
/lib
/usr/lib
. Поместите libMY_STATIC.a в один из этих каталогов:

Читайте также:  Iphone and windows apps

(Я, к примеру, засуну нашу библиотеку в каталог /usr/lib):

su -c ‘cp libMY_STATIC.a /usr/lib’
(в Ubuntu — sudo cp libMY_STATIC.a /usr/lib )
ldconfig
(ldconfig обновляет кеш данных о библиотеках линковщика)

Теперь скомпилируем и запустим нашу программу:

gcc program1.c -lMY_STATIC -o a2.out
./a2.out

Hello world! I’m static library
Return code: 0

Бинго! Кстати, таким вот способом вы можете подключать к своей программе любые статические библиотеки из приведенных выше каталогов.

* Бывает полезно определить все прототипы функций библиотеки в некотором заголовочном файле, который будет потом включаться в вашу программу. Это не обязательно, но удобно.

3) Статические библиотеки на языке Assembler.

Представьте, что вам необходимо оптимизировать выполнение некоторых действий в вашей программе. Разумеется, вы может применить ключевое слово asm (если пишите программу на C/C++), но лучшим решением будет создание оптимизированной вами библиотеки на языке Assembler и подключение ее к вашей программе. Давайте попробуем:

*Кстати, углубляться в процесс компиляции библиотеки и ее линковки с вашей программой я не буду (!). Этот процесс идентичен полностью (!) тому же процессу для библиотек, написанных на языке C.

Итак, имеем вот такую программу:

Сохраните ее в файле program2.c

Скомпилируйте ее и запустите:

Я привел этот пример, чтобы показать действительно возможность оптимизации программы с помощью библиотеки на Assembler’е. Вы можете заметить, что вызов printf в main() не оптимален, т.к. printf, по крайней мере, один раз использует цикл while для поиска вхождений конструкций «%. » в строку. Это не оптимально, т.к. очевидно, что таковых символов у нас нет. Оптимизируем нашу программу с помощью библиотеки на Assebmler’е:

my_printf:
movl $4,%eax
xorl %ebx,%ebx
incl %ebx
movl $hw,%ecx
movl $hw_e,%edx
int $0x80
xorl %eax,%eax
ret

Сохраните исходный код библиотеки в файле static2.s

Это AT&T наречие Assembler’а.

.globl my_printf — «my_printf» описывается как глобальная (видимая в других объектных файлах) последовательность
my_printf: — начало описание функции my_printf
movl $4,%eax — поместим 4 в eax (4 — номер системного вызова write)
xorl %ebx,%ebx и incl %ebx — поместим в ebx единицу — номер STDOUT
movl $message,%ecx — в ecx запишем адрес начала сообщения
movl $message_l,%edx — в edx поместим адрес конца сообщения
int $0x80 — произведем системный вызов write
xorl %eax,%eax — в eax — код возврата (0)
ret — вернемся в вызывающую процедуру
.data — секция данных (разумеется, мы могли бы передавать выводимую строку как параметр, но тогда вычисление ее конца потребовало бы от нас дополнительных усилий, что, согласитесь, лениво 🙂 )

Теперь получим библиотеку:

gcc -c static2.s -o static2.o
ar rc static2.a static2.o
ranlib static2.a

На выходе имеем статическую библиотеку static2.a

Теперь напишем программу, использующую эту статическую библиотеку (язык C):

Сохраните текст программы в файле program3.c

Заметьте, я добавил прототип библиотечной функции для удобства.

Скомпилируем и слинкуем программу с библиотекой, после чего запустим программу на выполнение:

gcc program3.c static2.a
./a.out

На выходе получим:

* Принцип линкования статических библиотек с программами на Assembler’е аналогичен принципу для программ на C. Просто, когда будете использовать статические библиотеки в Assembler’е, помните о соглашениях C по передаче аргументов в функцию и возвращению результата.

Читайте также:  Windows powershell администратор как запустить

4) Статические библиотеки на языке C++.

Принцип создания аналогичен статическим библиотекам на C, но перед каждой экспортируемой функцией не забывайте добавлять:

(экспортировать как функцию на C — т.е. без расширения имен).

* Кстати, используйте g++ вместо gcc, если захотите протестировать приведенные выше примеры.

Подключение к вашей программе аналогично подключению к программе, написанной на C, за исключением необходимости явно добавлять к тексту программы прототипы импортируемых функций в следующем виде:

extern «C» PROTOTYPE

Где PROTOTYPE — прототип импортируемой функции.

* При подключении статических библиотек на C++ к программе на C сопряжено с некоторыми трудностями — т.к. при компиляции и линковки программы необходимо будет также вручную подключить системные библиотеки для реализации функционала, предоставляемого библиотекой Standart C++ сверх того, что предоставляет библиотека Standart C.

Динамические библиотеки (shared).

1) Динамическая библиотека — библиотека, подключаемая к программе в момент выполнения. Это означает, что при создании библиотеки производится не только ее компиляция, но и линковка с другими, нужными ей, библиотеками (!).

Динамические библиотеки полезны в случаях, если:
— Важно не перекомпилировать всю программу, а только перекомпилировать ту часть, которая реализует определенные функции — тогда эти функции выносятся в динамическую библиотеку;
— Важно использовать в программах на C библиотеки, подготовленные на C++ и при этом избежать лишних трудностей с линковкой программы;
— Кроме того, динамические библиотеки позволяют экономить место на жестком диске и в оперативной памяти, если одна и таже библиотека используется несколькими программами.

В Linux, обычно, динамические библиотеки имеют расширение «.so».

2) Подготовим исходный код динамической библиотеки (пример на C++).

Исходный код динамической библиотеки по принципам создания ничем (!) не отличается от исходного кода статических библиотек.

Здесь мы подготовим некоторый пример, который в дальнейшем будем использовать повсеместно во всей части 2.

Итак, исходный код библиотеки (C++):

extern «C» int hello()
<
cout 3) Компиляция и линковка динамических библиотек.

Давайте получим динамическую библиотеку:

Получим файл с объектным кодом:

g++ -fPIC -c dynamic.cpp -o dynamic.o

(используйте gcc для программ на С и Assembler’е)

-fPIC — использовать относительную адресацию в переходах подпрограмм — во избежание конфликтов при динамическом связывании

А теперь из объектного файла получим библиотеку:

g++ -shared -olibdynamic.so dynamic.o

(используйте gcc для программ на С и Assembler’е)

libdynamic.so — имя результирующей библиотеки;
-shared — предписывает создать динамическую (т.е. «разделяемую») библиотеку.

* Именуйте динамические библиотеки следующим способом:

Итак, на выходе мы имеем libdynamic.so — нашу динамическую библиотеку.

4) Использование динамической библиотеки в программе на C/C++.

— Связывание с библиотекой во время компиляции программы (C/C++):

—— Подготовим исходный код нашей программы:

Сохраните его в файле Dprogram1.c

extern «C» int hello();

Сохраните его в файле Dprogram1.cpp

(единственное отличие, как вы можете заметить, в ключевом слове extern — см. часть 1 пункт 4)

—— Теперь добьемся того, чтобы система смогла найти нашу библиотеку. Поместим libdynamic.so в один из каталогов:

cat /etc/ld.so.conf
и выполните потом » ldconfig «

—— И, наконец, скомпилируем программу и слинкуем ее с библиотекой:

Читайте также:  Не ставиться линукс минт

gcc ИСХОДНИК -lИМЯ_БИБЛИОТЕКИ -o РЕЗУЛЬТИРУЮЩИЙ_БИНАРИК

В нашем случае: gcc Dprogram1.c -L/home/amv/c/libs/ -ldynamic

(используйте g++ для программы на C++)

Запустим на исполнение полученный файл:

В итоге должно получится:

— Связывание с библиотекой во время исполнения программы (C/C++):

Разумеется, предыдущий пример неплох. Однако бывает необходимо подключать библиотеку во время выполнения программы. Для этого можно использовать функционал из заголовочного файла .

Исходный код примера (C):

int main()
<
void *handle = dlopen(«libdynamic.so»,RTLD_LAZY);
int(*fun)(void) = dlsym(handle,»hello»);
int x = (*fun)();
dlclose(handle);
printf(«Return code: %d\n»,x);
return 0;
>;

######################

Сохраните его в файле Dprogram2.c

В dlfcn.h определены следующие функции:

void* dlopen(«PATH_AND_NAME»,FLAG) — загружает в память динамическую библиотеку с полным именем PATH_AND_NAME и возвращает ее описатель (HANDLE) (NULL в случае неудачи). FLAG — флаги, описанные в «man dlopen»;
void* dlsym(HANDLE,»NAME») — возвращает указатель на функцию/переменную, импортируемую из библиотеки;
int dlclose(HANDLE) — выгружает библиотеку из памяти;
const char *dlerror() — получить сообщение о последней возникшей ошибке (NULL — если ошибок не произошло с момента последнего вызова dlerror).

* Посмотрите на досуге вот этот перевод «man dlopen»: Привет, OpenNET

gcc -ldl Dprogram2.c

(используйте g++ для программы на C++)

Запустим на исполнение полученный файл:

В итоге должно получится:

* Важно! Нет необходимости помещать библиотеку в один из специальных каталогов, модифицировать переменные окружения и выполнять «ldconfig»

— Использование динамической библиотеки в программе на Python:

Все предельно просто.

—— Поместим libdynamic.so в один из каталогов:

cat /etc/ld.so.conf
и выполните потом «ldconfig»

Исходный текст программы на python’е:

Модуль ctypes входит в стандартную поставку модулей python версии 2.5 и выше.

Фуф. Мы проделали довольно большую работу, но ведь это только верхушка айсберга.

Источник

How to compile a static library in Linux?

I have a question: How to compile a static library in Linux with gcc , i.e. I need to compile my source code into a file named out.a. Is it sufficient to simply compile with the command gcc -o out.a out.c ? I’m not quite familiar with gcc , hope anyone can give me a hand.

3 Answers 3

-c means to create an intermediary object file, rather than an executable.

This creates the static library. r means to insert with replacement, c means to create a new archive, and s means to write an index. As always, see the man page for more info.

Here a full makefile example:

makefile

explaining the makefile:

  • target: prerequisites — the rule head
  • $@ — means the target
  • $^ — means all prerequisites
  • $ — means just the first prerequisite
  • ar — a Linux tool to create, modify, and extract from archives see the man pages for further information. The options in this case mean:
    • r — replace files existing inside the archive
    • c — create a archive if not already existent
    • s — create an object-file index into the archive

To conclude: The static library under Linux is nothing more than a archive of object files.

main.c using the lib

lib.h the libs main header

lib1.c first lib source

lib1.h the corresponding header

lib2.c second lib source

lib2.h the corresponding header

Источник

Оцените статью