
Recientemente actualicé mi máquina de desarrollo a Ubuntu 16.04 (instalación nueva, borrada 14.04)
La versión predeterminada de gcc es gcc-5.3.1
.
Un problema que tengo es que una biblioteca proporcionada por el proveedor solo se crea con gcc-4.9, que no es compatible con gcc-5.
Le pedí al proveedor que me proporcionara una nueva versión de la biblioteca, pero es poco probable que eso suceda pronto.
Mientras tanto, lo instalé gcc-4.9.3
desde los repositorios de paquetes de Ubuntu.
Ahora tengo instalados gcc-4.9 y gcc-5:
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é construir nuestra fuente con gcc-4.9, pero ahora me encuentro con los mismos problemas de ABI, pero en sentido contrario.
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 recibo errores del vinculador al vincular con libtcmalloc_minimal.a
, libprotobuf.a
etc.
Entonces, el siguiente paso que intenté fue eliminar todas las dependencias instaladas desde los repositorios de la 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 hundirme 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 Ubuntu 14.04 o alguna versión que venga con gcc-4.9 en lugar de gcc-5.
Antes de probar esta opción termonuclear, me preguntaba si existe una mejor manera de hacerlo.
¿Quizás sea posible instalar desde repositorios creados con gcc-4.9 o de alguna otra forma?
Respuesta1
El problema que tiene está relacionado con el estándar C++ 11 que requiere una implementación diferente de los tipos de cadena (y lista) 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 -std=c++11 o no), 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++ contieneambosABI. Entonces, si tiene archivos binarios que debe vincular con la antigua ABI que no cumple con los requisitos, debe configurar la macro anterior en sus compilaciones de g++. Esto debería producir archivos binarios compatibles con la antigua ABI.
Desafortunadamente, si está utilizando bibliotecas del sistema operativo que no sean las bibliotecas estándar de C++, a menos que estas bibliotecas sean de múltiples arcos en el sentido de proporcionar todas las funciones que difieren según ABI enambosABI, entonces estás jodido porque probablemente solo tendrán el nuevo ABI.
Dicho esto, tengo un problema en un antiguo Ubuntu al descargar un g++ moderno que no es de confianza y que simplemente se niega a producir la nueva ABI. Entonces, parece que el backport de ppa:ubuntu-toolchain-r/test
está realmente roto porque se niega a producir archivos binarios de acuerdo con la nueva ABI.
De todos modos, la conclusión es que cuando vinculas todo debe ser el ABI antiguo o el ABI nuevo. Lo siguiente le indicará cuál está utilizando:
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 elviejoABI. si tiene
std::__cxx11::basic_string<char, ...
en él, es elnuevoABI.
Respuesta2
Vaya a tty1 presionando:CTRL+ALT+F1
Purgue gcc-5.3.1 usando esto:
sudo apt-get purge gcc-5.3.1*
E instale gcc-4.9.3 usando esto:
sudo apt-get install gcc-4.9.3
Nota: ¡Esto requiere conexión a Internet!
Respuesta3
es bueno usarlo-D_GLIBCXX_USE_CXX11_ABI=0. pero también puedes usar esta opción de g++, que puede ser incluso mejor
-fabi-version=n
Use version n of the C++ ABI. The default is version 0.
Version 0 refers to the version conforming most closely to the C++ ABI specification. Therefore, the ABI obtained using version 0 will change in different versions of G++ as ABI bugs are
fixed.
Version 1 is the version of the C++ ABI that first appeared in G++ 3.2.
Version 2 is the version of the C++ ABI that first appeared in G++ 3.4, and was the default through G++ 4.9.
Version 3 corrects an error in mangling a constant address as a template argument.
Version 4, which first appeared in G++ 4.5, implements a standard mangling for vector types.
Version 5, which first appeared in G++ 4.6, corrects the mangling of attribute const/volatile on function pointer types, decltype of a plain decl, and use of a function parameter in the
declaration of another parameter.
Version 6, which first appeared in G++ 4.7, corrects the promotion behavior of C++11 scoped enums and the mangling of template argument packs, const/static_cast, prefix ++ and --, and a class
scope function used as a template argument.
Version 7, which first appeared in G++ 4.8, that treats nullptr_t as a builtin type and corrects the mangling of lambdas in default argument scope.
Version 8, which first appeared in G++ 4.9, corrects the substitution behavior of function types with function-cv-qualifiers.
Version 9, which first appeared in G++ 5.2, corrects the alignment of "nullptr_t".
See also -Wabi.
-fabi-compat-version=n
On targets that support strong aliases, G++ works around mangling changes by creating an alias with the correct mangled name when defining a symbol with an incorrect mangled name. This switch
specifies which ABI version to use for the alias.
With -fabi-version=0 (the default), this defaults to 2. If another ABI version is explicitly selected, this defaults to 0.
The compatibility version is also set by -Wabi=n.