在Xcode 7中,ENABLE_BITCODE是什么?

285
我对嵌入式位码一词有疑问。
什么是嵌入式位码?
何时启用新版Xcode中的ENABLE_BITCODE
在Xcode 7中启用ENABLE_BITCODE会发生什么?
6个回答

344

位码是指发送到iTunes Connect的“LLVM Bitcode”代码类型。这允许苹果使用某些计算来进一步优化应用程序(例如:可能缩小可执行文件大小)。如果苹果需要更改您的可执行文件,则可以在不上传新构建的情况下执行此操作。

这与以下不同: 切片是指苹果根据设备的分辨率和架构优化您的应用程序的过程。切片不需要位码。(例如:仅在5s上包含@2x图像)

应用程序精简是切片、位码和按需资源的组合

  

位码是已编译程序的中间表示形式。您上传到iTunes Connect的应用程序将在应用商店上进行编译和链接。包括位码将允许Apple在未来重新优化您的应用程序二进制文件,而无需提交新版本的应用程序到商店。

关于应用程序精简的苹果文档


你所引述的内容中并没有说启用位码可以减小用户设备上应用的大小。位码与像3x或2x这样的资源无关。 - user102008
1
资源与 Bitcode 无关,Bitcode 只与代码有关。用户仅下载某些架构的代码和某些版本的资源是 Slicing,这与 Bitcode 无关。 - user102008
20
我不同意这个说法,它并没有允许苹果公司减小你的应用程序大小。它说:“未来将允许苹果公司重新优化你的应用程序二进制文件,而无需提交新版本到商店”,我理解为它可以让苹果公司在新的设备架构出现时,重新编译你的应用程序以适应该架构,而无需你提交包含此架构的新版本。 - user102008
2
不,切片是将您的应用程序资源分组为特定设备的操作。Bitcode 是使 Apple 能够为特定架构生成可执行文件的技术。 - Jon Shier
4
苹果公司表示,“Slicing是为不同目标设备创建和交付应用程序包变体的过程。变体仅包含目标设备所需的可执行架构和资源。”因此,切片仅具备特定设备所需的可执行代码和资源。 - keji
显示剩余10条评论

87

什么是嵌入式位码?

根据文档:

位码是编译程序的中间表示。上传到iTunes Connect的应用程序包含位码,将在App Store上编译和链接。包含位码将使苹果能够在未来重新优化您的应用程序二进制文件,而无需向商店提交新版本的应用程序。

更新:Xcode 7中的新功能中的这句话让我长时间思考,认为需要位码才能进行切割以减小应用程序大小:

当您归档以提交到App Store时,Xcode会将您的应用程序编译成中间表示形式。然后,App Store将按需要将位码编译为64位或32位可执行文件。

然而实际上,BitcodeSlicing是相互独立的: Slicing可减小应用程序大小并生成应用程序包变体,而Bitcode则涉及某些二进制优化。通过检查非Bitcode应用程序的可执行文件中包含的架构,我已经验证了这一点,并发现它们仅包括必要的架构。 Bitcode允许其他名为Slicing的组件生成具有特定架构的特定可执行文件的应用程序包变体,例如iPhone 5S变体只包括arm64可执行文件,iPad Mini包括armv7等。

何时在新的Xcode中启用ENABLE_BITCODE?

对于iOS应用程序,Bitcode是默认值但是可选的。如果提供了Bitcode,则应用程序包中的所有应用程序和框架都需要包括Bitcode。对于watchOS和tvOS应用程序,Bitcode是必需的。

当在新的Xcode中启用ENABLE_BITCODE时,会发生什么?

来自Xcode 7参考:

激活此设置表示目标或项目应在支持的平台和架构上在编译期间生成位码。对于档案构建,将在链接的二进制文件中生成位码以提交到应用商店。对于其他构建,编译器和链接器将检查代码是否符合位码生成的要求,但不会生成实际的位码。
以下是一些有助于更深入理解位码的链接:
- 位码揭秘 - 为什么我不启用位码

