本页介绍如何使用 Bazel 构建或测试 Xcode 项目。它 介绍了 Xcode 和 Bazel 之间的区别,并提供了 将 Xcode 项目转换为 Bazel 项目。它还提供了 解决常见错误的解决方案。
Xcode 和 Bazel 之间的区别
Bazel 要求您明确指定每个构建目标及其 依赖项,以及通过构建规则指定的构建设置。
Bazel 要求项目所依赖的所有文件 工作区目录或在
MODULE.bazel
中指定为依赖项 文件。使用 Bazel 构建 Xcode 项目时,
BUILD
文件会成为 信息来源。如果您在 Xcode 中处理项目,则必须生成一个 使用BUILD
rules_xcodeprojBUILD
文件。BUILD
文件的特定更改 例如向目标添加依赖项时就无需重新生成 项目,从而加快开发速度。如果您使用的不是 Xcode,bazel build
和bazel test
命令提供构建和测试功能 但有一些限制。
准备工作
在开始之前,请执行以下操作:
安装 Bazel(如果尚未安装)。
如果您不熟悉 Bazel 及其概念,请完成 iOS 应用 教程)。您应该了解 Bazel 工作区 (包括
MODULE.bazel
和BUILD
文件)以及 构建规则和 Bazel 软件包分析和了解项目的依赖项。
分析项目依赖项
与 Xcode 不同,Bazel 要求您明确声明所有依赖项,
BUILD
文件中的每个目标。
如需详细了解外部依赖项,请参阅使用外部依赖项 依赖项。
使用 Bazel 构建或测试 Xcode 项目
要使用 Bazel 构建或测试 Xcode 项目,请执行以下操作:
-
a. 添加应用目标
b. (可选)添加测试目标
c. 添加库目标
第 1 步:创建 MODULE.bazel
文件
在新目录中创建一个 MODULE.bazel
文件。此目录会成为
Bazel 工作区根目录。如果项目不使用外部依赖项,则此文件
可以为空。如果项目依赖的文件或软件包不属于
项目的目录中,指定这些外部依赖项,请在
MODULE.bazel
文件。
第 2 步:(实验性)集成 SwiftPM 依赖项
如需将 SwiftPM 依赖项集成到 Bazel 工作区,请执行以下操作: swift_bazel,因此您必须 将其转换为 Bazel 软件包,如下面的 教程 ,了解所有最新动态。
第 3 步:创建 BUILD
文件
定义工作区和外部依赖项后,您需要
创建一个 BUILD
文件,告知 Bazel 如何构建项目。创建
BUILD
文件,并将其配置为
项目的初始 build,如下所示:
提示:要详细了解软件包和其他 Bazel 概念,请参阅工作区、 软件包和目标
第 3a 步:添加应用目标
将
macos_application
或
ios_application
规则目标。此目标分别构建 macOS 或 iOS 应用软件包。
在目标中,至少要指定以下内容:
bundle_id
- 应用的软件包 ID(反向 DNS 路径,后跟应用名称) 二进制文件provisioning_profile
- 您的 Apple Developer 的配置文件 (如果要针对 iOS 设备设备构建应用)。families
(仅限 iOS)- 是否针对 iPhone、iPad 或 或者两者兼有infoplists
- 要合并到最终 Info.plist 文件的 .plist 文件列表。minimum_os_version
- 应用提供的最低 macOS 或 iOS 版本 支持。这可确保 Bazel 使用 正确的 API 级别。
第 3b 步:(可选)添加测试目标
Bazel 的 Apple 版本 规则支持 单元测试和界面测试。添加测试目标,如下所示:
macos_unit_test
在 macOS 上运行基于库和基于应用的单元测试。ios_unit_test
在 iOS 上构建并运行基于库的单元测试。ios_ui_test
以便在 iOS 模拟器中构建并运行界面测试。
至少应为 minimum_os_version
属性指定一个值。虽然
其他包装属性,例如 bundle_identifier
和 infoplists
,
默认使用最常用的值,请确保这些默认值与
与项目进行协调,并根据需要进行调整。适用于需要 iOS
模拟器,还要将 ios_application
目标名称指定为
test_host
属性。
第 3c 步:添加库目标
为每个网址添加一个 objc_library
目标
Objective-C 库和
swift_library
和/或测试所依赖的每个 Swift 库的目标。
添加库目标,如下所示:
将应用库目标作为依赖项添加到应用中 目标。
将测试库目标作为依赖项添加到测试目标中。
在
srcs
属性中列出实现源代码。在
hdrs
属性中列出标头。
您可以直接在以下位置浏览各种类型应用的现有示例: rules_apple 示例 目录。例如:
有关构建规则的详情,请参阅适用于 Bazel。
此时,最好测试一下 build:
bazel build //:<application_target>
第 4 步:(可选)对 build 进行精细化构建
如果项目很大,或者随着项目规模的扩大,可以考虑将项目分成多个部分 Bazel 软件包。这种增大的粒度具有以下优势:
提高了构建增量
提高了构建任务的并行化,
为未来用户提供更好的可维护性,
更好地控制源代码在目标和软件包中的可见性。这个 防止问题,例如包含实现详情的库泄露 公共 API 中。
项目精细化的技巧:
将每个库放在各自的 Bazel 软件包中。先从需要 尽可能减少依赖项,并逐步遍历依赖项树。
在添加
BUILD
文件并指定目标时,将这些新目标添加到 依赖于它们的目标的deps
属性。glob()
函数不会跨越软件包边界,因此 package 会使glob()
匹配的文件变小。将
BUILD
文件添加到main
目录时,还要将BUILD
文件添加到 相应的test
目录。对软件包强制执行健康的可见性限制。
在
BUILD
文件每次发生重大更改后,构建项目并修复 build 错误。
第 5 步:运行构建
运行完全迁移的 build,确保其完成,没有错误或警告。 单独运行每个应用和测试目标,以便更轻松地查找源代码 检查所发生的任何错误。
例如:
bazel build //:my-target
第 6 步:使用 rules_xcodeproj 生成 Xcode 项目
使用 Bazel 进行构建时,MODULE.bazel
和 BUILD
文件会成为来源
真实信息为了让 Xcode 知道这一点,您必须生成一个
兼容 Bazel 的 Xcode 项目,
rules_xcodeproj
,了解所有最新动态。
问题排查
如果 Bazel 错误与所选 Xcode 版本不同步 例如应用更新时如果您 使用 Xcode 时遇到错误,例如“必须为 Xcode 版本指定 请使用 Apple CROSSTOOL”。
手动运行 Xcode 并接受任何条款及条件。
使用 Xcode select 指明正确的版本,接受许可,以及 清除 Bazel 状态
sudo xcode-select -s /Applications/Xcode.app/Contents/Developer
sudo xcodebuild -license
bazel sync --configure
- 如果此方法不起作用,您还可以尝试运行
bazel clean --expunge
。