iOS 解決一個因三方靜態庫沖突產生的duplicate symbol的問題


最近在開發項目時編譯三方.a時出現了沖突,原因是存在duplicate symbol。

<1>模擬器編譯時,應用的即時通訊模塊采用的三方庫(容聯雲),和視頻監控模塊采用的三方庫(海康威視)之間有沖突,無法編譯通過。

<2>真機編譯時,假如對other linker flags設置為-ObjC,海康威視自身的兩個.a文件存在沖突,假如不設置,CorePlot框架運行時會出現“selector not recognized”然后應用崩潰。

我真是頭都大了啊……

可以看到在針對模擬器架構下(x86_64)的文件會產生如下編譯錯誤:

 

這種情況一般都是文件里面使用C語言定義的全局變量名或是函數名,在導入的時候因為重復產生了沖突。

解決的方法:

1.對項目buildsetting里的other linker flags進行修改。

(參考下面的博客內容)

 

2.假如1不行,那只能重新打包三方庫了。

(刪除SDK內的重復的.o重新打包,詳細見:http://blog.csdn.net/djl4104804/article/details/43099061

 

other linker flags:

它的設置關乎到項目編譯時的鏈接方式。

根據一篇博客內容順便補腦下編譯過程:

從C代碼到可執行文件經歷的步驟是:源代碼 > 預處理器 > 編譯器 > 匯編器 > 機器碼 > 鏈接器 > 可執行文件

在最后一步需要把.o文件和C語言運行庫鏈接起來,這時候需要用到ld命令。源文件經過一系列處理以后,會生成對應的.obj文件,然后一個項目必然會有許多.obj文件,並且這些文件之間會有各種各樣的聯系,例如函數調用。鏈接器做的事就是把這些目標文件和所用的一些庫鏈接在一起形成一個完整的可執行文件。Other linker flags設置的值實際上就是ld命令執行時后面所加的參數

下面逐個介紹3個常用參數:
-ObjC:加了這個參數后,鏈接器就會把靜態庫中所有的Objective-C類和分類都加載到最后的可執行文件中
-all_load:會讓鏈接器把所有找到的目標文件都加載到可執行文件中,但是千萬不要隨便使用這個參數!假如你使用了不止一個靜態庫文件,然后又使用了這個參數,那么你很有可能會遇到ld: duplicate symbol錯誤,因為不同的庫文件里面可能會有相同的目標文件,所以建議在遇到-ObjC失效的情況下使用-force_load參數。
-force_load:所做的事情跟-all_load其實是一樣的,但是-force_load需要指定要進行全部加載的庫文件的路徑,這樣的話,你就只是完全加載了一個庫文件,不影響其余庫文件的按需加載

對於出現的問題我們一個個分析。

Q1:為什么不加-ObjC時,CorePlot會崩,出現“selector not recognized”情況?

“-Objc這個標志,和Objective-C的一個重要特性:類別(category)有關。根據這里的解釋,Unix的標准靜態庫實現和Objective-C的動態特性之間有一些沖突:Objective-C沒有為每個函數(或者方法)定義鏈接符號,它只為每個類創建鏈接符號。這樣當在一個靜態庫中使用類別來擴展已有類的時候,鏈接器不知道如何把類原有的方法和類別中的方法整合起來,就會導致你調用類別中的方法時,出現"selector not recognized",也就是找不到方法定義的錯誤。為了解決這個問題,引入了-ObjC標志,它的作用就是將靜態庫中所有的和對象相關的文件都加載進來。”

簡單的說就是,在沒有添加-ObjC的情況下,某些靜態庫中的Category函數是沒有被識別的,調用該函數時沒找到這個函數的指針,就報錯了。

 

Q2:真機編譯,為什么加-ObjC時,海康自身的SDK會出現duplicate symbol沖突?

在加入-ObjC標志后,編譯時會把所有OC文件都加載到可執行文件中,這樣的情況下,假如海康有2個OC文件中都用到同一個名字命名的變量或函數,就會出現重復定義的編譯錯誤。

 

Q3:如何解決有無-ObjC的矛盾?

使用-force_load加載特定的庫。

所以,目前對於真機的編譯問題我已經解決了,使用-force_load $(BUILT_PRODUCTS_DIR)/libCorePlot.a 以及-force_load $(PROJECT_DIR)/FuYang/Chat/YTX_iOS_IM_SDK_v5.1.6r/lib/libCCPiPhoneSDK_IMLib.a兩條規則來加載特定的.a文件,防止他們的部分函數符號沒建立的情況。

 

Q4:對於模擬器情況下兩個庫之間的.a文件沖突,有無解決辦法?

假如對other linker flag都未設置,卻出現了duplicate symbol的情況,那通過設置該標志只會讓情況更糟糕。

建議對.a庫重新打包,刪除部分重復的symbol。

具體如何操作.a靜態庫可以參考這篇文章:http://blog.csdn.net/djl4104804/article/details/43099061

 


免責聲明!

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



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