При запуске команды cc, показанной выше, мы использовали параметр — g для добавления отладочной информации в скомпилированную программу. В целом создание программ и библиотек, позволяющих выполнять отладку, является хорошей идеей (когда-то отладочную информацию иногда отключали, чтобы итоговый исполняемый файл задействовал меньше дискового пространства и оперативной памяти, но в современных реалиях эти ресурсы достаточно дешевые).
Кроме того, в некоторых архитектурах, таких как x86-32, не следует применять параметр — fomit-frame-pointer, поскольку он исключает возможность отладки (на таких платформах, как x86-64 данный параметр не мешает отлаживать программы, поэтому там он включен по умолчанию). По тем же причинам к исполняемым файлам и библиотекам не стоит применять утилиту strip(1), убирающую из них отладочную информацию.
Чтобы лучше понимать особенности и преимущества разделяемых библиотек, вначале кратко рассмотрим их статические аналоги.
Статические библиотеки (также известные как
• можно поместить набор часто используемых объектных файлов в единую библиотеку, которую потом можно будет применять для сборки разных программ; при этом не нужно будет перекомпилировать оригинальные исходные тексты при компоновке каждой программы;
• упрощаются команды для компоновки. Вместо перечисления длинного списка объектных файлов можно указать всего лишь имя статической библиотеки. Компоновщик знает, как выполнять поиск по ней и извлекать объекты, необходимые для создания исполняемого файла.
Статическая библиотека, по сути, является обычным файлом, содержащим копии всех помещенных в него объектных файлов. В архиве также хранятся различные атрибуты для каждого объектного файла, включая права доступа, числовые идентификаторы пользователя и группы и время последнего изменения. Статическим библиотекам принято давать имена вида libname.a.
Для создания и редактирования статических библиотек используется команда ar(1), которая имеет следующую общую форму:
$ ar options archive object-file…
Аргумент options состоит из набора букв, одна из которых является
• r (от англ. replace — «заменить»). Вставляет объектный файл в архив, заменяя им любой существующий файл с тем же именем. Это стандартный способ создания и обновления архивов. Таким образом, архив можно собрать с помощью следующих команд:
$ cc — g — c mod1.c mod2.c mod3.c
$ ar r libdemo.a mod1.o mod2.o mod3.o
$ rm mod1.o mod2.o mod3.o
Как видите, после создания библиотеки можно удалить оригинальные объектные файлы, поскольку они больше не нужны.
• t (от англ. table of contents — оглавление). Выводит оглавление архива. По умолчанию выводятся только имена объектных файлов. Но если дополнительно указать параметр v (от англ. verbose — «подробно»), можно просмотреть все атрибуты каждого файла в архиве, как показано ниже:
$ ar tv libdemo.a
rw-r-r- 1000/100 1001016 Nov 15 12:26 2009 mod1.o
rw-r-r- 1000/100 406668 Nov 15 12:21 2009 mod2.o
rw-r-r- 1000/100 46672 Nov 15 12:21 2009 mod3.o
Дополнительные атрибуты каждого объекта слева направо: права доступа на момент добавления в архив, пользовательский и групповой идентификаторы, размер, а также дата и время последнего изменения.
• d (от англ. delete — «удалить»). Удаляет из архива заданный модуль, как показано в следующем примере:
$ ar d libdemo.a mod3.o
Скомпоновать программу со статической библиотекой можно двумя способами. Первый из них таков: название файла библиотеки можно указать на этапе компоновки, как показано ниже:
$ cc — g — c prog.c
$ cc — g — o prog prog.o libdemo.a
Можно также поместить библиотеку в один из стандартных каталогов, по которым компоновщик выполняет поиск (например, /usr/lib), и затем указать ее имя (то есть имя файла без префикса lib и суффикса. a) с помощью параметра — l:
$ cc — g — o prog prog.o — ldemo
Если библиотека находится в каталоге, о котором компоновщику обычно ничего не известно, можно воспользоваться параметром — L, чтобы указать этот каталог отдельно:
$ cc — g — o prog prog.o — Lmylibdir — ldemo