Android 编译系统--06:Blueprint简介

449 阅读4分钟

本文转载自:Blueprint简介-Android10.0编译系统(六)

本文基于Android 10.0源码分析

1.概述

  Blueprint没有一个官方的文档,代码中有build/buleprint/doc.go和build/blueprint/README.md两个简要介绍可供参考。

  • Blueprint是一个meta-build系统,它读取描述需要构建的模块的bp文件,并生成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.代码位置

(1)代码位置

build/blueprint

(2)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来构建代码。