【Android 构建新工具】Bazel 构建Android项目

简介: Bazel只是编译工具,不是真正的编译器,所以还是需要Andorid开发的SD、NDK以及Android Studio,并配置开发环境。

image.png


本文我们使用Bazel构建一个最简单的Android项目。Bazel提供了编译Android程序内置的方法,具体参考:Android Rules


1. 环境准备


Bazel只是编译工具,不是真正的编译器,所以还是需要Andorid开发的SD、NDK以及Android Studio,并配置开发环境。


接下来就是安装Bazel。由于平时在macos开发为主,所以主要介绍macos系统的安装。macos下bazel有四种安装方式:


  1. 使用二进制安装器(官方推荐);
  2. 使用hombrew;
  3. 使用bazelisk;
  4. 从源码编译安装bazel。


下面介绍前两种常用方法。


1.1 二进制安装器安装


GitHub releases page 下载对应版本安装器。


第一步安装Xcode 命令行工具


如果不打算使用ios_*相关的规则编译,则只需要使用xcode-select安装Xcode命令行工具:


xcode-select --install


如果需要构建ios相关程序,则必须安装Xcode6.1或者最新版本,并且iOS SDK 版本8.1以上。我们可以在App Store中下载到Xcode。


Xcode安装成功后需要我们通过一下命令接收用户使用说明协议:


sudo xcodebuild -license accept


第二步:下载Bazel安装器


我们先在Github basel release页面下载bazel安装器baze-<version>-installer-darwin-x86_64.sh,mac中沃恩可以使用curl工具下载:


# Example installing version `3.2.0`. Replace the version below as appropriate.
export BAZEL_VERSION=3.2.0
curl -fLO "https://github.com/bazelbuild/bazel/releases/download/${BAZEL_VERSION}/bazel-${BAZEL_VERSION}-installer-darwin-x86_64.sh"


第三步:执行安装器脚本


使用下面命令安装bazel:


chmod +x "bazel-${BAZEL_VERSION}-installer-darwin-x86_64.sh"
./bazel-${BAZEL_VERSION}-installer-darwin-x86_64.sh --user


--user参数将Bazel安装到HOME/bin目录。


第四步:设置环境变量


--user参数将bazel可执行文件安装到$HOME/bin目录,我们将该路径配置到环境变量,在~/.bashrc或者~/.zshrc或者~/.profile文件中增加如下配置:


export PATH="$PATH:$HOME/bin"


此时我们可以运行bazel --version查看bazezl是否安装成功。


1.2通过HomeBrew安装


第一步:安装HomeBrew


如果系统未安装HomeBrew,可以通过如下命令安装HomeBrew:


/bin/bash -c "$(curl -fsSL \
https://raw.githubusercontent.com/Homebrew/install/master/install.sh)"


第二步:安装Bazel


可以通过下面命令安装bazel:


$ brew install bazel


通过bazel --version既可看到是否安装成功。还可以通过下列命令更新bazel:


brew upgrade bazel


2.准备Android项目


我们使用bazel官方提供的Android demo程序,这个程序只是在一个Activity中放置了一个按钮,点击可以在TextView中显示一句话。


下载到代码后我们进入examples/android/tutorial目录,代码结构如下:


.
├── README.html
└── 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项目结构。


3. 初始化项目空间


工作空间workspace是一个一个活多个软件项目源码的目录,在它的根目录下有一个WORKSPACE的文件。


WORKSPACE可能是空文件也可能包含外部依赖配置。我们可以通过bazel info workspace查看是否运行在正确的工作空间下。如果打印当前路径的地址,则表示是合理的空间,如果WORKSPACE文件不存在,会有如下报错:


ERROR: The 'info' command is only supported from within a workspace.


4.集成Android SDK


编译Android程序肯定要用到Android编译器,我们需要告诉Bazel Android相关SDK路径,我们可以在WORKSPACE文件中指定。


在WORKSPACE文件中增加如下代码:


android_sdk_repository(name = "androidsdk")


