開發(fā)中經(jīng)常會(huì)遇到 Undefined symbols for architecture xxx
的錯(cuò)誤,
有時(shí)候用模擬器運(yùn)行好好的,用設(shè)備運(yùn)行就報(bào)錯(cuò)屋匕,即便是設(shè)備運(yùn)行好好的,執(zhí)行打包
Archive
時(shí)又出現(xiàn)這樣的錯(cuò)誤蒜哀,還有就是引用第三方靜態(tài)庫(Framework, lib.a)彪置,簡直就是比禽獸還禽獸拄踪。遇到這類問題先不要慌,分析問題所在悉稠,準(zhǔn)確定位出問題來源才是快速解決問題的關(guān)鍵宫蛆。
我們知道這些代表著 iOS 設(shè)備的指令集,不同 iOS 設(shè)備運(yùn)行需要的指令集是不同的:
指令集 | 設(shè)備 | 備注 |
---|---|---|
armv7 | iPhone 4, iPhone 4s, iPod 5G, iPad 3 | 真機(jī)32位 |
armv7s | iPhone 5, iPhone 5c, 舊版 iPod touch, iPad 4 | 真機(jī)32位(可能已經(jīng)消失了) |
arm64 | iPhone 5s 及以上版本的猛,iPad Air, Retina iPad Mini, 新版 iPod touch | 真機(jī)64位 |
x86_64 | iphone 6 及以上的模擬器 | 模擬器 64位 |
這些是在 Xcode 9.0
以上版本常用的耀盗,當(dāng)然還有 armv6
,i386
等對(duì)應(yīng) iPhone 3G
以前版本卦尊,iPhone 5
之前的模擬器叛拷,都已過時(shí),現(xiàn)在App 完全可以忽略岂却。
- 在運(yùn)行
Xcode
時(shí)忿薇,需要對(duì)指令集設(shè)置的地方在Targets -> Building Settings -> Architectures
中
Architectures
當(dāng)前適用的指令集即為 Valid Architectures
中設(shè)置的,如圖為 armv7 armv7s arm64
, 為什么要這樣設(shè)置完全是為了適應(yīng)現(xiàn)在市面上所有的 iOS 設(shè)備躏哩,并使各個(gè)設(shè)備發(fā)揮最佳性能署浩,指令集都是向下兼容的,armv7, armv7s
完全可以運(yùn)行在 arm64
指令集的設(shè)備上扫尺,但是反過來拿 arm64
運(yùn)行在 armv7, armv7s
就不行筋栋,就好比 32位程序可以在64位的機(jī)器上運(yùn)行(只是無法發(fā)揮出64位機(jī)器優(yōu)越性),但是64位程序卻無法在32位機(jī)器上運(yùn)行一樣正驻。
所以再遇到類似 Undefined symbols for archite xxx
的編譯問題的時(shí)候弊攘,先想想是否運(yùn)行的設(shè)備環(huán)境不對(duì)呢?
而 Build Active Architecture Only
代表是否僅編譯當(dāng)前適用的指令集姑曙,一般是 Debug -> YES
加快編譯速度襟交, Release -> NO
, 讓程序盡可能的適應(yīng)各種設(shè)備。當(dāng)然伤靠,如果 Valid Architectures
只設(shè)置了一種捣域,比如說必須在 arm64
環(huán)境下運(yùn)行,那這里設(shè)置 YES/NO
就沒什么意義了宴合。
- 指令集另一個(gè)必須注意的地方就是在制作靜態(tài)庫的時(shí)候焕梅,編譯不同的靜態(tài)庫會(huì)生成支持不同指令集的靜態(tài)庫,而編譯限定指令集的靜態(tài)庫往往是
Undefined symbols for archite xxx
的元兇形纺。
其中
sim.a
代碼用模擬器編譯生成的靜態(tài)庫丘侠,generic
代表 Build Only Device
徒欣, comb
代表所有指令集的集合逐样,,其它顧名思義。
由此可見:
1脂新、 模擬器生成的 sim.a
只支持 x86_64
挪捕,包的大小也最小,8MB争便;
2级零、iPhone 5S 和 iPhone 6SP 生產(chǎn)的 iphone5S.a
支持 arm64
,由于支持一樣的指令集滞乙,所以靜態(tài)包也大小一致奏纪,9.1MB;
3斩启、選擇 Generic iOS Device 生成的指令集包含 armv7 arm64
包的大小基本等同于 sim.a
和 iphone5S.a
之和序调,明顯大了許多;
這也是上面 Build Active Architecture Only
為什么對(duì) Debug
和
Release
做出不同設(shè)置的原因兔簇;
4发绢、一般的開發(fā)人員不會(huì)同時(shí)擁有所有機(jī)型的設(shè)備,尤其一些新的機(jī)型垄琐,動(dòng)輒上萬边酒,實(shí)在傷不起,沒有設(shè)備狸窘,適配還是要做啊墩朦,這就必須要做 模擬器 x86_64
支持,所以就有了后來的 comb.a
朦前,當(dāng)然如果開發(fā)完成后發(fā)布應(yīng)用介杆,完全可以不用做模擬器支持,生成的靜態(tài)包大小需要再加上 sim.a
的韭寸,需要 25.4 MB春哨。
當(dāng)然如果靜態(tài)庫代碼量不大,所有加起來也就幾MB甚至更少恩伺,對(duì)整體App大小影響微乎其微赴背,發(fā)布包也支持 x86_64
也是可以的,如果影響很大晶渠,那還是在發(fā)布的版本中盡量去掉對(duì)模擬器的支持凰荚。
(所有生成的指令集中,沒有發(fā)現(xiàn) armv7s
,感覺應(yīng)該蘋果默默的把這個(gè)指令集的支持集成到了 armv7
中)
為了驗(yàn)證這個(gè)問題,特意(厚著臉皮)去借來了個(gè) iPhone 5 馬上試了下
明顯的 armv7
, 也驗(yàn)證了自己的猜測褒脯,至于是否完全棄用便瑟,或者在舊版的 iPod
中有使用,由于沒有設(shè)備番川,實(shí)在無法驗(yàn)證到涂。
由此也可以看出來脊框,指令集包的大小是累加的,總包大小與分包大小之和是等同的践啄。
文章開始的報(bào)錯(cuò)圖源自把 sim.a
和 iphone6sp.a
合并后生成的 comlib.a
放入工程中浇雹,而后用這個(gè)打包且打包設(shè)備選擇的 Generic iOS Device
,因?yàn)檫@兩個(gè)指令集中都不含有 armv7
屿讽, 而 Generic iOS Device
必須含有 armv7
指令集昭灵,所以報(bào)錯(cuò)就出現(xiàn)了,于是就有了這篇文章伐谈。
當(dāng)再遇到到 Undefined symbols for architecture xxx
錯(cuò)誤時(shí)烂完,就不必慌張了,基本就曉得是哪里的問題了诵棵,當(dāng)然有些第三方框架可能并沒有做模擬器的支持 x86_64
窜护,如果無法更改源代碼,只能把調(diào)試的模擬器換成 iOS設(shè)備了非春。