这个也是3月就todo了,但是一直没更新。最开始被android的编译系统搞得头大,因为和linux上区别还是很大,后面习惯了慢慢也好了,也一直没整理,现在整理一下吧。
官方文档:
https://source.android.com/docs/setup/build?hl=zh-cn
1 整体流程
首先,还是看看整个编译的流程。
通过这个图,可以看到流程就是输入还是Android.bp,通过soong转换成build.ninja,然后装换成大的ninja文件,通过ninja编译,生成各个产物。最后进行打包。
详细流程如下:
1. 初始化和配置阶段
当运行 make 或 soong 命令时,构建系统首先会执行初始化过程。初始化过程中,Soong 会解析环境变量、平台设置、构建配置等。
构建系统会读取 Android.bp 和 soong.config 文件,设置全局构建参数。soong.config 中可能会定义一些平台特定的设置,如编译选项、目标架构等。
Blueprint 的模块配置文件 .bp 会被加载,这些文件定义了不同的模块及其构建规则。
2. Blueprint 配置解析
在初始化完成后,Soong 会开始解析所有的 .bp 文件。每个 .bp 文件定义了一个或多个模块(如 cc_binary、cc_library 等)。
Soong 会根据模块的类型解析它们的构建规则,例如哪些源文件需要编译、哪些库是依赖项、输出文件是什么等。
Soong 会自动处理模块间的依赖关系,并构建模块间的依赖图。
3. 生成 Ninja 构建文件
在解析完所有的 Blueprint 配置后,Soong 会生成一个 build.ninja 文件,这个文件包含了详细的构建指令。
build.ninja 是 Ninja 构建系统所需要的文件,它描述了如何从源文件生成目标文件(如 .o 文件、静态库、共享库、可执行文件等)。
build.ninja 文件会定义每个构建任务的输入文件、输出文件和构建命令。
4. 执行 Ninja 构建任务
Soong 会将控制权交给 Ninja,它使用 build.ninja 文件来执行构建任务。
Ninja 会并行执行构建任务,根据 build.ninja 文件中的依赖关系,决定哪些文件需要重新编译,哪些可以跳过。
Ninja 会生成最终的构建输出,如可执行文件、库文件等,保存在 out/ 目录中。
5. 增量构建
Ninja 支持增量构建,它会检测源文件是否发生变化。如果没有变化,它会跳过相应的构建任务,只重新构建被修改或依赖于修改的文件。
Soong 和 Ninja 的增量构建机制显著提高了构建效率,避免了不必要的重新编译。
6. 构建完成
一旦 Ninja 完成了所有的构建任务,最终的输出文件(如 .apk、.so、.bin 等)将位于 out/ 目录中。
7 打包
使用这些输出文件进行进一步的测试、打包或部署。
由此可以看出,soong的主要组成部分就是BP文件Blueprint,soong,ninja。
2 Blueprint
Soong是基于Blueprint语法的,也就是经常看到的那个Android.bp。之前还有Android.mk,那个更接近makefile。
这里简单列一下Blueprint的语法。感觉有点接近python。
Blueprint 是 Soong 构建系统的配置语言,用于描述 Android 项目中的模块及其构建规则。它的语法简洁、声明式,主要用于
.bp
文件中。Blueprint 语法灵感来源于 Starlark(原名 Python),但它针对构建配置进行了定制,支持模块化和依赖关系管理。1. 基本语法结构
Blueprint 的语法主要由 模块、属性 和 赋值 组成。一个 Blueprint 文件通常包含多个模块的定义。
1.1 模块定义
模块通常通过关键字来定义,每个模块代表一个构建目标或任务。
cc_binary { name: "my_program", srcs: ["main.cpp", "utils.cpp"], shared_libs: ["libfoo"], }
cc_binary
:模块类型,表示一个 C++ 可执行文件。name
:模块的名称。srcs
:源文件列表,表示需要编译的源代码文件。shared_libs
:依赖的共享库列表。1.2 属性(Attributes)
每个模块都有一组属性,这些属性用于定义模块的特性和行为。
name
:模块的名称。srcs
:模块的源文件列表。deps
:依赖的其他模块。static_libs
:依赖的静态库。2. 常见模块类型
Blueprint 支持多种模块类型,用于描述不同类型的构建目标。常见的模块类型有:
cc_binary
:用于生成 C++ 可执行文件。cc_library
:用于生成 C++ 静态库或共享库。java_library
:用于生成 Java 库。android_app
:用于生成 Android 应用。cc_binary { name: "my_app", srcs: ["main.cpp"], static_libs: ["libfoo"], } cc_library { name: "libfoo", srcs: ["foo.cpp"], }
3. 属性赋值
Blueprint 使用 键值对 来定义属性。每个属性都由一个 键(key) 和 值(value) 组成,值可以是单个元素、列表或其他模块。
- 单个值:
name: "my_module"
- 列表:
srcs: ["file1.cpp", "file2.cpp"]
- 模块引用:
deps: ["libfoo"]
4. 条件语句
Blueprint 也支持条件表达式,通常用来控制属性的赋值或模块的包含。
if some_condition { srcs: ["file1.cpp"] } else { srcs: ["file2.cpp"] }
5. 函数和方法
Blueprint 支持一些内置函数,用来处理文件路径、版本控制等操作。例如,可以使用
join()
函数将路径合并:srcs: [join("src", "main.cpp")]
6. 模块依赖
模块之间的依赖关系在 Blueprint 中非常重要。依赖关系通过
deps
或shared_libs
等属性来指定。cc_binary { name: "my_program", srcs: ["main.cpp"], deps: ["libfoo", "libbar"], }
7. 嵌套模块
Blueprint 文件可以包含多个模块定义,每个模块都有独立的属性,可以通过嵌套来组织复杂的项目结构。
cc_library { name: "libfoo", srcs: ["foo.cpp"], } cc_binary { name: "my_program", srcs: ["main.cpp"], deps: ["libfoo"], }
8. 变量和表达式
Blueprint 支持使用变量来简化模块的配置。可以在一个地方定义变量,并在多个模块中引用。
MY_SRC_FILES = ["main.cpp", "utils.cpp"] cc_binary { name: "my_program", srcs: MY_SRC_FILES, }
9. 列表和字典
Blueprint 中的属性值可以是列表、字典等数据结构。列表用于存储多个元素,字典则用于存储键值对。
列表:
srcs: ["file1.cpp", "file2.cpp"]
字典:
cc_binary { name: "my_program", srcs: ["main.cpp"], flags: { cppflags: ["-DDEBUG", "-O2"], }, }
总结
Blueprint 是一个声明式的配置语言,使用简洁的语法来定义 Android 项目中的构建模块。它通过 模块、属性 和 依赖关系 来描述构建过程,并支持条件语句、函数、变量等特性来提高灵活性和可维护性。其语法简单明了,适合用于大规模的构建系统配置。
如果你有具体的模块或语法问题,欢迎继续提问!
3 Soong
Soong 本身是一个 Go 语言程序,通过
make
或m
来间接调用它。可以使用 Soong 提供的一些命令行工具来单独解析 Blueprint 配置文件。使用
soong
工具在 Android 源码目录下,你可以使用
soong
命令直接触发 Soong 构建过程。Soong 解析Android.bp
文件的过程是自动的,通常无需指定特定的命令来解析特定的bp
文件,但你可以通过以下方式来手动触发它。
使用
soong
生成 Ninja 构建文件: 在源码根目录下,运行:bash
复制代码
make soong
该命令会触发 Soong 解析
Android.bp
文件并生成build.ninja
文件。soong
会扫描所有的Android.bp
文件并生成适合 Ninja 执行的构建任务。直接运行 Soong 来解析 Blueprint 文件: 如果你想要仅仅解析 Blueprint 配置文件并不实际执行构建任务,可以使用
soong
作为独立命令来查看或验证 Blueprint 文件的内容。通常,通过以下命令运行:bash
复制代码
build/soong/soong_ui --make-mode
该命令会让 Soong 进入 make 模式,即开始解析所有
Android.bp
文件,并准备生成build.ninja
文件。3. 查看生成的
build.ninja
文件Soong 会生成
build.ninja
文件,里面包含了构建过程中需要执行的具体任务。你可以在构建目录(通常是out/
目录)中找到这个文件:bash
复制代码
out/soong/build.ninja
这个文件描述了如何编译和链接各个模块。
4. 调试和验证
如果你仅仅想调试 Blueprint 文件,验证 Soong 是否正确解析了你的
Android.bp
文件,可以使用 Soong 的调试工具来查看解析过程:bash
复制代码
build/soong/soong_ui --dump-vars
该命令会打印出与构建系统相关的所有变量和设置,帮助你了解构建过程中的所有配置。
5. 单独执行构建任务
一旦你生成了
build.ninja
文件,你可以直接使用 Ninja 来执行构建任务:bash
复制代码
ninja -C out/soong
这将根据
build.ninja
文件执行实际的编译和构建步骤。
4 Ninja
之前写过,可以直接参考Ninja小结_ninja-build-CSDN博客
参考:
Android学习13 -- 编译系统_android13编译-CSDN博客