iOS armv7, armv7s, arm64區(qū)別與應(yīng)用32位、64位配置

iOS armv7, armv7s, arm64區(qū)別與應(yīng)用32位、64位配置

歷程

  1. 2015年2月1日不允許不支持arm64的應(yīng)用的提交;
  2. iOS10發(fā)布后,如果你的應(yīng)用中使用到了32位的類、庫(kù),沒(méi)有相應(yīng)支持64位機(jī)型的庫(kù),則首次啟動(dòng)后會(huì)彈窗式提示:“ xxx可能使iPhone變慢...”;
  3. iOS10.3公測(cè)版發(fā)布:封殺32位應(yīng)用;
  4. 蘋(píng)果系統(tǒng)(iOS7/iOS8-iOS9),32位的framework和64位的framework是共存的,所以如果所有的應(yīng)用都是64位的話,系統(tǒng)就自動(dòng)不加載32位的framework,這樣可以少占用資源,另外對(duì)運(yùn)行的速度是有好處的,也就是說(shuō),你會(huì)感覺(jué)手機(jī)運(yùn)行的快了一點(diǎn)。應(yīng)用在兼容64位系統(tǒng)后,內(nèi)存的占用肯定會(huì)變多一點(diǎn),不過(guò)性能也有相應(yīng)的提升。

下面了解下64與32位的區(qū)別:

數(shù)據(jù)類型的變化:
  1. 在32位的年代,使用的是IPL32的規(guī)范,到了64位之后,改成了LP64規(guī)范。
  2. 數(shù)據(jù)類型里面,NSInteger在32位時(shí)等同于int,在64位時(shí)等同于long,而這個(gè)數(shù)據(jù)結(jié)構(gòu)使用很廣,很多不規(guī)范的時(shí)候會(huì)直接和int替換使用,在32位是毫無(wú)問(wèn)題,但在64位時(shí),這就是隱患了。CGFloat也有同樣的問(wèn)題
  3. 如果使用了偏移量來(lái)訪問(wèn)struct的項(xiàng),那么需要認(rèn)真仔細(xì)的檢查,其余的還算好,當(dāng)然如果你用了malloc,那么也請(qǐng)檢查一下分配的內(nèi)存大小,建議是多使用sizeof來(lái)幫助計(jì)算。
  4. 方法調(diào)用上的變化:在64位系統(tǒng)在運(yùn)行時(shí)調(diào)用函數(shù)和32位系統(tǒng)是不同的。主要的區(qū)別在于傳遞具有可變參數(shù)個(gè)數(shù)的函數(shù)的參數(shù)時(shí),我們來(lái)看下面的代碼:
    int fixedFunction(int a, int b);  
    int variadicFunction(int a, ...); 
       int main  
    {  
    int value2 = fixedFunction(5,5);  
    int value1 = variadicFunction(5,5);  
    }
    
    第一個(gè)函數(shù)是固定傳入2個(gè)參數(shù),第二個(gè)函數(shù)是參數(shù)個(gè)數(shù)不定的,在使用中,也
    傳入了2個(gè)參數(shù)。在32位系統(tǒng)下,這兩個(gè)函數(shù)的參數(shù)傳遞是非常類似的,在64
    位系統(tǒng)下,這兩者就是截然不同了。
  5. 項(xiàng)目中使用的第三方庫(kù)肯定需要支持64位系統(tǒng),否則還是白搭。大家需要檢查自己使用的第三方的庫(kù),看是否支持64位的版本。蘋(píng)果系統(tǒng)中(iOS7/iOS8-iOS9),32位的framework和64位的framework是共存的,所以如果所有的應(yīng)用都是64位的話,系統(tǒng)就自動(dòng)不加載32位的framework,這樣可以少占用資源,另外對(duì)運(yùn)行的速度是有好處的,也就是說(shuō),你會(huì)感覺(jué)手機(jī)運(yùn)行的快了一點(diǎn)。應(yīng)用在兼容64位系統(tǒng)后,內(nèi)存的占用肯定會(huì)變多一點(diǎn),不過(guò)性能也有相應(yīng)的提升。

增加應(yīng)用對(duì)64位的支持:

一、配置前確認(rèn)工作:

如果你不能確定庫(kù)是否支持了arm64,可以在cmd模式下用file命令來(lái)檢查一下庫(kù)文件:

$lipo -info /Users/xxx/NHPushStreamSDK/FFmpeg-iOS/lib/libavcodec.a
//指令說(shuō)明:lipo -info 靜態(tài)庫(kù)(動(dòng)態(tài)庫(kù))文件完整路徑

armv7,armv7s和arm64,i386,x86_64這些都代表什么?

  • armv7|armv7s|arm64都是ARM處理器的指令集
  • i386|x86_64 是Mac處理器的指令集

了解ARM

__Arm處理器,因?yàn)槠涞凸暮托〕叽缍劽瑤缀跛械氖謾C(jī)處理器都基于arm,其在嵌入式系統(tǒng)中的應(yīng)用非常廣泛,它的性能在同等功耗產(chǎn)品中也很出色。

