本页介绍如何使用 Bazel 构建或测试 Xcode 项目。它 介绍了 Xcode 和 Bazel 之间的区别,并提供了 用于将 Xcode 项目转换为 Bazel 项目的流程。它还提供 问题排查解决方案,以解决常见错误。
Xcode 和 Bazel 之间的区别
Bazel 要求您明确指定每个构建目标及其 依赖项,以及通过构建规则指定的构建设置。
Bazel 要求项目所依赖的所有文件都存在 工作区目录中,或在
WORKSPACE
中指定为导入项 文件。使用 Bazel 构建 Xcode 项目时,
BUILD
文件会成为 信息来源。如果您在 Xcode 中处理项目,则必须生成一个 使用BUILD
rules_xcodeprojBUILD
文件。BUILD
文件的特定更改 例如向目标添加依赖项时就无需重新生成 项目,从而加快开发速度。如果您使用的不是 Xcode,bazel build
和bazel test
命令提供构建和测试功能 但有一些限制。
准备工作
在开始之前,请执行以下操作:
安装 Bazel(如果尚未安装)。
如果您不熟悉 Bazel 及其概念,请先完成 iOS 应用教程)。您应该了解 Bazel 工作区包括
WORKSPACE
和BUILD
文件,以及 目标、构建规则和 Bazel 软件包的概念分析和了解项目的依赖项。
分析项目依赖项
与 Xcode 不同,Bazel 要求您明确声明所有依赖项,
BUILD
文件中的每个目标。
如需详细了解外部依赖项,请参阅 使用外部依赖项。
使用 Bazel 构建或测试 Xcode 项目
要使用 Bazel 构建或测试 Xcode 项目,请执行以下操作:
-
a. 添加应用目标
b. (可选)添加测试目标
c. 添加库目标
第 1 步:创建 WORKSPACE
文件
在新目录中创建一个 WORKSPACE
文件。此目录会成为 Bazel
工作区根目录。如果项目不使用任何外部依赖项,则此文件可以是
为空。如果项目依赖的文件或软件包不属于任何
项目的目录中,请在 WORKSPACE
中指定这些外部依赖项
文件。
第 2 步:(实验性)集成 SwiftPM 依赖项
如需使用 swift_bazel 将 SwiftPM 依赖项集成到 Bazel 工作区,请执行以下操作: 您必须按照以下教程中的说明将其转换为 Bazel 软件包。
第 3 步:创建 BUILD
文件
定义工作区和外部依赖项后,您需要
创建一个 BUILD
文件,告知 Bazel 如何构建项目。创建
运行 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 构建规则支持 在所有 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 的 Apple 规则。
此时,最好测试一下 build:
bazel build //:<application_target>
第 4 步:(可选)对 build 进行精细化构建
如果项目很大,或者随着项目规模的扩大,可以考虑将项目分成多个部分 Bazel 软件包。这种增大的粒度具有以下优势:
提高了构建增量
提高了构建任务的并行化,
为未来用户提供更好的可维护性,
更好地控制源代码在目标和软件包中的可见性。这个 防止问题,例如包含实现详情的库泄露 公共 API 中。
项目精细化的技巧:
将每个库放在各自的 Bazel 软件包中。先从需要 尽可能减少依赖项,并逐步遍历依赖项树。
在添加
BUILD
文件并指定目标时,将这些新目标添加到 依赖于它们的目标的deps
属性。glob()
函数不会跨越软件包边界,因此 的软件包使与glob()
匹配的文件变小。将
BUILD
文件添加到main
目录时,还要将BUILD
文件添加到 相应的test
目录。对软件包强制执行健康的可见性限制。
在
BUILD
文件每次发生重大更改后,构建项目并修复 构建错误。
第 5 步:运行构建
运行完全迁移的 build,确保其完成,没有错误或警告。 单独运行每个应用和测试目标,以便更轻松地查找源代码 检查所发生的任何错误。
例如:
bazel build //:my-target
第 6 步:使用 rules_xcodeproj 生成 Xcode 项目
使用 Bazel 进行构建时,WORKSPACE
和 BUILD
文件会成为来源
真实信息为了让 Xcode 知道这一点,您必须生成一个
使用 rules_xcodeproj 且与 Bazel 兼容的 Xcode 项目。
问题排查
如果 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
。