如果在提交到App Store之前启用了ENABLE_BITCODE但未选中“包括位码”,那么位码是否会被包含? - allaire
对于iOS应用程序,位码是默认设置,但是可选的。啥?再说一遍?它是可选的还是不可选的? - user2052717
正如答案所述,@NpC0mpl3t3对于iOS应用程序是可选的,但对于watchOS和tvOS应用程序是必需的。 - Maxim Pavlov
非常好的帮助!这个答案展示了如何禁用位码:https://dev59.com/AVkT5IYBdhLWcg3wPtMv#41418824 - Guerry

27

由于确切的问题是“启用位代码有什么作用”,因此我想提供一些我迄今为止发现的技术细节。在苹果发布此编译器的源代码之前,这些细节几乎不可能得到100%的确定。

首先,苹果的位代码似乎并不是LLVM字节码。至少,我没有找到它们之间的任何相似之处。它似乎具有专有的标头(始终以“xar!”开头),并且可能使用某些链接时间引用魔法来防止数据重复。如果您编写一个硬编码字符串,那么该字符串将仅被放入数据中一次,而不是像正常的LLVM字节码那样被放入两次。

其次,位代码实际上并没有像预期的那样作为单独的体系结构在二进制存档中进行交付。它不像将x86和ARM放入一个二进制文件(FAT归档)中那样进行交付。相反,它们在每个支持的体系结构中都使用名为“__LLVM”的特殊部分的MachO二进制文件进行交付(即重复)。我认为这是他们编译器系统的一个缺点,并且将来可能会进行修复以避免重复。

C代码(使用clang -fembed-bitcode hi.c -S -emit-llvm编译):

#include <stdio.h>

int main() {
    printf("hi there!");
    return 0;
}

LLVM IR输出:

; ModuleID = '/var/folders/rd/sv6v2_f50nzbrn4f64gnd4gh0000gq/T/hi-a8c16c.bc'
target datalayout = "e-m: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中的数据数组也会根据clang的优化和其他代码生成设置而改变。我完全不知道这是什么格式或任何相关信息。

编辑:

在Twitter上得到提示后,我决定重新审视并确认此事。我遵循了此博客文章,使用了他的比特码提取工具从MachO可执行文件中获取了Apple Archive二进制文件。并且在使用xar实用程序提取Apple Archive后,我得到了这个(当然是通过llvm-dis转换为文本)。

; ModuleID = '1'
target datalayout = "e-m: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等数字。 我还证实了嵌入在二进制文件中的比特码是在进行优化之后生成的。如果使用-O3编译并提取出比特码,则与使用-O0编译时不同。 另外,值得一提的是,当您下载iOS 9应用程序时,苹果不会向设备发送比特码。他们包括许多其他奇怪的部分,如__LINKEDIT,但不包括__LLVM.__bundle,因此似乎最终在设备上运行的二进制文件中没有包含比特码。不过,奇怪的是,苹果仍然向iOS 8设备发送带有单独的32/64位代码的Fat Binaries。

你看过LLVM的位码文件格式吗?魔数不同,但苹果公司强烈暗示这就是位码格式。 - Jeffery Thomas
“它不是重复的,因为每个mach-o切片的位码都是不同的,而这些切片是支持的每个架构都会附带的。” - AlexDenisov
@AlexDenisov 很有趣,我想通过优化可能是可行的。 - Earlz
@Earlz 除了优化之外,它们具有不同的数据布局、数据类型等。 - AlexDenisov
2
根据 https://twitter.com/mistydemeo/status/644555663373307904 的说法,“xar!”是苹果的归档文件格式。 - Riking
显示剩余3条评论

