Blueprint代码详细分析-Android10.0编译系统(七)

摘要:Blueprint解析Android.bp到ninja的代码流程是如何走的?

1 概述

    上一节,我们介绍了blueprint的作用和执行过程,这一节我们从代码的层面来分析blueprint的具体执行流程。

    启用Soong以后,在Android编译最开始的准备阶段,会执行build/soong/soong.bash进行环境准备。其中会先编译、安装Blueprint到out目录下。也就是说,在编译Android项目时,Android.bp相关工具链会自动编译,无需费神。

Soong是与Android强关联的一个项目,而Blueprint则相对比较独立,可以单独编译、使用。

 

2 blueprint相关编译链生成

    通过前面的MAKE编译,我们了解到blueprint等工具链的生成,是在runSoong()中编出来的,因此我们就从runSoong()为突破口进行分析。

 

2.1 Build调用栈

    make后,走的是Soong的构建,其中会把一些编译工具给编出来,例如blueprint,然后通过runSoong找到所有的Android.bp文件,编译成out/soong/build.ninja。

    通过runKatiBuild找到所有的Android通过runKatiBuild找到所有的Android.mk文件,编译 out/build-aosp_arm.ninja,最后把这些ninja文件合并成combined-aosp_arm.ninja,通过ninja完成最终编译。

    其中runSoong对工具进行编译,编译出blueprint等编译工具, 把*.bp 编译成 out/soong/build.ninja。

 

2.2 runSoong调用栈

  runSoong执行bootstrap.bash和blueprint_impl.bash,最终生成minibp和bpglob进程,建立/out/soong/.minibootstrap/build.ninja 和/out/soong/.bootstrap/build.ninja 两个文件。

  再通过out/soong/.bootstrap/bin/soong_build,

编译out/.module_paths/Android.bp.list 

及out/soong/.bootstrap/build-globs.ninja

生成out/soong/build.ninja,参与最终的ninja编译。

 

2.3 runSoong()

  runSoong()的执行过程:

  • 执行build/blueprint/bootstrap.bash  生成.minibootstrap/build.ninja 和.bootstrap/build.ninja

  •  生成minibp\bpglob

  • 通过ninja来编译.minibootstrap/build.ninja 和.bootstrap/build.ninja

 

首先执行build/blueprint/bootstrap.bash

