Вопрос или проблема
Ссылка:
Weak symbol
В ссылке упоминается следующий параметр компоновщика:
cc main.o -L`pwd` -Wl,-R`pwd` -lpowerslow -o main2
Назначение всех указанных выше флагов задокументировано в Руководстве по GCC, за исключением -R
.
Что этот флаг указывает компоновщику?
TIA
Vinod
Для GCC это всего лишь одна опция, а не две:
-Wl,-R`pwd`
Конструкция -Wl,<что-то>
используется для передачи части <что-то>
в виде опции(й) компоновщику (ld
). В данном случае, она указывает gcc
вызвать ld
как:
ld -R`pwd` <другие параметры...>
И если вы взгляните на man ld
в Linux, вы найдете (выделено мной):
-R файл
[…]
Читать имена символов и их адреса из файла, но не перемещать его и не включать в выходной файл. Это позволяет вашему выходному файлу ссылаться символически на абсолютные адреса памяти, определенные в других программах. Вы можете использовать эту опцию более одного раза.
Для совместимости с другими ELF компоновщиками, если опция
-R
сопровождается именем каталога, а не именем файла, она трактуется как опция-rpath
.
И опция -rpath
:
-rpath=dir
Добавить каталог в путь поиска библиотек времени выполнения. Это используется при компоновке ELF исполняемого файла с общими объектами. Все аргументы
-rpath
конкатенируются и передаются линкеру времени выполнения, который использует их для поиска общих объектов при выполнении. […]
Таким образом, вся конструкция означает “укажите линкеру времени выполнения искать общие объекты для компоновки в текущем рабочем каталоге”.
Документация ld
также отмечает:
Опция
-rpath
может также использоваться на SunOS. По умолчанию, на SunOS, компоновщик формирует путь поиска времени выполнения из всех предоставленных ему опций-L
. Если используется опция-rpath
, путь поиска времени выполнения будет формироваться исключительно с использованием опций-rpath
, игнорируя опции-L
. Это может быть полезно при использовании gcc, который добавляет много опций-L
, которые могут находиться на файловых системах, смонтированных через NFS.
Так, общая цель этой конструкционной опции, например в
cc -g -c -o main.o main.c
cc -g -fpic -c -o power_slow.po power_slow.c
cc -shared -fpic -o libpowerslow.so power_slow.po
cc main.o -L`pwd` -Wl,-R`pwd` -lpowerslow -o main
заключается в том, чтобы гарантировать, что результирующий бинарный файл main
будет искать libpowerslow.so
только в текущем рабочем каталоге, так чтобы он выбирал точную версию, скомпилированную третьей командой, а не любую другую версию libpowerslow.so
, которая может существовать в другом месте системы.
Вы должны понимать, что, хотя “встраивание” текущего рабочего каталога полезно в примерах краткосрочных бинарных файлов, таких как построенный здесь, вы должны указать что-то другое в качестве пути поиска библиотеки времени выполнения при построении чего-то, предназначенного для установки для системного использования.
Из страницы руководства ld
-R файл
--just-symbols=файл
.....
Для совместимости с другими ELF компоновщиками, если опция -R сопровождается именем каталога, а не именем файла, она трактуется как опция -rpath.
Это означает, что исполняемый файл добавит текущий каталог в список мест, в которых линкер времени выполнения будет искать общие библиотеки, что поможет ему обнаружить библиотеку powerslow
.
Было бы менее запутанно использовать -rpath
вместо -R
.
Ответ или решение
Флаг -R
в контексте использования с компилятором GCC и линковщиком ld
заслуживает внимания, поскольку его назначение и поведение у различных систем могут различаться, а также оно оказывается важным для корректной работы собранных исполняемых файлов. В данном контексте -R
на самом деле представляет собой алиас для -rpath
, когда он используется с директориями. Чтобы полностью понять, как работает этот флаг, необходимо рассмотреть теорию, примеры и практическое применение.
Теория
Флаг -R
в контексте компоновки исполняемых файлов служит для указания дополнительных директорий поиска динамических библиотек в момент выполнения программы (runtime). Если -R
указан вместе с именем файла, линкер загрузит символы и их адреса из этого файла, но не будет использовать его для создания выходного файла. Однако, когда -R
следует за именем директории, он становится эквивалентен флагу -rpath
.
Флаг -rpath
добавляет указанную директорию в путь поиска библиотек на стадии исполнения программы. Это особенно важно в UNIX-подобных системах, таких как Linux или Solaris, где динамические библиотеки (.so файлы) часто находятся в различных местах файловой системы, и необходимо сообщить загрузчику библиотек (runtime linker), где искать необходимые зависимости.
Пример
Рассмотрим следующий пример компиляции и линковки, приведенный в вопросе:
cc -g -c -o main.o main.c
cc -g -fpic -c -o power_slow.po power_slow.c
cc -shared -fpic -o libpowerslow.so power_slow.po
cc main.o -L`pwd` -Wl,-R`pwd` -lpowerslow -o main
- Первый этап компилирует исходный файл
main.c
в объектный файлmain.o
. - Второй этап компилирует
power_slow.c
в позиционно-независимый объектный файлpower_slow.po
. - Третий этап создает из
power_slow.po
динамическую библиотекуlibpowerslow.so
. - Четвертый этап связывает двоичный файл
main
, используяmain.o
иlibpowerslow.so
.
Ключевой частью является -Wl,-R\
pwd`, где
-Wl,указывает GCC передать флаг
-Rнапрямую линковщику, а
`pwd`подставляет текущую директорию. Таким образом, линковщик будет искать динамические библиотеки в текущей директории, гарантируя, что файл
mainвыполнится с версией
libpowerslow.so`, скомпилированной в третьем шаге.
Применение
Использование флага -R
важно при разработке программных продуктов, которые зависят от собственных динамических библиотек, находящихся не в стандартных путях поиска. Это помогает избежать конфликтов с системными библиотеками, которые могут иметь то же имя.
Тем не менее, на стадии деплоя следует осторожно использовать -rpath
, так как он добавляет дополнительные абсолютные пути в исполняемый файл, которые могут изменить поведение программы при перемещении внутри файловой системы или если системы различаются в структурах директорий. В частности, хранение таких путей может привести к потенциальным проблемам безопасности и повышению зависимости от конкретной конфигурации системы.
Заключение
Флаг -R
, хоть и недостаточно документирован в документации GCC, является мощным инструментом в руках разработчика для управления путями поиска динамических библиотек на стадии исполнения. Однако, для долгосрочных и переносимых решений, таких как производство и распространение ПО, рекомендуется использовать более целенаправленный подход к управлению путями поиска динамических библиотек, например использование LD_LIBRARY_PATH
или конфигурационных файлов загрузчика. Это поможет создать более надежные и универсальные приложения.