Wie gehe ich mit der ABI-Inkompatibilität zwischen gcc-4.9 und gcc-5 um?

Wie gehe ich mit der ABI-Inkompatibilität zwischen gcc-4.9 und gcc-5 um?

Ich habe meine Entwicklungsmaschine vor Kurzem auf Ubuntu 16.04 aktualisiert (Neuinstallation, 14.04 gelöscht).

Die Standardversion von gcc ist gcc-5.3.1.

Mein Problem besteht darin, dass eine vom Anbieter bereitgestellte Bibliothek nur mit gcc-4.9 erstellt wird, das nicht mit gcc-5 kompatibel ist.

Ich habe den Anbieter gebeten, eine neue Version der Bibliothek bereitzustellen, aber es ist unwahrscheinlich, dass dies bald geschehen wird.

In der Zwischenzeit habe ich die Installation gcc-4.9.3aus den Paket-Repos von Ubuntu durchgeführt.

Ich habe jetzt sowohl gcc-4.9 als auch gcc-5 installiert:

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

Ich habe versucht, unsere Quelle mit gcc-4.9 zu erstellen, stoße jetzt jedoch auf dieselben ABI-Probleme, allerdings in die andere Richtung.

Das Problem, das ich habe, ist, dass wir eine Reihe von Abhängigkeiten haben, die wir normalerweise aus den Distributionspaketen installieren würden

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

Ich kann meinen Build zwar so konfigurieren, dass er gcc-4.9 verwendet

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

Ich erhalte jetzt Linkerfehler beim Verknüpfen libtcmalloc_minimal.amit libprotobuf.ausw.

Der nächste Schritt, den ich versucht habe, bestand darin, alle aus den Distro-Repos installierten Abhängigkeiten zu entfernen und mit dem Erstellen der Abhängigkeiten aus dem Quellcode zu beginnen.

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

Das Problem hier ist, dass ich mich langsam in einem Kaninchenbau verliere. Jede Abhängigkeit hat andere Abhängigkeiten und ich bin mir nicht sicher, wo das endet.

Die andere Möglichkeit besteht darin, ein Downgrade zurück auf Ubuntu 14.04 oder eine Version durchzuführen, die mit gcc-4.9 statt gcc-5 ausgeliefert wird.

Bevor ich diese thurmonukleare Option ausprobiere, frage ich mich, ob es dafür eine bessere Möglichkeit gibt?

Vielleicht ist die Installation aus Repos möglich, die mit gcc-4.9 oder auf andere Weise erstellt wurden?

Antwort1

Das Problem, das Sie haben, hängt mit dem C++11-Standard zusammen, der eine andere Implementierung von C++-String- (und Listen-)Typen erfordert. Aus Kompatibilitätsgründen kompiliert g++5.2 und höher standardmäßig den neuen C++11-kompatiblen Typ (unabhängig davon, ob Sie -std=c++11 angeben oder nicht), aber Sie können das Makro festlegen

-D_GLIBCXX_USE_CXX11_ABI=0

um zum alten C++-Stringtyp zurückzukehren. Die neue libstdc++-Implementierung enthältbeideABIs. Wenn Sie also Binärdateien haben, die Sie mit der alten, nicht kompatiblen ABI verknüpfen müssen, müssen Sie das obige Makro bei Ihren G++-Kompilierungen festlegen. Dadurch sollten Binärdateien erstellt werden, die mit der alten ABI kompatibel sind.

Wenn Sie Bibliotheken des Betriebssystems verwenden, die nicht die C++-Standardbibliotheken sind, dann ist es leider so, dass diese Bibliotheken nicht multiarch sind, d. h. sie bieten alle Funktionen, die sich durch ABI unterscheiden, inbeideABIs, dann haben Sie Pech gehabt, denn wahrscheinlich haben sie nur das neue ABI.

Allerdings habe ich ein Problem mit einem alten Ubuntu, wenn ich ein nicht vertrauenswürdiges modernes G++ herunterlade, das sich einfach weigert, die neue ABI zu erstellen. Es scheint also, dass der Backport von ppa:ubuntu-toolchain-r/testtatsächlich stark beschädigt ist, da er sich weigert, Binärdateien gemäß der neuen ABI zu erstellen.

Unterm Strich gilt jedenfalls, dass beim Verknüpfen alles entweder die alte oder die neue ABI sein muss. Im Folgenden erfahren Sie, welche Sie verwenden:

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

Wenn das

std::basic_string<char, ....

darin ist dasaltABI. Wenn es

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

darin ist dasneuABI.

Antwort2

Gehen Sie zu tty1, indem Sie Folgendes drücken:CTRL+ALT+F1

Bereinigen Sie gcc-5.3.1 folgendermaßen:

sudo apt-get purge gcc-5.3.1*

Und installieren Sie gcc-4.9.3 folgendermaßen:

sudo apt-get install gcc-4.9.3

Hinweis: Hierzu ist eine Internetverbindung erforderlich!

Antwort3

Es ist gut zu verwenden-D_GLIBCXX_USE_CXX11_ABI=0. aber Sie können auch diese Option von g++ verwenden, die sogar noch besser sein kann

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

verwandte Informationen