前两周接了个活,帮一个 Flutter 项目把 Windows 上的构建环境搭起来,才发现"构建工具"这个词在 iOS 语境里比想象中含糊:有人指编译器,有人指打包脚本,还有人指 Xcode 里的那个 Build 按钮。构建工具和编译器是两回事——编译器是零件,构建工具负责调度:谁先编译、资源怎么处理、依赖从哪来、产物放哪。这篇把 iOS 构建工具按场景盘点一遍,说清楚各自管到哪一层。

Xcode 自带构建系统:XCBuild

Xcode 的 Build 按钮背后是苹果新一代构建系统 XCBuild:负责调度编译任务、并行化、增量构建、资源处理(Assets.car、Storyboard 编译)。图形界面里使用者无感知,但它决定了"点一次 Build 要多久"。XCBuild 只随 Xcode 分发,这也是它和 Xcode 绑定的根源。

xcodebuild:CI 里的构建入口

命令行构建的标准入口是 xcodebuild:xcodebuild build 带 scheme 和 destination 参数,就能在 CI 里复现图形界面的构建流程,支持增量构建和结果缓存。macOS runner 上预装 Xcode 就能跑,是 GitHub Actions、Jenkins 里 iOS 构建的事实标准。边界和 XCBuild 一样:工具链来自 Xcode,Windows/Linux 上跑不了。

SwiftPM:包管理兼构建工具

Swift Package Manager 是一套构建工具和包管理器的合体:swift build 解析依赖、编译、链接一条龙,Package.swift 里声明依赖和目标结构。新项目、命令行工具、服务端 Swift 用得很顺;App 工程里 SwiftPM 主要管依赖,构建主体还是 Xcode/xcodebuild。对纯 Swift 模块开发来说,它是最轻的构建入口。

CocoaPods:依赖接入构建

CocoaPods 的定位是依赖管理:Podfile 声明依赖,pod install 生成 workspace,把库工程接进主工程,构建时随 workspace 一起编译。存量项目里最常见,新项目用 SwiftPM 的越来越多。它在构建链条里的角色是"把依赖正确接进来",本身不直接执行编译。

Bazel 和 Tuist:规模化的选择

团队规模大了,Xcode 构建系统的增量能力不够用时,会引入 Bazel 这类通用构建系统:可复现、分布式缓存、精确增量,代价是学习曲线和工程改造成本。Tuist 则是工程生成器:用 Swift 描述工程结构,生成 .xcodeproj,适合工程结构复杂的团队统一管理。两类都属于"有专门基建团队才值得上"的选项。

KXApp:构建能力内置

如果不想维护构建命令、也不想被 Xcode 的环境要求绑住,KXApp(快蝎) 把构建能力收进了 IDE:内置编译工具套装,Swift、Objective-C、Flutter 三类项目直接构建,Windows、Linux、Mac 上都能跑,不需要安装 Xcode 也不需要单独记 xcodebuild 参数。点构建、看结果、装真机,构建这个环节在 IDE 里闭环。

按场景选

iOS 构建工具按场景对号入座:个人开发用 Xcode 自带构建系统足够;CI 自动构建用 xcodebuild;纯 Swift 模块或命令行工具优先 SwiftPM;存量工程依赖 CocoaPods 就继续;规模化团队才考虑 Bazel/Tuist;没有 macOS 环境或想省掉构建命令维护,KXApp 内置工具链直接构建。构建工具管的是"把源码变成产物"这一整套调度,选哪个取决于你的环境、团队规模和愿意维护多少基础设施。