一 blueprint介绍
之前我们介绍,blueprint负责解析Android.bp文件内容,我的理解是blueprint类似一个处理相关语法的库文件,soong则是定义具体如何处理相应的语法以及命令实现。也就是soong借助于blueprint定义Android.bp语法,完成Android.bp的解析。
Blueprint is a meta-build system that reads in Blueprints files that describe modules that need to be built, and produces a Ninja (http://martine.github.io/ninja/) manifest describing the commands that need to be run and their dependencie。
通过上面的定义,blueprint将blueprint file转换为ninja,如果要使用定制语法的话,需要使用golang自己进行自定义。blueprint语法如下:
cc_library {
name: "cmd",
srcs: [
"main.c",
],
deps: [
"libc",
],
}
subdirs = ["subdir1", "subdir2"]
Once all modules are read, Blueprint calls any registered Mutators, in registration order. Mutators can visit each module top-down or bottom-up, and modify them as necessar。每个目标已Module为单位,对于module的处理有注册mutator规则来处理,
After all Mutators have run, each module is asked to generate build rules based on property values, and then singletons can generate any build rules from the output of all modules.
还有一个singleton名词,针对所有的module生成build规则。
二 目录介绍
blueprint的目录结构如下:
bootstrapThe Blueprint bootstrapping mechanism is intended to enable building a source tree with minimal prebuilts.
bootstrap/bpdoc
bootstrap/bpglo bbpglob is the command line tool that checks if the list of files matching a glob has changed, and only updates the output file list if it has changed.bootstrap/minibp
bpfmt
bpmodify
deptools
gotestmain
gotestrunner
loadplugins
microfactory Microfactory is a tool to incrementally compile a go program.microfactory/main
parser
pathtools
proptools
这里面比较重要的有bootstarp目录,android需要先将blueprint和soong进行编译,然后才能识别项目中的android.bp文件,如何生成blueprint和soong,就在bootstarp中实现,具体的实现步骤如下:
step 1: 通过build/blueprint/http://build.ninja.in生成out/soong/.minibootstrap/build.ninja,其中out/soong/.minibootstrap/build.ninja用来生成minibp
step 2: minibp分析Android.bp用来生成out/soong/.bootstrap/build.ninja。其中的语法如下:
build ${g.bootstrap.buildDir}/.bootstrap/build.ninja: g.bootstrap.build.ninja $
${g.bootstrap.srcDir}/Android.bp | ${builder}
builder = ${g.bootstrap.BinDir}/minibp
extra = --build-primary
default ${g.bootstrap.buildDir}/.bootstrap/build.ninja
step 3:生成out/soong/build.ninja文件
build ${g.bootstrap.buildDir}/build.ninja: g.bootstrap.build.ninja $
${g.bootstrap.srcDir}/Android.bp | ${builder}
builder = ${g.bootstrap.BinDir}/soong_build
extra = $ -t
default ${g.bootstrap.buildDir}/build.ninja
out/soong/build.ninja是通过soong_build分析android目录下Android.bp文件生成。
build ${g.bootstrap.BinDir}/soong_build: g.bootstrap.cp $
${g.bootstrap.buildDir}/.bootstrap/soong_build/obj/a.out || $
${g.bootstrap.buildDir}/.bootstrap/soong-android/test/test.passed $
${g.bootstrap.buildDir}/.bootstrap/soong-cc-config/test/test.passed $
${g.bootstrap.buildDir}/.bootstrap/soong-cc/test/test.passed $
${g.bootstrap.buildDir}/.bootstrap/soong-java/test/test.passed $
${g.bootstrap.buildDir}/.bootstrap/soong-python/test/test.passed
default ${g.bootstrap.BinDir}/soong_build
通过上面的分析可以得出,bootstarp主要作用就是编译blueprint soong以及生成out/soong/build.ninja文件。因此bootstrap有个别称叫 "primary builder".
结合之前的分析,大体执行流程是
- Runs microfactory.bash to build minibp microfactory.bash在soong_ui.bash中执行
- Runs the .minibootstrap/build.ninja to build .bootstrap/build.ninja
- Runs .bootstrap/build.ninja to build and run the primary builder
上面两步对应的函数为runSoongBootstrap 和 runSoong(具体执行soong.bash)
- Runs build.ninja to build your code runNinja执行
看soong_build,用来生成最后的build.ninja,依赖blueprint 和soong等相关库。
bootstrap_go_binary {
name: "soong_build",
deps: [
"blueprint",
"blueprint-bootstrap",
"soong",
"soong-android",
"soong-env",
],
srcs: [
"main.go",
],
primaryBuilder: true,
}
三 blueprint重要函数
blueprint有几个函数比较重要,比如自定义一个module
my_module {
name: "myName",
foo: "my foo string",
bar: ["my", "bar", "strings"],
}
可以使用如下函数进行自定义规则
func (c *Context) RegisterModuleType(name string, factory ModuleFactory)
type myModule struct {
properties struct {
Foo string
Bar []string
}
}
func NewMyModule() (blueprint.Module, []interface{}) {
module := new(myModule)
properties := &module.properties
return module, []interface{}{properties}
}
func main() {
ctx := blueprint.NewContext()
ctx.RegisterModuleType("my_module", NewMyModule)
// ...
}
blueprint具体的步骤如下:
A Context contains all the state needed to parse a set of Blueprints files
and generate a Ninja file. The process of generating a Ninja file proceeds
through a series of four phases. Each phase corresponds with a some methods
on the Context object
Phase Methods
------------ -------------------------------------------
1. Registration RegisterModuleType, RegisterSingletonType
2. Parse ParseBlueprintsFiles, Parse
3. Generate ResolveDependencies, PrepareBuildActions
4. Write WriteBuildFile
The registration phase prepares the context to process Blueprints files
containing various types of modules. The parse phase reads in one or more
Blueprints files and validates their contents against the module types that
have been registered. The generate phase then analyzes the parsed Blueprints
contents to create an internal representation for the build actions that must
be performed. This phase also performs validation of the module dependencies
and property values defined in the parsed Blueprints files. Finally, the
write phase generates the Ninja manifest text based on the generated build
actions.
可以看到在soong下每个init函数下都有 RegisterModuleType或者 RegisterSingletonType进行module注册。具体的流程在build/blueprint/bootstrap/command.go
func Main(ctx *blueprint.Context, config interface{}, extraNinjaFileDeps ...string) {
ctx.RegisterBottomUpMutator("bootstrap_plugin_deps", pluginDeps)
ctx.RegisterModuleType("bootstrap_go_package", newGoPackageModuleFactory(bootstrapConfig))
ctx.RegisterModuleType("bootstrap_core_go_binary", newGoBinaryModuleFactory(bootstrapConfig, StageBootstrap))
ctx.RegisterModuleType("bootstrap_go_binary", newGoBinaryModuleFactory(bootstrapConfig, StagePrimary))
ctx.RegisterModuleType("blueprint_go_binary", newGoBinaryModuleFactory(bootstrapConfig, StageMain))
ctx.RegisterTopDownMutator("bootstrap_stage", propagateStageBootstrap)
ctx.RegisterSingletonType("bootstrap", newSingletonFactory(bootstrapConfig))
ctx.RegisterSingletonType("glob", globSingletonFactory(ctx))
deps, errs := ctx.ParseBlueprintsFiles(bootstrapConfig.topLevelBlueprintsFile)
if len(errs) > 0 {
fatalErrors(errs)
}
errs = ctx.ResolveDependencies(config)
extraDeps, errs := ctx.PrepareBuildActions(config)
err := ctx.WriteBuildFile(buf)
soong_build和minibp的入口都是在上面的Main中,只不过minibp规则没有soong复杂,soong_build添加了soong中定义的规则。