注意:使用 Bazel 构建 Android 应用存在一些已知限制。访问 GitHub 上的 team-Android 热点列表,查看已知问题列表。虽然 Bazel 团队和开源软件 (OSS) 贡献者正积极解决已知问题,但用户应注意,Android Studio 未正式支持 Bazel 项目。
本教程介绍如何使用 Bazel 构建简单的 Android 应用。
Bazel 支持使用 Android 规则构建 Android 应用。
本教程面向 Windows、macOS 和 Linux 用户,无需具备 Bazel 或 Android 应用开发经验。在本教程中,您无需编写任何 Android 代码。
学习内容
在本教程中,您将学习如何:
- 安装 Bazel 和 Android Studio 并下载示例项目,以设置您的环境。
- 设置一个 Bazel 工作区,其中包含应用的源代码和一个用于标识工作区目录顶层的
MODULE.bazel
文件。 - 更新
MODULE.bazel
文件,使其包含对所需外部依赖项(例如 Android SDK)的引用。 - 创建
BUILD
文件。 - 使用 Bazel 构建应用。
- 在 Android 模拟器或实体设备上部署并运行应用。
准备工作
安装 Bazel
在开始学习本教程之前,请安装以下软件:
- Bazel。如需安装,请按照安装说明执行操作。
- Android Studio。如需安装,请按照下载 Android Studio 的步骤操作。 执行设置向导,下载 SDK 并配置您的环境。
- (可选)Git。使用
git
下载 Android 应用项目。
获取示例项目
对于示例项目,请使用 Bazel 的示例代码库中的基本 Android 应用项目。
此应用只有一个按钮,点击该按钮时会打印问候语:
图 1. Android 应用按钮问候语。
使用 git
克隆代码库(或直接下载 ZIP 文件):
git clone https://github.com/bazelbuild/examples
本教程的示例项目位于 examples/android/tutorial
中。在本教程的其余部分,您将在此目录中执行命令。
查看源文件
查看应用的源文件。
.
├── README.md
└── src
└── main
├── AndroidManifest.xml
└── java
└── com
└── example
└── bazel
├── AndroidManifest.xml
├── Greeter.java
├── MainActivity.java
└── res
├── layout
│ └── activity_main.xml
└── values
├── colors.xml
└── strings.xml
关键文件和目录包括:
名称 | 位置 |
---|---|
Android 清单文件 | src/main/AndroidManifest.xml 和src/main/java/com/example/bazel/AndroidManifest.xml |
Android 源文件 | src/main/java/com/example/bazel/MainActivity.java 和Greeter.java |
资源文件目录 | src/main/java/com/example/bazel/res/ |
使用 Bazel 构建
设置工作区
工作区是一个目录,其中包含一个或多个软件项目的源文件,并且其根目录中有一个 MODULE.bazel
文件。
MODULE.bazel
文件可能为空,也可能包含构建项目所需的外部依赖项的引用。
首先,运行以下命令以创建空的 MODULE.bazel
文件:
操作系统 | 命令 |
---|---|
Linux、macOS | touch MODULE.bazel |
Windows(命令提示符) | type nul > MODULE.bazel |
Windows (PowerShell) | New-Item MODULE.bazel -ItemType file |
运行 Bazel
现在,您可以使用以下命令检查 Bazel 是否正常运行:
bazel info workspace
如果 Bazel 打印了当前目录的路径,则说明一切正常!如果 MODULE.bazel
文件不存在,您可能会看到类似如下的错误消息:
ERROR: The 'info' command is only supported from within a workspace.
与 Android SDK 集成
Bazel 需要运行 Android SDK build tools 来构建应用。这意味着您需要向 MODULE.bazel
文件添加一些信息,以便 Bazel 知道在哪里可以找到这些工具。
将以下行添加到 MODULE.bazel
文件中:
bazel_dep(name = "rules_android", version = "0.5.1")
这会使用 ANDROID_HOME
环境变量所引用路径中的 Android SDK,并自动检测该位置中安装的最高 API 级别和最新版本的 build 工具。
您可以将 ANDROID_HOME
变量设置为 Android SDK 的位置。使用 Android Studio 的 SDK 管理器查找已安装 SDK 的路径。
假设 SDK 安装在默认位置,您可以使用以下命令设置 ANDROID_HOME
变量:
操作系统 | 命令 |
---|---|
Linux | export ANDROID_HOME=$HOME/Android/Sdk/ |
macOS | export ANDROID_HOME=$HOME/Library/Android/sdk |
Windows(命令提示符) | set ANDROID_HOME=%LOCALAPPDATA%\Android\Sdk |
Windows (PowerShell) | $env:ANDROID_HOME="$env:LOCALAPPDATA\Android\Sdk" |
上述命令仅为当前 shell 会话设置变量。如需永久应用这些更改,请运行以下命令:
操作系统 | 命令 |
---|---|
Linux | echo "export ANDROID_HOME=$HOME/Android/Sdk/" >> ~/.bashrc |
macOS | echo "export ANDROID_HOME=$HOME/Library/Android/Sdk/" >> ~/.bashrc |
Windows(命令提示符) | setx ANDROID_HOME "%LOCALAPPDATA%\Android\Sdk" |
Windows (PowerShell) | [System.Environment]::SetEnvironmentVariable('ANDROID_HOME', "$env:LOCALAPPDATA\Android\Sdk", [System.EnvironmentVariableTarget]::User) |
可选:如果您想将原生代码编译到 Android 应用中,还需要下载 Android NDK,并通过向 MODULE.bazel
文件添加以下行来使用 rules_android_ndk
:
bazel_dep(name = "rules_android_ndk", version = "0.1.2")
如需了解详情,请参阅将 Android 原生开发套件与 Bazel 搭配使用。
不必将 SDK 和 NDK 的 API 级别设置为相同的值。本页包含从 Android 版本到 NDK 支持的 API 级别的映射。
创建 BUILD 文件
BUILD
文件用于描述一组 build 输出(例如来自 aapt
的已编译 Android 资源或来自 javac
的类文件)及其依赖项之间的关系。这些依赖项可以是工作区中的源文件(Java、C++),也可以是其他 build 输出。BUILD
文件采用名为 Starlark 的语言编写。
BUILD
文件是 Bazel 中称为软件包层次结构的概念的一部分。软件包层次结构是一种逻辑结构,可覆盖工作区中的目录结构。每个软件包都是一个目录(及其子目录),其中包含一组相关的源文件和一个 BUILD
文件。该软件包还包含所有子目录,但包含自己的 BUILD
文件的子目录除外。软件包名称是相对于 MODULE.bazel
文件的 BUILD
文件路径。
请注意,Bazel 的软件包层次结构在概念上不同于 Android 应用目录(其中包含 BUILD
文件)的 Java 软件包层次结构,尽管目录的组织方式可能相同。
对于本教程中的简单 Android 应用,src/main/
中的源文件构成一个 Bazel 软件包。更复杂的项目可能包含许多嵌套的软件包。
添加 android_library 规则
BUILD
文件包含多种不同类型的 Bazel 声明。最重要的类型是build 规则,它会告知 Bazel 如何从一组源文件或其他依赖项构建中间或最终软件输出。Bazel 提供了两个构建规则:android_library
和 android_binary
,您可以使用它们来构建 Android 应用。
在本教程中,您将首先使用 android_library
规则告知 Bazel 从应用源代码和资源文件构建 Android 库模块。然后,您将使用 android_binary
规则告知 Bazel 如何构建 Android 应用软件包。
在 src/main/java/com/example/bazel
目录中创建一个新的 BUILD
文件,并声明一个新的 android_library
目标:
src/main/java/com/example/bazel/BUILD
:
package(
default_visibility = ["//src:__subpackages__"],
)
android_library(
name = "greeter_activity",
srcs = [
"Greeter.java",
"MainActivity.java",
],
manifest = "AndroidManifest.xml",
resource_files = glob(["res/**"]),
)
android_library
build 规则包含一组属性,用于指定 Bazel 从源文件构建库模块所需的信息。另请注意,规则的名称为 greeter_activity
。您将在 android_binary
规则中将此名称用作依赖项来引用该规则。
添加 android_binary 规则
android_binary
规则用于为您的应用构建 Android 应用软件包(.apk
文件)。
在 src/main/
目录中创建一个新的 BUILD
文件,并声明一个新的 android_binary
目标:
src/main/BUILD
:
android_binary(
name = "app",
manifest = "AndroidManifest.xml",
deps = ["//src/main/java/com/example/bazel:greeter_activity"],
)
在此示例中,deps
属性引用了您添加到上述 BUILD
文件中的 greeter_activity
规则的输出。这意味着,当 Bazel 构建此规则的输出时,它会先检查 greeter_activity
库规则的输出是否已构建且是最新的。如果不存在,Bazel 会构建该文件,然后使用该输出文件来构建应用软件包文件。
现在,保存并关闭该文件。
构建应用
尝试构建应用!运行以下命令以构建 android_binary
目标:
bazel build //src/main:app
build
子命令指示 Bazel 构建后面的目标。目标指定为 BUILD
文件内 build 规则的名称,以及相对于工作区目录的软件包路径。在此示例中,目标为 app
,软件包路径为 //src/main/
。
请注意,有时您可以省略软件包路径或目标名称,具体取决于您在命令行中的当前工作目录和目标的名称。如需详细了解目标标签和路径,请参阅标签。
Bazel 将开始构建示例应用。在构建过程中,其输出将类似于以下内容:
INFO: Analysed target //src/main:app (0 packages loaded, 0 targets configured).
INFO: Found 1 target...
Target //src/main:app up-to-date:
bazel-bin/src/main/app_deploy.jar
bazel-bin/src/main/app_unsigned.apk
bazel-bin/src/main/app.apk
找到 build 输出
Bazel 会将中间和最终构建操作的输出放置在一组按用户和工作区划分的输出目录中。这些目录通过符号链接从项目目录顶层的以下位置链接,其中包含 MODULE.bazel
文件:
bazel-bin
存储二进制可执行文件和其他可运行的 build 输出bazel-genfiles
存储由 Bazel 规则生成的中间源文件bazel-out
存储其他类型的 build 输出
Bazel 会将使用 android_binary
规则生成的 Android .apk
文件存储在 bazel-bin/src/main
目录中,其中子目录名称 src/main
派生自 Bazel 软件包的名称。
在命令提示符处,列出此目录的内容并找到 app.apk
文件:
操作系统 | 命令 |
---|---|
Linux、macOS | ls bazel-bin/src/main |
Windows(命令提示符) | dir bazel-bin\src\main |
Windows (PowerShell) | ls bazel-bin\src\main |
运行应用
现在,您可以使用 bazel
mobile-install
命令从命令行将应用部署到连接的 Android 设备或模拟器。此命令使用 Android 调试桥 (adb
) 与设备通信。在部署之前,您必须按照 Android 调试桥中的说明设置设备以使用 adb
。您也可以选择在 Android Studio 中包含的 Android 模拟器上安装应用。请确保在执行以下命令之前模拟器正在运行。
输入以下内容:
bazel mobile-install //src/main:app
接下来,找到并启动“Bazel 教程应用”:
图 2. Bazel 教程应用。
恭喜!您刚刚安装了第一个由 Bazel 构建的 Android 应用。
请注意,mobile-install
子命令还支持 --incremental
标志,该标志可用于仅部署自上次部署以来发生更改的应用部分。
它还支持 --start_app
标志,以便在安装应用后立即启动该应用。
深入阅读
如需了解详情,请参阅以下页面:
- 在 GitHub 上提交问题
- 详细了解移动安装
- 使用 rules_jvm_external 从 Maven 代码库集成 AppCompat、Guava 和 JUnit 等外部依赖项
- 通过 robolectric-bazel 集成运行 Robolectric 测试。
- 使用 Android 插桩测试测试应用
- 使用 NDK 将 C 和 C++ 代码集成到 Android 应用中
- 查看以下方面的更多 Bazel 示例项目:
祝您构建顺利!