Вопрос или проблема
Я прочитал много руководств, которые говорят, что LD_LIBRARY_PATH
ищется в первую очередь, но одна из моих .so библиотек ссылается на libtdc++.so.6
в /usr/lib64
.
ldd mylib.so:
...
libstdc++.so.6 => /usr/lib64/libstdc++.so.6 (0x00007f82abd18000)
...
Я хочу, чтобы mylib.so
ссылалась на libstdc++.so.6
в другом месте, например, в /apps/gcc_4.8.0/lib/libstdc++.so.6
.
Поэтому я добавляю /apps/gcc_4.8.0/lib
в LD_LIBRARY_PATH
, который не содержит /usr/lib64
, но он по-прежнему не находит его там.
Если я добавлю:
setenv LD_PRELOAD /apps/gcc_4.8.0/lib/libstdc++.so.6
в свою среду, нет больше ошибок компоновщика. Ура, но это не решает проблему. Пользователи ниже по течению не захотят зависеть от того, что эта библиотека находится в нужном месте. ПОЧЕМУ LD_LIBRARY_PATH
НЕ ИСКАЕТСЯ В ПЕРВУЮ ОЧЕРЕДЬ!?!
Это должно работать с переключателем компилятора Wl,--rpath=/apps/gcc_4.8.0/lib/libstdc++.so.6
.
Обновление: Если вам также нужен новый загрузчик, используйте этот переключатель компилятора: -Wl,--dynamic-linker=<path-to-the-new-dynamic-linker>
Ответ или решение
Как заставить компоновщик находить библиотеку stdc++ в нестандартном каталоге
Если вы столкнулись с проблемой, когда динамическая библиотека mylib.so
связывается с libstdc++.so.6
, находящейся в каталоге /usr/lib64
, а вы хотите, чтобы она использовала библиотеку из другого местоположения, например /apps/gcc_4.8.0/lib/libstdc++.so.6
, вам необходимо принять во внимание несколько ключевых аспектов настройки среды выполнения.
1. Проблема с LD_LIBRARY_PATH
Общепринятое мнение заключается в том, что переменная окружения LD_LIBRARY_PATH
имеет приоритет перед системными путями, включая /usr/lib64
. Однако, если до её установки уже была выполнена сборка или ваша библиотека ссылается на статически связанные библиотеки, это может привести к неожиданным результатам. То есть отсутствие libstdc++
в LD_LIBRARY_PATH
, с одной стороны, не всегда гарантирует, что будет выбрана библиотека из указанного пути.
2. Настройка LD_LIBRARY_PATH
Убедитесь, что вы правильно экспортировали переменную окружения. Это можно сделать следующим образом:
export LD_LIBRARY_PATH=/apps/gcc_4.8.0/lib:$LD_LIBRARY_PATH
Проверьте, что сетевые настройки среды, включая ваш текущий LD_LIBRARY_PATH
, действительно содержат нестандартный путь. Также обратите внимание на то, какие версии libstdc++
присутствуют в этих каталогах.
3. Использование LD_PRELOAD
Как вы отметили, использование LD_PRELOAD
позволяет явно указать библиотеку для связывания. Это временное решение, которое может не подходить для всех пользователей вашего приложения. Тем не менее, это может помочь проверить, что именно библиотека из корректного каталога имеет у вас корректные зависимости. Пример:
setenv LD_PRELOAD /apps/gcc_4.8.0/lib/libstdc++.so.6
Хотя это и не является идеальным долгосрочным решением, оно может помочь выявить другие проблемы на этапе тестирования.
4. Использование параметра -Wl,--rpath
Чтобы команды компоновщика знали, где искать нужные динамические библиотеки во время выполнения, используйте параметр -Wl,--rpath
в вашей команде компиляции. Это добавит путь к библиотекам непосредственно в заголовок вашей библиотеки:
g++ -o mylib.so mylib.o -Wl,--rpath=/apps/gcc_4.8.0/lib
Это означает, что при запуске вашей программы компоновщик будет искать libstdc++.so.6
в указанном вами каталоге перед тем, как проверять системные пути.
5. Указание нового динамического компоновщика
Если требуется использовать совершенно другой динамический компоновщик, добавьте флаг -Wl,--dynamic-linker=<path-to-the-new-dynamic-linker>
к командной строке компиляции, чтобы, таким образом, указать, какой компоновщик использовать:
g++ -o mylib.so mylib.o -Wl,--dynamic-linker=/path/to/new/ld.so
Заключение
Следуя этим рекомендациям, вы сможете решить проблему связывания вашей библиотеки с нужной версией libstdc++
. Используйте LD_LIBRARY_PATH
в сочетании с -Wl,--rpath
как надежное решение для управления путями к библиотекам, чтобы гарантировать максимальную совместимость без необходимости применения LD_PRELOAD
пользователями вашего приложения.