| Создание совместно используемых библиотек |
|
Процесс создания и подключения совместно используемых библиотек несколько сложнее, чем статических. Динамические библиотеки создаются при помощи gcc по следующему шаблону: $ gcc -shared -о LIBRARY_NAME FILE1.о FILE2.о ... В действительности gcc вызывает компоновщик Id с опциями для создания совместно используемой библиотеки. В принципе, этот процесс внешне ничем (кроме опции -shared) не отличается от компоновки обычного исполняемого файла. Но не все так просто. При создании динамических библиотек следует учитывать два нюанса:
В момент запуска программы для поиска библиотек просматриваются каталоги, перечисленные в файле /etc/ld.so.conf и в переменной окружения LD_LIBRARY_PATH. Переменная окружения ld_library_path имеет тот же формат, что и переменная path, т. е. содержит список каталогов, разделенных двоеточиями. Известно, что окружение нестабильно и может изменяться в ходе наследования от процесса к процессу. Поэтому использование ld_library_path — не самый разумный ход. В процессе компоновки программы можно отдельно указать каталог, где будет размещаться библиотека. Для этого линковщику Id необходимо передать опцию -rpath при помощи опции -wi компилятора gcc. Например, чтобы занести в исполняемый файл prog месторасположение библиотеки Hbfoo.so, нужно сделать следующее: $ gcc -о ргод ргод.о -L./lib/foo -lfoo -Wl,-rpath,/lib/foo Итак, опция -wi сообщает gcc о необходимости передать линковщику определенную опцию. Далее, после запятой, следует сама опция и ее аргументы, также разделенные запятыми. Такой подход выглядит лучше, чем применение ld_library_path, однако и здесь есть существенный недостаток. Нет никаких гарантий, что на компьютере у конечного пользователя библиотека Hbfoo.so будет также находиться в каталоге /lib/foo. Есть еще один способ заставить программу искать совместно используемую библиотеку в нужном месте. Во время инсталляции программы можно добавить запись с каталогом месторасположения библиотеки в файл /etc/ld.so.conf. Но это делают крайне редко, поскольку слишком длинный список каталогов в этом файле может отразиться на скорости загрузки системы. Обычно к такому подходу прибегают только такие "именитые" проекты, как Qt или X11. Многие Linux-системы при загрузке читают файл /etc/ld.so.conf и создают кэш динамических библиотек. Наилучший выход из сложившегося положения — размещать библиотеки в специально предназначенных для этого каталогах (/usr/lib или /usr/local/lib). Естественно, программист в ходе работы над проектом может для удобства пользоваться переменной ld_library_path или опциями -wl и -rpath, но в конечной программе лучше избегать этих приемов и просто располагать библиотеки в обозначенных выше каталогах. Теперь, уяснив все тонкости, переходим к делу. За основу возьмем пример из предыдущего раздела. Рассмотрим сначала концепцию использования переменной окружения ld_library_path. Чтобы переделать предыдущий пример для работы с динамической библиотекой, требуется лишь изменить Makefile. Модифицированный файл myenv: envmain.o libmyenv.so Обратите внимание, что файлы mysetenv.o и myprintenv.o, участвующие в создании библиотеки, компилируются с опцией -fPic для генерирования позиционно-независимого кода. Файл envmain.o не добавляется в библиотеку, поэтому он компилируется без опции -fpic. Если теперь попытаться запустить исполняемый файл myenv, то будет выдано сообщение об ошибке: $ ./myenv MYVAR Hello Проблема в том, что программа не нашла библиотеку в стандартном списке каталогов. После установки переменной ld_library_path проблема исчезнет: $ export LD_LIBRARY_PATH=. $ ./myenv MYVAR Hello Setting variable MYVAR MYVAR=Hello Если подняться в родительский каталог и попытаться оттуда запустить программу myenv, то опять будет обнаружена ошибка: $ cd . . Очевидно, что ошибка произошла из-за того, что в текущем каталоге не нашлась требуемая библиотека. Этот поучительный пример говорит о том, что в ld_library_path лучше заносить абсолютные имена каталогов, а не относительные. Попробуем еще раз: $ cd myenv Переменная окружения pwd содержит абсолютный путь к текущему каталогу, а запись $pwd подставляет это значение в команду. Попробуем теперь указать линковщику опцию -rpath. Для этого изменим в make-файле первую целевую связку: myenv: envmain.o libmyenv.so Помимо этого, для чистоты эксперимента удалим из окружения переменную ld_library_path: Теперь программа запускается из любого каталога без манипуляций с окружением.
Related Articles
Set as favorite
Bookmark
Email This
Hits: 348 Комментарии (0)RSS feed CommentsНаписать комментарий |