Gcc как подключить библиотеку

Gcc как подключить библиотеку

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

Рассмотрим преимущества и недостатки статических и совместно используемых библиотек. Статические библиотеки делают программу более автономной: программа, скомпонованная со статической библиотекой может запускаться на любом компьютере, не требуя наличия этой библиотеки (она уже «внутри» бинарника). Программа, скомпонованная с динамической библиотекой, требует наличия этой библиотеки на том компьютере, где она запускается, поскольку в бинарнике не код, а ссылка на код библиотеки. Не смотря на такую зависимость, динамические библиотеки обладают двумя существенными преимуществами. Во-первых, бинарник, скомпонованный с совместно используемой библиотекой меньше размером, чем такой же бинарник, с подключенной к нему статической библиотекой (статически скомпонованный бинарник). Во-вторых, любая модернизация динамической библиотеки, отражается на всех программах, использующих ее. Таким образом, если некоторую библиотеку foo используют 10 программ, то исправление какой-нибудь ошибки в foo или любое другое улучшение библиотеки автоматически улучшает все программы, которые используют эту библиотеку. Именно поэтому динамические библиотеки называют совместно используемыми. Чтобы применить изменения, внесенные в статическую библиотеку, нужно пересобрать все 10 программ.

В Linux статические библиотеки обычно имеют расширение .a (Archive), а совместно используемые библиотеки имеют расширение .so (Shared Object). Хранятся библиотеки, как правило, в каталогах /lib и /usr/lib. В случае иного расположения (относится только к совместно используемым библиотекам), приходится немного «подшаманить», чтобы программа запустилась.

3.2. Пример статической библиотеки

Теперь давайте создадим свою собственную библиотеку, располагающую двумя функциями: h_world() и g_world(), которые выводят на экран «Hello World» и «Goodbye World» соответственно. Начнем со статической библиотеки.

Начнем с интерфейса. Создадим файл world.h: Здесь просто объявлены функции, которые будут использоваться.

Теперь надо реализовать серверы. Создадим файл h_world.c: Теперь создадим файл g_world.c, содержащий реализацию функции g_world(): Можно было бы с таким же успехом уместить обе функции в одном файле (hello.c, например), однако для наглядности мы разнесли код на два файла.

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

Теперь напишем сценарий для make. Для этого создаем Makefile: Не забывайте ставить табуляции перед каждым правилом в целевых связках.

Осталось только проверить, работает ли программа и разобраться, что же мы такое сделали:

Итак, в приведенном примере появились три новые вещи: опции -l и -L компилятора, а также команда ar. Начнем с последней. Как вы уже догадались, команда ar создает статическую библиотеку (архив). В нашем случае два объектных файла объединяются в один файл libworld.a. В Linux практически все библиотеки имеют префикс lib.

3.3. Пример совместно используемой библиотеки

Для того, чтобы создать и использовать динамическую (совместно используемую) библиотеку, достаточно переделать в нашем проекте Makefile.

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

Источник

C/C++ Создание своих библиотек на gcc

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

READ  Как правильно подключить электронное зажигание на ваз 2106

Под катом я объясню как создать свою динамическую библиотеку, и как подключить ее к своим проектам. Так же будет немного информации о статических библиотеках.

Небольшое отступление

Программируя одним прекрасным морозным утром был не приятно удивлен тем, что мой gcc напрочь отказывается переваривать функцию swap(), тогда я не заострил на этом внимание, но постепенно я нуждался в swap все больше и больше. И вот мое терпение закончилось. А результаты вы увидите ниже.

От слов к делу

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

В рамках поста будет описан способ создания динамической библиотеки.

Для простоты будет приведен пример, который запрашивает ввод 2х чисел с клавиатуры, меняет их местами и выводит на экран. Операция обмена будет представлена в виде библиотеки.

От теории к практике

Программный код основной программы (main.c)

А теперь код библиотеки (swap.c)

void swap (int *x, int *y)
<
int temp;
temp=*x;
*x=*y;
*y=temp;
>

