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

Под капотом: что такое статические библиотеки?

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

Зачем использовать статические библиотеки?

Мы могли бы связать отдельные объектные файлы, даже объектные файлы из нескольких папок, в одну программу. Но, как мы уже говорили, полная программа содержит несколько — а часто и много — исходных файлов: столько же файлов нужно искать, открывать и закрывать: это медленно!

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

Как создать статическую библиотеку C

Во-первых, нам нужно преобразовать исходные файлы C в их версию объектного кода. Мы будем использовать некоторые упражнения Холбертона, в которых мы воссоздали некоторые стандартные библиотечные функции:

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

|gcc -c *.c

Теперь мы можем добавить их все в архив с помощью программы ar GNU. Имена архивов обычно имеют вид lib‹name›.a, поэтому давайте создадим библиотеку с именем my.

|ar rc libmy.a *.o
  • Флаг r указывает ar вставить файлы в архив libmy.a, заменив старые объектные файлы новыми, если это применимо.
  • c приказывает создать его.
  • Мы указываем все объектные файлы текущего каталога благодаря подстановке.

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

|ranlib libmy.a

для создания индекса для архива.

Теперь у нас есть статическая библиотека!

Осталось только сказать gcc искать библиотеки по определенному пути и связать их с нашей основной программой.

|gcc main.c -L. -lmy -o main
  • -Lкакой путь искать в дополнение к пути по умолчанию
  • -l какой архив связать с нашей программой main.c. Gcc добавит префикс lib и суффикс .a
  • -o затем заменит имя исполняемого файла по умолчанию a.out на main.

И молниеносно, вот и все! Теперь у вас есть исполняемая программа, связанная со статической библиотекой, которую можно выполнять без каких-либо зависимостей. Просто помните, что если вы или ваши коллеги обновите свою библиотеку, вам придется перекомпилировать саму библиотеку и снова скомпилировать вашу программу. Это главный недостаток использования статической библиотеки, а не динамической.