解決 iOS 第三方 SDK 之間重複的 symbols 問題

發表於2016-12-08

前言:今天公司專案準備使用高德導航,其中用到了高德3D地圖SDK,然後就出現bug了。在真機上可以完美執行,但是在模擬器上,就出現了一大片的bug:提示有82個Duplicate symbols,仔細一看是MobileVLCKit和高德的MAMapKit之間的問題。(PS:今天是真心累啊,不過解決了bug,還是很值得的。)


現在,我就今天踩過的坑,做個簡單的整理,以備以後翻看。 也希望以後遇到類似坑的小夥伴們,可以有些許啟發和不同見解。


問題描述及猜想


111635397-5df828203c61f6ed

上圖為部分報錯內容。兩個第三方SDK之間在某些特定平臺存在一些duplicate symbols。分析:那是不是除掉其中一個SDK中相應平臺上,重複的那部分symbols,是不是就解決問題了呢?且繼續向下看。


解決問題


通過查詢資料,各種扒論壇,終於發現,跟我一起踩坑的小夥伴們還真不少。
然後通過借鑑他們的經驗,在對linux的相關語法實在小白的情況下,終於解決問題了,好感動啊!!!


工具介紹


lipo

lipo是管理Fat File的工具, 可以檢視平臺列表, 提取特定平臺, 重新打包。

nm

nm用來顯示一個程式包的符號表, 預設會顯示入口地址, 符號型別, 符號名。

strip

strip用來刪除程式裡的符號表。-R 用來指定一個要刪除的符號列表, 使用上述生成的symbols檔案.。新增 -S 選項來保留其他符號。

ar

ar可以檢視一個程式包裡的物件檔案列表, 解壓出其中的物件檔案並重新打包。

ld

ld蘋果系統下的連結器, 可以更精確的控制符號表的匯出。


具體步驟


因為擔心修改MobileVLCKit對已上線的視訊播放造成不可估計的影響,因此,此次修改MAMapKit,出現任何bug也可以儘快發現並解決。
下面將進行十分小白式的記錄(PS:主要是我太小白了。)

121635397-3c064e759c962b9f
lipo info MAMapKit

檢視MAMapKit的適用平臺,可以發現arm7,i386,x86_64,arm64均可用。並且前面bug只是存在於x86_64平臺上,那麼就先修改這個平臺的內容。

檔案瘦身,提取x86_64平臺的MAMapKit到新的檔案MAMapKit.x86_64,發現該檔案只有3M而已(原始檔20.2M),該檔案位置與MAMapKit相同,發現確實單個平臺的檔案比較小。

  • 獲取MAMapKit.x86_64檔案中以_png為字首的所有符號,生成符號列表並存於symbols檔案中。( -j 選項控制只輸出符號名)
  • 因為上面的symbols內容不是上述bug中包含的內容,因此,需要更改該symbols檔案,刪除裡面所有符號,將報錯的所有重複符號

這些符號依次輸入到該檔案中,每行一個。這就將本次需要刪除的符號存在符號列表中了。

131635397-3f1cd746032495aa
ar -t MAMapKit.x86_64

可以發現整個包中就一個主要檔案MAMapKit-x86_64-master.o檔案,這也是前面bug中提到的重名符號所在的位置。(PS:更確定找對了方法)

141635397-c24d651fe457924c
Duplicate symbols path

151635397-fdbd6568be7f9cd8
MAMapKit.x86_64 File Path

可以發現多出了三個檔案,也獲得了需要的MAMapKit-86_64-master.o檔案。

可以將symbols檔案中的符號列表在MAMapKit-x86_64-master.o檔案中刪除掉,並生成一個新的檔案MAMapKit-x86_64-master.o.strip。

  • 在執行此命令之前,可以將前面獲得MAMapKit.x86_64檔案放在其他位置作為對比。
  • 然後通過該命令得到一個新打包好的x86_64平臺包。
  • 也可以用以前的獲取symbols的方式從這個新包中獲取相應的_png的所有符號表,查詢剛才需要刪除的符號,驗證那些符號是否已被刪除。(很高興確實已經刪除了,這下問題應該可以解決了吧。)

下面將替換原有包中的x86_64平臺包。(該檔案中只修改了x86_64平臺的內容)

用上面生成的新包替換MAMapKit包中的x86_64平臺包,然後生成一個新的檔案包,最後將舊的MAMapKit包移除,其他多餘內容也一併移除,將MAMapKitTest更名為MAMapKit。至此,MAMapKit.framework看起來跟原來的沒有什麼區別了。(看事情不能只看表面哦,我們修改的是內在!)

多餘的話:如果修改多個平臺的包(因為我只需要修改x86_64這一個平臺包),可能需要重新生成一個新包更合適。

  • 根據前面的方法,生成每個平臺的新包;
  • 將所有新包對應各個平臺,生成一個新包。
161635397-6efac1acf17798c1
合成新包

上圖紅色標記即最後的合成新包方法。在此之前記得將前面更改過的x86_64平臺包拷貝到這些包的相同路徑下。

最後重新編譯工程,就這麼完美解決了!!!這一刻的感覺,太激動了。暫時未發現有什麼問題,以後有什麼由此衍生的bug,到時候再更新了。也希望小夥伴們共同學習,有問題大家一定要指出來喲!歡迎大家找我交流問題一起進步哦。


感謝下面兩位大神踩過的坑,有了它們的經驗,才讓我如此順利的解決問題!
[1]Mac系統下lipo, ar, nm等工具的使用簡介
[2]Lipo – 如何為ARMv7/ARMv7s/ARM64架構 建立通用檔案(Universal Files)](http://blog.csdn.net/volvet/article/details/50097563)

相關文章