我應該如何處理 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.alibprotobuf.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 建置的儲存庫或其他方式安裝?

答案1

您遇到的問題與需要不同的 C++ 字串(和列表)類型實現的 C++11 標準有關。為了相容性,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.

相關內容