我应该如何处理 gcc-4.9 和 gcc-5 之间的 ABI 不兼容问题?

我应该如何处理 gcc-4.9 和 gcc-5 之间的 ABI 不兼容问题?

我最近将我的开发机器升级到了 Ubuntu 16.04(全新安装,删除了 14.04)

gcc 的默认版本是gcc-5.3.1

我遇到的一个问题是供应商提供的库仅使用 gcc-4.9 构建,与 gcc-5 不兼容。

我已经要求供应商提供新版本的库,但这不太可能很快实现。

同时,我已经gcc-4.9.3从 Ubuntu 的软件包存储库进行了安装。

我现在已经安装了 gcc-4.9 和 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

我尝试使用 gcc-4.9 构建我们的源,但是现在我遇到了相同的 ABI 问题,但是却遇到了相反的问题。

我遇到的问题是我们有一堆依赖项,通常会从发行版包中安装

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

虽然我可以将我的构建配置为使用 gcc-4.9

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

现在,当我链接等时libtcmalloc_minimal.a,会出现链接器错误。libprotobuf.a

因此,我尝试的下一步是删除从发行版存储库安装的所有依赖项,然后开始从源代码构建依赖项。

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

这里的问题是我开始陷入困境。每个依赖项都有其他依赖项,我不确定它会在哪里结束。

另一个选择是降级回 Ubuntu 14.04 或者某些搭载 gcc-4.9 而不是 gcc-5 的版本。

在尝试这个热核选项之前,我想知道是否有更好的方法来做到这一点?

也许可以从用 gcc-4.9 构建的 repos 进行安装,或者通过其他方式?

答案1

您遇到的问题与 C++11 标准有关,该标准要求对 C++ 字符串(和列表)类型进行不同的实现。为了兼容,g++5.2 及更高版本默认编译新的符合 C++11 的类型(无论您是否指定 -std=c++11),但您可以设置宏

-D_GLIBCXX_USE_CXX11_ABI=0

恢复到旧的 C++ 字符串类型。新的 libstdc++ 实现包含两个都ABI。因此,如果您有必须与旧的不兼容 ABI 链接的二进制文件,则必须在 g++ 编译中设置上述宏。这应该会生成与旧 ABI 兼容的二进制文件。

不幸的是,如果你正在使用除 C++ 标准库之外的操作系统库,那么除非这些库是多架构的,即提供所有与 ABI 不同的函数,否则两个都ABI,那么你就麻烦了,因为他们可能只有新的 ABI。

话虽如此,我在旧版 Ubuntu 上下载不受信任的现代 g++ 时遇到了问题,它拒绝生成新的 ABI。因此,似乎反向移植实际上ppa:ubuntu-toolchain-r/test存在严重问题,因为它拒绝根据新的 ABI 生成二进制文件。

无论如何,底线是,当你将所有内容链接在一起时,必须是旧 ABI 或新 ABI。以下内容将告诉你正在使用哪个:

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

如果有的话

std::basic_string<char, ....

在其中,它的老的ABI。如果有

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

在其中,它的新的ABI。

答案2

按以下方式进入 tty1:CTRL+ALT+F1

使用以下命令清除 gcc-5.3.1:

sudo apt-get purge gcc-5.3.1*

并使用以下命令安装 gcc-4.9.3:

sudo apt-get install gcc-4.9.3

注意:这需要互联网连接!

答案3

使用起来很好-D_GLIBCXX_USE_CXX11_ABI=0. 但你也可以使用 g++ 的这个选项,它甚至可以更好

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

相关内容