Как я могу развернуть программу С++ 11 (с зависимостями) на CentOS 6, GCC - С++ 03?

GCC отлично сочетается с ABI-совместимостью, если вы используете тот же стандарт С++ [1].

Но мне кажется, что если общая библиотека, скомпилированная GCC 4.3 в режиме С++ 03, выставляет, скажем, std::string, это будет другой std::string, чем тот, который понимается исполняемым файлом, скомпилированным GCC 4.8 в режиме С++ 11.

Причина, по которой я спрашиваю, заключается в том, что я планирую развернуть программу, скомпилированную GCC 4.8 в режиме С++ 11 на CentOS 6, максимальный упакованный GCC - 4.3... и некоторые из разделяемых библиотек (будь то сторонние, сторонних библиотек С++ или других компонентов на системном уровне), вероятно, все это будет С++ 03. Но если это так, мы никогда не сможем развернуть какие-либо программы на С++ 11 в старых дистрибутивах Linux, что кажется маловероятным.

Я наивно думаю, что здесь может быть проблема? И, если есть, как я могу его решить?

Ответы

Ответ 1

На самом деле вы можете распространять программу, скомпилированную с помощью нового компилятора g++ на платформе Vanilla CentOS 6. Существует несколько способов сделать это: проще всего использовать DevToolset 3, который даст вам g++ 4.9.2 (dev toolset 2 даст вам gcc 4.8.2). Затем просто скомпилируйте приложение с помощью этого g++. При распространении своего программного обеспечения вам необходимо также отправить libstdc++.so, который поставляется вместе с g++ 4.9. Либо установите LD_LIBRARY_PATH, чтобы он загрузился при запуске, либо установите RPATH, чтобы сообщить исполняемому файлу, где сначала искать библиотеки.

По существу, вы можете сделать это также с более новыми компиляторами, но тогда вам сначала нужно скомпилировать сам компилятор. Если вы не хотите сначала компилировать компилятор, перейдите к соответствующему набору инструментов dev, и все будет в порядке.

Да, вы также можете попробовать статически связать libstdС++. a. Найдите вариант -static-libstdc++:

Когда программа g++ используется для связывания программы на С++, она обычно автоматически связывается с libstdС++. Если libstdС++ доступен как разделяемая библиотека, а параметр -static не используется, то это связано с общей версией libstdС++. Это нормально. Тем не менее иногда бывает полезно заморозить версию libstdС++, используемую программой, не переходя полностью к статической ссылке. Опция -static-libstdС++ направляет драйвер g++ для связывания libstdС++ статически, не обязательно ставя статически связывание других библиотек.

Но если вы статически свяжетесь, вы не получите никаких обновлений для системы безопасности и т.д. Конечно, вы не получите обновления, если вы отправляете libstdС++, поэтому по своему усмотрению, но инкрементные обновления могут быть проще.

И в отношении запуска вашего приложения: Правило большого пальца: Компиляция на самой старой платформе, которую вам нужно поддерживать, тогда ваши двоичные файлы (с самонагруженными libstdС++ и другими необходимыми библиотеками), скорее всего, будут работать и в более новых версиях. То есть, если вы скомпилируете на CentoOS 6, и это работает, то вы можете ожидать, что он также будет работать на CentOS 7. На связанную тему это именно та причина, почему, например, AppImage и соответствующие решения рекомендуют использовать старую систему.

Ответ 2

Есть замечательная страница по этому вопросу: https://gcc.gnu.org/wiki/Cxx11AbiCompatibility

Короче говоря, С++ 11 в gcc в основном ABI совместим с С++ 98, но есть несколько несоответствий. На странице выше перечислены все эти.

Чтобы облегчить проблему, я могу предложить следующий подход:

  • Четко определите все ваши зависимости, которые являются библиотеками С++. Вы, как правило, не слишком много из них - в первую очередь приходит на ум, у вас есть что-то еще?
  • Чем вы проверяете, нужны ли символы вашего приложения в списке сломанных ABI (см. выше). Если это не так, вы в явном виде.
  • Если это так, вы перекомпилируете lib и либо распространяете его как shared lib вместе с вашим приложением (играя с флагами Rpath, чтобы убедиться, что ваше приложение загружает вашу версию), либо статически ставит против него.

На всякий случай, вы можете также статически ставить ссылку на libstdС++.

Ответ 3

В моей компании мы используем gcc 5.1.0, скомпилированный и используемый на CentOS 5.5 (со старым gcc-бортом).

При развертывании нашего приложения мы также перераспределяем libstdc++.so и libgcc_s.so, скомпилированные из источников gcc 5.1.0.

Например:

/opt/ourapp/lib/libstdc++.so
/opt/ourapp/lib/libgcc_s.so
/opt/ourapp/bin/myapp

И для правильного запуска двоичного кода мы выполняем:

LD_LIBRARY_PATH=/opt/ourapp/lib/ myapp.

Надеюсь, что это поможет.

Недостатки: По крайней мере, вы не можете использовать родной gdb в такой среде, потому что несовместимость формата DWARF.

Ответ 4

Если вы создаете свою программу на С++ 11 с помощью определения _GLIBCXX_USE_CXX11_ABI=0 (см. this) и опции --abi-version=2 (см. this), вы должны быть совместимы с любой библиотекой с GCC 4.3, включая libstdС++.

Версия ABI по умолчанию была от 2 до 4.9, кажется, что это безопасное предположение, что CentOS использует ABI по умолчанию.

Макрос _GLIBCXX_USE_CXX11_ABI будет влиять на стандартные типы библиотек, чтобы использовать тот же макет, что и версия pre С++ 11. Это приведет к появлению некоторых вопросов соответствия С++ 11 (причина их изменения в первую очередь), таких как сложность std::list<>::size().

Параметр командной строки --abi-version= влияет на компилятор ABI, вызывные соглашения, манипулирование именами и т.д. ABI по умолчанию равнялся 2 с 3.4 по 4.9.