Como devo lidar com a incompatibilidade da ABI entre o gcc-4.9 e o gcc-5?

Como devo lidar com a incompatibilidade da ABI entre o gcc-4.9 e o gcc-5?

Recentemente atualizei minha máquina de desenvolvimento para o Ubuntu 16.04 (nova instalação, apagada 14.04)

A versão padrão do gcc é gcc-5.3.1.

Um problema que tenho é que uma biblioteca fornecida pelo fornecedor só é construída usando o gcc-4.9, que não é compatível com o gcc-5.

Pedi ao fornecedor que fornecesse uma nova versão da biblioteca, mas é improvável que isso aconteça tão cedo.

Enquanto isso, instalei gcc-4.9.3a partir dos repositórios de pacotes do Ubuntu.

Agora tenho o gcc-4.9 e o 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

Tentei construir nosso código-fonte com gcc-4.9, mas agora me deparo com os mesmos problemas de ABI, mas indo na direção oposta.

O problema que tenho é que temos um monte de dependências que normalmente instalaríamos a partir dos pacotes da distribuição

sudo apt-get install \
    python-dev \
    libbz2-dev \
    libboost-all-dev \
    libprotobuf-dev \
    libgoogle-perftools-dev \
    postgresql \
    libpqxx-dev

Embora eu possa configurar minha compilação para usar gcc-4.9

mkdir build && cd build
CC=/usr/bin/gcc-4.9 CXX=/usr/bin/g++-4.9 cmake ..
make -j8

Agora recebo erros de vinculador ao vincular a libtcmalloc_minimal.a, libprotobuf.aetc.

Portanto, a próxima etapa que tentei foi remover todas as dependências instaladas dos repositórios da distribuição e começar a construir as dependências a partir do código-fonte.

CC=/usr/bin/gcc-4.9 CXX=/usr/bin/g++-4.9 ./configure
make -j8
sudo make install

O problema aqui é que estou começando a cair na toca do coelho. Cada dependência tem outras dependências e não tenho certeza de onde isso vai terminar.

A outra opção é fazer o downgrade para o Ubuntu 14.04 ou alguma versão que vem com o gcc-4.9 em vez do gcc-5.

Antes de tentar esta opção turmonuclear, queria saber se existe uma maneira melhor de fazer isso.

Talvez seja possível instalar a partir de repositórios criados com o gcc-4.9 ou de alguma outra forma?

Responder1

O problema que você tem está relacionado ao padrão C++ 11, que exige uma implementação diferente do (s) tipo (s) de string (e lista) C++. Para compatibilidade, g++5.2 e superior compilam o novo tipo compatível com C++11 por padrão (independentemente de você especificar -std=c++11 ou não), mas você pode definir a macro

-D_GLIBCXX_USE_CXX11_ABI=0

para reverter para o antigo tipo de string C++. A nova implementação da libstdc++ contémambosABI. Portanto, se você tiver binários para vincular à antiga ABI não compatível, deverá definir a macro acima em suas compilações g++. Isto deve produzir binários compatíveis com a antiga ABI.

Infelizmente, se você estiver usando bibliotecas do sistema operacional que não sejam as bibliotecas padrão C++, a menos que essas bibliotecas sejam multi-arch no sentido de fornecer todas as funções que diferem pela ABI emambosABIs, então você está ferrado porque eles provavelmente só terão a nova ABI.

Dito isto, tenho um problema em um Ubuntu antigo ao baixar um g++ moderno não confiável que simplesmente se recusa a produzir a nova ABI. Portanto, parece que o backport from ppa:ubuntu-toolchain-r/testestá de fato muito quebrado porque se recusa a produzir binários de acordo com a nova ABI.

De qualquer forma, o resultado final é que quando você vincula tudo, deve ser a ABI antiga ou a nova ABI. O seguinte dirá qual você 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

Se isso tiver

std::basic_string<char, ....

nele, é ovelhoABI. Se tiver

std::__cxx11::basic_string<char, ...

nele, é onovoABI.

Responder2

Vá para tty1 pressionando:CTRL+ALT+F1

Limpe o gcc-5.3.1 usando isto:

sudo apt-get purge gcc-5.3.1*

E instale o gcc-4.9.3 usando isto:

sudo apt-get install gcc-4.9.3

Nota: Isso requer conexão com a Internet!

Responder3

É bom usar-D_GLIBCXX_USE_CXX11_ABI=0. mas você também pode usar esta opção do g++, que pode ser ainda melhor

       -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.

informação relacionada