Как установить RPATH и RUNPATH с GCC/LD?
Я недавно столкнулся с этой проблемой после обновления системы: с помощью GCC -Wl,-rpath=
Опция работает иначе, чем раньше.
Я использовал его, чтобы установить пути поиска для некоторых общих библиотек, которые были встроены в подмодуль моего проекта. В то время я считал это лучше, чем настройка LD_LIBRARY_PATH
для всей системы (я не хотел устанавливать его каждый раз, когда включал компьютер). Все работало нормально, и эти два подхода казались эквивалентными.
Теперь кажется, что поведение -rpath
изменился Это все еще работает для напрямую зависимых библиотек, но не для тех, которые связывают другие библиотеки из того же каталога, установленного через -rpath=
, Экспорт LD_LIBRARY_PATH
все еще работает, как и раньше.
Я проверил вывод компиляции, используя readelf
и есть разница. Перед обновлением (Linux Mint 18.2 с GCC 5.4) динамический раздел имел следующую строку:
0x000000000000000f (RPATH) Library rpath: [submod/lib]
После обновления (Linux Mint 19 с GCC 7.3) строка изменилась на:
0x000000000000001d (RUNPATH) Library runpath: [submod/lib]
Используете RPATH, но не RUNPATH? Предполагается, что RPATH был заменен на RUNPATH (или что он, по крайней мере, обслуживает другие цели, так как имеет более низкий приоритет), но не дает ответа относительно того, почему это влияет на косвенные ссылки. Сами библиотеки не имеют ни RPATH, ни RUNPATH в readelf
выход.
Итак, мой вопрос заключается в следующем: почему компоновщик вдруг начал интерпретировать -rpath=
вариант по-другому, а есть ли способ заставить старое поведение? (Или сделайте что-то другое, что даст эквивалентный результат.)
Другой вопрос: можно ли сказать старой версии компоновщика, что нужно создать новый вывод (т.е. RUNPATH вместо RPATH)?
РЕДАКТИРОВАТЬ
Это не дубликат Как установить RunPath двоичного файла? - мой вопрос противоположен: я хочу поведение RPATH. Я понял это (благодаря подсказке в комментарии), и я отвечу на мои вопросы здесь.
1 ответ
Есть ли способ заставить старое поведение?
Да. Вы можете использовать эту опцию -Wl,--disable-new-dtags
сказать новому компоновщику использовать старое поведение, то есть RPATH.
Можно ли сказать старой версии компоновщика произвести новый вывод (т.е. RUNPATH вместо RPATH)?
Да. использование -Wl,--enable-new-dtags
сказать старому компоновщику использовать новое поведение, т.е. RUNPATH.
Я проверил исполняемый файл с readelf
и эти две опции, кажется, управляют тем, что будет написано в разделе ELF Dynamic. Я думаю, что проблема была вызвана изменением настроек по умолчанию для новой версии, хотя, что интересно, страница руководства для ld
предположил бы, что это все еще должно быть то же самое:
--enable-новые-dtags
--disable-новые-dtags
Этот компоновщик может создавать новые динамические теги в ELF. Но старые системы ELF могут не понимать их. Если вы укажете --enable-new-dtags, новые динамические теги будут созданы по мере необходимости, а старые динамические теги будут опущены. Если вы укажете --disable-new-dtags, новые динамические теги не будут созданы. По умолчанию новые динамические теги не создаются. Обратите внимание, что эти опции доступны только для систем ELF.
Проект GNU Binutils (содержащий компоновщик GNU (ld)) не является источником этого изменения поведения, но Debian (2016)1 и Gentoo (2013!)2.
Согласно фиксации gentoo от Майка Фрайзингера от января 2013 года:
"Новые опции dtags существуют уже более 14 лет, поэтому для целей Linux и GNU включите их по умолчанию".
Это изменение не очень хорошо воспринимается 3, 4, 5, поскольку RUNPATH и RPATH имеют "недокументированную разницу в поведении"... Как ни удивительно, эти изменения теперь применяются в стабильной версии Debian.
Проблема в том, что использование RUNPATH приводит к непредсказуемым проблемам... Но в основном просто работает. Из википедии:
В отличие от DT_RPATH, динамический компоновщик ld не ищет в расположениях DT_RUNPATH транзитивные зависимости.