iOS 解決一個因三方靜態(tài)庫沖突產(chǎn)生的duplicate symbol的問題

轉(zhuǎn)自:http://www.cnblogs.com/rayshen/p/5160218.html

最近在開發(fā)項目時編譯三方.a時出現(xiàn)了沖突,原因是存在duplicate symbol。

<1>模擬器編譯時,應(yīng)用的即時通訊模塊采用的三方庫(容聯(lián)云),和視頻監(jiān)控模塊采用的三方庫(??低暎┲g有沖突,無法編譯通過。

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

我真是頭都大了啊……

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

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

解決的方法:

1.對項目buildsetting里的other linker flags進(jìn)行修改。

(參考下面的博客內(nèi)容)

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

(刪除SDK內(nèi)的重復(fù)的.o重新打包,詳細(xì)見:http://blog.csdn.net/djl4104804/article/details/43099061)

other linker flags:

它的設(shè)置關(guān)乎到項目編譯時的鏈接方式。

根據(jù)一篇博客內(nèi)容順便補(bǔ)腦下編譯過程:

從C代碼到可執(zhí)行文件經(jīng)歷的步驟是:源代碼 > 預(yù)處理器 > 編譯器 > 匯編器 > 機(jī)器碼 > 鏈接器 > 可執(zhí)行文件

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

下面逐個介紹3個常用參數(shù):

-ObjC:加了這個參數(shù)后,鏈接器就會把靜態(tài)庫中所有的Objective-C類和分類都加載到最后的可執(zhí)行文件中

-all_load:會讓鏈接器把所有找到的目標(biāo)文件都加載到可執(zhí)行文件中,但是千萬不要隨便使用這個參數(shù)!假如你使用了不止一個靜態(tài)庫文件,然后又使用了這個參數(shù),那么你很有可能會遇到ld: duplicate symbol錯誤,因為不同的庫文件里面可能會有相同的目標(biāo)文件,所以建議在遇到-ObjC失效的情況下使用-force_load參數(shù)。

-force_load:所做的事情跟-all_load其實是一樣的,但是-force_load需要指定要進(jìn)行全部加載的庫文件的路徑,這樣的話,你就只是完全加載了一個庫文件,不影響其余庫文件的按需加載

對于出現(xiàn)的問題我們一個個分析。

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

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

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

Q2:真機(jī)編譯,為什么加-ObjC時,??底陨淼腟DK會出現(xiàn)duplicate symbol沖突?

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

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

使用-force_load加載特定的庫。

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

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

假如對other linker flag都未設(shè)置,卻出現(xiàn)了duplicate symbol的情況,那通過設(shè)置該標(biāo)志只會讓情況更糟糕。

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

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

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容