Как указать предпочтения пути к библиотеке? - PullRequest
77 голосов
/ 28 апреля 2010

Я компилирую программу на c ++, используя g++ и ld.У меня есть библиотека .so, которую я хочу использовать при компоновке.Однако библиотека с таким же именем существует в /usr/local/lib, и ld выбирает эту библиотеку вместо той, которую я прямо указываю.Как я могу это исправить?

Для приведенных ниже примеров мой библиотечный файл - /my/dir/libfoo.so.0.То, что я пробовал, не работает:

  • моя команда g ++ g++ -g -Wall -o my_binary -L/my/dir -lfoo bar.cpp
  • добавление /my/dir в начало или конец моей $PATH en`
  • добавление /my/dir/libfoo.so.0 в качестве аргумента для g ++

Ответы [ 5 ]

80 голосов
/ 28 апреля 2010

Добавьте путь к новой библиотеке LD_LIBRARY_PATH (на Mac она имеет немного другое имя ...)

Ваше решение должно работать с использованием параметров -L/my/dir -lfoo, во время выполнения используйте LD_LIBRARY_PATH, чтобы указать местоположение вашей библиотеки.

Осторожнее с использованием LD_LIBRARY_PATH - коротко (по ссылке):

.. последствия ..:
Безопасность : Помните, что каталоги, указанные в LD_LIBRARY_PATH, ищутся до (!) Стандартных местоположений? В этом Кстати, отвратительный человек может заставить ваше приложение загрузить версию общая библиотека, содержащая вредоносный код! Это одна из причин, почему Исполняемые файлы setuid / setgid игнорируют эту переменную!
Производительность : загрузчик ссылок должен искать все указанные каталоги, пока не найдет каталог, в котором находится общая библиотека находится - для ВСЕХ разделяемых библиотек приложение связано с! Это означает, что много системных вызовов open (), которые потерпят неудачу с «ENOENT (нет такого файла или каталога)»! Если путь содержит много каталоги, количество неудачных звонков будет расти линейно, и Вы можете сказать это по времени запуска приложения. Если некоторые (или все) из каталогов находятся в среде NFS, при запуске время ваших приложений может действительно стать длинным - и это может замедлиться вся система!
Несоответствие : Это самая распространенная проблема. LD_LIBRARY_PATH заставляет приложение загружать разделяемую библиотеку, которая не была связана против, и это, скорее всего, не совместимо с оригиналом версия. Это может быть очень очевидным, то есть приложение сбой, или это может привести к неправильным результатам, если подобранная библиотека не вполне делает то, что сделала бы оригинальная версия. Особенно последний иногда трудно отладить.

OR

Используйте параметр rpath через gcc для компоновщика - будет использован путь поиска библиотеки времени выполнения вместо просмотра в стандартном каталоге (опция gcc):

-Wl,-rpath,$(DEFAULT_LIB_INSTALL_PATH)

Это хорошо для временного решения. Компоновщик сначала ищет библиотеки в LD_LIBRARY_PATH, а затем просматривает стандартные каталоги.

Если вы не хотите постоянно обновлять LD_LIBRARY_PATH, вы можете сделать это на лету в командной строке:

LD_LIBRARY_PATH=/some/custom/dir ./fooo

Вы можете проверить, что компоновщик библиотеки знает об использовании (пример):

/sbin/ldconfig -p | grep libpthread
        libpthread.so.0 (libc6, OS ABI: Linux 2.6.4) => /lib/libpthread.so.0

И вы можете проверить, какую библиотеку использует ваше приложение:

ldd foo
        linux-gate.so.1 =>  (0xffffe000)
        libpthread.so.0 => /lib/libpthread.so.0 (0xb7f9e000)
        libxml2.so.2 => /usr/lib/libxml2.so.2 (0xb7e6e000)
        librt.so.1 => /lib/librt.so.1 (0xb7e65000)
        libm.so.6 => /lib/libm.so.6 (0xb7d5b000)
        libc.so.6 => /lib/libc.so.6 (0xb7c2e000)
        /lib/ld-linux.so.2 (0xb7fc7000)
        libdl.so.2 => /lib/libdl.so.2 (0xb7c2a000)
        libz.so.1 => /lib/libz.so.1 (0xb7c18000)
20 голосов
/ 28 апреля 2010

Указание абсолютного пути к библиотеке должно работать нормально:

g++ /my/dir/libfoo.so.0  ...

Вы не забыли удалить -lfoo после добавления абсолютного пути?

17 голосов
/ 15 ноября 2016

Это старый вопрос, но, кажется, никто не упомянул об этом.

Вам повезло, что эта штука вообще связывала.

Вы должны были изменить

g++ -g -Wall -o my_binary -L/my/dir -lfoo bar.cpp

к этому:

g++ -g -Wall -o my_binary -L/my/dir bar.cpp -lfoo

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

Кроме того, -lfoo заставляет его искать файл с именем libfoo.a или libfoo.so при необходимости. Не libfoo.so.0. Так что или ln имя или переименуйте библиотеку как appopriate.

Цитировать справочную страницу gcc:

-l library
   ...
   It makes a difference where in the command you 
   write this option; the linker searches and processes 
   libraries and object files in the order they are 
   specified.  Thus, foo.o -lz bar.o searches library z 
   after file foo.o but before bar.o.  If bar.o refers 
   to functions in z, those functions may not be loaded.

Добавление файла непосредственно в командную строку g++ должно работать, если, конечно, вы положили его до bar.cpp, вызывая компоновщик игнорировать его за отсутствие каких-либо необходимых символов, потому что символы еще не были необходимы.

11 голосов
/ 28 апреля 2010

В качестве альтернативы вы можете использовать переменные окружения LIBRARY_PATH и CPLUS_INCLUDE_PATH, которые соответственно указывают, где искать библиотеки и где искать заголовки (CPATH также выполнит работу), не указывая - Варианты L и -I.

Edit: CPATH включает заголовок с -I и CPLUS_INCLUDE_PATH с -isystem.

0 голосов
/ 09 января 2016

Если кто-то используется для работы с DLL в Windows и хочет пропустить номера версий .so в linux / QT, добавление CONFIG += plugin приведет к удалению номеров версий. Использование абсолютного пути к .so, предоставление его компоновщику работает нормально, как отметил г-н Клатчко.

...