18
位码(iOS,watchOS)
Bitcode是一个已编译程序的中间表示形式。上传到iTunes Connect的应用程序包含位码,将在App Store上进行编译和链接。包括位码将允许苹果在未来重新优化您的应用程序二进制文件,而无需将新版本提交到商店。
基本上,这个概念与Java类似,其中字节码在不同的JVM上运行,在这种情况下,位码被放置在iTune商店中,而不是向不同平台(设备)提供中间代码,它提供了已编译的代码,无需任何虚拟机即可运行。
因此,我们需要创建一次位码,它将适用于现有或即将推出的设备。苹果的责任是编译并使其与每个平台兼容。
开发人员无需更改并重新提交应用程序以支持新平台。
举个例子,当苹果在iPhone 5s中引入x64芯片时。虽然x86应用程序完全与x64架构兼容,但为了充分利用x64平台,开发人员必须更改架构或某些代码。完成后,应用程序将提交给应用商店进行审核。
如果早些时候推出了这个位码概念,那么我们开发人员就不必做出任何更改来支持x64位架构。

@user102008 切片是启用 Bitcode 的结果。 - keji
@kdogisthebest:不是这样的。没有任何地方说过这一点。我已经观看了有关切片的WWDC视频,它并没有提到启用Bitcode。 - user102008
当涉及企业应用商店时,Inder Kumar Rathore如何处理?企业应用商店是否支持此功能? - damithH
@damithH 没有企业应用商店,我们必须将应用程序保存在我们的服务器上。我不确定应用程序瘦身是否适用于企业应用程序。但据我所知,企业应用程序不应该有这个功能。 - Inder Kumar Rathore
请在您的答案中更新图片,它与 Bitcode 无关。 - hsafarya
@InderKumarRathore,有一个企业应用商店,它叫做Custom B2B。 - Bryan Bryce

5

更新

苹果已经澄清,切片是独立于启用位码的。我在实践中也观察到这一点,未启用位码的应用程序只会按照目标设备所需的架构进行下载。

原始内容

更具体地说:

位码。将您的应用程序存档以提交给App Store,在传递时编译为64位或32位可执行文件的中间表示形式。

切片。合并到资源目录中并标记为特定平台的艺术品,允许App Store仅提供安装所需的内容。

我的理解是,如果支持位码,则应用程序的下载者将只获取针对其设备所需的编译架构。