Armv6、armv7、armv7s、arm64都是arm處理器的指令集,所有指令集原則上都是向下兼容的,如iPhone4S的CPU默認(rèn)指令集為armv7指令集,但它同時(shí)也兼容armv6指令集,只是使用armv6指令集時(shí)無(wú)法充分發(fā)揮其性能,即無(wú)法使用armv7指令集中的新特性,同理,iPhone5的處理器標(biāo)配armv7s指令集,同時(shí)也支持armv7指令集,只是無(wú)法進(jìn)行相關(guān)的性能優(yōu)化,從而導(dǎo)致程序的執(zhí)行效率沒(méi)那么高。

這些指令集在哪些設(shè)備中有用到呢?

arm64 armv7s armv7
iPhone6s iPhone5 iPhone4
iphone6s plus iPhone5C iPhone4S
iphone6 iPad4(iPad with Retina Display) iPad
iphone6 plus iPad2
iphone5s iPad3(The New iPad)
iPad Air iPad mini
iPad mini2 (iPad mini with Retina Display) iPod Touch 3G
iPod Touch4

i386是針對(duì)intel通用微處理器32位處理器
x86_64是針對(duì)x86架構(gòu)的64位處理器

模擬器32位處理器測(cè)試需要i386架構(gòu),
模擬器64位處理器測(cè)試需要x86_64架構(gòu),
真機(jī)32位處理器需要armv7,或者armv7s架構(gòu),
真機(jī)64位處理器需要arm64架構(gòu)。

Xcode Build Setting中指令集相關(guān)選項(xiàng)釋義
  1. Architectures
    指定工程被編譯成可支持哪些指令集類型,而支持的指令集越多,就會(huì)編譯出包含多個(gè)指令集代碼的數(shù)據(jù)包,對(duì)應(yīng)生成二進(jìn)制包就越大,也就是ipa包會(huì)變大(Space-separated list of identifiers. Specifies the architectures (ABIs, processor models) to which the binary is targeted. When this build setting specifies more than one architecture, the generated binary may contain object code for each of the specified architectures. )。

  2. Valid Architectures
    限制可能被支持的指令集的范圍,也就是Xcode編譯出來(lái)的二進(jìn)制包類型最終從這些類型產(chǎn)生,而編譯出哪種指令集的包,將由Architectures與Valid Architectures(因此這個(gè)不能為空)的交集來(lái)確定(Space-separated list of identifiers. Specifies the architectures for which the binary may be built. During the build, this list is intersected with the value of ARCHS build setting; the resulting list specifies the architectures the binary can run on. If the resulting architecture list is empty, the target generates no binary.)。

  3. Build Active Architecture Only
    指定是否只對(duì)當(dāng)前連接設(shè)備所支持的指令集編譯
    當(dāng)其值設(shè)置為YES,這個(gè)屬性設(shè)置為yes,是為了debug的時(shí)候編譯速度更快,它只編譯當(dāng)前的architecture版本,而設(shè)置為no時(shí),會(huì)編譯所有的版本。 所以,一般debug的時(shí)候可以選擇設(shè)置為yes,release的時(shí)候要改為no,以適應(yīng)不同設(shè)備。



二、工程配置,增加64位的支持

note:在Xcode6.1.1及以上 Valid Architectures 設(shè)置里, 默認(rèn)為 Standard architectures(armv7,arm64),如果你想改的話,自己在other中更改。

  • 使用 standard architectures (including 64-bit)(armv7,arm64) 參數(shù),則打的包里面有32位、64位兩份代碼,在iPhone5s( iPhone5s的cpu是64位的 )下,會(huì)首選運(yùn)行64位代碼包, 其余的iPhone( 其余iPhone都是32位的,iPhone5c也是32位 ),只能運(yùn)行32位包,但是包含兩種架構(gòu)的代碼包,只有運(yùn)行在ios6,ios7系統(tǒng)上。 這也就是說(shuō),這種打包方式,對(duì)手機(jī)幾乎沒(méi)要求,但是對(duì)系統(tǒng)有要求,即ios6以上。
  • 使用 standard architectures (armv7,armv7s) 參數(shù), 則打的包里只有32位代碼, iPhone5s的cpu是64位,但是可以兼容32位代碼,即可以運(yùn)行32位代碼。但是這會(huì)降低iPhone5s的性能。 其余的iPhone對(duì)32位代碼包更沒(méi)問(wèn)題, 而32位代碼包,對(duì)系統(tǒng)也幾乎也沒(méi)什么限制。
  • 要發(fā)揮iPhone5s及以上的64位機(jī)型性能,就要包含64位包,那么系統(tǒng)最低要求為ios6。 如果要兼容ios5以及更低的系統(tǒng),只能打32位的包,系統(tǒng)都能通用,但是會(huì)喪失iPhone5s的性能。

Valid Architectures與Architectures指令集交集表:

