前言:今天公司專案準備使用高德導航,其中用到了高德3D地圖SDK,然後就出現bug了。在真機上可以完美執行,但是在模擬器上,就出現了一大片的bug:提示有82個Duplicate symbols,仔細一看是MobileVLCKit和高德的MAMapKit之間的問題。(PS:今天是真心累啊,不過解決了bug,還是很值得的。)
現在,我就今天踩過的坑,做個簡單的整理,以備以後翻看。 也希望以後遇到類似坑的小夥伴們,可以有些許啟發和不同見解。
問題描述及猜想
上圖為部分報錯內容。兩個第三方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:主要是我太小白了。)
1 2 |
cd path(framework的路徑) lipo -info MAMapKit |
檢視MAMapKit的適用平臺,可以發現arm7,i386,x86_64,arm64均可用。並且前面bug只是存在於x86_64平臺上,那麼就先修改這個平臺的內容。
1 |
lipo -thin x86_64 MAMapKit -output MAMapKit.x86_64 |
檔案瘦身,提取x86_64平臺的MAMapKit到新的檔案MAMapKit.x86_64,發現該檔案只有3M而已(原始檔20.2M),該檔案位置與MAMapKit相同,發現確實單個平臺的檔案比較小。
1 |
nm -j MAMapKit.x86_64 | grep png > symbols |
- 獲取MAMapKit.x86_64檔案中以_png為字首的所有符號,生成符號列表並存於symbols檔案中。( -j 選項控制只輸出符號名)
- 因為上面的symbols內容不是上述bug中包含的內容,因此,需要更改該symbols檔案,刪除裡面所有符號,將報錯的所有重複符號
1 2 3 4 |
_png_do_invert _png_set_shift _png_get_user_transfom_ptr ... |
這些符號依次輸入到該檔案中,每行一個。這就將本次需要刪除的符號存在符號列表中了。
1 |
ar -t MAMapKit.x86_64 |
可以發現整個包中就一個主要檔案MAMapKit-x86_64-master.o檔案,這也是前面bug中提到的重名符號所在的位置。(PS:更確定找對了方法)
1 |
ar -x MAMapKit.x86_64 |
可以發現多出了三個檔案,也獲得了需要的MAMapKit-86_64-master.o檔案。
1 |
ld -x -r -unexported_symbols_list symbols MAMapKit-x86_64-master.o -o MAMapKit-x86_64-master.o.strip |
可以將symbols檔案中的符號列表在MAMapKit-x86_64-master.o檔案中刪除掉,並生成一個新的檔案MAMapKit-x86_64-master.o.strip。
1 |
ar -r MAMapKit.x86_64 MAMapKit-x86_64-master.o.strip Pods-MAMapKit-dummy.o |
- 在執行此命令之前,可以將前面獲得MAMapKit.x86_64檔案放在其他位置作為對比。
- 然後通過該命令得到一個新打包好的x86_64平臺包。
- 也可以用以前的獲取symbols的方式從這個新包中獲取相應的_png的所有符號表,查詢剛才需要刪除的符號,驗證那些符號是否已被刪除。(很高興確實已經刪除了,這下問題應該可以解決了吧。)
下面將替換原有包中的x86_64平臺包。(該檔案中只修改了x86_64平臺的內容)
1 |
lipo MAMapKit -replace x86_64 MAMapKit.x86_64 -output MAMapKitTest |
用上面生成的新包替換MAMapKit包中的x86_64平臺包,然後生成一個新的檔案包,最後將舊的MAMapKit包移除,其他多餘內容也一併移除,將MAMapKitTest更名為MAMapKit。至此,MAMapKit.framework看起來跟原來的沒有什麼區別了。(看事情不能只看表面哦,我們修改的是內在!)
多餘的話:如果修改多個平臺的包(因為我只需要修改x86_64這一個平臺包),可能需要重新生成一個新包更合適。
- 根據前面的方法,生成每個平臺的新包;
- 將所有新包對應各個平臺,生成一個新包。
上圖紅色標記即最後的合成新包方法。在此之前記得將前面更改過的x86_64平臺包拷貝到這些包的相同路徑下。
最後重新編譯工程,就這麼完美解決了!!!這一刻的感覺,太激動了。暫時未發現有什麼問題,以後有什麼由此衍生的bug,到時候再更新了。也希望小夥伴們共同學習,有問題大家一定要指出來喲!歡迎大家找我交流問題一起進步哦。
感謝下面兩位大神踩過的坑,有了它們的經驗,才讓我如此順利的解決問題!
[1]Mac系統下lipo, ar, nm等工具的使用簡介
[2]Lipo – 如何為ARMv7/ARMv7s/ARM64架構 建立通用檔案(Universal Files)](http://blog.csdn.net/volvet/article/details/50097563)