Обогативные разные версии статической библиотеки в динамических библиотеках

StackOverflow https://stackoverflow.com/questions/2801666

  •  25-09-2019
  •  | 
  •  

Вопрос

В моем проекте есть зависимость от статической библиотеки (только что называется libsomething Отныне) от 3-го вечеринки. Совсем недавно, libsomething стал доступен в другой версии. Моя задача - обеспечить мое программное обеспечение поддержкой старой и новой версии. Только одна версия libsomething Используется во время выполнения в любой момент времени, но какая версия должна быть настраиваемой между прогонами программы.

Я использую MSVC2005 на WinXP, вторичная цель состоит в том, чтобы стать готовым переключиться на Linux и GCC.

Так как обе версии libsomething Используете те же символы, связывая их как в моем исполняемому исполнению, выходит из вопроса, поскольку символы обеих версий собираются столкнуться по всему круглосуточному времени.

Хотя я мог бы создать два исполняемых файла (одна ссылка против старой версии, другой, используя новую версию), я не могу реализовать решение, на котором исполняемовается, чтобы позвонить в окончательной среде развертывания (устаревшие причины).

Я пришел с идеей создания динамической обертки библиотеки для каждой версии libsomething и связывая их во время выполнения в зависимости от некоторого файла конфигурации. С MSCV, это значит идти по дороге с использованием LoadLibrary(), GetProcAddress(), и т. Д., В то время как на Linux мне придется использовать dlopen() а также dlsym().

Я понимаю, что используя libtool (т.е. libtldl) обещает эту платформу-зависимость для использования общих библиотек. Это соответствующий путь к следующему? Есть ли лучше (или, по крайней мере, разные) способы? Делать альтернативы libtldl существуют как открытый источник?

Это было полезно?

Решение

Это было несколько лет, но я хотел бы упомянуть еще одно решение для полноты. Вместо руководства dlopen а также dlsym Вы можете генерировать простые заглушки для всех необходимых функций и на первом вызове (или при запуске программы) решить, какая версия библиотеки требуется, загрузите ее и разрешите адреса.

Вы можете написать сценарий, специально разработанный для вашего проекта или использования Implib.so.so инструмент:

# This will generate mylib.so.init.c and mylib.so.tramp.S
# which implement stubs. These need to be linked to your
# executable.
$ implib-gen.py mylib.so

Imbrib.so - это Linux - только банкомат, но должен легко адаптироваться к Windows.

Другие советы

Я знаю, что вы сказали, что не можете использовать два исполняемых файла из-за решения о том, что для выполнения, но вы не могли exec Взад и вперед между исполняемыми файлами в зависимости от того, какая версия выбрана при конфигурации?

На Linux вам было бы легче ссылаться на общую библиотеку и использовать SymLinks для исправления версии - IMO намного проще, чем использование dlopen() + dlsym().

Таким образом, вы создадите общие библиотеки для старых и новых версий вашей библиотеки:

g++ -shared -o libshared.so.1.1 -Wl,-soname=libshared.so.1 -L. -Wl,--whole-archive libstatic.a.old -Wl,-no-whole-archive

а также

g++ -shared -o libshared.so.1.2 -Wl,-soname=libshared.so.1 -L. -Wl,--whole-archive libstatic.a.new -Wl,-no-whole-archive

Создайте SymLinks:

ln -s libshared.so.1.1 libshared.so.1
ln -s libshared.so.1 libshared.so

Создайте свое приложение, связывая его к старой версии библиотеки. Я полагаю, что обе версии являются двоичными совместимыми (ABI не сломаны), но новый может иметь новые символы.

g++ -o myapp myapp.cpp -L. -lshared

Поскольку общие библиотеки SONAME является libshared.so.1 Ваше приложение будет зависеть от него и будет искать libshared.so.1 в путях от /etc/ld.so.conf или LD_LIBRARY_PATH

Прежде чем запустить ваше приложение, вы можете установить libshared.so.1 SymLink указывает на libshared.so.1.2 или libshared.so.1.1.


Маленькая информация о параметрах линкера, используемых здесь:

- Чолый архив
Для каждого архива, упомянутого в командной строке после опции «Удобрения», включите каждый объектный файл в архиве в ссылке, а не поиск архива для необходимых объектных файлов. Обычно это используется для превращения файла архива в общую библиотеку, принудительно принудительный объект в результате общую библиотеку. Эта опция может использоваться более одного раза.
Два примечания при использовании этой опции от GCC: Во-первых, GCC не знает об этой опции, поэтому вы должны использовать -WL, -WOHOL-Archive. Во-вторых, не забудьте использовать --wl, -no-все-архив после вашего списка архивов, потому что GCC добавит свой список архивов к вашей ссылке, и вы не хотите, чтобы этот флаг также повлиял на них.

-soname = name.
При создании общего объекта ELF установите внутреннее поле DT_Soname к указанному имени. Когда исполняемый файл связан с общим объектом, который имеет поле DT_SONAME, то когда исполняемый файл запускается, динамический линкер попытается загрузить общий объект, указанный поле DT_SONAME, а не с помощью имени файла, данного ссылками.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top