¿Cómo puedo implementar un programa C++ 11(con dependencias) en CentOS 6, cuyo GCC es C++ 03?
c++11 compatibility (4)
GCC es excelente con la compatibilidad con ABI siempre que utilice el mismo estándar de C ++ [ 1 ].
Pero me sorprende que si una biblioteca compartida compilada por GCC 4.3 en modo C ++ 03 expone, digamos, una std::string
, esta va a ser una std::string
diferente de la que entiende un ejecutable compilado por GCC 4.8. en modo C ++ 11.
La razón por la que pregunto es que estoy planeando implementar un programa compilado por GCC 4.8 en modo C ++ 11 en CentOS 6, cuyo GCC máximo empaquetado es 4.3 ... y algunas de las bibliotecas compartidas (ya sean bibliotecas de C ++ de terceros). o más cosas a nivel de sistema) presumiblemente, por lo tanto, todas serán C ++ 03. Pero si ese fuera el caso, nunca podríamos implementar ningún programa C ++ 11 en distribuciones de Linux más antiguas, lo que parece poco probable.
¿Soy ingenuo para pensar que podría haber un problema aquí? Y, si la hay, ¿cómo puedo resolverlo?
En mi empresa utilizamos gcc 5.1.0, compilado y usado en CentOS 5.5 (con gcc antiguo incorporado).
Cuando implementamos nuestra aplicación, también redistribuimos libstdc++.so
libgcc_s.so
y libgcc_s.so
, compilados desde las fuentes de gcc 5.1.0.
Por ejemplo:
/opt/ourapp/lib/libstdc++.so
/opt/ourapp/lib/libgcc_s.so
/opt/ourapp/bin/myapp
Y para arrancar correctamente el binario ejecutamos:
LD_LIBRARY_PATH=/opt/ourapp/lib/ myapp.
Espero eso ayude.
Inconvenientes: al menos no puede usar gdb nativo en un entorno de este tipo debido a las incompatibilidades del formato DWARF.
En realidad, puede distribuir un programa compilado con un compilador g ++ más nuevo en una plataforma vainilla CentOS 6. Hay varias formas de hacer esto: la más fácil es usar DevToolset 3 , que le dará g ++ 4.9.2 (el conjunto de herramientas dev 2 le dará gcc 4.8.2). Luego, simplemente compile su aplicación con este g ++. Al distribuir su software, debe asegurarse de enviar también libstdc++.so
que se envíe con g ++ 4.9. Configure el LD_LIBRARY_PATH
para que se RPATH en el inicio, o configure el RPATH para decirle a su ejecutable dónde buscar primero las bibliotecas.
Esencialmente, puedes hacer esto también con compiladores más nuevos, pero primero necesitas compilar el compilador en sí. Si no quieres compilar un compilador primero, ve con un conjunto de herramientas de desarrollo respectivo y estarás bien.
Sí, también puedes intentar vincular estáticamente libstdc ++. A. Busque la opción -static-libstdc++
:
Cuando se utiliza el programa g ++ para vincular un programa C ++, normalmente se vincula automáticamente con libstdc ++. Si libstdc ++ está disponible como una biblioteca compartida, y la opción -static no se usa, entonces esto enlaza con la versión compartida de libstdc ++. Eso normalmente está bien. Sin embargo, a veces es útil congelar la versión de libstdc ++ utilizada por el programa sin llegar a un enlace completamente estático. La opción -static-libstdc ++ dirige al controlador g ++ para vincular estáticamente libstdc ++, sin necesariamente vincular estáticamente otras bibliotecas.
Pero si realiza un enlace estático, no obtendrá ninguna actualización de seguridad, etc. Por supuesto, no obtendrá las actualizaciones, si envía libstdc ++. También lo hará por su cuenta, pero las actualizaciones incrementales pueden ser más fáciles.
Y con respecto a la ejecución de su aplicación: la regla empírica es: compilar en la plataforma más antigua que necesita para admitir, entonces sus binarios (con libstdc ++ auto-enviados y otras libs requeridas) probablemente funcionarán también en las versiones más recientes. Es decir, si compila en CentoOS 6 y funciona, entonces puede esperar que también funcione en CentOS 7. En un tema relacionado, esta es exactamente la razón por la que, por ejemplo, AppImage y las soluciones relacionadas recomiendan construir en un sistema antiguo .
Hay una página maravillosa sobre este asunto: https://gcc.gnu.org/wiki/Cxx11AbiCompatibility
En resumen, C ++ 11 en gcc es mayormente ABI compatible con c ++ 98, pero hay un par de desajustes. La página de arriba enumera todos esos.
Para aliviar el problema puedo sugerir el siguiente enfoque:
- Identifique claramente todas sus dependencias que son bibliotecas de C ++. Por lo general, no tienes muchos de ellos: el impulso viene a la mente primero, ¿tienes algo más?
- A continuación, compruebe si los símbolos que necesita su aplicación están en la lista de ABI roto (ver arriba). Si no lo son, estás a salvo.
- Si lo son, recompila la biblioteca y distribúyelo como biblioteca compartida junto con tu aplicación (jugando con las banderas Rpath para asegurarte de que la aplicación carga tu versión) o haz un enlace estático contra ella.
Por si acaso, también podrías enlazar estáticamente contra libstdc ++.
Si _GLIBCXX_USE_CXX11_ABI=0
su programa C ++ 11 con la definición _GLIBCXX_USE_CXX11_ABI=0
(vea this ) y la opción --abi-version=2
(vea this ) debe ser compatible con cualquier compilación de biblioteca con GCC 4.3, incluyendo libstdc ++.
La versión ABI predeterminada fue del 2 al 4.9, parece una suposición segura de que CentOS usa el ABI predeterminado.
La macro _GLIBCXX_USE_CXX11_ABI
afectará los tipos de la biblioteca estándar, para usar el mismo diseño que la versión anterior a C ++ 11. Esto introducirá algunos problemas de conformidad con C ++ 11 (la razón por la que se modificaron en primer lugar), como la complejidad de std::list<>::size()
.
La opción de línea de comando --abi-version=
afecta a la ABI del compilador, a las convenciones de llamadas, a la manipulación de nombres, etc. La ABI predeterminada era 2 de 3.4 a 4.9.