Интернет-магазин
- Программное обеспечение
- Дистрибутивы
- 1С: Предприятие
- Офисное ПО
- СПО для Windows
- Игры для Linux
- Виртуализация VMware
- vCenter Converter
- VMware vSphere
- vSphere Hypervisor
- Сертифицированно ФСТЭК
- ССПТ-2
- SUSE
- Altel
- АПКШ «Континент»
- ПАК "Соболь"
- Аппаратное обеспечение
- Открытое аппаратное обеспечение
- Серверы
- Системы видеонаблюдения
- 3D Печать
- Литература и обучение
- Журналы, подписка
- Книги
- Учебные курсы
- Услуги
- Лицензии и купоны на тех.поддержку
- Консалтинг, сервис, техническая поддержка
- Реклама
- Атрибутика
- Новинки
- Распродажа
- Все товары сразу
Продукты Oracle
Где купить ?
Дистрибутивы
Помощь



Библиотеки, утилита libtool
Библиотеки, утилита libtool
Смысл использования библиотек в том, что один и тот же код может применяться в разных программах, и его не надо писать каждый раз заново. В случае динамических библиотек выгода ещё и в том, что можно этот код вообще не включать в исполняемые файлы. В случае вызова, он прочитается из файла библиотеки.
В нашем калькуляторе мы содержимое исходника calculate.c целиком включали в исполняемый файл. Следовательно, если мы захотим те же функции использовать в другой программе, мы должны писать их заново. Можно, конечно, воспользоваться широко известными командами Выделить-Копировать-Вставить. Но, всё равно, это – лишние телодвижения, лишнее увеличение в размерах исполняемого файла вследствие засорения его рутинными функциями. Да и самого исходника может не оказаться под рукой. А, может быть, я захочу внести в эти функции улучшение. Это значит, придётся переделывать все программы, в которых эти функции используются, чтобы во всех этих программах были новые версии функций. Нельзя ли, чтобы они находились где-нибудь в одном месте, и их можно было брать оттуда для всех программ, когда они понадобятся?
Как вы, наверное, догадываетесь, мы будем делать из исходника calculate.c библиотеку, которую потом будем подключать к исполняемой программе, полученной из одного main.c.
Итак, берёмся за очередную переделку нашего калькулятора.
Простейший способ создать библиотеку из файла calculate.c следующий:
gcc -c calculate.c
ar cru libcalculate.a calculate.o
ranlib libcalculate.a
Здесь gcc с флагом -c получает известный уже нам объектный файл, команда ar создаёт архив, в виде которых библиотеки и существуют. А команда ranlib генерирует индекс функций, содержащихся в библиотеке, и сохраняет этот индекс в её же файле. Эту процедуру всегда рекомендуется проделывать, поскольку индекс ускоряет процедуру связывания библиотеки с программой.
В дальнейшем этот файл можно вручную поместить в стандартный каталог библиотек (это /usr/lib и /usr/local/lib) и можно связывать её с помощью флага -lcalculate (обратите внимание, что название библиотек должно начинаться с префикса lib-).
Но понятно, что это нерациональный способ в отношении производительности труда. Давайте рассмотрим более практичные варианты. Для этого мы познакомимся с ещё одним компонентом набора инструментов GNU – libtool. Его предназначение – автоматизировать рутинные операции по работе с библиотеками и обеспечивать разработчику удобство при их написании и тестировании.
Создайте новый каталог проекта libtooldemo. Перенесите в него файлы calculate.c и main.c из C-версии калькулятора. Только обязательно удалите из каждого из них три строчки, требующие подключения заголовочного файла config.h. Пока мы пользоваться этим заголовочным файлом не будем.
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
Вышеуказанные строки должны быть удалены!
А что же файл calculate.h?
О нём особый разговор. Наша библиотека будет компилироваться компилятором C. Но вызываться она может и из программы,написанной на С++. А компилятор C++ имеет такую особенность – он изменяет названия функций при компиляции. Следовательно, название функции в вызывающей программе будет не совпадать с названием функции в библиотеке.
Чтобы избежать такой ситуации, надо в заголовочном файле, включаемом в код исполняемой программы явно указать, что библиотечная функция написана на C. Таким образом, наш новый заголовочный файл calculate.h будет выглядеть так:
///////////////////////////////////////
// calculate.h
#ifndef CALCULATE_H_
#define CALCULATE_H_
#ifdef __cplusplus
extern "C" {
#endif /*__cplusplus*/
float Calculate(float Numeral, char Operation[4]);
#ifdef __cplusplus
}
#endif /*__cplusplus*/
#endif /*CALCULATE_H_*/
Давайте создадим подключаемую библиотеку из исходника calculate.c. Для этого вначале создадим объектный файл.
libtool gcc -c calculate.c
Посмотрите, что появилось в каталоге проекта. Это, во-первых, уже знакомый нам объектный файл calculcate.o. Во-вторых, это скрипт calculate.lo, сгенерированный утилитой libtool. Он будет указывать, как собрать библиотеку из объектных файлов. Больше ничего не видите? Тогда наберите:
cd .libs
И вы обнаружите, что перешли во вложенный каталог .libs, который не виден в файловом менеджере, потому что по умолчанию в нём не видны все файлы и папки, названия которых начинаются с точки. В этом вложенном каталоге находится другая версия объектного файла calculate.o. Разница между ними в том, то один имеет позиционно-независимый код, а другой – позиционно-зависимый. Но позвольте пока не вдаваться в подробности об этом. Утилита libtool сама решит за нас, какой вариант лучше взять для формирования библиотеки при данной конфигурации системы.
Наконец сформируем саму библиотеку.
libtool gcc -rpath /usr/local/lib -o libcalculate.la calculate.lo
В проекте появился файл libcalculate.la. Это скрипт, который понадобится программе libtool. Сама же библиотека находится во вложенном каталоге .libs. Если вы туда зайдёте, вы обнаружите файл с расширением статической библиотеки libcalculate.a и файлы с расширением динамической библиотеки libcalculate.so (мы уже в своё время упоминали что эти типы библиотек имеют именно такие расширения файлов).
Содержимое файла libcalculate.a связывается с программой при компоновке, но библиотечных функций этот файл не содержит. Она содержит лишь ссылку на другой файл – libcalculate.so, который содержит библиотечные функции и связывается с программой динамически, то есть, по требованию в процессе выполнения программы.
Опция -rpath с указанием пути к стандартному каталогу библиотек указывает компоновщику, что необходимо создать библиотеку с динамическим связыванием, то есть предусмотреть оба – и a-файл и so-файл, и что они при инсталляции будут помещаться именно в тот каталог, который указан после -rpath. Путь к этому каталогу будет сохранён в a-файле, и именно по этому пути будет осуществляться поиск динамической библиотеки.
Можно указать компоновщику, что нужно создать статическую библиотеку. Для этого следует воспользоваться опцией -static.
libtool gcc -static -o libcalculate.la calculate.lo
Как вы видите, опции -rpath здесь нет. Она и не нужна, так как все библиотечные функции будут включены в исполняемый файл и нет необходимости что-либо откуда-либо вызывать динамически.
В каталоге .libs вы so-файла уже не найдёте, так как всё его содержимое включено в статически подключаемый a-файл.
Давайте теперь создадим исполняемый файл, который будет связан с этой библиотекой.
libtool gcc -o kalkul main.c libcalculate.la -lm
Можно при желании сделать так, чтобы математические функции входили в нашу библиотеку. Для этого перекомпонуем её, с указанием обязательного включения libm.
libtool gcc -rpath /usr/local/lib -o libcalculate.la calculate.lo -lm
Тогда к исполняемой программе можно уже не подключать libm.
libtool gcc -o kalkul main.c libcalculate.la
Поскольку мы исполняемый файл kalkul формировали с помощью libtool, он также помещается в каталог .libs, а в каталоге проекта формируется скрипт с таким же названием kalkul. Но это не должно вас беспокоить. Эти скрипты создаются в целях обеспечения главного удобства libtool. Главное удобство в том, что она позволяет одновременно в одном каталоге работать и с исполняемыми программами и с необходимыми им библиотеками. Попробуйте запустить исполняемую программу. Программа без проблем найдёт и откроет библиотеку, хотя эта библиотека расположена не в системном каталоге. Это позволяет избежать лишнего обращения к системному каталогу на этапе разработки.
Она также даёт возможность одномоментно установить все файлы библиотеки в системный каталог. Давайте установим библиотеку libcalculate в каталог /usr/local/lib (предварительно зайдя от имени суперпользователя).
su
libtool cp libcalculate.la /usr/local/lib
exit
Если при этой команде выдаются ошибки, просто повторите с начала всю процедуру компиляции и сборки библиотеки. Возможно, при каких-то манипуляциях вы потеряли некоторые вспомогательные файлы.
Обратите внимание, что установка должна осуществляться именно в тот каталог, который был указан в опции -rpath. В этот каталог будет скопирован не сам скрипт libcalculate.la, а статическая и динамическая библиотеки libcalculate.a и libcalculate.so.
Теперь также с помощью libtool сделаем по-новому исполняемый файл.
libtool gcc -o kalkul main.c -lcalculate
Скопируем его в системный каталог.
su
libtool cp kalkul /usr/local/bin
exit
Запустим его.
kalkul
И вот здесь скорее всего многих из вас ждёт неприятный сюрприз – программа первый раз не запустится. Она выдаст сообщение:
error while loading shared libraries: libcalculate.so.0: cannot open shared object file: No such file or directory
То есть, линкер знает путь /usr/local/lib, а загрузчик динамических библиотек его не знает. Это свойство большинства современных дистрибутивов. Путь к загружаемым библиотекам придётся добавлять в систему вручную. Это ужасно неудобно. Человек, впервые столкнувшийся с этой проблемой, будет долго думать, в чём дело. Сделано так, вероятно, в целях безопасности, чтобы «левая» библиотека, случайно установленная невнимательным пользователем, не вступила в конфликт с системными библиотеками. Разумеется, вы должны очень подробно описать эту ситуацию для пользователя в файле README.
Добавим вручную нужный нам путь. Для этого надо задать системной переменной LD_LIBRARY_PATH значение /usr/local/lib (по умолчанию эта переменная в большинстве версий Linux вообще отсутствует).
export LD_LIBRARY_PATH=/usr/local/lib:$LD_LIBRARY_PATH
Снова запускаем kalkul. Наконец-то он заработал!
Замести следы своих экспериментов можно следующим образом:
su
libtool rm /usr/local/lib/libcalculate.la
libtool rm /usr/local/bin/kalkul
exit
Оглавление | Назад | Вперед
[ опубликовано 06/09/2006 ]
Дмитрий Пантелеичев (dimanix2006 at rambler dot ru) - Библиотеки, утилита libtool Версия для печатиБиблиотека Линуксцентра. Список разделов
- Презентации
- Книги и руководства
- Linux для пользователя
- Разработка программного обеспечения для Linux. Инструментарий
- Программирование на Shell (Unix)
- Учебник FTP
- Энциклопедия VMWare
- Slackware Linux Essentials
- Slackware ЧаВО
- Разработка графического интерфейса с помощью библиотеки Qt3
- Разделы диска и средства для работы с ними в Линукс
- Введение в POSIX'ивизм
- Статьи
- Пресс-релизы ЛинуксЦентра
- История Linux
- Linux'оиды шутят
Топ-10 интернет магазина Линуксцентра
- Лицензия на право установки и использования операционной системы специального назначения "Astra Linux Special Edition" РУСБ.10015-07 (формат BOX), сертифицированной ФСБ
- Linux Format #2 Электронная версия журнала, февраль 2018
- Linux Format #1 Электронная версия журнала, январь 2018
- LibreOffice 5.3 (1DVD) (Поставляется с лицензионным договором присоединения)
- Журнал Linux Format #12 + DVD, декабрь 2017
- Linux Format #12 Электронная версия журнала, декабрь 2017
- Журнал Linux Format #11 + DVD, ноябрь 2017
- Журнал Linux Format #10 + DVD, октябрь 2017
- Журнал Linux Format #9 + DVD, сентябрь 2017
- Linux Format #11 Электронная версия журнала, ноябрь 2017
© 2000-2018 ГНУ/Линуксцентр © Группа компаний
info@linuxcenter.ru - По вопросам заказов, оплаты, доставки, общим вопросам
zabota@linuxcenter.ru - По проблемам работы интернет-магазина, функционирования сайта
partner@linuxcenter.ru - По вопросам сотрудничества, партнерства, оптовых закупок
Перепечатка, цитирование и переработка материалов Linuxcenter.Ru разрешается в любой форме, при этом обязательна ссылка на www.linuxcenter.ru
Свидетельство о регистрации СМИ ЭЛ № ФС 77 - 37801 выдано Федеральной службой по надзору в сфере связи,
информационных технологий и массовых коммуникаций
15.10.2009
12+
Страница загружена за 0.10 сек.