Как принудительно включить cxx11 ABI в Red Hat?

Я создаю небольшую библиотеку .so на Ubuntu 16.04 и Red Hat 7, используя gcc 7.3. Когда я проверяю имена символов экспорта с помощью команды nm, я обнаруживаю, что библиотека, скомпилированная в Ubuntu, использует ABI cxx11, а библиотека, скомпилированная в RedHat, — нет.

Например, символ экспорта для функции, скомпилированной в Ubuntu, выглядит так.

_Z12customLoad3DPKN8nlohmann10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaNS_14adl_serializerEEEPP11IVolumeDataPSA_

Но тот же символ экспорта при компиляции на RedHat выглядит так.

_Z12customLoad3DPKN8nlohmann10basic_jsonISt3mapSt6vectorSsblmdSaNS_14adl_serializerEEEPP11IVolumeDataPS4_

Обе библиотеки используют один и тот же make-файл. В коде используется #define _GLIBCXX_USECXX11_ABI 1 и параметр командной строки -std=c++11. Я также пробовал использовать параметр -fabi-version с разными значениями, но все безрезультатно. Я не могу решить эту проблему с помощью метода #ifdef __cplusplus extern "C", потому что функции используют параметры класса шаблона.

Как заставить gcc на RedHat использовать ABI cxx11? Я не могу использовать двойную связь ABI, потому что библиотека .so используется в качестве плагина для приложения, которое во время выполнения связывается с функциями в библиотеке, используя жестко заданный список искаженных имен. Плагин не будет работать на Red Hat, потому что искаженные имена не соответствуют ожиданиям программы. Как это исправить?

Спасибо!


person noah.b    schedule 31.10.2019    source источник
comment
Вы уверены, что gcc 7 используется в красной шляпе?   -  person Oblivion    schedule 31.10.2019
comment
Мне кажется, что этот плагин сломан по дизайну. И Fedora/Red Hat, и, как я полагаю, Ubuntu включают незначительные исправления в соответствующие компиляторы и библиотеки C++ своих дистрибутивов. Нет никакой гарантии, что компилятор C++ даже с одной и той же базовой версией, но в разных дистрибутивах Linux, будет производить идентичное искажение имен. Вы не можете полагаться на искаженные символы.   -  person Sam Varshavchik    schedule 31.10.2019
comment
@oblivion с devtoolset-7. Вы также можете получить GCC 8 с помощью devtoolset-8. Там, где я работаю, мы используем GCC 8 и C++17 на RHEL7 посредством devtoolset-8 — полностью поддерживается.   -  person Jesper Juhl    schedule 31.10.2019
comment
@JesperJuhl уверен, но не включен по умолчанию.   -  person Oblivion    schedule 31.10.2019
comment
Я уверен, что использую gcc 7.3. Я установил его сам, и команда gcc -v сообщает 7.3. Я заметил, что когда я вызываю gcc -v, он сообщает об опции --with-default-libstdcxx-abi=gcc4-compatable. Это заставляет использовать старый ABI?   -  person noah.b    schedule 31.10.2019
comment
@ Сэм, когда вы говорите, что плагин «сломан по дизайну», что бы вы порекомендовали в качестве исправления?   -  person noah.b    schedule 31.10.2019
comment
Используйте портативный C ABI и неискаженные символы. Это можно сделать с помощью кода C++, объявив символы как extern "C" {   -  person Sam Varshavchik    schedule 31.10.2019
comment
Red Hat поставляет антикварное программное обеспечение. Используйте другую операционную систему.   -  person jww    schedule 01.11.2019
comment
@SamVarshavchij Как я уже упоминал в своем исходном сообщении, я не могу использовать extern C {, потому что все экспортируемые функции используют параметры класса шаблона.   -  person noah.b    schedule 01.11.2019


Ответы (1)


libstdc++ C++11 ABI не поддерживается в Red Hat Enterprise Linux 7. У вас есть два варианта:

  • Обновитесь до Red Hat Enterprise Linux 8. Его системный компилятор по умолчанию использует более новый ABI.

  • Перестройте приложение в Red Hat Enterprise Linux 7, используя набор инструментов разработчика. Гибридная модель связывания гарантирует, что приложение будет работать в Red Hat Enterprise Linux 7. Доступен только старый ABI, но это обычно не имеет значения из-за перестройки, поскольку результат внутренне непротиворечив.

person Florian Weimer    schedule 31.10.2019