Подтвердить что ты не робот

Что такое опция "soname" для создания разделяемых библиотек?

Я узнал " " Библиотека программ HOWTO". Он упоминает, что с помощью soname для управления версией, например, следуйте.

gcc -shared -fPIC -Wl,-soname,libfoo.so.1  -o libfoo.so.1.0.0 foo.c
ln -s libfoo.so.1.0.0  libfoo.so.1
ln -s libfoo.so.1 libfoo.so

И я получаю информацию, что если soname не установлен. он будет равен libfoo.so.1.0.0, см. ответ здесь.

И я считаю, что он также может работать без soname, например, следуя

 gcc -shared -fPIC -o libfoo.so.1.0.0 foo.c
 ln -s libfoo.so.1.0.0  libfoo.so.1
 ln -s libfoo.so.1 libfoo.so

Поэтому я считаю, что единственная полезная точка в том, что параметр soname может сообщить вам версию разделяемой библиотеки, когда вы используете команду readelf -d libfoo.so для ее проверки.

Что еще он может сделать?

4b9b3361

Ответ 1

soname используется, чтобы указать, какая бинарная api совместимость с вашей библиотекой.

SONAME используется во время компиляции компоновщиком, чтобы определить из файла библиотеки, какую фактическую версию целевой библиотеки. gcc -l NAME будет искать lib NAME.so ссылку или файл, а затем захватить его SONAME, что, безусловно, будет более конкретным (ex libnuke.so ссылки на libnuke.so.0.1.4, который содержит SONAME libnuke.so.0).

Во время выполнения он связывается с этим, затем устанавливается в динамический раздел ELF NEEDED, тогда существует библиотека с этим именем (или ссылкой на нее). Во время выполнения SONAME игнорируется, поэтому достаточно только ссылки или существования файла.

Примечание: SONAME применяется только при времени соединения/сборки, а не во время выполнения.

"SONAME" библиотеки можно увидеть с помощью "objdump -p file | grep SONAME". "НЕОБХОДИМЫЕ" двоичных файлов можно увидеть с помощью "objdump -p file | grep NEEDED".

[РЕДАКТИРОВАТЬ] ПРЕДУПРЕЖДЕНИЕ Ниже приведено общее замечание, а не то, что было развернуто в Linux. См. В конце.

Предположим, у вас есть библиотека с именем libnuke.so.1.2, и вы создаете новую библиотеку libnuke:

  • Если ваша новая библиотека является исправлением из предыдущего без изменения api, вы должны просто сохранить такое же имя, увеличить версию имени файла. т.е. файл будет libnuke.so.1.2.1, но soname все равно будет libnuke.so.1.2.
  • Если у вас есть новая библиотека, которая только добавила новую функцию, но не нарушила функциональность и по-прежнему совместима с предыдущей, вы хотели бы использовать тот же сонайт, что и предыдущий, плюс новый суффикс типа .1. т.е. файл и soname будут libnuke.so.1.2.1. Любая программа, связанная с libnuke.1.2, по-прежнему будет работать с этим. Новые программы, связанные с libnuke.1.2.1, будут работать только с этим (пока новая подрывная операция не станет похожей на libnuke.1.2.1.1).
  • Если ваша новая библиотека несовместима с любым libnuke: libnuke.so.2
  • если ваша новая библиотека совместима с голой старой версией: libnuke.so.1.3 [т.е. все еще совместима с libnuke.so.1]

[EDIT], чтобы завершить: дело linux.

В реальной жизни SONAME как конкретная форма: Lib [NAME] [API-версия].so. [главная-версия] основная версия - это только одно целочисленное значение, которое увеличивается при каждом изменении основной библиотеки. API-VERSION по умолчанию пуст.

ex libnuke.so.0

Тогда действительное имя файла включает второстепенные версии и субверсии ex: libnuke.so.0.1.5

Я думаю, что не предоставление сонама является плохой практикой, так как переименование файла изменит его поведение.

Ответ 2

Предположим, что libA.so зависит от libB.so, и все они в каталоге (конечно, каталог не может быть найден динамическим компоновщиком). Если вы не установили soname, тогда dlopen не работает:

auto pB = dlopen("./libB.so", RTLD_LAZY | RTLD_GLOBAL);
auto pA = dlopen("./libA.so", RTLD_LAZY | RTLD_GLOBAL);

Поскольку компоновщик времени выполнения не может найти libB.so, поэтому pA устанавливается на NULL.

В этом случае soname спасет вас от ада...

Ответ 3

Вот пример в поддержку ответа Иоганна Класека.

Короче говоря, SONAME необходим во время выполнения. Во время компиляции требуется только имя компоновщика или настоящее имя (например, g++ main.cpp -L. -Ladd или g++ main.cpp -L. -L:libadd.so.1.1), Определения имени и реального имени компоновщика приведены в разделе " Библиотека программ" HOWTO: 3. Общие библиотеки.

Исходное дерево:

├── add.cpp
├── add.h
├── main.cpp
└── Makefile

Makefile:

SOURCE_FILE=add.cpp
# main.cpp includes 'add.h', whose implementation is 'add.cpp'
MAIN_FILE=main.cpp
SONAME=libadd.so.1
REAL_NAME=libadd.so.1.1
LINKER_NAME=libadd.so
OUTPUT_FILE=a.out

all:
   g++ -shared -fPIC -Wl,-soname,${SONAME} -o ${REAL_NAME} ${SOURCE_FILE}
   ln -s ${REAL_NAME} ${LINKER_NAME}
   g++ main.cpp -I. -L. -ladd -o ${OUTPUT_FILE} 
   # Same as 'ldconfig -n .', creates a symbolic link
   ln -s ${REAL_NAME} ${SONAME}
   #./a.out: error while loading shared libraries: libadd.so.1: cannot open 
   # shared object file: No such file or directory
   LD_LIBRARY_PATH=. ./${OUTPUT_FILE}
clean:
   rm ${SONAME} ${REAL_NAME} ${LINKER_NAME} ${OUTPUT_FILE}

Ответ 4

Вы создали динамическую библиотеку с именем libx.1.0.0 в традиции именования libname. {A}. {B}. {C}

{a} stand for primary version, should changes when APIs changes(which making things incompatible).
{b} stand for sub version, should changes by adding APIs.
{c} stand for mirror version, should changes by bug fixing or optimizing

Теперь вы выпускаете libx.1.2.0, и вам нужно объявить, что libx.1.2.0 совместима с libx.1.0.0, так как простое добавление функций и исполняемых файлов не приведет к сбою, просто свяжите это, как в старое время:

Установка для libx.1.0.0 и libx.1.2.0 одинакового имени, например libx.1

Это то, что делает soname.

Ответ 5

Другой аспект: По крайней мере, в Linux запись SONAME дает подсказку для системы runtime-linker о том, как создавать соответствующие ссылки в /lib,/lib64 и т.д. Запуск команды ldconfig пытается создать символическую ссылку с именем SONAME, которая также будет взята в кеш компоновщика времени выполнения. Самая новая одна из библиотек, помечающая ту же самую SONAME, выигрывает ранг. Если какое-то программное обеспечение зависит от конкретного SONAME, и вы хотите обновить библиотеку, вы должны предоставить этому SONAME, чтобы получить ldconfig в этой новой библиотеке (если ldconfig используется для перестройки кеша и ссылок). Например. libssl.so.6 и libcrypto.so.6 являются такими случаями.