摘要:Android.bp由Blueprint进行解析翻译,最终通过soong build编译成ninja文件,那么Blueprint是什么呢?
阅读本文大约需要花费10分钟。
文章首发微信公众号:IngresGe
专注于Android系统级源码分析,Android的平台设计,欢迎关注我,谢谢!
欢迎关注我的公众号!
[Android取经之路] 的源码都基于Android-Q(10.0) 进行分析
[Android取经之路] 系列文章:
《系统启动篇》
- Android系统架构
- Android是怎么启动的
- Android 10.0系统启动之init进程
- Android10.0系统启动之Zygote进程
- Android 10.0 系统启动之SystemServer进程
- Android 10.0 系统服务之ActivityMnagerService
- Android10.0系统启动之Launcher(桌面)启动流程
- Android10.0应用进程创建过程以及Zygote的fork流程
- Android 10.0 PackageManagerService(一)工作原理及启动流程
- Android 10.0 PackageManagerService(二)权限扫描
- Android 10.0 PackageManagerService(三)APK扫描
- Android 10.0 PackageManagerService(四)APK安装流程
《日志系统篇》
- Android10.0 日志系统分析(一)-logd、logcat 指令说明、分类和属性
- Android10.0 日志系统分析(二)-logd、logcat架构分析及日志系统初始化
- Android10.0 日志系统分析(三)-logd、logcat读写日志源码分析
- Android10.0 日志系统分析(四)-selinux、kernel日志在logd中的实现
《Binder通信原理》:
- Android10.0 Binder通信原理(一)Binder、HwBinder、VndBinder概要
- Android10.0 Binder通信原理(二)-Binder入门篇
- Android10.0 Binder通信原理(三)-ServiceManager篇
- Android10.0 Binder通信原理(四)-Native-C\C++实例分析
- Android10.0 Binder通信原理(五)-Binder驱动分析
- Android10.0 Binder通信原理(六)-Binder数据如何完成定向打击
- Android10.0 Binder通信原理(七)-Framework binder示例
- Android10.0 Binder通信原理(八)-Framework层分析
- Android10.0 Binder通信原理(九)-AIDL Binder示例
- Android10.0 Binder通信原理(十)-AIDL原理分析-Proxy-Stub设计模式
- Android10.0 Binder通信原理(十一)-Binder总结
《HwBinder通信原理》
- HwBinder入门篇-Android10.0 HwBinder通信原理(一)
- HIDL详解-Android10.0 HwBinder通信原理(二)
- HIDL示例-C++服务创建Client验证-Android10.0 HwBinder通信原理(三)
- HIDL示例-JAVA服务创建-Client验证-Android10.0 HwBinder通信原理(四)
- HwServiceManager篇-Android10.0 HwBinder通信原理(五)
- Native层HIDL服务的注册原理-Android10.0 HwBinder通信原理(六)
- Native层HIDL服务的获取原理-Android10.0 HwBinder通信原理(七)
- JAVA层HIDL服务的注册原理-Android10.0 HwBinder通信原理(八)
- JAVA层HIDL服务的获取原理-Android10.0 HwBinder通信原理(九)
- HwBinder驱动篇-Android10.0 HwBinder通信原理(十)
- HwBinder原理总结-Android10.0 HwBinder通信原理(十一)
《编译原理》
- 编译系统入门篇-Android10.0编译系统(一)
- 编译环境初始化-Android10.0编译系统(二)
- make编译过程-Android10.0编译系统(三)
- Image打包流程-Android10.0编译系统(四)
- Kati详解-Android10.0编译系统(五)
- Blueprint简介-Android10.0编译系统(六)
- Blueprint代码详细分析-Android10.0编译系统(七)
1 概述
blueprint没有一个官方的文档,代码中有build/buleprint/doc.go 和 build/blueprint/README.md两个简要介绍可供参考。
Blueprint是一个meta-build系统,它读取描述需要构建的模块的bp文件,并生成[Ninja](http://martine.github.io/ninja/)描述需要运行的命令及其依赖项的清单。
大多数构建系统使用内置规则或特定域的语言来描述模块如何转换为构建规则的逻辑,Blueprint将其委托给Go中编写的每个项目构建逻辑。
对于大型、异构的项目,这使得构建逻辑的内在复杂性可以用高级语言来维护,同时仍然允许通过修改易于理解的Blueprint文件对单个模块进行简单的更改。
Blueprint使用引导过程来允许Blueprint的代码、构建逻辑的代码和正在编译的项目的代码都在项目中。
层之间的依赖关系被完全跟踪-对逻辑代码的更改将导致重新编译逻辑,重新生成项目生成清单,并运行修改后的项目规则。
对Blueprint本身的更改将导致Blueprint重新构建,然后重新构建逻辑,等等。
Blueprint文件是一个伪python数据格式的模块列表,其中模块类型看起来像函数调用,模块的属性看起来像可选参数。例如,一个简单的模块可能看起来像:
cc_library {
name: "cmd",
srcs: [
"main.c",
],
deps: [
"libc",
],
}
subdirs = ["subdir1", "subdir2"]
Blueprint读取顶层Blueprint文件中的模块以及递归地通过“subdirs”变量列出的任何子目录的模块,它们的属性按模块类型存储到属性结构中。
一旦读取了所有模块,Blueprint将按注册顺序调用任何已注册的赋值函数(Mutators)。
赋值函数(Mutators)可以自上而下或自下而上访问每个模块,并根据需要修改它们。
常见的修改包括设置模块的属性以将信息从依赖项传播到从属项(例如,告诉模块哪些父类依赖于它),或者将模块拆分为多个变量(例如,正在编译的每个体系结构一个变量)。
在所有的赋值函数(Mutators)运行之后,每个模块都被要求根据属性值生成构建规则,然后单例可以从所有模块的输出生成任何构建规则。
每个项目的构建逻辑定义了一个顶层命令,在文档中称为“主构建器”。
此命令负责注册项目所需的模块类型以及任何单例或赋值函数,然后使用根Blueprint文件的路径调用Blueprint。
2 代码位置
代码位置:
build/blueprint
Google代码托管路径:
https://github.com/google/blueprint
3 Soong编译系统家族成员
Blueprint负责解析Android.bp生成规则,翻译成*.ninja文件。Soong_build生成out/soong/build.ninja编译。
4. blueprint-soong的执行过程
android需要先将blueprint和soong进行编译,然后才能识别项目中的android.bp文件,如何生成blueprint和soong,就在bootstarp中实现,具体的实现步骤如下:
1)通过build/blueprint/bootstrap.bash 生成out/soong/.minibootstrap/build.ninja
[out/soong/.minibootstrap/build.ninja]内容如下:
bootstrapBuildDir = out/soong
topFile = ./Android.bp
extraArgs = -t -l out/.module_paths/Android.bp.list
builddir = out
include ./build/blueprint/bootstrap/build.ninja
2)生成minibp 和bpglob
运行build/blueprint/microfactory/microfactory.bash,
加载out/soong/.minibootstrap/build.ninja 来生成minibp,同时,生成bpglob。
BUILDDIR="${BUILDDIR}/.minibootstrap" build_go minibp github.com/google/blueprint/bootstrap/minibp
BUILDDIR="${BUILDDIR}/.minibootstrap" build_go bpglob github.com/google/blueprint/bootstrap/bpglob
3) 生成out/soong/.bootstrap/build.ninja
minibp解析Android.bp用来生成out/soong/.bootstrap/build.ninja。其中的语法如下:
[build/blueprint/bootstrap/build.ninja]
rule build.ninja
command = ${builder} ${extraArgs} -b ${bootstrapBuildDir} -n ${builddir} -d ${out}.d -globFile ${myGlobs} -o ${out} ${in}
deps = gcc
depfile = ${out}.d
description = ${builder} ${out}
bootstrapNinja = ${bootstrapBuildDir}/.bootstrap/build.ninja
build ${bootstrapNinja}: build.ninja ${topFile} | ${builder}
builder = ${bootstrapBuildDir}/.minibootstrap/minibp
default ${bootstrapNinja}
命令展开后:
out/soong/.minibootstrap/minibp -t -l out/.module_paths/Android.bp.list -b out/soong -n out -d build.ninja.d -globFile out/soong/.minibootstrap/build-globs.ninja -o build.ninja ${in}
build out/soong/.bootstrap/build.ninja: build.ninja ./Android.bp out/soong/.minibootstrap/minibp
mibp最终编译生成out/soong/.bootstrap/build.ninja
4)生成out/soong/build.ninja文件从下面可知:
通过out/soong/.bootstrap/bin/soong_build 编译out/.module_paths/Android.bp.list 及out/soong/.bootstrap/build-globs.ninja 来生成out/soong/build.ninja其中out/.module_paths/Android.bp.list 包含了工程中所有的Android.bp
[out/soong/.bootstrap/build.ninja]
g.bootstrap.BinDir = out/soong/.bootstrap/bin
g.bootstrap.buildDir = out/soong
g.bootstrap.srcDir = .
build ${g.bootstrap.buildDir}/build.ninja: g.bootstrap.build.ninja $
${g.bootstrap.srcDir}/Android.bp | ${builder}
builder = ${g.bootstrap.BinDir}/soong_build
extra = -t -l out/.module_paths/Android.bp.list
globFile = out/soong/.bootstrap/build-globs.ninja
default ${g.bootstrap.buildDir}/build.ninja
5)通过ninja来完成编译
编译命令:
./prebuilts/build-tools/linux-x86/bin/ninja -w dupbuild=err -f out/soong/build.ninja "$@"
5.总结
bluepring--soong的编译过程经历下面四个阶段:
1.运行microfactory.bash以建立minibp -
2.运行.minibootstrap / build.ninja来构建.bootstrap / build.ninja -
3.运行.bootstrap / build.ninja来构建和运行主构建器 -
4.运行build.ninja来构建您的代码
我的微信公众号:IngresGe