由于CSDN;复制近来的mk笔记格式太乱 建议看这个pdf文档
https://download.csdn.net/download/qq_41537499/89512254
为什么要学习bazel?
- 从Android 14开始,Google仍然强烈建议开发者使用Bazel和Kleaf构建Android内核及其工件。这表明Bazel在特定领域(如内核模块构建)的应用得到了推广和加强。
- 编译流程:截止到Android 13,大部分配置文件还是Android.bp,通过Soong解析成Ninja文件。而来到Android 14,Bazel的解析流程会被加入进来,使得Bazel在编译过程中的应用更为深入。
- 官方支持:对于独立应用开发,大多数开发者更习惯于使用build.gradle。不过,随着Google逐渐扩大Bazel在Android框架代码中的应用范围,未来可能会有更多的官方支持和文档来指导开发者使用Bazel进行Android开发
0.简介
Bazel是一个开源的构建工具,用于自动化软件构建过程。它主要用于构建大型、复杂的项目,如Google的内部项目和开源项目。Bazel使用一种名为Starlark的高级编程语言来描述构建规则,这使得构建过程更加灵活和可扩展。
Bazel的主要特点包括:
- 高度可扩展:Bazel允许用户自定义构建规则,以满足各种项目的特定需求。
- 跨平台支持:Bazel可以在多种操作系统上运行,包括Linux、macOS和Windows。
- 高性能:Bazel通过并行构建和缓存机制,提高了构建速度。
- 依赖管理:Bazel可以自动处理项目的依赖关系,确保正确的构建顺序。
- 持续集成:Bazel与持续集成系统(如Jenkins、Travis CI等)无缝集成,方便进行自动化构建和测试。
要开始使用Bazel,首先需要安装Bazel二进制文件,然后创建一个名为WORKSPACE
的文件,其中包含项目的元数据和依赖项。接下来,编写一个或多个名为BUILD
的文件,其中包含构建规则。最后,使用bazel build
命令构建项目。
bazel官网
https://bazel.google.cn/?hl=zh-cn
需要环境:
linux(Ubuntu)
zip、unzip
C++ 构建工具链
JDK.版本 21
Python。支持版本 2 和 3,安装其中一个就足够了。
例如,在 Ubuntu Linux 上,您可以使用以下命令安装这些要求:
sudo apt-get install build-essential openjdk-21-jdk python zip unzip
安装:
所有操作环境是在ubuntu下面
安装教程地址:https://bazel.google.cn/install/ubuntu?hl=zh-cn
推荐使用二进制安装程序
下载地址:
https://github.com/bazelbuild/bazel/releases
sudo apt install g++ unzip zip
#安装jdk
sudo apt-get install default-jdk
#下载bazel
wget https://github.com/bazelbuild/bazel/releases/download/7.2.0/bazel-7.2.0-installer-linux-x86_64.sh
#加执行权限
chmod +x bazel-version-installer-linux-x86_64.sh
#配置环境变量
vim ~/.bashrc
export PATH=“ P A T H : PATH: PATH:HOME/bin”
#执行安装
./bazel-version-installer-linux-x86_64.sh --user
–user 标志将 Bazel 安装到系统上的 $HOME/bin 目录中,并将 .bazelrc 路径设置为 $HOME/.bazelrc。使用 --help 命令可查看其他安装选项。
#查看版本
root@zyp:/opt/test_Cmake/lib/build# bazel --version
bazel 7.2.0
下载Demo示例
git clone https://github.com/bazelbuild/examples
这个Demo里面有C++、Java、Android等示例
Demo目录内容
root@zyp:/opt/test_bazel/examples# ll
总计 13580
drwxr-xr-x 17 root root 4096 7月 1 17:37 ./
drwxr-xr-x 3 root root 4096 7月 1 15:54 …/
drwxr-xr-x 7 root root 4096 7月 1 15:54 android/
-rw-r–r-- 1 root root 333 7月 1 15:54 AUTHORS
-rwxr-xr-x 1 root root 13788864 7月 1 17:37 bazel-7.2.0-installer-linux-x86_64.sh*
drwxr-xr-x 2 root root 4096 7月 1 15:54 .bazelci/
drwxr-xr-x 9 root root 4096 7月 1 15:54 bzlmod/
-rw-r–r-- 1 root root 381 7月 1 15:54 CODEOWNERS
drwxr-xr-x 12 root root 4096 7月 1 15:54 configurations/
-rw-r–r-- 1 root root 1685 7月 1 15:54 CONTRIBUTING.md
-rw-r–r-- 1 root root 779 7月 1 15:54 CONTRIBUTORS
drwxr-xr-x 6 root root 4096 7月 1 15:54 cpp-tutorial/
drwxr-xr-x 2 root root 4096 7月 1 15:54 flags-parsing-tutorial/
drwxr-xr-x 7 root root 4096 7月 1 15:54 frontend/
drwxr-xr-x 8 root root 4096 7月 1 15:54 .git/
drwxr-xr-x 2 root root 4096 7月 1 15:54 .github/
-rw-r–r-- 1 root root 107 7月 1 15:54 .gitignore
drwxr-xr-x 3 root root 4096 7月 1 15:54 java-maven/
drwxr-xr-x 3 root root 4096 7月 1 15:54 java-tutorial/
-rw-r–r-- 1 root root 11358 7月 1 15:54 LICENSE.txt
drwxr-xr-x 3 root root 4096 7月 1 15:54 make-variables/
-rw-r–r-- 1 root root 478 7月 1 15:54 .pre-commit-config.yaml
drwxr-xr-x 3 root root 4096 7月 1 15:54 query-quickstart/
-rw-r–r-- 1 root root 2688 7月 1 15:54 README.md
-rw-r–r-- 1 root root 320 7月 1 15:54 renovate.json
drwxr-xr-x 20 root root 4096 7月 1 15:54 rules/
drwxr-xr-x 3 root root 4096 7月 1 15:54 third-party-dependencies/
3.运行C++
https://bazel.google.cn/start/java?hl=zh-cn
编译stage1
git clone https://github.com/bazelbuild/examples
结构
examples
└── cpp-tutorial
├──stage1
│ ├── main
│ │ ├── BUILD
│ │ └── hello-world.cc
│ └── WORKSPACE
├──stage2
│ ├── main
│ │ ├── BUILD
│ │ ├── hello-world.cc
│ │ ├── hello-greet.cc
│ │ └── hello-greet.h
│ └── WORKSPACE
└──stage3
├── main
│ ├── BUILD
│ ├── hello-world.cc
│ ├── hello-greet.cc
│ └── hello-greet.h
├── lib
│ ├── BUILD
│ ├── hello-time.cc
│ └── hello-time.h
└── WORKSPACE
#编译stage1
cd cpp-tutorial/stage1
bazel build //main:hello-world
#会生成以下内容
Starting local Bazel server and connecting to it…
INFO: Analyzed target //main:hello-world (85 packages loaded, 6529 targets configured).
INFO: Found 1 target…
Target //main:hello-world up-to-date:
bazel-bin/main/hello-world
INFO: Elapsed time: 24.589s, Critical Path: 0.34s
INFO: 6 processes: 4 internal, 2 linux-sandbox.
INFO: Build completed successfully, 6 total actions
bazel-bin/main/hello-world
输出:
Hello world
Tue Jul 2 14:01:27 2024
stage1的hello-world.cc
#include
#include
#include
std::string get_greet(const std::string& who) {
return "Hello " + who;
}
void print_localtime() {
std::time_t result = std::time(nullptr);
std::cout << std::asctime(std::localtime(&result));
}
int main(int argc, char** argv) {
std::string who = “world”;
if (argc > 1) {
who = argv[1];
}
std::cout << get_greet(who) << std::endl;
print_localtime();
return 0;
}
#cpp-tutorial/stage1/main 目录中的 BUILD 文件
cc_binary(
name = “hello-world”,
srcs = [“hello-world.cc”],
)
hello-world 目标实例化 Bazel 的内置 cc_binary rule。
该规则会指示 Bazel 从没有依赖项的 hello-world.cc 源文件构建独立的可执行二进制文件
编译stage2
cpp-tutorial/stage2/main 目录中的 BUILD 文件
cc_library(
name = “hello-greet”,
srcs = [“hello-greet.cc”],
hdrs = [“hello-greet.h”],
)
cc_binary(
name = “hello-world”,
srcs = [“hello-world.cc”],
deps = [
“:hello-greet”,
],
)
使用此 BUILD 文件后,Bazel 会先构建 hello-greet 库(使用 Bazel 的内置 cc_library rule),
然后再构建 hello-world 二进制文件。hello-world 目标中的 deps 属性告知 Bazel,
必须使用 hello-greet 库才能构建 hello-world 二进制文件
root@zyp:/opt/test_bazel/examples/cpp-tutorial/stage2# ll
总计 56
drwxr-xr-x 3 root root 4096 7月 2 10:12 ./
drwxr-xr-x 6 root root 4096 7月 1 15:54 …/
lrwxrwxrwx 1 root root 105 7月 2 10:12 bazel-bin -> /root/.cache/bazel/_bazel_root/9e74109a65c3535de4ae1a422daa22e6/execroot/_main/bazel-out/k8-fastbuild/bin/
lrwxrwxrwx 1 root root 88 7月 2 10:12 bazel-out -> /root/.cache/bazel/_bazel_root/9e74109a65c3535de4ae1a422daa22e6/execroot/_main/bazel-out/
-rw-r–r-- 1 root root 327 7月 1 15:54 .bazelrc
lrwxrwxrwx 1 root root 78 7月 2 10:12 bazel-stage2 -> /root/.cache/bazel/_bazel_root/9e74109a65c3535de4ae1a422daa22e6/execroot/_main/
lrwxrwxrwx 1 root root 110 7月 2 10:12 bazel-testlogs -> /root/.cache/bazel/_bazel_root/9e74109a65c3535de4ae1a422daa22e6/execroot/_main/bazel-out/k8-fastbuild/testlogs/
drwxr-xr-x 2 root root 4096 7月 1 15:54 main/
-rw-r–r-- 1 root root 399 7月 2 10:05 MODULE.bazel
-rw-r–r-- 1 root root 9514 7月 2 10:12 MODULE.bazel.lock
-rw-r–r-- 1 root root 645 7月 1 15:54 README.md
-rw-r–r-- 1 root root 651 7月 1 15:54 WORKSPACE
root@zyp:/opt/test_bazel/examples/cpp-tutorial/stage2# bazel-bin/main/hello-world
Hello world
4.运行java
cd examples/java-tutorial
#目录结构
java-tutorial
├── BUILD
├── src
│ └── main
│ └── java
│ └── com
│ └── example
│ ├── cmdline
│ │ ├── BUILD
│ │ └── Runner.java
│ ├── Greeting.java
│ └── ProjectRunner.java
└── MODULE.bazel
bazel build //:ProjectRunner
bazel-bin/ProjectRunner
输出 Hi
#java-tutorial/BUILD
java_binary(
name = “ProjectRunner”,
srcs = glob([“src/main/java/com/example/*.java”]),
)
ProjectRunner 目标实例化了 Bazel 的内置 java_binary 规则。该规则会告知 Bazel 构建 .jar 文件和封装容器 Shell 脚本(均以目标命名)。
目标中的属性明确声明了其依赖项和选项。虽然 name 属性是必需的,但许多属性是可选的。例如,在 ProjectRunner 规则目标中,name 是目标的名称,
srcs 指定 Bazel 用于构建目标的源文件,main_class 指定包含主方法的类。(您可能已经注意到,我们的示例使用 glob 将一组源文件传递给 Bazel,而不是逐个列出它们。
输出
root@zyp:/opt/test_bazel/examples/java-tutorial# bazel build //:ProjectRunner
Starting local Bazel server and connecting to it…
WARNING: --enable_bzlmod is set, but no MODULE.bazel file was found at the workspace root. Bazel will create an empty MODULE.bazel file. Please consider migrating your external dependencies from WORKSPACE to MODULE.bazel. For more details, please refer to https://github.com/bazelbuild/bazel/issues/18958.
INFO: Analyzed target //:ProjectRunner (92 packages loaded, 1493 targets configured).
INFO: From Building ProjectRunner.jar (2 source files):
warning: [options] source value 8 is obsolete and will be removed in a future release
warning: [options] target value 8 is obsolete and will be removed in a future release
warning: [options] To suppress warnings about obsolete options, use -Xlint:-options.
INFO: Found 1 target…
Target //:ProjectRunner up-to-date:
bazel-bin/ProjectRunner
bazel-bin/ProjectRunner.jar
INFO: Elapsed time: 260.100s, Critical Path: 1.54s
INFO: 8 processes: 5 internal, 2 linux-sandbox, 1 worker.
INFO: Build completed successfully, 8 total actions
root@zyp:/opt/test_bazel/examples/java-tutorial# bazel-bin/ProjectRunner
Hi!
总结
root@zyp:/opt/test_bazel/examples/java-tutorial/src/main/java/com/example# ll
总计 20
drwxr-xr-x 3 root root 4096 7月 1 15:54 ./
drwxr-xr-x 3 root root 4096 7月 1 15:54 …/
drwxr-xr-x 2 root root 4096 7月 1 15:54 cmdline/
-rw-r–r-- 1 root root 122 7月 1 15:54 Greeting.java
-rw-r–r-- 1 root root 130 7月 1 15:54 ProjectRunner.java
root@zyp:/opt/test_bazel/examples/java-tutorial/src/main/java/com/example# cat Greeting.java
package com.example;
public class Greeting {
public static void sayHi() {
System.out.println(“Hi!”);
}
}
root@zyp:/opt/test_bazel/examples/java-tutorial/src/main/java/com/example# cat ProjectRunner.java
package com.example;
public class ProjectRunner {
public static void main(String args[]) {
Greeting.sayHi();
}
}
在java目录下src/main/com/example下有两个java文件,代码如上 、
ProjectRunner是程序入口 通过调用Greeting 中的sayHi()方法 输出Hi
5.运行Android
cd 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
bazel info workspace
运行报错 解决方法
ERROR: The ‘info’ command is only supported from within a workspace (below a directory having a WORKSPACE file).
root@zyp:/opt/test_bazel/examples/android/tutorial/# touch WORKSPACE
root@zyp:/opt/test_bazel/examples/android/tutorial/# vim WORKSPACE
android_sdk_repository(name = “androidsdk”)
#配置sdk路径
echo “export ANDROID_HOME=$HOME/home/zyp/Android/Sdk” >> ~/.bashrc
root@zyp:/opt/test_bazel/examples/android# bazel info workspace
/opt/test_bazel/examples/android/tutorial/
能输出路径即ok
android_library
在 src/main/java/com/example/bazel 目录中创建一个新的 BUILD 文件,在BUILD中定义如何编译
java源代码,如何处理资源文件生成APK,例如声明一个新的 android_library 规则来编译java源代码:
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_binary 规则来编译整个应用:
android_binary规则为应用构建 Android 应用软件包(.apk)。生成的apk位于bazel-bin下
在 src/main/ 目录中创建一个新的 BUILD 文件,并声明一个新的 android_binary 目标:
android_binary(
name = “app”,
manifest = “AndroidManifest.xml”,
deps = [“//src/main/java/com/example/bazel:greeter_activity”],
)
构建
bazel build //src/main:app
//https://maven.google.com/com/android/tools/r8/8.3.37/r8-8.3.37.jar
bazel mobile-install //src/main:app
Bazel还支持自动化测试和部署。
bazel test命令运行单元测试,并通过bazel run命令运行应用。
此外,还可以使用bazel mobile-install命令将应用安装到连接的Android设备上
名称 位置
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/
…/android/tutorial下的目录结构
root@zyp:/opt/test_bazel/examples/android/tutorial/bazel-tutorial# ll
总计 12
drwxr-xr-x 3 root root 4096 7月 2 14:31 ./
drwxr-xr-x 3 root root 4096 7月 2 13:42 …/
drwxr-xr-x 4 root root 4096 7月 2 14:31 bazel-out/
lrwxrwxrwx 1 root root 54 7月 2 14:31 MODULE.bazel -> /opt/test_bazel/examples/android/tutorial/MODULE.bazel
lrwxrwxrwx 1 root root 59 7月 2 14:31 MODULE.bazel.lock -> /opt/test_bazel/examples/android/tutorial/MODULE.bazel.lock
lrwxrwxrwx 1 root root 51 7月 2 14:31 README.md -> /opt/test_bazel/examples/android/tutorial/README.md
lrwxrwxrwx 1 root root 45 7月 2 14:31 src -> /opt/test_bazel/examples/android/tutorial/src/
lrwxrwxrwx 1 root root 51 7月 2 14:31 WORKSPACE -> /opt/test_bazel/examples/android/tutorial/WORKSPACE