本文还是 adat 项目的延伸,开始介绍打包实践。打包相关的内容繁多,作者把它分成了多篇文章,本文主要是概念部分。理解这些概念对于自己动手编写打包命令至关重要。如果你使用 fastlane、bitrise 或其他构建工具来打包,但对于某些配置项不是很理解,看完这篇文章,或许会很有帮助。
内容概览
- 了解架构
- xcodebuild 命令中打包相关的用法
- ExportOptions.plist 详解
了解架构
芯片设计采用什么指令集架构,在其上运行的软件就要支持对应的指令集架构。常见的指令集架构有x86
系列和arm
系列。
x86 和 arm
x86 是复杂指令集架构,由Intel
公司设计,主要应用在桌面计算机和服务器。有16 位(16-bit)版本、32 位(32-bit)版本、64 位(64-bit)版本等,早期的i386
是 32 位的 x86 架构,显然x86_64
就是 64 位的 x86 架构。
arm 是精简指令集架构,由Arm
公司设计,主要用于移动设备,比 x86 架构更加省电。同样,arm 架构也有 32 位和 64 位之分。Arm 公司发布的第一代ARM1
就已经是 32 位架构,后来的ARMv3
、ARMv7
依然是 32 位,直到 2011 年发布的ARMv8-A
才开始支持 64 位。
armv7 和 arm64
armv7,即ARMv7-A
架构,是 32 位 arm 架构之一,因此不能统称为 arm32。例如 Apple 最早的 A 系列芯片 A4 以及后面的 A5/A5X/A6/A6X 芯片均采用ARMv7-A
架构。A4 芯片服务了 iPhone 4 和第一代 iPad,A6 服务了 iPhone 5/iPhone 5c,直到 A6X 服务完第四代 iPad,armv7 就结束了它的使命,从 iPhone 5s 搭载的 A7 芯片开始,都是 64 位 arm 的天下。
arm64 是 64 位 arm 架构的统称,即ARMv8-A
及以后版本的 64 位系列架构,并非是某一个架构。例如 Apple 的 A7/A8/A8X/A9/A9X/A10/A10X 芯片采用ARMv8-A
架构,A11芯片采用ARMv8.2-A
架构,A12/A12X/A12Z 芯片采用ARMv8.3-A
架构,而在最新的 iPhone 13 系列手机上搭载的 A15 芯片则采用ARMv8.5-A
架构。M 系列芯片 M1/M1 Pro/M1 Max 均是支持 arm64 架构的芯片。
M1 和 Rosetta 2
这么多架构,我们并未针对每一种架构输出二进制,而是通常将 Build Settings 的ARCHS
项设置为armv7 arm64
来统一处理。而能够统一处理的前提,则是每一个版本的架构都兼容前一个版本的。ARCHS
值默认由$(ARCHS_STANDARD)
决定,它由 Xcode 根据项目支持的平台和版本自动确定。例如在 M1 芯片的 Mac 上利用 Xcode 13.1 创建的 macOS 项目,$(ARCHS_STANDARD)
实际值是arm64
,在 Intel 芯片的 Mac 上创建的 macOS 项目,其值是x86_64 arm64
。而在 Intel 芯片的 Mac 上利用低版本的 Xcode 创建的 macOS 项目,其值是x86_64
。
如果应用只支持 x86_64 架构,它是不能直接跑在 M1 芯片上的,那么 Mac AppStore 上海量的应用无法在 M1 设备上运行。缺失应用生态支持,直接导致 M1 设备几乎无人购买。而 M1 设备又是苹果打开自研芯片 Apple Silicon 市场的切入点,那么这条路注定很艰难。为了解决这个问题,Apple 创造了Rosetta 2
工具,它支持 x86_64 应用运行在 arm64 架构的芯片上。这是一项伟大的技术,解决了前面的问题。但这种转换运行始终不可能和在 x86_64 架构的芯片上直接运行相媲美,最好还是开发者提供支持 arm64 架构的应用程序,这也是 Apple 大力呼吁开发者修改自己的应用程序以增加对 Apple Silicon 支持的原因。
现在不难理解为什么 iOS 应用可以在搭载 M1 的 MacBookPro 上运行了。因为芯片架构不同的鸿沟已经被填平,剩下软件层进行适配就相对容易了。
Universal binaries 和 Fat file
为了让一个应用程序在不同的架构上都可以运行,将支持不同架构的二进制打包在一起,就形成了通用二进制(Universal)文件,最终形成通用应用程序。作者使用的是 Intel 芯片的 Mac,导航到应用程序
目录,在系统日