在《应用瘦身指南》(https://developer.apple.com/library/prerelease/ios/documentation/IDEs/Conceptual/AppDistributionGuide/AppThinning/AppThinning.html)中,“切片(Slicing)是创建和提供面向不同目标设备的应用程序包变体的过程。 变体仅包含目标设备所需的可执行架构和资源。” 您的应用程序下载者只获取其架构的部分是切片功能的一部分。 - user102008

3

Bitcode 官方页面

[LLVM中间表示(IR)]有三种形式:

  1. 人类可读的汇编语言表示
  2. 内存编译器IR
  3. Bitcode(磁盘上的Bitcode表示,Bitcode文件格式,二进制格式)。

这是用于LLVM IR的位流(二进制编码)文件格式。它是LLVM IR序列化的结果。它可以选择地嵌入到包装器或本机对象文件中(Mach-O在裸段数据内[关于])。它适用于即时编译器。 您可以使用llvm-disBitcode IR转换为人类可读的IR。

苹果公司另一个使用的好处是,可以重新编译二进制文件以支持其他(新)体系结构(指令集架构(ISA)),无需开发人员进行调整。此外,还有一种小的附加功能,可以进行反向工程,这使得苹果更容易分析二进制文件,但另一方面,这也是一个缺点,可以被恶意分子利用。它还增加了构建时间。

在生成Bitcode .BCSymbolMap[关于]时,也会生成以分析错误堆栈跟踪。

请注意,不会为模拟器(arch x86_64)生成Bitcode。 Xcode在以下情况下使用Bitcode:

标志:

  • -fembed-bitcode - 嵌入Bitcode
  • -fembed-bitcode-marker - 只是标记它的位置。 __LLVM段为空,没有任何数据

使用:

  • 启用位码 (ENABLE_BITCODE)。对于应用程序、框架目标,默认值为 YES

    • 在常规构建中使用 -fembed-bitcode-marker
    • 归档 (Product -> Archive) 或 (xcodebuild archive) 中使用 -fembed-bitcode 嵌入位码
  • 显式地将标志添加到其他 C 标志(OTHER_CFLAGS)

  • 用户定义的设置 BITCODE_GENERATION_MODE

    • marker - 添加 -fembed-bitcode-marker
    • bitcode - 添加 -fembed-bitcode
  • 使用上述适当选项的xcodebuild

//please make sure that this settings is placed before xcodebuild params(.e.g. -workspace, -scheme...)
xcodebuild ENABLE_BITCODE=YES
//or
xcodebuild BITCODE_GENERATION_MODE="bitcode"
//or
xcodebuild OTHER_CFLAGS="-fembed-bitcode"

如果你在应用中使用了嵌入式位码,但不是所有库都支持,那么你会得到:
ld: bitcode bundle could not be generated because '<path>' was built without full bitcode. All frameworks and dylibs for bitcode must be generated from Xcode Archive or Install build file '<path>' for architecture <arch>

检查二进制文件是否包含位代码

位代码必须存储在对象文件的一个名为__LLVM,__bitcode(MachO)或.llvmbc(其他对象格式)的部分中。

位代码注入到__LLVM段的三个部分中:__bitcode__cmdline__asm。苹果版本的LLVM使用略微不同的逻辑,并将__bitcode__cmdline移动到__bundle部分作为.xar存档。

eXtensible ARchive(XAR) -.xar,.pkg归档器的文件格式,由头、目录表(toc)、堆组成。TOC用于访问归档文件。xar中的每个文件都可以独立压缩。

  1. 执行 otool -l 命令并查找 __LLVM __bundle。

您可以在Mach-O文件中检查段名称和节名称。

但是,这并不能保证包含位代码(例如标记)。

//<segname> <sectname> e.g. __LLVM __bundle. They are started from __

otool -l "/Users/alex/MyModule.framework/MyModule"
//or universal framework(specify arch)
otool -arch arm64 -l "/Users/alex/MyModule.framework/MyModule"
//or all arch
otool -arch all -l "/Users/alex/MyModule.framework/MyModule"

//-l print the load commands

输出:

Section
  sectname __bundle
   segname __LLVM
      addr 0x00000000000c0000
      size 0x00000000003af3ce
    offset 770048
...
  1. otool -v -s __LLVM __bundle
otool -v -s __LLVM __bundle <binary_path>
//e.g.
otool -v -s __LLVM __bundle "/Users/alex/MyModule.framework/MyModule" 

// -s <segname> <sectname> print contents of section. e.g. -s __LLVM __bundle

// -v print verbosely (symbolically) when possible

otool -s __LLVM __bundle 的输出结果是位流(二进制编码)。

Contents of (__LLVM,__bundle) section
00000000000b4000    21726178 01001c00 00000000 c60d0000 
00000000000b4010    00000000 be860000 01000000 9decda78 
00000000000b4020    b6dc735b f3dfc715 5f7a3429 bdc1ce2f 

otool -v -s __LLVM __bundle 的输出结果是 XAR 的目录表(TOC)。-v 把比特流(二进制编码)转换成 XAR 目录表的 XML 格式。

For (__LLVM,__bundle) section: xar table of contents:
<?xml version="1.0" encoding="UTF-8"?>
<xar>
 <subdoc subdoc_name="Ld">
  <version>1.0</version>
...
  1. 另外一个指示器是生成了.bcsymbolmap[关于]

查找并提取位代码

ebcutil

Closed source Library developer - XCFramework
App developer - enable bitcode

位码是否强制 官方

对于 iOS 应用来说,位码是默认的,但是可选的。对于 watchOS 和 tvOS 应用来说,要求使用位码。

二进制文件大小

当位码不是强制使用时,可以通过使用 bitcode_strip 来手动从二进制文件中删除位码。

例如

xcrun bitcode_strip -r "/Users/alex/MyModule.framework/MyModule" -o "/Users/alex/MyModule.framework/MyModule"

// -r remove bitcode
// -o output file name

[词汇表]


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接