Как я могу развернуть программу С++ 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.