这里指定了编译Android程序的SDK路径通过ANDROID_HOME环境变量获取,并且会自动检测最高API版本以及已经安装的最新build tools工具。


我们还可以通过包含path、api_level和build_tools_version属性来明确指定Android SDK的绝对路径、API级别和要使用的构建工具的版本。如果api_level和build_tools_version没有指定,android_sdk_repository规则将使用SDK中相应的最新版本。只要它们在SDK中存在,我们可以任意组合这些属性,例如:


android_sdk_repository(
    name = "androidsdk",
    path = "/path/to/Android/sdk",
    api_level = 25,
    build_tools_version = "30.0.3"
)


如果我们还要编译JNI代码,还需要在WORKSPACE中指定Android NDK路径:


ndroid_ndk_repository(name = "androidndk")


与Android SDK类似,这里面也是通过ANDROID_NDK_HOME环境变量控制NDK路径。


5. 创建BUILD文件


BUILD文件描述了一组构建输出(比如来自aapt的编译过的Android资源或来自javac编译的类文件)和它们之间的关系。这些依赖项可能是工作区中的源文件(Java、c++)或其他构建输出。BUILD文件是用Starlark语言编写的。


在Bazel中,BUILD文件是包层次结构概念的一部分。包层次结构是覆盖工作区中的目录结构的逻辑结构。每个包都是一个目录(及其子目录),其中包含一组相关的源文件和一个BUILD文件。包还包括任何子目录,不包括那些包含自己的BUILD文件的子目录。包名是相对于工作区的BUILD文件的路径。


注意:Bazel的包层次结构在概念上不同于BUILD文件所在的Android App目录的Java包层次结构,即使目录可能是相同的组织方式。


对于本文使用的简单Android Demo,src/main/中的源文件包含一个Bazel包。更复杂的项目可能有许多嵌套的包。


5.1 添加android_library规则


BUILD文件包含几种不同类型的Bazel声明。最重要的类型是构建规则,它告诉Bazel如何从一组源文件或其他依赖项构建中间或最终的软件输出。Bazel提供了两个构建规则,android_library和android_binary,我们可以用它们来构建Android应用。

我们首先使用android_library规则来告诉Bazel从应用程序源代码和资源文件构建一个Android库模块。然后使用android_binary规则告诉Bazel如何构建Android应用程序包。


我们在src/main/java/com/example/bazel目录中创建BUILD文件,并且声明一个新的android_library目标:


package(
    default_visibility = ["//src:__subpackages__"],
)
android_library(
    name = "greeter_activity",
    srcs = [
        "Greeter.java",
        "MainActivity.java",
    ],
    manifest = "AndroidManifest.xml",
    resource_files = glob(["res/**"]),
)


android_library构建规则包含一组属性,这些属性指定了Bazel从源文件构建库模块所需的信息。还要注意,规则的名称是greeter_activity,我们将在android_binary规则中使用这个名字作为依赖项引用规则。


5.2 添加android_binary规则


android_binary规则帮助我们编译成最终的apk文件。


我们在src/main/路径中增加BUILD文件,并且声明android_binary目标:


android_binary(
    name = "app",
    manifest = "AndroidManifest.xml",
    deps = ["//src/main/java/com/example/bazel:greeter_activity"],
)


在这里,deps属性引用我们之前添加到上面BUILD文件中的greeter_activity规则的输出。这意味着当Bazel构建该规则的输出时,它首先检查greeter_activity库规则的输出是否已经构建并且是最新的。如果没有,Bazel构建它,然后使用该输出构建应用程序包文件。


6.构建APP


通过运行bazel build //src/main:app构建android_binary目标。


build子命令指示Bazel构建下面的目标。目标被指定为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


7.构建输出文件路径


Bazel将中间和最终构建操作的输出都放在一组每个用户、每个工作区的输出目录中。这些目录从项目目录的顶层的以下位置进行symlink,其中的WORKSPACE是:


  • bazel-bin 存储二进制可执行文件和其他可运行的构建输出


  • bazel-genfiles存储由Bazel规则生成的中间源文件


  • bazel-out 存储其他类型的构建输出