bootstrap.bash的作用:

  • 它可以引导独立的blueprint来生成minibp二进制文件, 

           可以直接运行 ./build/blueprint/bootstrap.bash。

  • 也可以从另一个脚本调用它来引导基于Bleprint的自定义构建系统。


 
 
  1. [/build/soong/ui/build/soong. go]
  2. func runSoong(ctx Context, config Config) {
  3. ctx.BeginTrace(metrics.RunSoong, "soong")
  4. defer ctx.EndTrace()
  5. func() {
  6. ctx.BeginTrace(metrics.RunSoong, "blueprint bootstrap")
  7. defer ctx.EndTrace()
  8. cmd := Command(ctx, config, "blueprint bootstrap", "build/blueprint/bootstrap.bash", "-t")
  9. cmd.Environment.Set( "BLUEPRINTDIR", "./build/blueprint")
  10. cmd.Environment.Set( "BOOTSTRAP", "./build/blueprint/bootstrap.bash")
  11. cmd.Environment.Set( "BUILDDIR", config.SoongOutDir())
  12. cmd.Environment.Set( "GOROOT", "./"+filepath.Join( "prebuilts/go", config.HostPrebuiltTag()))
  13. cmd.Environment.Set( "BLUEPRINT_LIST_FILE", filepath.Join(config.FileListDir(), "Android.bp.list"))
  14. cmd.Environment.Set( "NINJA_BUILDDIR", config.OutDir())
  15. cmd.Environment.Set( "SRCDIR", ".")
  16. cmd.Environment.Set( "TOPNAME", "Android.bp")
  17. cmd.Sandbox = soongSandbox
  18. //执行build/blueprint/bootstrap.bash
  19. cmd.RunAndPrintOrFatal()
  20. }()
  21. func() {
  22. ctx.BeginTrace(metrics.RunSoong, "environment check")
  23. defer ctx.EndTrace()
  24. envFile := filepath.Join(config.SoongOutDir(), ".soong.environment")
  25. envTool := filepath.Join(config.SoongOutDir(), ".bootstrap/bin/soong_env")
  26. if _, err := os.Stat(envFile); err == nil {
  27. if _, err := os.Stat(envTool); err == nil {
  28. cmd := Command(ctx, config, "soong_env", envTool, envFile)
  29. cmd.Sandbox = soongSandbox
  30. var buf strings.Builder
  31. cmd.Stdout = &buf
  32. cmd.Stderr = &buf
  33. if err := cmd.Run(); err != nil {
  34. ctx.Verboseln( "soong_env failed, forcing manifest regeneration")
  35. os.Remove(envFile)
  36. }
  37. if buf.Len() > 0 {
  38. ctx.Verboseln(buf.String())
  39. }
  40. } else {
  41. ctx.Verboseln( "Missing soong_env tool, forcing manifest regeneration")
  42. os.Remove(envFile)
  43. }
  44. } else if !os.IsNotExist(err) {
  45. ctx.Fatalf( "Failed to stat %f: %v", envFile, err)
  46. }
  47. }()
  48. var cfg microfactory.Config
  49. cfg.Map( "github.com/google/blueprint", "build/blueprint")
  50. cfg.TrimPath = absPath(ctx, ".")
  51. func() {
  52. ctx.BeginTrace(metrics.RunSoong, "minibp")
  53. defer ctx.EndTrace()
  54. minibp := filepath.Join(config.SoongOutDir(), ".minibootstrap/minibp")
  55. if _, err := microfactory.Build(&cfg, minibp, "github.com/google/blueprint/bootstrap/minibp"); err != nil {
  56. ctx.Fatalln( "Failed to build minibp:", err)
  57. }
  58. }()
  59. func() {
  60. ctx.BeginTrace(metrics.RunSoong, "bpglob")
  61. defer ctx.EndTrace()
  62. bpglob := filepath.Join(config.SoongOutDir(), ".minibootstrap/bpglob")
  63. if _, err := microfactory.Build(&cfg, bpglob, "github.com/google/blueprint/bootstrap/bpglob"); err != nil {
  64. ctx.Fatalln( "Failed to build bpglob:", err)
  65. }
  66. }()
  67. ninja := func(name, file string) {
  68. ctx.BeginTrace(metrics.RunSoong, name)
  69. defer ctx.EndTrace()
  70. fifo := filepath.Join(config.OutDir(), ".ninja_fifo")
  71. nr := status.NewNinjaReader(ctx, ctx.Status.StartTool(), fifo)
  72. defer nr.Close()
  73. cmd := Command(ctx, config, "soong "+name,
  74. config.PrebuiltBuildTool( "ninja"),
  75. "-d", "keepdepfile",
  76. "-w", "dupbuild=err",
  77. "-j", strconv.Itoa(config.Parallel()),
  78. "--frontend_file", fifo,
  79. "-f", filepath.Join(config.SoongOutDir(), file))
  80. cmd.Sandbox = soongSandbox
  81. cmd.RunAndPrintOrFatal()
  82. }
  83. ninja( "minibootstrap", ".minibootstrap/build.ninja")
  84. ninja( "bootstrap", ".bootstrap/build.ninja")
  85. }

 

2.4 minibp的生成

  从build/blueprint/Blueprints 中可知,需要编译的二进制文件名为 minibp,源文件为:bootstrap/minibp/main.go,依赖于 blueprint、blueprint-bootstrap、gotestmain-tests。


 
 
  1. [build/blueprint/Blueprints]
  2. bootstrap_go_binary {
  3. name: "minibp",
  4. deps: [
  5. "blueprint",
  6. "blueprint-bootstrap",
  7. "gotestmain-tests",
  8. ],
  9. srcs: [ "bootstrap/minibp/main.go"],
  10. }

