Библиотека – это файл, содержащий скопилированный код из нескольких объектных файлов в один файл библиотеки, который может содержать функции используемые другими программами.
Библиотеки могут быть статичными (static) и динамическими или разделяемыми (dynamic, shared).
Ниже – краткий пример создания и применения shared library на C в Linux.
Доступ к общей библиотеке может осуществляться по нескольким именам:
- имя, используемое “линкером”
/usr/bin/ld
(linker name), в виде слова lib + имя библиотеки + расширение.so
, например –libpthread.so
- Полное имя (fully qualified name или soname), в виде lib + name +
.so
+ версия (например –libpthread.so.1
) - реальное имя – полное имя файла, содержащего версию библиотеки, в виде lib + имя +
.so
+ версия + минорная версия и опционально – версия релиза (например –libpthread.so.1.1
)
Версия для общей бибилиотеки меняется в случае, когда изменения в коде этой бибилиотеки делают её несовместимой с предыдущими версиями, например – если из библиотеки была убрана какая-то функция (libpthread.so.1
)
Минорная версия меняется, если изменения не затронули совметимость библиотеки, например – какой-то фикс в одной из функций. В таком случае версия останется прежней, а изменится только минорная часть (libpthread.so.1.1
).
Такое соглашение об именах версий библиотек позволяет существование разных версий одной библиотеки в одной системе.
Программа, которая будет линковаться с этой бибилиотекой, не будет привязана к определённому файлу с последней версией библиотеки. Вместо этого, после установки последней версии – все связанные программы будут использовать её.
Содержание
Создание библиотеки
Создадим простой файл libhello.c
с одной функцией:
#include <stdio.h> void print_hello() { printf("Hello, World!\n"); }
Создаём заголовочный файл библиотеки libhello.h
с прототипом функции:
void print_hello();
Приступаем к сборке библиотеки.
Создаём объектный файл, указав опцию PIC (Position Independent Code), Warning (-Wall -
warning all), -g
для добавления дебаг-информации и -c
– что бы создать только файл библиотеки, без вызова линкера:
[simterm]
$ gcc -fPIC -Wall -g -c libhello.c
[/simterm]
Проверяем – теперь у нас имеется объектный файл .o
:
[simterm]
$ ls -l total 16 -rw-r--r-- 1 setevoy setevoy 75 Jul 31 13:21 libhello.c -rw-r--r-- 1 setevoy setevoy 18 Jul 31 13:22 libhello.h -rw-r--r-- 1 setevoy setevoy 5032 Jul 31 13:33 libhello.o
[/simterm]
Теперь создадим общую библиотеку с дебагом (-g
), тип общая (-shared
), указав (с помощь -Wl
) линковщику (/usr/bin/ld
) на использование имени libhello и версии 0, результат сохранить в файл libhello.so.0.0
(опция -o
), и использовать объектный файл libhello.o
:
[simterm]
$ gcc -g -shared -Wl,-soname,libhello.so.0 -o libhello.so.0.0 libhello.o -lc
[/simterm]
Проверяем:
[simterm]
$ gcc -g ls -l total 28 -rw-r--r-- 1 setevoy setevoy 75 Jul 31 13:21 libhello.c -rw-r--r-- 1 setevoy setevoy 18 Jul 31 13:22 libhello.h -rw-r--r-- 1 setevoy setevoy 5032 Jul 31 13:33 libhello.o -rwxr-xr-x 1 setevoy setevoy 10312 Jul 31 13:47 libhello.so.0.0
[/simterm]
Далее – используем ldconfig
, что бы создать файл с linker name, который будет являться симлинком на файл с soname (полным именем), который в свою очередь – будет ссылкой на реальное имя:
[simterm]
$ ldconfig -v -n . .: libhello.so.0 -> libhello.so.0.0 (changed)
[/simterm]
Проверяем:
[simterm]
$ ls -l total 28 -rw-r--r-- 1 setevoy setevoy 75 Jul 31 13:21 libhello.c -rw-r--r-- 1 setevoy setevoy 18 Jul 31 13:22 libhello.h -rw-r--r-- 1 setevoy setevoy 5032 Jul 31 13:33 libhello.o lrwxrwxrwx 1 setevoy setevoy 15 Jul 31 13:50 libhello.so.0 -> libhello.so.0.0 -rwxr-xr-x 1 setevoy setevoy 10312 Jul 31 13:47 libhello.so.0.0
[/simterm]
Создаём символьную ссылку на файл (для linker name):
[simterm]
$ ln -sf libhello.so.0 libhello.so
[/simterm]
Проверяем:
[simterm]
$ ls -l total 28 -rw-r--r-- 1 setevoy setevoy 75 Jul 31 13:21 libhello.c -rw-r--r-- 1 setevoy setevoy 18 Jul 31 13:22 libhello.h -rw-r--r-- 1 setevoy setevoy 5032 Jul 31 13:33 libhello.o lrwxrwxrwx 1 setevoy setevoy 13 Jul 31 13:59 libhello.so -> libhello.so.0 lrwxrwxrwx 1 setevoy setevoy 15 Jul 31 13:50 libhello.so.0 -> libhello.so.0.0 -rwxr-xr-x 1 setevoy setevoy 10312 Jul 31 13:47 libhello.so.0.0
[/simterm]
Ещё раз про имена:
libhello.so
: linker name файл, симлинк на Fully qualified name или soname файл, в данном случае этоlibhello.so.0
libhello.so.0
: soname, который указывает на файл с real name –libhello.so.0.0
libhello.so.0.0
: непосредственно файл общей библиотеки
Использование shared lib
Попробуем применить созданную библиотеку.
Создаём файл программы, hello.c
:
#include "libhello.h" int main(){ print_hello(); return 0; }
Собираем программу, указав через -l
– имя библиотеки (без lib), и с помощью -L
– путь, по которому необходимо искать файл библиотеки:
[simterm]
$ gcc hello.c -o hello -lhello -L.
[/simterm]
Добавляем текущий каталог в $LD_LIBRARY_PATH
:
[simterm]
$ export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:.
[/simterm]
Проверяем:
[simterm]
$ ./hello Hello, World!
[/simterm]
Проверить используемые программой библиотеки можно с помощью ldd
:
[simterm]
$ ldd hello linux-vdso.so.1 (0x00007ffeef1b9000) libhello.so.0 (0x00007f44cf513000) libc.so.6 => /usr/lib/libc.so.6 (0x00007f44cf16d000) /lib64/ld-linux-x86-64.so.2 (0x00007f44cf715000)
[/simterm]
Если убрать файл билиотеки – ldd
сразу сообщит об ошибке:
[simterm]
$ mv libhello.so.0 /tmp/ $ ldd hello linux-vdso.so.1 (0x00007ffcab1ee000) libhello.so.0 => not found libc.so.6 => /usr/lib/libc.so.6 (0x00007fb85152e000) /lib64/ld-linux-x86-64.so.2 (0x00007fb8518d4000)
[/simterm]
И программа откажется запускаться:
[simterm]
$ ./hello ./hello: error while loading shared libraries: libhello.so.0: cannot open shared object file: No such file or directory
[/simterm]
Готово.