2015-11-03 76 views
4

我嘗試瞭解如何解決GCC 5中引入的雙重ABI問題。但是,我沒有設法做到這一點。這裏是一個非常簡單的例子來重現錯誤。我使用的GCC版本是5.2。正如你所看到的,我的主要功能(在main.cpp中的文件)很簡單:如何處理GCC 5中的雙重ABI?

// main.cpp 

#include <iostream> 
#include <string> 

int main() 
{ 
    std::string message = "SUCCESS!"; 
    std::cout << message << std::endl; 
} 

當我鍵入

/home/aleph/gcc/5.2.0/bin/g++ main.cpp 

我收到以下錯誤信息:

/tmp/ccjsTADd.o: In function `main': 
main.cpp:(.text+0x26): undefined reference to `std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string(char const*, std::allocator<char> const&)' 
main.cpp:(.text+0x43): undefined reference to `std::basic_ostream<char, std::char_traits<char> >& std::operator<< <char, std::char_traits<char>, std::allocator<char> >(std::basic_ostream<char, std::char_traits<char> >&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)' 
main.cpp:(.text+0x5c): undefined reference to `std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::~basic_string()' 
main.cpp:(.text+0x8c): undefined reference to `std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::~basic_string()' 
collect2: erreur: ld a retourné 1 code d'état d'exécution 

如果我將_GLIBCXX_USE_CXX11_ABI的值更改爲0,則問題消失。

但是,如何使用默認的ABI工作?

編輯:簡單的問題(去除CMake的腳本)

+0

在兩種情況下,gcc 5.x和gcc 4.x都告訴'make VERBOSE = 1?在兩種情況下,實際上有不同的gcc使用?由於cmake緩存CXX_COMPILER值和正在運行的腳本(Cmakelists.txt)時間,您無法更改編譯器 – fghj

+0

「如果您獲取有關涉及std :: __ cxx11命名空間或標記[abi:cxx11中的類型的符號的未定義引用的鏈接器錯誤]那麼它可能表明你正試圖鏈接使用_GLIBCXX_USE_CXX11_ABI宏的不同值編譯的目標文件「https://gcc.gnu.org/onlinedocs/libstdc++/manual/using_dual_abi.html – Ben

+0

我在構建中刪除了evrything存儲庫,以避免任何緩存問題 – Aleph

回答

5

我通過添加更多的冗長海灣合作委員會(-v標誌)找到了解決辦法。如果您遇到同樣的問題,則需要告訴gcc在包含libstdC++版本的發行版的存儲庫中搜索庫。換句話說,你應該嘗試這樣的事情:

/home/aleph/gcc/5.2.0/bin/g++ -L /home/aleph/gcc/5.2.0/lib64 main.cpp 

之後的連接步驟應該正確執行。但是,您可能無法運行程序。進入

./a.out 

可能會導致以下錯誤:

./a.out: relocation error: ./a.out: symbol _ZNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEC1EPKcRKS3_, version GLIBCXX_3.4.21 not defined in file libstdc++.so.6 with link time reference 

事實上,你可以檢查你的可執行文件取決於錯誤版本的libstdC++通過鍵入

ldd a.out 

這應該引起類似的東西:

linux-vdso.so.1 => (0x00007ffebb722000) 
libstdc++.so.6 => /usr/lib/x86_64-linux-gnu/libstdc++.so.6 (0x0000003a71400000) 
libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x0000003d03a00000) 
libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x0000003a71000000) 
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x0000003d02e00000) 
/lib64/ld-linux-x86-64.so.2 (0x0000003d02a00000) 

將LD_LIBRARY_PATH設置爲路徑,以你自己的版本的libstdC++就能解決問題:

LD_LIBRARY_PATH=/home/aleph/gcc/5.2.0/lib64 ./a.out 

希望它能幫助!

編輯:正如Marc所注意到的,可以修改rpath而不是修改環境變量LD_LIBRARY_PATH。這是一個CMake配置腳本來完成它。

project (example CXX) 

add_executable(main main.cpp) 

if(GCC_ROOT) 
    set(CMAKE_CXX_COMPILER ${GCC_ROOT}/bin/g++) 
    target_link_libraries(main ${GCC_ROOT}/lib64/libstdc++.so) 
    link_directories(${GCC_ROOT}/lib64) 
endif(GCC_ROOT) 

該腳本可以與通常的組合

cmake .. 
make 

在 '構建' 子目錄中。但它也有可能通過提供給我們的GCC分佈根的路​​徑選擇自己的編譯器:

cmake -D GCC_ROOT=/home/aleph/gcc/5.2.0 .. 
make 

劇本是這麼寫的的libstdC++版本對應於輸入GCC發行的版本。

+2

'-Wl,-rpath,/ home/aleph/gcc/5.2.0/lib64'是LD_LIBRARY_PATH的替代方案。 –

+0

是的,這是一個更好的選擇。我在回答中添加了一個cmake版本。 – Aleph

+0

運行時錯誤(用rpath或LD_LIBRARY_PATH解決)是可以預料的,但不應該用'-L'來告訴g ++如何找到它自己的庫。 GCC 5.2安裝中的某些內容已損壞。 –