out/soong/.bootstrap/build.ninja中模块的相关规则如下:


 
 
  1. # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
  2. # Module: minibp
  3. # Variant:
  4. # Type: bootstrap_go_binary
  5. # Factory: github.com/google/blueprint/bootstrap.newGoBinaryModuleFactory.func1
  6. # Defined: build/blueprint/Blueprints:132:1
  7. build ${g.bootstrap.buildDir}/.bootstrap/minibp/obj/minibp.a: $
  8. g.bootstrap.compile $
  9. ${g.bootstrap.srcDir}/build/blueprint/bootstrap/minibp/main.go | $
  10. ${g.bootstrap.compileCmd} $
  11. ${g.bootstrap.buildDir}/.bootstrap/blueprint-parser/pkg/github.com/google/blueprint/parser.a $
  12. ${g.bootstrap.buildDir}/.bootstrap/blueprint-deptools/pkg/github.com/google/blueprint/deptools.a $
  13. ${g.bootstrap.buildDir}/.bootstrap/blueprint-pathtools/pkg/github.com/google/blueprint/pathtools.a $
  14. ${g.bootstrap.buildDir}/.bootstrap/blueprint-proptools/pkg/github.com/google/blueprint/proptools.a $
  15. ${g.bootstrap.buildDir}/.bootstrap/blueprint/pkg/github.com/google/blueprint.a $
  16. ${g.bootstrap.buildDir}/.bootstrap/blueprint-bootstrap-bpdoc/pkg/github.com/google/blueprint/bootstrap/bpdoc.a $
  17. ${g.bootstrap.buildDir}/.bootstrap/blueprint-bootstrap/pkg/github.com/google/blueprint/bootstrap.a $
  18. ${g.bootstrap.buildDir}/.bootstrap/gotestmain-tests/pkg/github.com/google/blueprint/gotestmain.a
  19. incFlags = -I ${g.bootstrap.buildDir}/.bootstrap/blueprint-parser/pkg -I ${g.bootstrap.buildDir}/.bootstrap/blueprint-deptools/pkg -I ${g.bootstrap.buildDir}/.bootstrap/blueprint-pathtools/pkg -I ${g.bootstrap.buildDir}/.bootstrap/blueprint-proptools/pkg -I ${g.bootstrap.buildDir}/.bootstrap/blueprint/pkg -I ${g.bootstrap.buildDir}/.bootstrap/blueprint-bootstrap-bpdoc/pkg -I ${g.bootstrap.buildDir}/.bootstrap/blueprint-bootstrap/pkg -I ${g.bootstrap.buildDir}/.bootstrap/gotestmain-tests/pkg
  20. pkgPath = minibp
  21. build ${g.bootstrap.buildDir}/.bootstrap/minibp/obj/a.out: g.bootstrap.link $
  22. ${g.bootstrap.buildDir}/.bootstrap/minibp/obj/minibp.a | $
  23. ${g.bootstrap.linkCmd} $
  24. ${g.bootstrap.buildDir}/.bootstrap/blueprint-parser/pkg/github.com/google/blueprint/parser.a $
  25. ${g.bootstrap.buildDir}/.bootstrap/blueprint-deptools/pkg/github.com/google/blueprint/deptools.a $
  26. ${g.bootstrap.buildDir}/.bootstrap/blueprint-pathtools/pkg/github.com/google/blueprint/pathtools.a $
  27. ${g.bootstrap.buildDir}/.bootstrap/blueprint-proptools/pkg/github.com/google/blueprint/proptools.a $
  28. ${g.bootstrap.buildDir}/.bootstrap/blueprint/pkg/github.com/google/blueprint.a $
  29. ${g.bootstrap.buildDir}/.bootstrap/blueprint-bootstrap-bpdoc/pkg/github.com/google/blueprint/bootstrap/bpdoc.a $
  30. ${g.bootstrap.buildDir}/.bootstrap/blueprint-bootstrap/pkg/github.com/google/blueprint/bootstrap.a $
  31. ${g.bootstrap.buildDir}/.bootstrap/gotestmain-tests/pkg/github.com/google/blueprint/gotestmain.a
  32. libDirFlags = -L ${g.bootstrap.buildDir}/.bootstrap/blueprint-parser/pkg -L ${g.bootstrap.buildDir}/.bootstrap/blueprint-deptools/pkg -L ${g.bootstrap.buildDir}/.bootstrap/blueprint-pathtools/pkg -L ${g.bootstrap.buildDir}/.bootstrap/blueprint-proptools/pkg -L ${g.bootstrap.buildDir}/.bootstrap/blueprint/pkg -L ${g.bootstrap.buildDir}/.bootstrap/blueprint-bootstrap-bpdoc/pkg -L ${g.bootstrap.buildDir}/.bootstrap/blueprint-bootstrap/pkg -L ${g.bootstrap.buildDir}/.bootstrap/gotestmain-tests/pkg
  33. build out/soong/.bootstrap/bin/minibp: g.bootstrap.cp $
  34. ${g.bootstrap.buildDir}/.bootstrap/minibp/obj/a.out || $
  35. ${g.bootstrap.buildDir}/.bootstrap/blueprint-parser/test/test.passed $
  36. ${g.bootstrap.buildDir}/.bootstrap/blueprint-pathtools/test/test.passed $
  37. ${g.bootstrap.buildDir}/.bootstrap/blueprint-proptools/test/test.passed $
  38. ${g.bootstrap.buildDir}/.bootstrap/blueprint/test/test.passed $
  39. ${g.bootstrap.buildDir}/.bootstrap/blueprint-bootstrap-bpdoc/test/test.passed $
  40. ${g.bootstrap.buildDir}/.bootstrap/gotestmain-tests/test/test.passed

 

   可以看到最终策划你改成的minibp需要三部生成,第一部编译成minibp.a其中依赖于 blueprint、blueprint-pathtools 和main.go,第二部是link成a.out,第三部通过cp到对应的bin的目录下,完成一个module的解析。

 

