Использование (старого) libstdC++.so.5 и libstdC++.so.6 в одном приложении Linux

У нас есть набор устаревших библиотек C++, скомпилированных в старой системе выпуска с очень старым компилятором gcc 3.2, использующим libstdC++. So.5.0.0. Современный CentOS7 будет запускать исполняемый файл, скомпилированный на старой ОС, с использованием библиотеки совместимости libstdC++. So.5.0.7, в то время как текущей версией C++ с другой библиотекой ABI является libstdC++. So.6.

Наша новая версия исполняемого файла построена на новой ОС и больше не может быть построена на старой платформе. Но в настоящее время перекомпиляция устаревших библиотек на CentOS7 также не возможна: численные результаты будут немного отличаться. Поэтому я хотел бы использовать их как они с их libstdC++. So.5, в то время как остальная часть моего двоичного файла использует C++ версии 6.

В этом посте предлагается использовать библиотеку c-interface-оболочки, которая связана со статической версией libstdC++. a.5.

этот пост в основном предлагает то же самое.

Этот метод кажется возможным в нашем случае, так как интерфейс только в стиле C и не использует объекты C++. И C-ABI, похоже, работает как своего рода барьер между двумя версиями C++ lib.

Тем не менее, я еще не нашел кого-то, кто предоставил статические библиотеки C++.5. Также я думаю, что когда-то слышал разговоры об одновременном использовании двух совместно используемых версий libstdC++ для lib в одном приложении. Так есть ли решение для сохранения общих библиотек C++.5? У меня слабая память, что они также использовали C-библиотеку в качестве границы. Будет ли это также работать с dlopen()?

Моя текущая ситуация такова:

Скомпилировано на старой ОС со старым gcc-3.2, libstdC++. So.5, 32-битный режим:

  • libA1.so с использованием C++
  • libA2.so вызывает libB.so, оба используют C++, libA2 явно связаны с libstdC++ с опцией компоновщика -lstdC++, libB нет, но, вероятно, он получает свои символы из libA
  • libwrapper.so только с использованием C, а не C++, связанный с / используя libA1 и libA2.

Скомпилировано на новой ОС с новым gcc-4.8.5:

  • исполняемый (32-битный) вызов libwrapper.so с помощью системного вызова dlopen (), поэтому косвенный вызов C++ вызывает библиотеки libA1.so и libA2.
  • Исполняемый файл также использует совместно используемую C++ lib libC.so (но интерфейс в стиле C)
  • Исполняемый файл также использует совместно используемую C++ lib libB.so (но интерфейс в стиле C), что также необходимо для libA1 и libA2.

Таким образом, исполняемый файл должен использовать новый libstdC++. So.6 для libC, но будет косвенно вызывать libA1, libA2, libB, который должен использовать старый libstdC++. So.5.

Должен ли я ограничить символы, экспортируемые библиотекой-оберткой, точно в мой API, не выставляя символы C++, как в комментарии pobedims в 1, используя флаг version-script для компоновщика?

Или, может быть, я просто связал устаревшую библиотеку на старой ОС не с -lstdC++, а с полным именем /usr/lib/libstdc++.so.5? И libB продолжит получать правильные символы из libA2?

Мои исполняемые ссылки / зависят от...

  1. libB.so (C++)
  2. libC.so (C++), который нуждается в libstdC++. 6
  3. libwrapper.so (с интерфейсом C), который загружается с использованием динамической загрузки dlopen () и который сам связан с "рабочими" libA1 и libA2 (которые также представляют интерфейс C):
    • libA1.so с использованием C++.5
    • libA2.so с использованием C++.5
      • libB.so с использованием C++.5

Исполняемый файл связан с -rdynamic, может быть, это проблема? Как я могу быть уверен, что никакие символы в libA1, A2, B не разрешены с использованием символов из исполняемого файла с таким же именем?

Изменить позже / Решение: Примечание 1. Попытка на старой платформе связать с использованием архивной версии libstdC++. A.5 приводит к ошибке, которая исправляется только в более поздней версии gcc >= 3.4:
Ошибка: ld: libwrapper.so: неопределенное имя версионного символа _ZSt10time_put_w @@ GLIBCPP_3.2
ld: не удалось установить динамические размеры раздела: неверное значение

так что это не вариант.

Примечание 2: LibB была проблемой, так как она ожидается рабочими библиотеками и самим исполняемым файлом. Если исполняемый файл использует новую версию libB, он вводит libstdC++. So.6, символы которого передаются рабочим библиотекам, которые вылетают при запуске. Я изменил версию libB, использованную на версию, скомпилированную в старой системе, просто заменив ее на систему времени выполнения. Это возможно из-за того, что простой интерфейс C является двоично-совместимым. Таким образом, мой исполняемый файл (через libB) и рабочие библиотеки libA1 и libA2 используют один и тот же libstdC++. So.5. Мой (C) исполняемый файл построен напрямую с использованием libstdC++. So.5. Теперь мой исполняемый файл может быть запущен и работает.

Примечание 3: я нашел некоторые числовые различия между контрольными результатами и новым результатом. Использование механизма LD_PRELOAD помогло решить эти проблемы: LD_PRELOAD=libstdC++. So.5 my_executable

Кажется, это работает хорошо. Я думаю, что с помощью LD_PRELOAD я убедился, что libstdC++. So.5 имеет преимущество в предоставлении символов, разрешенных из libstdC++. То, что я не упомянул ранее: мы использовали компилятор Intel на старой платформе, и я использовал математический lib libimf.so из него так: LD_PRELOAD="libimf.so libstdC++. So.5", чтобы предоставить обе библиотеки. В результате числовые различия исчезли, что, по-видимому, связано с реализацией общих математических функций.

0 ответов

Другие вопросы по тегам