А теперь самое интересное (Makefile)

#Makefile fo user lib

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

В принципе программный код весьма прост и не требует пояснений, поэтому потратим время на понимание Makefile.

Вот и все, теперь с радостью и нетерпением пишем «make». В итоге мы должны получить следующие файлы: MAIN, main.c, main.o, swap.c, swap.o, libuser.so, Makefile

Теперь если в других проектах нам понадобиться обратиться к функции swap, нам достаточно будет следующей конфигурации Makefile

Заключение

Ссылки по теме

Помощь
Задать вопрос
программы
обучение
экзамены
компьютеры
ICQ-консультанты
Skype-консультанты
Общая справка
Как оформить заказ
Тарифы доставки
Способы оплаты
Прайс-лист
Карта сайта

О нас
Интернет-магазин ITShop.ru предлагает широкий спектр услуг информационных технологий и ПО.

На протяжении многих лет интернет-магазин предлагает товары и услуги, ориентированные на бизнес-пользователей и специалистов по информационным технологиям.

Хорошие отзывы постоянных клиентов и высокий уровень специалистов позволяет получить наивысший результат при совместной работе.

Источник

Gcc как подключить библиотеку

Библиотеки

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

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

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

Парадигма разделяемых библиотек предоставляет три существенных преимущества:

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

2. Код разделяемой библиотеки используемый несколькими приложениями храниться в оперативной памяти в одном экземпляре (на самом деле не всё так просто. ), в результате сокращается потребность системы в доступной оперативной памяти.

3. Отпадает необходимость пересобирать каждый исполняемый файл в случае внесения изменений в код общей для них библиотеки. Изменения и исправления кода динамической библиотеки автоматически отразятся на каждой из использующих её программ.

Без парадигмы разделяемых библиотек не существовало бы прекомпиллированных (бинарных) дистрибутивов Linux (да ни каких бы не существовало). Представьте размеры дистрибутива, в каждый бинарный файл которого, был бы помещен код стандартной библиотеки C (и всех других подключаемых библиотек). Так же представьте что пришлось бы делать для того, что бы обновить систему, после устранения критической уязвимости в одной из широко задействованных библиотек.

Теперь немного практики.

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

В начале создадим и используем статическую библиотеку.

Функции first() и second() составят содержимое нашей библиотеки libhello. Имя файла библиотеки, соответственно, будет libhello.a. Библиотеке сопоставим заголовочный файл hello.h.

Для создания индекса архива существует специальная утилита ranlib. Библиотеку libhello.a можно было сотворить и так:

$ ar cr libhello.a first.o second.o
$ ranlib libhello.a

Впрочем библиотека будет прекрасно работать и без индекса архива.

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

Ну теперь комментарии. Появились две новые опции gcc:

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

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

Существует альтернативный способ указания местоположения библиотек в системе. В зависимости от дистрибутива, переменная окружения LD_LIBRARY_PATH или LIBRARY_PATH может хранить список разделенных знаком двоеточия каталогов, в которых линковщик должен искать библиотеки. Как правило, по умолчанию эта переменная вообще не определена, но ни чего не мешает её создать:

Теперь создадим и используем библиотеку динамическую.

Набор исходных файлов остается без изменения. Вводим команды, смотрим что получилось, читаем комментарии:

Что получили в результате?

$ file libhello.so.2.4.0.5
libhello.so.2.4.0.5: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, not stripped

Файл libhello.so.2.4.0.5, это и есть наша разделяемая библиотека. Как её использовать поговорим чуть ниже.

Таким образом, на этапе компиляции линковщику необходимо предоставить файл библиотеки (или символическую ссылку на файл библиотеки) с именем libname.so, на этапе исполнения загрузчику потребуется файл (или символическая ссылка) с именем libname.so.x.y. При чем имя libname.so.x.y должно совпадать со строкой soname использованной библиотеки.