Bazel将使用android_binary规则生成的Android .apk文件存储在Bazel -bin/src/main目录中,其中的子目录名src/main来自于Bazel包的名称。


8. 运行APP


现在我们可以通过命令行使用bazel mobile-install命令将应用程序部署到连接的Android设备或模拟器上。该命令使用adb与设备通信。在部署之前,我们必须按照adb中的说明设置我们的设备来使用adb。我们也可以选择在Android Studio中包含的Android模拟器上安装应用程序。


bazel mobile-install //src/main:app


接下来我们在手机上找到"Bazel Tutorial App"程序点击打开即可看到下面效果:


image.png


现在我们跑通了第一个Bazel构建的Android项目。


注意:mobile-install子命令还支持——incremental标志,该标志可用于仅部署自上次部署以来已更改的应用程序部分;它还支持——start_app标志,以便在安装应用程序时立即启动它。


9. 总结


我们我们使用Bazel构建了一个Android应用程序。主要步骤总结如下:


  • 通过安装Bazel和Android Studio来设置环境,并下载示例项目。
  • 设置一个Bazel工作空间,其中包含应用程序的源代码和一个识别工作空间目录顶层的workspace文件。
  • 更新WORKSPACE文件,以包含对所需外部依赖项的引用,如Android SDK。
  • 创建了BUILD文件。
  • 使用bazel构建该应用。
  • 在Android模拟器或物理设备上部署和运行应用程序。


我们通过最简单的Android项目编译了解了Bazel相关语法及规则,后续对我们学习谷歌新的基于Bazel构建的项目提供了很大帮助。后续我们介绍TensorFlow Lite在Android平台和iOS平台的编译。

