EAXBLE_BITCODE在Xcode 7中做什么?
我有embedded位码术语的问题。
什么是embedded式位码?
何时启用,在新的Xcode的ENABLE_BITCODE
?
当启用Xcode 7中的ENABLE_BITCODE
时,会发生什么情况?
位码是指发送到iTunes Connect的代码types:“LLVM位码”。 这允许Apple使用某些计算来进一步重新优化应用程序(例如:可能缩小可执行文件大小)。 如果苹果需要改变你的可执行文件,那么他们可以做到这一点,而不需要上传新的版本
这不同于: 切片这是苹果基于设备的分辨率和体系结构优化用户设备的应用程序的过程。 切片不需要位码。 (例如:只包括@ 5张5倍的图像)
应用程序细化是切片,位代码和按需资源的组合
位码是编译程序的中间表示。 包含位码的上传到iTunes Connect的应用程序将在App Store上编译和链接。 包括位码将允许苹果在将来重新优化您的应用程序二进制文件,而无需将新版本的应用程序提交给商店。
苹果关于应用程序细化的文档
什么是embedded式位码?
根据文档 :
位码是编译程序的中间表示。 包含位码的上传到iTunes Connect的应用程序将在App Store上编译和链接。 包括位码将允许苹果在将来重新优化您的应用程序二进制文件,而无需将新版本的应用程序提交给商店。
更新: “Xcode 7中的新function”中的这句话使我想了很长一段时间,为了减less应用程序的大小,需要使用Bitcode :
当您存档提交到App Store时,Xcode会将您的应用程序编译为中间表示。 App Store会根据需要将位代码编译成64位或32位可执行文件。
然而,事实并非如此, Bitcode和Slicing是独立工作的: 切片是关于减小应用程序大小和生成应用程序包变体, Bitcode是关于某些二进制优化。 我通过检查包含在非bitcode应用程序的可执行文件中的体系结构来validation这一点,并发现它们只包含必要的。
Bitcode允许其他名称为Slicing的 应用程序细化组件为特定的架构生成特定的可执行文件的应用程序包变体,例如,iPhone 5S变体将仅包含arm64可执行文件,iPad Mini armv7等。
何时在新的Xcode中启用ENABLE_BITCODE?
对于iOS应用程序,位代码是默认的,但是可选的。 如果你提供位码,应用程序包中的所有应用程序和框架都需要包含位码。 对于watchOS和tvOS应用程序,位码是必需的。
在新的Xcode中启用ENABLE_BITCODE时,二进制文件会发生什么?
从Xcode 7参考:
激活此设置表示目标或项目应在编译期间为支持它的平台和体系结构生成位代码。 对于存档构build,位代码将在链接的二进制文件中生成,以提交给app store。 对于其他版本,编译器和链接器将检查代码是否符合位代码生成的要求,但不会生成实际的位代码。
以下是一些有助于深入了解Bitcode的链接 :
- 位代码解密
- 为什么我不启用位码
就位代码和启用位代码而言,首先需要了解的是从这里开始的故事。
所以,基本上如果我谈到iOS 9中引入的ENABLE_BITCODE ,就是应用程序细化过程的一部分。
这是问题的一部分,它回答说:“ 苹果公司是如何将iOS 9的存储容量从5GB减less到1GB的?
这是由于一项名为“App Thinning”的新技术
应用程序细化到底是什么?
App Thinning将iOS 9 OTA更新从4.6GB降低到1.3GB,减less了71%。 这不仅将有助于未来的OTA更新,而且开发人员可以利用该技术来减less第三方应用程序所需的存储空间。
应用细化基本上有三个组成部分,即分片,比特码和按需资源。
应用程序切片 :iOS应用程序是为了在各种设备上运行而开发的,所以它们提供了代码来支持所有这些设备,无论您的特定设备是否需要它。 应用程序切片将允许您的设备只下载我们的设备所需的文件。 示例:如果您正在运行4英寸型号,则不需要3x iPhone 6 Plus资产。
按需资源(ODR) :它的工作原理是,应用程序可能在任何时候都不需要整个资源库,因此可以根据需要下载或删除部分资源。 开发人员可以通过将部分代码标记为ODR来指定需要什么代码。 这些部分将在需要时自动从App Store下载,并在不再需要时删除。
位码 :指的是开发人员上传到App Store的应用程序的“中间表示”,而不是预编译的二进制文件。 这与App Slicing一起工作,允许根据需要将位编码编译为32位或64位,具体取决于下载设备。 这也将允许Apple自动实现的任何编译器改进,而不是让开发者重新提交他们的应用程序。
由于确切的问题是“什么使bitcode做”,我想提供一些我迄今弄清楚的技术细节。 在苹果公司发布这个编译器的源代码之前,大部分的这些实际上是不可能100%确定的
首先,苹果的位码不像LLVM字节码那样。 至less,我还没有弄清楚他们之间的任何相似之处。 它似乎有一个专有的标题(总是以“xar!”开头),可能还有一些链接时参考魔术可以防止数据重复。 如果你写出一个硬编码的string,这个string只会被放入数据一次,而不是正常的LLVM字节码所期望的两倍。
其次,bitcode在二进制档案库中并不是真正作为一个单独的体系结构提供的。 它没有像x86和ARM被放入一个二进制文件(FAT归档文件)一样运输。 相反,他们在架构特定的MachO二进制文件中使用了一个名为“__LLVM”的特殊部分,这个二进制文件随每个支持的体系结构(即重复的)一起提供。 我认为这是他们的编译器系统的一个短暂的未来,可能会被修复,以避免重复。
C代码(用clang -fembed-bitcode hi.c -S -emit-llvm
编译):
#include <stdio.h> int main() { printf("hi there!"); return 0; }
LLVM红外输出:
; ModuleID = '/var/folders/rd/sv6v2_f50nzbrn4f64gnd4gh0000gq/T/hi-a8c16c.bc' target datalayout = "em:o-i64:64-f80:128-n8:16:32:64-S128" target triple = "x86_64-apple-macosx10.10.0" @.str = private unnamed_addr constant [10 x i8] c"hi there!\00", align 1 @llvm.embedded.module = appending constant [1600 x i8] c"\DE\C0\17\0B\00\00\00\00\14\00\00\00$\06\00\00\07\00\00\01BC\C0\DE!\0C\00\00\86\01\00\00\0B\82 \00\02\00\00\00\12\00\00\00\07\81#\91A\C8\04I\06\1029\92\01\84\0C%\05\08\19\1E\04\8Bb\80\10E\02B\92\0BB\84\102\148\08\18I\0A2D$H\0A\90!#\C4R\80\0C\19!r$\07\C8\08\11b\A8\A0\A8@\C6\F0\01\00\00\00Q\18\00\00\C7\00\00\00\1Bp$\F8\FF\FF\FF\FF\01\90\00\0D\08\03\82\1D\CAa\1E\E6\A1\0D\E0A\1E\CAa\1C\D2a\1E\CA\A1\0D\CC\01\1E\DA!\1C\C8\010\87p`\87y(\07\80p\87wh\03s\90\87ph\87rh\03xx\87tp\07z(\07yh\83r`\87th\07\80\1E\E4\A1\1E\CA\01\18\DC\E1\1D\DA\C0\1C\E4!\1C\DA\A1\1C\DA\00\1E\DE!\1D\DC\81\1E\CAA\1E\DA\A0\1C\D8!\1D\DA\A1\0D\DC\E1\1D\DC\A1\0D\D8\A1\1C\C2\C1\1C\00\C2\1D\DE\A1\0D\D2\C1\1D\CCa\1E\DA\C0\1C\E0\A1\0D\DA!\1C\E8\01\1D\00s\08\07v\98\87r\00\08wx\876p\87pp\87yh\03s\80\876h\87p\A0\07t\00\CC!\1C\D8a\1E\CA\01 \E6\81\1E\C2a\1C\D6\A1\0D\E0A\1E\DE\81\1E\CAa\1C\E8\E1\1D\E4\A1\0D\C4\A1\1E\CC\C1\1C\CAA\1E\DA`\1E\D2A\1F\CA\01\C0\03\80\A0\87p\90\87s(\07zh\83q\80\87z\00\C6\E1\1D\E4\A1\1C\E4\00 \E8!\1C\E4\E1\1C\CA\81\1E\DA\C0\1C\CA!\1C\E8\A1\1E\E4\A1\1C\E6\01X\83y\98\87y(\879`\835\18\07|\88\03;`\835\98\87y(\076X\83y\98\87r\90\036X\83y\98\87r\98\03\80\A8\07w\98\87p0\87rh\03s\80\876h\87p\A0\07t\00\CC!\1C\D8a\1E\CA\01 \EAa\1E\CA\A1\0D\E6\E1\1D\CC\81\1E\DA\C0\1C\D8\E1\1D\C2\81\1E\00s\08\07v\98\87r\006\C8\88\F0\FF\FF\FF\FF\03\C1\0E\E50\0F\F3\D0\06\F0 \0F\E50\0E\E90\0F\E5\D0\06\E6\00\0F\ED\10\0E\E4\00\98C8\B0\C3<\94\03@\B8\C3;\B4\819\C8C8\B4C9\B4\01<\BCC:\B8\03=\94\83<\B4A9\B0C:\B4\03@\0F\F2P\0F\E5\00\0C\EE\F0\0Em`\0E\F2\10\0E\EDP\0Em\00\0F\EF\90\0E\EE@\0F\E5 \0FmP\0E\EC\90\0E\ED\D0\06\EE\F0\0E\EE\D0\06\ECP\0E\E1`\0E\00\E1\0E\EF\D0\06\E9\E0\0E\E60\0Fm`\0E\F0\D0\06\ED\10\0E\F4\80\0E\809\84\03;\CCC9\00\84;\BCC\1B\B8C8\B8\C3<\B4\819\C0C\1B\B4C8\D0\03:\00\E6\10\0E\EC0\0F\E5\00\10\F3@\0F\E10\0E\EB\D0\06\F0 \0F\EF@\0F\E50\0E\F4\F0\0E\F2\D0\06\E2P\0F\E6`\0E\E5 \0Fm0\0F\E9\A0\0F\E5\00\E0\01@\D0C8\C8\C39\94\03=\B4\C18\C0C=\00\E3\F0\0E\F2P\0Er\00\10\F4\10\0E\F2p\0E\E5@\0Fm`\0E\E5\10\0E\F4P\0F\F2P\0E\F3\00\AC\C1<\CC\C3<\94\C3\1C\B0\C1\1A\8C\03>\C4\81\1D\B0\C1\1A\CC\C3<\94\03\1B\AC\C1<\CCC9\C8\01\1B\AC\C1<\CCC9\CC\01@\D4\83;\CCC8\98C9\B4\819\C0C\1B\B4C8\D0\03:\00\E6\10\0E\EC0\0F\E5\00\10\F50\0F\E5\D0\06\F3\F0\0E\E6@\0Fm`\0E\EC\F0\0E\E1@\0F\809\84\03;\CCC9\00\00I\18\00\00\02\00\00\00\13\82`B \00\00\00\89 \00\00\0D\00\00\002\22\08\09 d\85\04\13\22\A4\84\04\13\22\E3\84\A1\90\14\12L\88\8C\0B\84\84L\100s\04H*\00\C5\1C\01\18\94`\88\08\AA0F7\10@3\02\00\134|\C0\03;\F8\05;\A0\836\08\07x\80\07v(\876h\87p\18\87w\98\07|\88\038p\838\80\037\80\83\0DeP\0Em\D0\0Ez\F0\0Em\90\0Ev@\07z`\07t\D0\06\E6\80\07p\A0\07q \07x\D0\06\EE\80\07z\10\07v\A0\07s \07z`\07t\D0\06\B3\10\07r\80\07:\0FDH #EB\80\1D\8C\10\18I\00\00@\00\00\C0\10\A7\00\00 \00\00\00\00\00\00\00\868\08\10\00\02\00\00\00\00\00\00\90\05\02\00\00\08\00\00\002\1E\98\0C\19\11L\90\8C\09&G\C6\04C\9A\22(\01\0AM\D0i\10\1D]\96\97C\00\00\00y\18\00\00\1C\00\00\00\1A\03L\90F\02\134A\18\08&PIC Level\13\84a\D80\04\C2\C05\08\82\83c+\03ab\B2j\02\B1+\93\9BK{s\03\B9q\81q\81\01A\19c\0Bs;k\B9\81\81q\81q\A9\99q\99I\D9\10\14\8D\D8\D8\EC\DA\5C\DA\DE\C8\EA\D8\CA\5C\CC\D8\C2\CE\E6\A6\04C\1566\BB6\974\B227\BA)A\01\00y\18\00\002\00\00\003\08\80\1C\C4\E1\1Cf\14\01=\88C8\84\C3\8CB\80\07yx\07s\98q\0C\E6\00\0F\ED\10\0E\F4\80\0E3\0CB\1E\C2\C1\1D\CE\A1\1Cf0\05=\88C8\84\83\1B\CC\03=\C8C=\8C\03=\CCx\8Ctp\07{\08\07yH\87pp\07zp\03vx\87p \87\19\CC\11\0E\EC\90\0E\E10\0Fn0\0F\E3\F0\0E\F0P\0E3\10\C4\1D\DE!\1C\D8!\1D\C2a\1Ef0\89;\BC\83;\D0C9\B4\03<\BC\83<\84\03;\CC\F0\14v`\07{h\077h\87rh\077\80\87p\90\87p`\07v(\07v\F8\05vx\87w\80\87_\08\87q\18\87r\98\87y\98\81,\EE\F0\0E\EE\E0\0E\F5\C0\0E\EC\00q \00\00\05\00\00\00&`<\11\D2L\85\05\10\0C\804\06@\F8\D2\14\01\00\00a \00\00\0B\00\00\00\13\04A,\10\00\00\00\03\00\00\004#\00dC\19\020\18\83\01\003\11\CA@\0C\83\11\C1\00\00#\06\04\00\1CB\12\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00", section "__LLVM,__bitcode" @llvm.cmdline = appending constant [67 x i8] c"-triple\00x86_64-apple-macosx10.10.0\00-emit-llvm\00-disable-llvm-optzns\00", section "__LLVM,__cmdline" ; Function Attrs: nounwind ssp uwtable define i32 @main() #0 { %1 = alloca i32, align 4 store i32 0, i32* %1 %2 = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([10 x i8]* @.str, i32 0, i32 0)) ret i32 0 } declare i32 @printf(i8*, ...) #1 attributes #0 = { nounwind ssp uwtable "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="core2" "target-features"="+ssse3,+cx16,+sse,+sse2,+sse3" "unsafe-fp-math"="false" "use-soft-float"="false" } attributes #1 = { "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="core2" "target-features"="+ssse3,+cx16,+sse,+sse2,+sse3" "unsafe-fp-math"="false" "use-soft-float"="false" } !llvm.module.flags = !{!0} !llvm.ident = !{!1} !0 = !{i32 1, !"PIC Level", i32 2} !1 = !{!"Apple LLVM version 7.0.0 (clang-700.0.53.3)"}
IR中的数据arrays也根据铛的优化和其他代码生成设置而改变。 我完全不知道这是什么格式或任何东西。
编辑:
在Twitter上的提示后,我决定重新审视这一点,并确认它。 我跟着这个博客文章,并使用他的位码提取工具从MachO可执行文件中获取Apple Archive二进制文件。 用xar实用工具解压苹果档案后,我得到了这个(当然是用llvm-dis转换成文本)
; ModuleID = '1' target datalayout = "em:o-i64:64-f80:128-n8:16:32:64-S128" target triple = "x86_64-apple-macosx10.10.0" @.str = private unnamed_addr constant [10 x i8] c"hi there!\00", align 1 ; Function Attrs: nounwind ssp uwtable define i32 @main() #0 { %1 = alloca i32, align 4 store i32 0, i32* %1 %2 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([10 x i8], [10 x i8]* @.str, i32 0, i32 0)) ret i32 0 } declare i32 @printf(i8*, ...) #1 attributes #0 = { nounwind ssp uwtable "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="core2" "target-features"="+ssse3,+cx16,+sse,+sse2,+sse3" "unsafe-fp-math"="false" "use-soft-float"="false" } attributes #1 = { "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="core2" "target-features"="+ssse3,+cx16,+sse,+sse2,+sse3" "unsafe-fp-math"="false" "use-soft-float"="false" } !llvm.module.flags = !{!0} !llvm.ident = !{!1} !0 = !{i32 1, !"PIC Level", i32 2} !1 = !{!"Apple LLVM version 7.0.0 (clang-700.1.76)"}
非比特码IR与比特码IR之间的唯一显着区别在于,每个体系结构的文件名已经被剥离为1,2等。
我也证实,优化后生成embedded在二进制文件中的位码。 如果使用-O3进行编译并提取位码,则与使用-O0编译时不同。
为了获得额外的功劳,我也证实,当你下载一个iOS 9的应用程序时,苹果不会将位码发送到设备。 他们包括了许多其他奇怪的部分,我不认为__LINKEDIT,但他们不包括__LLVM .__包,因此似乎没有包括在设备上运行的最终二进制位码。 奇怪的是,苹果公司仍然向iOS 8设备发送单独的32/64位代码的胖二进制文件。
位码(iOS,watchOS)
位码是编译程序的中间表示。 包含位码的上传到iTunes Connect的应用程序将在App Store上编译和链接。 包括位码将允许苹果在将来重新优化您的应用程序二进制文件,而无需将新版本的应用程序提交给商店。
基本上这个概念有点类似于java,其中字节码在不同的JVM上运行,在这种情况下,位码被放置在iTune存储上,而不是将中间代码提供给不同的平台(设备),它提供了不需要的编译代码任何虚拟机运行。
因此,我们需要创build一次比特码,并且可用于现有或即将到来的设备。 苹果公司很头痛地编译出一个与每个平台兼容的程序。
开发人员无需再进行更改并重新提交应用程序来支持新的平台。
我们以 iPhone 5s 为例介绍苹果在其中引入了x64
芯片。 尽pipex86
应用程序完全与x64
架构兼容,但要充分利用x64
平台,开发人员必须更改架构或代码。 一旦完成,应用程序将被提交给应用程序商店进行审查。
如果这个比特码的概念是早些时候推出的,那么我们开发人员不需要做任何改变来支持x64
比特体系结构。
更新
苹果已经澄清 ,切片发生独立于启用位代码。 我已经在实践中观察到了这一点,在那里一个非bitcode启用的应用程序将只能作为适合目标设备的体系结构下载。
原版的
更具体地说 :
位码。 归档您的应用程序,以中间表示forms提交给App Store,在交付时将其编译为64位或32位可执行文件。
切片。 合并到资产目录中并为平台标记的艺术品使App Store只能提供安装所需的内容。
我读到这个的方式,如果你支持bitcode的话,你的应用程序的下载程序只会得到他们自己设备所需的编译体系结构。