3 Blueprint的编译阶段

    生成Ninja文件的过程分为四个阶段。

    解析一个Blueprint文件需要四步:

    第一步:注册阶段准备上下文来处理包含各种类型模块的Blueprint文件。注册module也就是bootstrap_go_binary和内容处理规则,如deps等。

    第二步:解析阶段读取一个或多个Blueprint文件,并根据已注册的模块类型验证其内容。

    第三步:generate阶段分析解析的Blueprint内容,为必须执行的构建操作创建一个内部表示。此 阶段还执行模块依赖项和已解析Bleprint文件中定义的属性值的验证。

    第四步:写入阶段根据生成的构建操作生成Ninja文件。

 

3.1 minibp编译入口

主要步骤:

1.配置一个Context结构

2.执行 command.go 的Main() 进行最终编译


 
 
  1. [/build/blueprint/bootstrap/minibp/main. go]
  2. func main() {
  3. flag.Parse()
  4. ctx := blueprint.NewContext() //配置一个Context结构
  5. if !runAsPrimaryBuilder {
  6. ctx.SetIgnoreUnknownModuleTypes( true)
  7. }
  8. config := Config{
  9. generatingPrimaryBuilder: !runAsPrimaryBuilder,
  10. }
  11. //执行 command.go 的Main() 进行最终编译
  12. bootstrap.Main(ctx, config)
  13. }

 

3.2 Context配置

    返回一个Context的结构,存储了bp里面的一些字段,例如之前看到的

bootstrap_core_go_binary。


 
 
  1. [/build/blueprint/context. go]
  2. func newContext() *Context {
  3. return &Context{
  4. Context: context.Background(),
  5. moduleFactories: make( map[ string]ModuleFactory), //存储着我们后面注册的module如“bootstrap_core_go_binary”
  6. nameInterface: NewSimpleNameInterface(),
  7. moduleInfo: make( map[Module]*moduleInfo),
  8. globs: make( map[ string]GlobPath),
  9. fs: pathtools.OsFs,
  10. ninjaBuildDir: nil,
  11. requiredNinjaMajor: 1,
  12. requiredNinjaMinor: 7,
  13. requiredNinjaMicro: 0,
  14. }
  15. }

 

3.3 执行 command.go Main()

3.3.1 调用栈


 
 
  1. [/build/blueprint/bootstrap/command. go]
  2. package bootstrap
  3. func Main(ctx *blueprint.Context, config interface{}, extraNinjaFileDeps ...string) {
  4. ...
  5. ctx.RegisterBottomUpMutator( "bootstrap_plugin_deps", pluginDeps)
  6. ctx.RegisterModuleType( "bootstrap_go_package", newGoPackageModuleFactory(bootstrapConfig))
  7. ctx.RegisterModuleType( "bootstrap_go_binary", newGoBinaryModuleFactory(bootstrapConfig, false))
  8. ctx.RegisterModuleType( "blueprint_go_binary", newGoBinaryModuleFactory(bootstrapConfig, true))
  9. ctx.RegisterSingletonType( "bootstrap", newSingletonFactory(bootstrapConfig))
  10. ctx.RegisterSingletonType( "glob", globSingletonFactory(ctx))
  11. deps, errs := ctx.ParseFileList(filepath.Dir(bootstrapConfig.topLevelBlueprintsFile), filesToParse)
  12. if len(errs) > 0 {
  13. fatalErrors(errs)
  14. }
  15. // Add extra ninja file dependencies
  16. deps = append(deps, extraNinjaFileDeps...)
  17. extraDeps, errs := ctx.ResolveDependencies(config)
  18. ...
  19. extraDeps, errs = ctx.PrepareBuildActions(config)
  20. ...
  21. err = ctx.WriteBuildFile(out)
  22. ...
  23. }

步骤:

1.注册一些bp模块类型、依赖和类型

2.解析Blueprints文件

3.检查解析的Blueprint文件中定义的所有模块指定的依赖项是否有效

4.生成需要执行的所有生成操作的内部表示

5.将生成的构建操作的Ninja manifest文本写入文件

 

3.3.2 RegisterBottomUpMutator()

    RegisterBottomUpMutator注册一个mutator,它将被调用来将模块拆分为变量。每个注册的mutator按注册顺序调用(混合使用toppownmutator和BottomUpMutators)每个模块一次,在所有模块依赖项的调用返回之前,不会在模块上调用。

    此处给定的赋值函数类型名称对于上下文中所有自下而上或早期的赋值函数必须是唯一的。

返回一个MutatorHandle,在这个句柄上可以调用Parallel来设置mutator在维护顺序的同时并行访问模块。


 
 
  1. [/build/blueprint/context. go]
  2. func (c *Context) RegisterBottomUpMutator(name string, mutator BottomUpMutator) MutatorHandle {
  3. for _, m := range c.variantMutatorNames {
  4. if m == name {
  5. panic(fmt.Errorf( "mutator name %s is already registered", name))
  6. }
  7. }
  8. info := &mutatorInfo{
  9. bottomUpMutator: mutator,
  10. name: name,
  11. }
  12. c.mutatorInfo = append(c.mutatorInfo, info)
  13. c.variantMutatorNames = append(c.variantMutatorNames, name)
  14. return info
  15. }

 

3.3.3 RegisterSingletonType()

    RegisterSingletonType注册将被调用以生成生成操作的单例类型。作为生成阶段的一部分,每个注册的单例类型被实例化和调用一次。按照注册顺序调用每个已注册的单例。

    此处给定的单例类型名称对于上下文必须是唯一的。factory函数应该是一个命名函数,这样它的包和名称就可以包含在生成的Ninja文件中,以便进行调试。


 
 
  1. [/build/blueprint/context. go]
  2. func (c *Context) RegisterSingletonType(name string, factory SingletonFactory) {
  3. for _, s := range c.singletonInfo {
  4. if s.name == name {
  5. panic(errors.New( "singleton name is already registered"))
  6. }
  7. }
  8. c.singletonInfo = append(c.singletonInfo, &singletonInfo{
  9. factory: factory,
  10. singleton: factory(),
  11. name: name,
  12. })
  13. }

 

3.3.4 ResolveDependencies()

    ResolveDependencies检查解析的Blueprint文件中定义的所有模块指定的依赖项是否有效。这意味着依赖的模块已经定义,并且不存在循环依赖。


 
 
  1. [/build/blueprint/context. go]
  2. func (c *Context) resolveDependencies(ctx context.Context, config interface{}) (deps [] string, errs [] error) {
  3. pprof.Do(ctx, pprof.Labels( "blueprint", "ResolveDependencies"), func(ctx context.Context) {
  4. c.liveGlobals = newLiveTracker(config)
  5. deps, errs = c.generateSingletonBuildActions(config, c.preSingletonInfo, c.liveGlobals)
  6. if len(errs) > 0 {
  7. return
  8. }
  9. errs = c.updateDependencies()
  10. if len(errs) > 0 {
  11. return
  12. }
  13. var mutatorDeps [] string
  14. mutatorDeps, errs = c.runMutators(ctx, config)
  15. if len(errs) > 0 {
  16. return
  17. }
  18. deps = append(deps, mutatorDeps...)
  19. c.cloneModules()
  20. c.dependenciesReady = true
  21. })
  22. if len(errs) > 0 {
  23. return nil, errs
  24. }
  25. return deps, nil
  26. }

 

3.3.5 PrepareBuildActions

    PrepareBuildActions生成需要执行的所有生成操作的内部表示。

这个过程包括对在解析阶段创建的每个Module对象调用GenerateBuildActions方法,然后对每个注册的单例对象调用GenerateBuildActions方法。

    如果尚未调用ResolveDependencies方法,则此方法会自动调用该方法。

    通过传递给GenerateBuildActions的ModuleContext和SingletonContext对象上的config方法,config参数可用于所有Module和Singleton对象。

    它还传递给通过PoolFunc、RuleFunc和VariableFunc指定的函数,以便它们可以计算特定配置的值。

    返回的deps是由模块和singleton通过ModuleContext添加的ninja文件依赖项的列表。