目录
相关文章
|
3天前
|
Java 数据库 Android开发
【专栏】构建高效 Android 应用:探究 Kotlin 多线程优化策略
【4月更文挑战第27天】本文探讨了Kotlin在Android开发中的多线程优化,包括线程池、协程的使用,任务分解、避免阻塞操作以及资源管理。通过案例分析展示了网络请求、图像处理和数据库操作的优化实践。同时,文章指出并发编程的挑战,如性能评估、调试及兼容性问题,并强调了多线程优化对提升应用性能的重要性。开发者应持续学习和探索新的优化策略,以适应移动应用市场的竞争需求。
|
4天前
|
传感器 Android开发 开发者
构建高效Android应用:Kotlin的协程与Flow
【4月更文挑战第26天】随着移动应用开发的不断进步,开发者寻求更简洁高效的编码方式以应对复杂多变的业务需求。在众多技术方案中,Kotlin语言凭借其简洁性和强大的功能库逐渐成为Android开发的主流选择。特别是Kotlin的协程和Flow这两个特性,它们为处理异步任务和数据流提供了强大而灵活的工具。本文将深入探讨如何通过Kotlin协程和Flow来优化Android应用性能,实现更加流畅的用户体验,并展示在实际开发中的应用实例。
|
4天前
|
安全 数据处理 Android开发
构建高效Android应用:Kotlin协程的实践之路
【4月更文挑战第26天】 在面对现代Android开发时,性能优化和流畅的用户体验成为了开发者们追求的目标。Kotlin作为一种现代化的编程语言,通过其协程特性为Android应用带来了前所未有的并发处理能力。本文将深入探讨如何利用Kotlin协程提升Android应用的响应性和效率,同时保持代码的简洁性。我们将从协程的基础概念出发,逐步揭示如何在实际应用中运用这些强大的工具,以及它们如何改善应用架构和用户交互体验。
|
1天前
|
机器学习/深度学习 安全 数据处理
构建未来:基于Android的智能家居控制系统开发
【4月更文挑战第29天】 随着物联网技术的蓬勃发展,智能家居已成为现代技术革新的重要领域。本文将深入探讨基于Android平台的智能家居控制系统的设计和实现,旨在提供一种用户友好、高度集成且功能丰富的解决方案。通过利用Android设备的广泛普及和其强大的处理能力,结合最新的无线通讯技术和人工智能算法,我们旨在打造一个可靠、易用且具有高度可定制性的智能家居控制环境。文中不仅详细阐述了系统架构、关键技术选型以及界面设计,还对可能遇到的安全挑战进行了分析,并提出了相应的解决策略。
|
1天前
|
存储 缓存 数据库
构建高效Android应用:内存优化策略深度剖析
【4月更文挑战第29天】 在移动开发领域,性能一直是衡量应用质量的关键指标之一。特别是对于Android平台,由于设备硬件配置的多样性,内存管理成为开发者面临的一大挑战。本文将深入探讨Android应用内存优化的有效策略,旨在帮助开发者提升应用性能,减少内存消耗,避免常见的内存泄漏问题。通过对Android内存管理机制的分析与实际案例的结合,我们将提供一系列实用的优化技巧,助力应用在竞争激烈的市场中脱颖而出。
|
1天前
|
移动开发 数据库 Android开发
构建高效Android应用:探究Kotlin协程的优化实践
【4月更文挑战第29天】在移动开发领域,尤其是Android平台上,性能优化一直是开发者关注的重点。近年来,Kotlin语言凭借其简洁性和功能性成为Android开发的热门选择。其中,Kotlin协程作为一种轻量级的并发处理机制,为编写异步代码、网络请求和数据库操作提供了极大的便利。本文将深入探讨Kotlin协程在Android应用中的性能优化技巧,帮助开发者构建更加高效的应用程序。
|
1天前
|
存储 数据库 Android开发
构建高效Android应用:采用Kotlin与Jetpack的实践指南
【4月更文挑战第29天】 在现代移动开发领域,构建一个既高效又稳定的Android应用对于开发者来说是一个持续的挑战。随着技术的不断进步和用户需求的日益增长,传统的开发方法已不足以满足市场的要求。本文将深入探讨如何结合Kotlin编程语言以及Android Jetpack组件,来提升Android应用的性能、稳定性及开发效率。通过分析Kotlin的优势、介绍Jetpack的核心组件,并结合实际案例,我们将展示如何在实际项目中应用这些技术,以期达到优化应用架构、提高代码质量和加快开发流程的目的。
5 1
|
2天前
|
数据处理 调度 Android开发
构建高效Android应用:探究Kotlin的协程优势
【4月更文挑战第28天】 随着移动应用开发日趋复杂,传统的线程和异步处理模型在处理并发任务时显得笨重且易出错。本文深入分析了Kotlin协程作为一种轻量级线程管理方案的优势,探讨了其在Android应用中实现流畅用户界面和提升性能的潜力。通过对协程原理的剖析以及与现有技术的比较,揭示了如何利用协程优化应用结构、简化代码逻辑,并提高应用的响应性和可维护性。
|
2天前
|
API 调度 Android开发
构建高效Android应用:Kotlin协程的实践之路
【4月更文挑战第28天】随着移动应用开发的不断深入,开发者们追求更高效的编码方式和性能优化。Kotlin作为一种现代的编程语言,其协程特性提供了异步编程的新范式,使得处理并发任务更加简洁高效。本文将探讨如何在Android应用开发中利用Kotlin协程提升性能和用户体验,同时确保代码的可读性和可维护性。通过实例分析和代码演示,我们将深入了解协程在Android中的实际应用及其带来的优势。
8 1
|
2天前
|
移动开发 调度 Android开发
构建高效Android应用:探究Kotlin协程的优势与实践
【4月更文挑战第28天】 在移动开发领域,尤其是针对Android平台,性能优化和异步处理一直是开发者关注的焦点。随着Kotlin语言的普及,其提供的协程功能已经成为处理异步任务的强大工具。本文将深入探讨Kotlin协程在Android应用开发中的优势,并通过实例展示如何利用协程提升应用性能和响应能力。我们将分析协程与传统线程和AsyncTask的对比,以及如何在实际项目中有效集成和调试协程。