Что такое библиотека?

Библиотека в программировании — это набор функций, которые могут вызываться и использоваться вашей программой, что делается на этапе компоновки компиляции. Библиотеки обычно пишутся так, чтобы другие могли использовать их в своих программах по многим причинам. Как уже говорилось, одним из них является удобство. Повторное использование кода — это здорово, поэтому вам не нужно создавать его самостоятельно с нуля. Если это с открытым исходным кодом, даже лучше, так как он, вероятно, был обновлен для устранения ошибок. Использование библиотек также полезно для ускорения процесса компиляции, поскольку библиотеки обычно индексируются, что значительно ускоряет поиск функций и переменных.

В Unix есть два типа библиотек: статические и динамические. В этой статье мы сосредоточимся конкретно на статических библиотеках в C.

Что такое статическая библиотека в C?

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

Как правило, имена файлов библиотек всегда начинаются с lib и имеют расширение .a, которое является расширением для статических библиотек (в отличие от .soдля динамические библиотеки). В нашем примере мы назовем статическую библиотеку, которую собираемся создать:

libholberton.a

Шаги по созданию статической библиотеки на C

Сначала создайте объектные файлы

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

$ gcc -c *.c

После того, как вы запустите этот код и запустите ls -l в своем терминале, чтобы получить список файлов в вашем текущем рабочем каталоге, вы должны увидеть ряд объектных файлов .o, соответствующих их исходным файлам .c.

Создание файла вашей библиотеки

Затем мы берем объектные файлы .o и упаковываем их в один файл статической библиотеки .a с именем libholberton.a. Для этого мы используем команду ar, которая представляет собой утилиту архиватора Unix, которая создает и поддерживает библиотечные архивы. Мы можем дополнить команду флагами, в этом случае мы используем -c, которая создает библиотеку, если ее еще нет, и -r, которая заменяет старые файлы с их новыми версиями.

$ ar -rc libholberton.a *.o

Приведенная выше команда ar, по сути, берет все созданные вами объектные файлы и архивирует их в единую статическую библиотеку libholberton.a.

Индексирование вашей библиотеки

В зависимости от вашей компьютерной системы или вашего архиватора вам может понадобиться проиндексировать вашу библиотеку с помощью команды ranlib, которая создает заголовок в библиотеке с символами (функциями и именами переменных) объектных файлов внутри нее. .

$ ranlib libholberton.a

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

Некоторые системы или архиваторы (например, компилятор Sun C) создают архив, который уже проиндексирован, а это означает, что вам не нужно запускать ranlib для самостоятельного индексирования.

Повторный запуск ls -l после этой команды должен показать сгенерированную статическую библиотеку:

Список файлов в библиотеке

Чтобы дважды проверить файлы в вашей библиотеке или просто просмотреть файлы в любой библиотеке, вы можете использовать команду ar с флагом -t.

$ ar -t libholberton.a

Это должно перечислить объектные файлы, которые он заархивировал. Для нашей библиотеки libholberton.a она включает следующее:

Вы также можете увидеть символы, проиндексированные в библиотеке, с помощью команды nm. В нем перечислены все символы, их значение, тип и имя символа из соответствующего объектного файла.

$ nm libholberton.a

Использование вашей библиотеки

Поздравляем! Вы создали свою статическую библиотеку, теперь вы хотите использовать ее в своей программе. Мы можем сделать это, указав его в терминале как часть процесса компиляции.

Когда мы запускаем gcc для компиляции нашей программы main.c, мы заменяем часть имени библиотеки lib на флаг -l, который сообщает вашему компилятору, что вы подключение библиотеки.

Мы также добавляем флаг -L, чтобы указать путь к библиотеке. В этом случае мы следуем за флагом -L с расширением . для обозначения нашего текущего рабочего каталога, в котором находится библиотека. Если ваша библиотека находится в другом месте, вы просто добавляете путь к флагу -L. Например, если ваша библиотека находится в каталоге /usr/lib, вместо этого вы добавляете -L/usr/lib.

$ gcc main.c -L. -lholberton.a -o main

Это должно сгенерировать ваш исполняемый файл, который мы назвали main. Теперь вы можете запустить его так:

$ ./main

Другие примечания о статических библиотеках

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

Однако у использования статических библиотек есть недостатки. Во-первых, баги:

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

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

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

А пока получайте удовольствие, создавая, делясь, используя и обновляя свои статические библиотеки!