В бинарных дистрибутивах, как правило, файл библиотеки libhello.so.2.4.0.5 и ссылка на него libhello.so.2 будут помещены в пакет libhello, а необходимая только для компиляции ссылка libhello.so, вместе с заголовочным файлом библиотеки hello.h будет упакована в пакет libhello-devel (в devel пакете окажется и файл статической версии библиотеки libhello.a, статическая библиотека может быть использована, также только на этапе компиляции). При распаковке пакета все перечисленные файлы и ссылки (кроме hello.h) окажутся в одном каталоге.

В приведенном примере создания библиотеки мы неотступно следовали принципам раздельной компиляции. Разумеется скомпилировать библиотеку можно было бы и вот так, одним вызовом gcc:

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

Линковщик ругается. Вспоминаем, что было сказано выше о символических ссылках. Создаем libhello.so и повторяем попытку:

Теперь все довольны. Запускаем созданный бинарник:

Ошибка. Ругается загрузчик, не может найти библиотеку libhello.so.2. Убедимся, что в исполняемом файле действительно прописана ссылка на libhello.so.2:

Создаем соответствующую ссылку и повторно запускаем приложение:

Заработало. Теперь комментарии по новым опциям gcc.

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

Узнать какие разделяемые библиотеки необходимы приложению можно и с помощью утилиты ldd:

В выводе ldd для каждой требуемой библиотеки указывается её soname и полный путь к файлу библиотеки, определённый в соответствии с настройками системы.

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

В соответствии с соглашениями FHS (Filesystem Hierarchy Standard) в системе должны быть два (как минимум) каталога для хранения файлов библиотек:

Соответствующие библиотекам заголовочные файлы должны находиться в каталоге /usr/include.

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

В ряде дистрибутивов (в Ubuntu) загрузчик не настроен просматривать каталог /usr/local/lib, соответственно, если пользователь установит библиотеку из исходников, система её не увидит. Сиё авторами дистрибутива сделано специально, что бы приучить пользователя устанавливать программное обеспечение только через систему управления пакетами. Как поступить в данном случае будет рассказано ниже.

В действительности, для упрощения и ускорения процесса поиска файлов библиотек, загрузчик не просматривает при каждом обращении указанные выше каталоги, а пользуется базой данных, хранящейся в файле /etc/ld.so.cache (кэшем библиотек). Здесь собрана информация о том, где в системе находится соответствующий данному soname файл библиотеки. Загрузчик, получив список необходимых конкретному приложению библиотек (список soname библиотек, заданных в исполняемом файле программы), посредством /etc/ld.so.cache определяет путь к файлу каждой требуемой библиотеки и загружает её в память. Дополнительно, загрузчик может просмотреть каталоги перечисленные в системных переменных LD_LIBRARY_PATH, LIBRARY_PATH и в поле RPATH исполняемого файла (смотри выше).

Для управления и поддержания в актуальном состоянии кэша библиотек используется утилита ldconfig. Если запустить ldconfig без каких-либо опций, программа просмотрит каталоги заданные в командной строке, доверенные каталоги /lib и /usr/lib, каталоги перечисленные в файле /etc/ld.so.conf. Для каждого файла библиотеки, оказавшегося в указанных каталогах, будет считано soname, создана основанная на soname символическая ссылка, обновлена информация в /etc/ld.so.cache.

Убедимся в сказанном:

Ну и в конце поговорим о том как уживаются вместе статические и динамические версии библиотек. В чем собственно вопрос? Выше, когда обсуждались принятые имена и расположение файлов библиотек было сказано, что файлы статической и динамической версий библиотеки хранятся в одном и том же каталоге. Как же gcc узнает какой тип библиотеки мы хотим использовать? По умолчанию предпочтение отдается динамической библиотеки. Если линковщик находит файл динамической библиотеки, он не задумываясь цепляет его к исполняемому файлу программы:

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

Так как размер кода библиотеки libhello ничтожен,

Источник

Поделиться с друзьями
Как подключить и установить...
Adblock
detector