高版本gcc編譯代碼,鏈接低版本gcc編譯的庫


CFLAG 里面指定  -D_GLIBCXX_USE_CXX11_ABI=0,

set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -D_GLIBCXX_USE_CXX11_ABI=0")

set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -D_GLIBCXX_USE_CXX11_ABI=0")

 1、先用舊版本gcc編譯整套代碼。

2、然后修改要單獨編譯的可執行文件的makefile或者CmakeLIST.TXT,增加-D_GLIBCXX_USE_CXX11_ABI=0編譯連接選項。

3、然后刪除之前被編譯出來的可執行文件。

4、變更為新版本的gcc(gcc-5.1以上)

4、重新編譯make xxxapp。

注:   更新gcc編譯器,不需要更新stdc++

 

為什么我們需要-D_GLIBCXX_USE_CXX11_ABI=0

當您嘗試構建 tensorflow 時,會提示您需要添加“-D_GLIBCXX_USE_CXX11_ABI=0”標志,如果您使用的是 GCC 5 或更高版本,以保持您構建的 tensorflow 和官方 tensorflow 構建的兼容性。

官方 TensorFlow 包是使用 GCC 4 構建的,並使用較舊的 ABI。對於 GCC 5 及更高版本,使用以下命令使您的構建與舊 ABI 兼容:–cxxopt=”-D_GLIBCXX_USE_CXX11_ABI=0”。ABI 兼容性確保針對官方 TensorFlow 包構建的自定義操作繼續與 GCC 5 構建包一起使用

非常詳細和正式地解釋ABI長話短說,根據我的理解,這是編譯器之間的協議/協議,關於如何從另一個編譯單元找到路由/符號,以及如何傳遞參數,獲取例程之間的返回值,如何解釋函數/符號名稱(來源文件和編譯器中間二進制文件對於相同的函數/類具有不同的名稱)。

如果您的軟件的所有代碼/組件都是從您機器上的單個編譯器編譯的,則 ABI 兼容性根本不是問題,因為編譯器將處理所有臟細節。但是,如果您正在編寫一個將分發給各種用戶的庫,將有許多潛在的配置/環境,那么 ABI 絕對是您需要考慮的重要事項之一。

假設您正在用 C++ 編寫一個庫,並且您不想分發庫的源代碼。您可以將其編譯為動態庫(linux 中的.so 文件),然后將動態庫和頭文件提供給您的用戶。用戶然后使用他/她的編譯器將他/她的源文件編譯為目標文件,然后使用您的動態庫將他/她的目標文件再次鏈接到可執行文件/庫。問題來了:

  • 假設您使用的是版本 X 的 GCC 編譯器,但用戶使用的是另一個版本 Y。在這種情況下,Y 需要知道 X 編譯的庫的二進制格式。

關於 C++11_ABI 標志

這里的文章對此進行了解釋。https://developers.redhat.com/blog/2015/02/05/gcc5-and-the-c11-abi/

基本思想是

依賴第三方庫或仍然使用舊 ABI 的插件接口的用戶可以使用 -D_GLIBCXX_USE_CXX11_ABI=0 構建他們的代碼,一切都應該正常工作。在大多數情況下,很明顯何時需要這個標志是因為鏈接器的錯誤抱怨涉及“__cxx11”的未解析符號

例子

步驟 1. 編寫並編譯 lib

假設您正在編寫一個只有一個 cpp 文件的庫mylib.cpp,並通過以下方式導出您的 APImylib.h

//mylib.cpp #include <string> #include <iostream> void print_string(const std::string & a) { std::cout <<__FILE__ << __LINE__ << " content of a:" << a << std::endl; } 
#ifndef __MYLIB_H #define __MYLIB_H #include <string> void print_string(const std::string & a); #endif

使用以下命令將 cpp 文件編譯為動態庫。

    g++ -fPIC mylib.cpp -shared -o libmy.so 

步驟 2. 編寫並編譯和應用

假設您的應用程序的cpp 文件以 命名myapp.cpp,並且它步驟1 中的mylib.cppmylib.hmylib.so同一目錄中。具有以下內容。

#include <string> #include "mylib.h" int main(){ print_string("FromMyApp"); return 0; } 

使用以下命令將cpp文件編譯為可執行文件。

g++ myapp.cpp -o myapp -lmy -L./ -I./ 

該命令將myapp在當前目錄下生成一個exectuble,該 exetuble 運行良好,您只需執行它即可。

Step 3. 更改庫的 ABI 會影響應用程序

但是如果我將 libary 編譯命令更改為以下命令會怎樣

g++ -fPIC mylib.cpp -shared -o libmy.so -D_GLIBCXX_USE_CXX11_ABI=0 

在此之后,如果我執行與 step.2 中相同的命令來編譯 app g++ myapp.cpp -lmy -L./ -o myapp編譯器給出以下錯誤

/tmp/ccDPFccW.o: In function `main': myapp.cpp:(.text+0x43): undefined reference to `print_string(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)' collect2: error: ld returned 1 exit status 

這明顯表明我需要使用與 libary 編譯命令相同的編譯標志。

g++ myapp.cpp -lmy -L./ -o myapp -D_GLIBCXX_USE_CXX11_ABI=0 

4. 回到 tensorflow 的例子。

現在讓我們回到 tensorflow 示例,因為官方預構建的 tensorflow 庫 (.so) 是由較舊的 GCC 編譯的,(這等於較新版本的 GCC wht 標志 -DGLIBCXX_USE_CXX11_ABI=0)。因此,如果使用官方 tensorflow 的現有上級應用程序/庫希望由 NO CXX 11 ABI 編譯,如果您希望應用程序/庫也與您編譯的 tensorflow 一起使用,那么您要么需要使用較舊的編譯器編譯它,要么使用帶有標志的新編譯器-DGLIBCXX_USE_CXX11_ABI=0


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM