Recientemente actualicé mi máquina de desarrollo a Ubuntu 16.04 (instalación nueva, borrado 14.04)
La versión predeterminada de gcc es gcc-5.3.1
.
Un problema que tengo es que una biblioteca proporcionada por un proveedor solo se crea con gcc-4.9, que no es compatible con gcc-5.
Le pedí al proveedor que proporcione una nueva versión de la biblioteca, pero es poco probable que eso suceda pronto.
Mientras tanto he instalado gcc-4.9.3
de los repositorios de paquetes de Ubuntu.
Ahora tengo tanto gcc-4.9 como gcc-5 instalados:
ls -l /usr/bin/gcc*
lrwxrwxrwx 1 root root 5 May 9 11:49 /usr/bin/gcc -> gcc-5
-rwxr-xr-x 1 root root 838008 Apr 13 23:23 /usr/bin/gcc-4.9
-rwxr-xr-x 1 root root 915704 Apr 13 11:29 /usr/bin/gcc-5
Intenté compilar nuestro código fuente con gcc-4.9, pero ahora me encuentro con los mismos problemas de ABI, pero al revés.
El problema que tengo es que tenemos un montón de dependencias que normalmente instalaríamos desde los paquetes de distribución
sudo apt-get install \
python-dev \
libbz2-dev \
libboost-all-dev \
libprotobuf-dev \
libgoogle-perftools-dev \
postgresql \
libpqxx-dev
Si bien puedo configurar mi compilación para usar gcc-4.9
mkdir build && cd build
CC=/usr/bin/gcc-4.9 CXX=/usr/bin/g++-4.9 cmake ..
make -j8
Ahora obtengo errores del enlazador cuando vinculo contra libtcmalloc_minimal.a
, libprotobuf.a
etc.
Entonces, el siguiente paso que probé fue eliminar todas las dependencias instaladas de los repositorios de distribución y comenzar a construir las dependencias desde la fuente.
CC=/usr/bin/gcc-4.9 CXX=/usr/bin/g++-4.9 ./configure
make -j8
sudo make install
El problema aquí es que estoy empezando a meterme en una madriguera de conejo. Cada dependencia tiene otras dependencias y no estoy seguro de dónde terminará.
La otra opción es volver a la versión anterior a Ubuntu 14.04 o alguna versión que se envíe con gcc-4.9 en lugar de gcc-5.
Antes de probar esta opción thurmonuclear, me preguntaba si hay una mejor manera de hacer esto.
¿Tal vez sea posible instalar desde repositorios creados con gcc-4.9, o de alguna otra manera?
Respuesta aceptada:
El problema que tiene está relacionado con el estándar C++ 11 que requiere una implementación diferente de los tipos de cadenas (y listas) de C++. Por compatibilidad, g++5.2 y versiones posteriores compilan el nuevo tipo compatible con C++11 de forma predeterminada (ya sea que especifique o no -std=c++11), pero puede configurar la macro
-D_GLIBCXX_USE_CXX11_ABI=0
para volver al antiguo tipo de cadena de C++. La nueva implementación de libstdc++ contiene ambos ABI. Entonces, si tiene archivos binarios que debe vincular con el antiguo ABI no compatible, debe configurar la macro anterior en sus compilaciones g ++. Esto debería producir binarios compatibles con la antigua ABI.
Relacionado:¿Cómo obtener una resolución de 2560 × 1440 dentro de VirtualBox en una Mac?Desafortunadamente, si está utilizando bibliotecas del sistema operativo que no sean las bibliotecas estándar de C++, a menos que estas bibliotecas sean de varias arquitecturas en el sentido de proporcionar todas las funciones que difieren según ABI en ambas ABI, entonces estás jodido porque probablemente solo tendrán el nuevo ABI.
Habiendo dicho eso, tengo un problema en un viejo Ubuntu que descarga un g ++ moderno que no es de confianza y que simplemente se niega a producir el nuevo ABI. Entonces parece que la copia de seguridad de ppa:ubuntu-toolchain-r/test
de hecho, está muy dañado porque se niega a producir binarios de acuerdo con el nuevo ABI.
De todos modos, la conclusión es que cuando vincula todo debe ser el ABI antiguo o el ABI nuevo. Lo siguiente le dirá cuál está usando:
g++ --version
echo '#include <string>' > test.cpp
echo 'void f(std::string s) {}' >> test.cpp
cat test.cpp
g++ -std=gnu++11 -c -o test.o test.cpp
nm test.o | c++filt
Si eso tiene
std::basic_string<char, ....
en él, es el viejo ABI. Si tiene
std::__cxx11::basic_string<char, ...
en él, es el nuevo ABI.