AddNinjaFileDeps(),SingletonContext.AddNinjaFileDeps(),和PackageContext.AddNinjaFileDeps()方法。


 
 
  1. [/build/blueprint/context. go]
  2. func (c *Context) PrepareBuildActions(config interface{}) (deps [] string, errs [] error) {
  3. pprof.Do(c.Context, pprof.Labels( "blueprint", "PrepareBuildActions"), func(ctx context.Context) {
  4. c.buildActionsReady = false
  5. if !c.dependenciesReady {
  6. var extraDeps [] string
  7. extraDeps, errs = c.resolveDependencies(ctx, config)
  8. if len(errs) > 0 {
  9. return
  10. }
  11. deps = append(deps, extraDeps...)
  12. }
  13. var depsModules [] string
  14. depsModules, errs = c.generateModuleBuildActions(config, c.liveGlobals)
  15. if len(errs) > 0 {
  16. return
  17. }
  18. var depsSingletons [] string
  19. depsSingletons, errs = c.generateSingletonBuildActions(config, c.singletonInfo, c.liveGlobals)
  20. if len(errs) > 0 {
  21. return
  22. }
  23. deps = append(deps, depsModules...)
  24. deps = append(deps, depsSingletons...)
  25. if c.ninjaBuildDir != nil {
  26. err := c.liveGlobals.addNinjaStringDeps(c.ninjaBuildDir)
  27. if err != nil {
  28. errs = [] error{err}
  29. return
  30. }
  31. }
  32. pkgNames, depsPackages := c.makeUniquePackageNames(c.liveGlobals)
  33. deps = append(deps, depsPackages...)
  34. // This will panic if it finds a problem since it's a programming error.
  35. c.checkForVariableReferenceCycles(c.liveGlobals.variables, pkgNames)
  36. c.pkgNames = pkgNames
  37. c.globalVariables = c.liveGlobals.variables
  38. c.globalPools = c.liveGlobals.pools
  39. c.globalRules = c.liveGlobals.rules
  40. c.buildActionsReady = true
  41. })
  42. if len(errs) > 0 {
  43. return nil, errs
  44. }
  45. return deps, nil
  46. }

 

3.3.6 WriteBuildFile()

  WriteBuildFile将生成的构建操作的Ninja manifest文本写入文件。

  如果在PrepareBuildActions成功完成之前调用此函数,则返回errBuildActionsOnTready。


 
 
  1. [/build/blueprint/context.go]
  2. func (c *Context) WriteBuildFile(w io.Writer) error {
  3. var err error
  4. pprof.Do(c.Context, pprof.Labels( "blueprint", "WriteBuildFile"), func(ctx context.Context) {
  5. if !c.buildActionsReady {
  6. err = ErrBuildActionsNotReady
  7. return
  8. }
  9. nw := newNinjaWriter(w)
  10. err = c.writeBuildFileHeader(nw)
  11. if err != nil {
  12. return
  13. }
  14. err = c.writeNinjaRequiredVersion(nw)
  15. if err != nil {
  16. return
  17. }
  18. err = c.writeSubninjas(nw)
  19. if err != nil {
  20. return
  21. }
  22. // TODO: Group the globals by package.
  23. err = c.writeGlobalVariables(nw)
  24. if err != nil {
  25. return
  26. }
  27. err = c.writeGlobalPools(nw)
  28. if err != nil {
  29. return
  30. }
  31. err = c.writeBuildDir(nw)
  32. if err != nil {
  33. return
  34. }
  35. err = c.writeGlobalRules(nw)
  36. if err != nil {
  37. return
  38. }
  39. err = c.writeAllModuleActions(nw)
  40. if err != nil {
  41. return
  42. }
  43. err = c.writeAllSingletonActions(nw)
  44. if err != nil {
  45. return
  46. }
  47. })
  48. if err != nil {
  49. return err
  50. }
  51. return nil
  52. }

 

4. 总结

       根据上面的总结,我们明白了 Blueprint到ninja的流程,详细流程如下:

 1.执行build/blueprint/bootstrap.bash  生成.minibootstrap/build.ninja 和.bootstrap/build.ninja

    2.编译生成minibp\bpglob 两个可执行程序

    3.通过minibp 解析并生成out/soong/.bootstrap/build.ninja

       1)注册一些bp模块类型、依赖和类型

       2)解析Blueprints文件

       3)检查解析的Blueprint文件中定义的所有模块指定的依赖项是否有效

       4)生成需要执行的所有生成操作的内部表示

      5)将生成的构建操作的Ninja manifest文本写入文件

    4.通过ninja来编译.minibootstrap/build.ninja 和.bootstrap/build.ninja,最终生成out/soong/build.ninja

    下面我们再进一步探讨一些Android.bp的配置,以及ninja的编译过程。

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值