Valid Architectures設(shè)置 Architectures設(shè)置 生成二進(jìn)制包支持的指令集(取交集)
armv7, armv7s, arm64 armv7s armv7s
armv7, armv7s armv7s,arm64 armv7s
armv7, armv7s, arm64 armv6, armv7s, arm64 armv7s, arm64
armv6, armv7, armv7s armv6, armv7s, arm64 armv6, armv7s
armv7, arm64 ,armv7s armv7, arm64 ,armv7s armv7, arm64 ,armv7s
armv7, armv7s, arm64 armv7,armv7s armv7s, armv7
  1. 比如 Valid Architectures設(shè)置的支持arm指令集版本有:armv7/armv7s/arm64,對(duì)應(yīng)的Architectures設(shè)置的支持arm指令集版本有:armv7s,這時(shí)Xcode只會(huì)生成一個(gè)armv7s指令集的二進(jìn)制包。
  2. xcode默認(rèn)的設(shè)置:
    Architectures : Strandard architectures - $(ARCHS_STANDARD) //相當(dāng)于arm64 armv7s armv7
    Valid Architectures : arm64 armv7s armv7
  3. 如果你對(duì)ipa安裝包大小有要求,可以減少安裝包的指令集的數(shù)量,這樣就可以盡可能的減少包的大小。
自定設(shè)置

系統(tǒng)默認(rèn)設(shè)置


制作靜態(tài)庫(kù).a是指令集選擇

現(xiàn)在回歸到正題,如何制作一個(gè)“沒(méi)有問(wèn)題”的.a靜態(tài)庫(kù),通過(guò)以上信息了解到,當(dāng)我們做App的時(shí)候,為了追求高效率,并且減小包的大小,Build Active Architecture Only設(shè)置成YES,Architectures按Xcode默認(rèn)配置就可以,因?yàn)閍rm64向前兼容。但制作.a靜態(tài)庫(kù)就不同了,因?yàn)橐WC兼容性,包括不同iOS設(shè)備以及模擬器運(yùn)行不出錯(cuò),所以結(jié)合當(dāng)前行業(yè)情況,要做到最大的兼容性。
ValidArchitectures設(shè)置為:armv7|armv7s|arm64|i386|x86_64
Architectures設(shè)置不變(或根據(jù)你需要): armv7|arm64
然后分別選擇iOS設(shè)備和模擬器進(jìn)行編譯,最后找到相關(guān)的.a進(jìn)行合包:

  • 合并兩個(gè)不同構(gòu)架的庫(kù)文件
$ lipo -create /Users/xxxxxx/lib/libv7.a  /Users/xxxxxx/lib/lib64.a  -output /Users/xxxxxx/lib/lib.a
//指令說(shuō)明: lipo -create 庫(kù)文件1一完整路徑  庫(kù)文件2完整路徑  -output 輸出的文件名路徑
  • 從某個(gè)庫(kù)文件中提起出指定構(gòu)架的庫(kù)文件
Desktop$ lipo -thin arm64 debugserver -output debugserver2
//指令說(shuō)明:lipo -thin 對(duì)應(yīng)構(gòu)架指令 對(duì)應(yīng)文件 -output 輸出的文件名路徑

使用lipo -create 真機(jī)庫(kù).a的路徑 模擬器庫(kù).a的的路徑 -output 合成庫(kù)的名字.a ,這樣就制作了一個(gè)通用的靜態(tài)庫(kù).a。
制作動(dòng)態(tài)、靜態(tài)庫(kù)詳情可以參考【鏈接】


其它注意點(diǎn):

  1. 因此如果一些程序中使用的靜態(tài)庫(kù)不支持armv7s,而你的工程支持armv7s時(shí),就會(huì)出現(xiàn)“xxxx does not contain a(n) armv7s slice:xxxxx for architecture armv7s"的編譯錯(cuò)誤,想要解決這個(gè)問(wèn)題,有兩個(gè)方法:
    1. 如果是開(kāi)源的,能夠找到源代碼,則可以用源代碼重新打一個(gè)支持armv7s的libaray, 或者在工程中直接使用源代碼,而不是靜態(tài)庫(kù)。
    2. 如果不是開(kāi)源的,要么就坐等第三方庫(kù)的支持,要么就暫時(shí)讓你的工程不支持armv7s。
  2. 此外,模擬器并不運(yùn)行arm代碼,軟件會(huì)被編譯成x86可以運(yùn)行的指令。所以生成靜態(tài)庫(kù)時(shí)都是會(huì)先生成兩個(gè).a,一個(gè)是i386的用于在模擬器運(yùn)行,另一個(gè)是在真實(shí)設(shè)備上運(yùn)行的,然后再用命令將兩個(gè).a合并成一個(gè)。
  3. 需要注意的是iOS模擬器沒(méi)有運(yùn)行arm指令集,編譯運(yùn)行的是x86指令集,所以,只有在iOS設(shè)備上,才會(huì)執(zhí)行設(shè)備對(duì)應(yīng)的arm指令集。
  4. 連接的手機(jī)指令集匹配是由高到低(arm64 > armv7s > armv7)依次匹配的。

部份資源鏈接

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容