Конечно, возможно создание исполняемого файла, использующего любую доступную версию разделяемой библиотеки.
Проблема заключалась в том, что вы связали свой исполняемый файл с soname (libsomething.so.1
и libsomething.so.2
) для конкретной версии. Вы должны были сделать это с неверсированной soname libsomething.so
.
Чтобы добиться этого, на машине для сборки вы должны скомпилировать и установить библиотеку с soname (ELF SONAME
), равным libsomething.so
(без версии), чтобы компоновщик мог выбрать это soname, пока создается исполняемый файл. *
В соответствии с HOWTO Shared Libraries , вы можете передать требуемую неверсированную soname при создании библиотеки:
gcc -shared -Wl,-soname,libsomething.so -o libsomething.so.X objectsomething.o
Затем, как только вы установите библиотеку и запустите ldconfig
, вы получите:
- символическая ссылка
/lib/libsomething.so
, указывающая на /lib/libsomething.so.1
на машине A;
- символическая ссылка
/lib/libsomething.so
, указывающая на /lib/libsomething.so.2
на машине B.
Загрузчик (прогон ldd
) будет выбирать неверсионные символические ссылки независимо от того, куда он указывает:
libsomething.so => /lib/libsomething.so (0xNNNNNNNN)
на машине A;
libsomething.so => /lib/libsomething.so (0xNNNNNNNN)
на машине B.
Динамический загрузчик Linux (ld.so
) разрешает библиотеки на основе значения их сына, записанного в исполняемом файле (ELF NEEDED
). Значение копируется из файла библиотеки (ELF SONAME
) при сборке исполняемого файла. Пока в целевой системе есть символическая ссылка, совпадающая с именем, записанным в исполняемом файле, библиотека, указанная этой символической ссылкой, будет загружена.
Давайте пройдемся по вашей настройке и покажем команды для проверки предположений.
Я использовал Fedora 18 X86_64
для теста и настроил вывод на i686
для ясности.
Скомпилируйте libsomething.so.1
и libsomething.so.2
. Убедитесь, что SONAME
установлен в неверсированный libsomething.so
:
readelf -a libsomething.so.1 | grep SONAME
0xNNNNNNNN (SONAME) Library soname: [libsomething.so]
readelf -a libsomething.so.2 | grep SONAME
0xNNNNNNNN (SONAME) Library soname: [libsomething.so]
Установите библиотеки на соответствующие компьютеры в каталоге /lib/
. Запустите ldconfig -v
на обеих машинах и проверьте вывод.
ldconfig -v 2>&1 | grep something
libsomething.so -> libsomething.so.1 (changed)
ldconfig -v 2>&1 | grep something
libsomething.so -> libsomething.so.2 (changed)
Скомпилируйте исполняемый файл и убедитесь, что он ссылается на одно и то же имя без версии в NEEDED
.
readelf -a executable | grep NEEDED
0xNNNNNNNN (NEEDED) Shared library: [libsomething.so]
Ваш исполняемый файл зависит от неверсированного libsomething.so
сейчас. Скопируйте исполняемый файл на обе машины и запустите ldd
для обеих копий.
ldd executable
libsomething.so => /lib/libsomething.so (0xNNNNNNNN)
Последний вывод одинаков на обеих машинах, поскольку исполняемый файл был собран с soname без версии. Это заставляет загрузчик принимать неверсионные символические ссылки на целевые машины. И в зависимости от машины символическая ссылка может указывать на различную реализацию библиотеки libsomething.so.1
или libsomething.so.2
.