Android 編譯系統(tǒng)--07:Blueprint詳細分析

本文轉(zhuǎn)載自:Blueprint代碼詳細分析-Android10.0編譯系統(tǒng)(七)

本文基于Android 10.0源碼分析

1.概述

??上一節(jié)庄新,我們介紹了blueprint的作用和執(zhí)行過程峡继,這一節(jié)我們從代碼的層面來分析blueprint的具體執(zhí)行流程较坛。啟用Soong以后殉摔,在Android編譯最開始的準備階段唯咬,會執(zhí)行build/soong/soong.bash進行環(huán)境準備秃殉。其中會先編譯姥份、安裝Blueprint到out目錄下树埠。也就是說祠丝,在編譯Android項目時疾呻,Android.bp相關(guān)工具鏈會自動編譯除嘹,無需費神。

??Soong是與Android強關(guān)聯(lián)的一個項目岸蜗,而Blueprint則相對比較獨立憾赁,可以單獨編譯、使用散吵。

2.blueprint相關(guān)編譯鏈生成

??通過前面的make編譯龙考,我們了解到blueprint等工具鏈的生成,是在runSoong()中編出來的矾睦,因此我們就從runSoong()為突破口進行分析晦款。

2.1 Build調(diào)用棧

??make后,走的是Soong的構(gòu)建枚冗,其中會把一些編譯工具給編出來缓溅,例如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。

編譯系統(tǒng)7-1.PNG

2.2 runSoong調(diào)用棧

??runSoong執(zhí)行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編譯。

編譯系統(tǒng)7-2.PNG

2.3 runSoong()

??runSoong()的執(zhí)行過程:

  • 執(zhí)行build/blueprint/bootstrap.bash生成.minibootstrap/build.ninja和.bootstrap/build.ninja赂鲤;

  • 生成minibp\bpglob噪径;

  • 通過ninja來編譯.minibootstrap/build.ninja和.bootstrap/build.ninja。

(1)首先執(zhí)行build/blueprint/bootstrap.bash

(2)bootstrap.bash的作用
??它可以引導獨立的blueprint來生成minibp二進制文件蛤袒,可以直接運行./build/blueprint/bootstrap.bash熄云。也可以從另一個腳本調(diào)用它來引導基于Bleprint的自定義構(gòu)建系統(tǒng)。

// /build/soong/ui/build/soong.go
func runSoong(ctx Context, config Config) {
    ctx.BeginTrace(metrics.RunSoong, "soong")
    defer ctx.EndTrace()

    func() {
        ctx.BeginTrace(metrics.RunSoong, "blueprint bootstrap")
        defer ctx.EndTrace()

        cmd := Command(ctx, config, "blueprint bootstrap", "build/blueprint/bootstrap.bash", "-t")
        cmd.Environment.Set("BLUEPRINTDIR", "./build/blueprint")
        cmd.Environment.Set("BOOTSTRAP", "./build/blueprint/bootstrap.bash")
        cmd.Environment.Set("BUILDDIR", config.SoongOutDir())
        cmd.Environment.Set("GOROOT", "./"+filepath.Join("prebuilts/go", config.HostPrebuiltTag()))
        cmd.Environment.Set("BLUEPRINT_LIST_FILE", filepath.Join(config.FileListDir(), "Android.bp.list"))
        cmd.Environment.Set("NINJA_BUILDDIR", config.OutDir())
        cmd.Environment.Set("SRCDIR", ".")
        cmd.Environment.Set("TOPNAME", "Android.bp")
        cmd.Sandbox = soongSandbox

     //執(zhí)行build/blueprint/bootstrap.bash
        cmd.RunAndPrintOrFatal()
    }()

    func() {
        ctx.BeginTrace(metrics.RunSoong, "environment check")
        defer ctx.EndTrace()

        envFile := filepath.Join(config.SoongOutDir(), ".soong.environment")
        envTool := filepath.Join(config.SoongOutDir(), ".bootstrap/bin/soong_env")
        if _, err := os.Stat(envFile); err == nil {
            if _, err := os.Stat(envTool); err == nil {
                cmd := Command(ctx, config, "soong_env", envTool, envFile)
                cmd.Sandbox = soongSandbox

                var buf strings.Builder
                cmd.Stdout = &buf
                cmd.Stderr = &buf
                if err := cmd.Run(); err != nil {
                    ctx.Verboseln("soong_env failed, forcing manifest regeneration")
                    os.Remove(envFile)
                }

                if buf.Len() > 0 {
                    ctx.Verboseln(buf.String())
                }
            } else {
                ctx.Verboseln("Missing soong_env tool, forcing manifest regeneration")
                os.Remove(envFile)
            }
        } else if !os.IsNotExist(err) {
            ctx.Fatalf("Failed to stat %f: %v", envFile, err)
        }
    }()

    var cfg microfactory.Config
    cfg.Map("github.com/google/blueprint", "build/blueprint")

    cfg.TrimPath = absPath(ctx, ".")

    func() {
        ctx.BeginTrace(metrics.RunSoong, "minibp")
        defer ctx.EndTrace()

        minibp := filepath.Join(config.SoongOutDir(), ".minibootstrap/minibp")
        if _, err := microfactory.Build(&cfg, minibp, "github.com/google/blueprint/bootstrap/minibp"); err != nil {
            ctx.Fatalln("Failed to build minibp:", err)
        }
    }()

    func() {
        ctx.BeginTrace(metrics.RunSoong, "bpglob")
        defer ctx.EndTrace()

        bpglob := filepath.Join(config.SoongOutDir(), ".minibootstrap/bpglob")
        if _, err := microfactory.Build(&cfg, bpglob, "github.com/google/blueprint/bootstrap/bpglob"); err != nil {
            ctx.Fatalln("Failed to build bpglob:", err)
        }
    }()

    ninja := func(name, file string) {
        ctx.BeginTrace(metrics.RunSoong, name)
        defer ctx.EndTrace()

        fifo := filepath.Join(config.OutDir(), ".ninja_fifo")
        nr := status.NewNinjaReader(ctx, ctx.Status.StartTool(), fifo)
        defer nr.Close()

        cmd := Command(ctx, config, "soong "+name,
            config.PrebuiltBuildTool("ninja"),
            "-d", "keepdepfile",
            "-w", "dupbuild=err",
            "-j", strconv.Itoa(config.Parallel()),
            "--frontend_file", fifo,
            "-f", filepath.Join(config.SoongOutDir(), file))
        cmd.Sandbox = soongSandbox
        cmd.RunAndPrintOrFatal()
    }

    ninja("minibootstrap", ".minibootstrap/build.ninja")
    ninja("bootstrap", ".bootstrap/build.ninja")
}

2.4 minibp的生成

??從build/blueprint/Blueprints中可知妙真,需要編譯的二進制文件名為minibp缴允,源文件為:bootstrap/minibp/main.go,依賴于blueprint、blueprint-bootstrap练般、gotestmain-tests矗漾。

// build/blueprint/Blueprints
bootstrap_go_binary {
    name: "minibp",
    deps: [
        "blueprint",
        "blueprint-bootstrap",
        "gotestmain-tests",
    ],
    srcs: ["bootstrap/minibp/main.go"],
}

out/soong/.bootstrap/build.ninja中模塊的相關(guān)規(guī)則如下:

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# Module:  minibp
# Variant:
# Type:    bootstrap_go_binary
# Factory: github.com/google/blueprint/bootstrap.newGoBinaryModuleFactory.func1
# Defined: build/blueprint/Blueprints:132:1

build ${g.bootstrap.buildDir}/.bootstrap/minibp/obj/minibp.a: $
        g.bootstrap.compile $
        ${g.bootstrap.srcDir}/build/blueprint/bootstrap/minibp/main.go | $
        ${g.bootstrap.compileCmd} $
        ${g.bootstrap.buildDir}/.bootstrap/blueprint-parser/pkg/github.com/google/blueprint/parser.a $
        ${g.bootstrap.buildDir}/.bootstrap/blueprint-deptools/pkg/github.com/google/blueprint/deptools.a $
        ${g.bootstrap.buildDir}/.bootstrap/blueprint-pathtools/pkg/github.com/google/blueprint/pathtools.a $
        ${g.bootstrap.buildDir}/.bootstrap/blueprint-proptools/pkg/github.com/google/blueprint/proptools.a $
        ${g.bootstrap.buildDir}/.bootstrap/blueprint/pkg/github.com/google/blueprint.a $
        ${g.bootstrap.buildDir}/.bootstrap/blueprint-bootstrap-bpdoc/pkg/github.com/google/blueprint/bootstrap/bpdoc.a $
        ${g.bootstrap.buildDir}/.bootstrap/blueprint-bootstrap/pkg/github.com/google/blueprint/bootstrap.a $
        ${g.bootstrap.buildDir}/.bootstrap/gotestmain-tests/pkg/github.com/google/blueprint/gotestmain.a
    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
    pkgPath = minibp

build ${g.bootstrap.buildDir}/.bootstrap/minibp/obj/a.out: g.bootstrap.link $
        ${g.bootstrap.buildDir}/.bootstrap/minibp/obj/minibp.a | $
        ${g.bootstrap.linkCmd} $
        ${g.bootstrap.buildDir}/.bootstrap/blueprint-parser/pkg/github.com/google/blueprint/parser.a $
        ${g.bootstrap.buildDir}/.bootstrap/blueprint-deptools/pkg/github.com/google/blueprint/deptools.a $
        ${g.bootstrap.buildDir}/.bootstrap/blueprint-pathtools/pkg/github.com/google/blueprint/pathtools.a $
        ${g.bootstrap.buildDir}/.bootstrap/blueprint-proptools/pkg/github.com/google/blueprint/proptools.a $
        ${g.bootstrap.buildDir}/.bootstrap/blueprint/pkg/github.com/google/blueprint.a $
        ${g.bootstrap.buildDir}/.bootstrap/blueprint-bootstrap-bpdoc/pkg/github.com/google/blueprint/bootstrap/bpdoc.a $
        ${g.bootstrap.buildDir}/.bootstrap/blueprint-bootstrap/pkg/github.com/google/blueprint/bootstrap.a $
        ${g.bootstrap.buildDir}/.bootstrap/gotestmain-tests/pkg/github.com/google/blueprint/gotestmain.a
    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

build out/soong/.bootstrap/bin/minibp: g.bootstrap.cp $
        ${g.bootstrap.buildDir}/.bootstrap/minibp/obj/a.out || $
        ${g.bootstrap.buildDir}/.bootstrap/blueprint-parser/test/test.passed $
        ${g.bootstrap.buildDir}/.bootstrap/blueprint-pathtools/test/test.passed $
        ${g.bootstrap.buildDir}/.bootstrap/blueprint-proptools/test/test.passed $
        ${g.bootstrap.buildDir}/.bootstrap/blueprint/test/test.passed $
        ${g.bootstrap.buildDir}/.bootstrap/blueprint-bootstrap-bpdoc/test/test.passed $
        ${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和內(nèi)容處理規(guī)則蛔垢,如deps等。

第二步:解析階段讀取一個或多個Blueprint文件迫悠,并根據(jù)已注冊的模塊類型驗證其內(nèi)容鹏漆。

第三步:generate階段分析解析的Blueprint內(nèi)容,為必須執(zhí)行的構(gòu)建操作創(chuàng)建一個內(nèi)部表示创泄。此 階段還執(zhí)行模塊依賴項和已解析Bleprint文件中定義的屬性值的驗證艺玲。

第四步:寫入階段根據(jù)生成的構(gòu)建操作生成Ninja文件。

3.1 minibp編譯入口

編譯系統(tǒng)7-3.png

主要步驟:

  • 配置一個Context結(jié)構(gòu)鞠抑;

  • 執(zhí)行command.go的Main()進行最終編譯饭聚。

// /build/blueprint/bootstrap/minibp/main.go
func main() {
    flag.Parse()

    ctx := blueprint.NewContext() //配置一個Context結(jié)構(gòu)
    if !runAsPrimaryBuilder {
        ctx.SetIgnoreUnknownModuleTypes(true)
    }

    config := Config{
        generatingPrimaryBuilder: !runAsPrimaryBuilder,
    }

    //執(zhí)行 command.go 的Main() 進行最終編譯
    bootstrap.Main(ctx, config)
}

3.2 Context配置

??返回一個Context的結(jié)構(gòu),存儲了bp里面的一些字段碍拆,例如之前看到的bootstrap_core_go_binary若治。

// /build/blueprint/context.go
func newContext() *Context {
    return &Context{
        Context:            context.Background(),
        moduleFactories:    make(map[string]ModuleFactory), //存儲著我們后面注冊的module如“bootstrap_core_go_binary”
        nameInterface:      NewSimpleNameInterface(),
        moduleInfo:         make(map[Module]*moduleInfo),
        globs:              make(map[string]GlobPath),
        fs:                 pathtools.OsFs,
        ninjaBuildDir:      nil,
        requiredNinjaMajor: 1,
        requiredNinjaMinor: 7,
        requiredNinjaMicro: 0,
    }
}

3.3 執(zhí)行 command.go Main()

3.3.1 調(diào)用棧

編譯系統(tǒng)7-4.png
// /build/blueprint/bootstrap/command.go
package bootstrap
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_go_binary", newGoBinaryModuleFactory(bootstrapConfig, false))
    ctx.RegisterModuleType("blueprint_go_binary", newGoBinaryModuleFactory(bootstrapConfig, true))
    ctx.RegisterSingletonType("bootstrap", newSingletonFactory(bootstrapConfig))

    ctx.RegisterSingletonType("glob", globSingletonFactory(ctx))

    deps, errs := ctx.ParseFileList(filepath.Dir(bootstrapConfig.topLevelBlueprintsFile), filesToParse)
    if len(errs) > 0 {
        fatalErrors(errs)
    }

    // Add extra ninja file dependencies
    deps = append(deps, extraNinjaFileDeps...)

    extraDeps, errs := ctx.ResolveDependencies(config)
    ...
    extraDeps, errs = ctx.PrepareBuildActions(config)

    ...
    err = ctx.WriteBuildFile(out)

    ...
}

步驟:

  1. 注冊一些bp模塊類型、依賴和類型感混;

  2. 解析Blueprints文件;

  3. 檢查解析的Blueprint文件中定義的所有模塊指定的依賴項是否有效礼烈;

  4. 生成需要執(zhí)行的所有生成操作的內(nèi)部表示弧满;

  5. 將生成的構(gòu)建操作的Ninja manifest文本寫入文件。

3.3.2 RegisterBottomUpMutator()

??RegisterBottomUpMutator注冊一個mutator此熬,它將被調(diào)用來將模塊拆分為變量庭呜。每個注冊的mutator按注冊順序調(diào)用(混合使用toppownmutator和BottomUpMutators)每個模塊一次,在所有模塊依賴項的調(diào)用返回之前犀忱,不會在模塊上調(diào)用募谎。

??此處給定的賦值函數(shù)類型名稱對于上下文中所有自下而上或早期的賦值函數(shù)必須是唯一的。返回一個MutatorHandle阴汇,在這個句柄上可以調(diào)用Parallel來設(shè)置mutator在維護順序的同時并行訪問模塊数冬。

// /build/blueprint/context.go
func (c *Context) RegisterBottomUpMutator(name string, mutator BottomUpMutator) MutatorHandle {
    for _, m := range c.variantMutatorNames {
        if m == name {
            panic(fmt.Errorf("mutator name %s is already registered", name))
        }
    }

    info := &mutatorInfo{
        bottomUpMutator: mutator,
        name:            name,
    }
    c.mutatorInfo = append(c.mutatorInfo, info)

    c.variantMutatorNames = append(c.variantMutatorNames, name)

    return info
}

3.3.3 RegisterSingletonType()

??RegisterSingletonType注冊將被調(diào)用以生成生成操作的單例類型。作為生成階段的一部分搀庶,每個注冊的單例類型被實例化和調(diào)用一次拐纱。按照注冊順序調(diào)用每個已注冊的單例铜异。此處給定的單例類型名稱對于上下文必須是唯一的。factory函數(shù)應該是一個命名函數(shù)秸架,這樣它的包和名稱就可以包含在生成的Ninja文件中揍庄,以便進行調(diào)試。

// /build/blueprint/context.go
func (c *Context) RegisterSingletonType(name string, factory SingletonFactory) {
    for _, s := range c.singletonInfo {
        if s.name == name {
            panic(errors.New("singleton name is already registered"))
        }
    }

    c.singletonInfo = append(c.singletonInfo, &singletonInfo{
        factory:   factory,
        singleton: factory(),
        name:      name,
    })
}

3.3.4 ResolveDependencies()

??ResolveDependencies檢查解析的Blueprint文件中定義的所有模塊指定的依賴項是否有效东抹。這意味著依賴的模塊已經(jīng)定義蚂子,并且不存在循環(huán)依賴。

// /build/blueprint/context.go
func (c *Context) resolveDependencies(ctx context.Context, config interface{}) (deps []string, errs []error) {
    pprof.Do(ctx, pprof.Labels("blueprint", "ResolveDependencies"), func(ctx context.Context) {
        c.liveGlobals = newLiveTracker(config)

        deps, errs = c.generateSingletonBuildActions(config, c.preSingletonInfo, c.liveGlobals)
        if len(errs) > 0 {
            return
        }

        errs = c.updateDependencies()
        if len(errs) > 0 {
            return
        }

        var mutatorDeps []string
        mutatorDeps, errs = c.runMutators(ctx, config)
        if len(errs) > 0 {
            return
        }
        deps = append(deps, mutatorDeps...)

        c.cloneModules()

        c.dependenciesReady = true
    })

    if len(errs) > 0 {
        return nil, errs
    }

    return deps, nil
}

3.3.5 PrepareBuildActions()

??PrepareBuildActions生成需要執(zhí)行的所有生成操作的內(nèi)部表示缭黔。這個過程包括對在解析階段創(chuàng)建的每個Module對象調(diào)用GenerateBuildActions方法食茎,然后對每個注冊的單例對象調(diào)用GenerateBuildActions方法。

??如果尚未調(diào)用ResolveDependencies方法试浙,則此方法會自動調(diào)用該方法董瞻。通過傳遞給GenerateBuildActions的ModuleContext和SingletonContext對象上的config方法,config參數(shù)可用于所有Module和Singleton對象田巴。它還傳遞給通過PoolFunc钠糊、RuleFunc和VariableFunc指定的函數(shù),以便它們可以計算特定配置的值壹哺。返回的deps是由模塊和singleton通過ModuleContext添加的ninja文件依賴項的列表抄伍。AddNinjaFileDeps(),SingletonContext.AddNinjaFileDeps()管宵,和PackageContext.AddNinjaFileDeps()方法夭谤。

// /build/blueprint/context.go
func (c *Context) PrepareBuildActions(config interface{}) (deps []string, errs []error) {
    pprof.Do(c.Context, pprof.Labels("blueprint", "PrepareBuildActions"), func(ctx context.Context) {
        c.buildActionsReady = false

        if !c.dependenciesReady {
            var extraDeps []string
            extraDeps, errs = c.resolveDependencies(ctx, config)
            if len(errs) > 0 {
                return
            }
            deps = append(deps, extraDeps...)
        }

        var depsModules []string
        depsModules, errs = c.generateModuleBuildActions(config, c.liveGlobals)
        if len(errs) > 0 {
            return
        }

        var depsSingletons []string
        depsSingletons, errs = c.generateSingletonBuildActions(config, c.singletonInfo, c.liveGlobals)
        if len(errs) > 0 {
            return
        }

        deps = append(deps, depsModules...)
        deps = append(deps, depsSingletons...)

        if c.ninjaBuildDir != nil {
            err := c.liveGlobals.addNinjaStringDeps(c.ninjaBuildDir)
            if err != nil {
                errs = []error{err}
                return
            }
        }

        pkgNames, depsPackages := c.makeUniquePackageNames(c.liveGlobals)

        deps = append(deps, depsPackages...)

        // This will panic if it finds a problem since it's a programming error.
        c.checkForVariableReferenceCycles(c.liveGlobals.variables, pkgNames)

        c.pkgNames = pkgNames
        c.globalVariables = c.liveGlobals.variables
        c.globalPools = c.liveGlobals.pools
        c.globalRules = c.liveGlobals.rules

        c.buildActionsReady = true
    })

    if len(errs) > 0 {
        return nil, errs
    }

    return deps, nil
}

3.3.6 WriteBuildFile()

??WriteBuildFile將生成的構(gòu)建操作的Ninja manifest文本寫入文件。如果在PrepareBuildActions成功完成之前調(diào)用此函數(shù)烦磁,則返回errBuildActionsOnTready驾孔。

// /build/blueprint/context.go
func (c *Context) WriteBuildFile(w io.Writer) error {
    var err error
    pprof.Do(c.Context, pprof.Labels("blueprint", "WriteBuildFile"), func(ctx context.Context) {
        if !c.buildActionsReady {
            err = ErrBuildActionsNotReady
            return
        }

        nw := newNinjaWriter(w)

        err = c.writeBuildFileHeader(nw)
        if err != nil {
            return
        }

        err = c.writeNinjaRequiredVersion(nw)
        if err != nil {
            return
        }

        err = c.writeSubninjas(nw)
        if err != nil {
            return
        }

        // TODO: Group the globals by package.

        err = c.writeGlobalVariables(nw)
        if err != nil {
            return
        }

        err = c.writeGlobalPools(nw)
        if err != nil {
            return
        }

        err = c.writeBuildDir(nw)
        if err != nil {
            return
        }

        err = c.writeGlobalRules(nw)
        if err != nil {
            return
        }

        err = c.writeAllModuleActions(nw)
        if err != nil {
            return
        }

        err = c.writeAllSingletonActions(nw)
        if err != nil {
            return
        }
    })

    if err != nil {
        return err
    }

    return nil
}

4.總結(jié)

  1. 根據(jù)上面的總結(jié),我們明白了Blueprint到ninja的流程炸庞,詳細流程如下:

  2. 執(zhí)行build/blueprint/bootstrap.bash 生成.minibootstrap/build.ninja 和.bootstrap/build.ninja钱床;

  3. 編譯生成minibp\bpglob 兩個可執(zhí)行程序;

  4. 通過minibp 解析并生成out/soong/.bootstrap/build.ninja埠居;

    1)注冊一些bp模塊類型查牌、依賴和類型

    2)解析Blueprints文件;

    3)檢查解析的Blueprint文件中定義的所有模塊指定的依賴項是否有效滥壕;

    4)生成需要執(zhí)行的所有生成操作的內(nèi)部表示纸颜;

    5)將生成的構(gòu)建操作的Ninja manifest文本寫入文件。

  5. 通過ninja來編譯.minibootstrap/build.ninja 和.bootstrap/build.ninja绎橘,最終生成out/soong/build.ninja胁孙。

??下面我們再進一步探討一些Android.bp的配置,以及ninja的編譯過程。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末浊洞,一起剝皮案震驚了整個濱河市牵敷,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌法希,老刑警劉巖枷餐,帶你破解...
    沈念sama閱讀 219,270評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異苫亦,居然都是意外死亡毛肋,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,489評論 3 395
  • 文/潘曉璐 我一進店門屋剑,熙熙樓的掌柜王于貴愁眉苦臉地迎上來润匙,“玉大人,你說我怎么就攤上這事唉匾≡谢洌” “怎么了?”我有些...
    開封第一講書人閱讀 165,630評論 0 356
  • 文/不壞的土叔 我叫張陵巍膘,是天一觀的道長厂财。 經(jīng)常有香客問我,道長峡懈,這世上最難降的妖魔是什么璃饱? 我笑而不...
    開封第一講書人閱讀 58,906評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮肪康,結(jié)果婚禮上荚恶,老公的妹妹穿的比我還像新娘。我一直安慰自己磷支,他們只是感情好谒撼,可當我...
    茶點故事閱讀 67,928評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著雾狈,像睡著了一般嗤栓。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上箍邮,一...
    開封第一講書人閱讀 51,718評論 1 305
  • 那天,我揣著相機與錄音叨叙,去河邊找鬼锭弊。 笑死,一個胖子當著我的面吹牛擂错,可吹牛的內(nèi)容都是我干的味滞。 我是一名探鬼主播,決...
    沈念sama閱讀 40,442評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼剑鞍!你這毒婦竟也來了昨凡?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,345評論 0 276
  • 序言:老撾萬榮一對情侶失蹤蚁署,失蹤者是張志新(化名)和其女友劉穎便脊,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體光戈,經(jīng)...
    沈念sama閱讀 45,802評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡哪痰,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,984評論 3 337
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了久妆。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片晌杰。...
    茶點故事閱讀 40,117評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖筷弦,靈堂內(nèi)的尸體忽然破棺而出肋演,到底是詐尸還是另有隱情,我是刑警寧澤烂琴,帶...
    沈念sama閱讀 35,810評論 5 346
  • 正文 年R本政府宣布爹殊,位于F島的核電站,受9級特大地震影響监右,放射性物質(zhì)發(fā)生泄漏边灭。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,462評論 3 331
  • 文/蒙蒙 一健盒、第九天 我趴在偏房一處隱蔽的房頂上張望绒瘦。 院中可真熱鬧,春花似錦扣癣、人聲如沸惰帽。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,011評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽该酗。三九已至,卻和暖如春士嚎,著一層夾襖步出監(jiān)牢的瞬間呜魄,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,139評論 1 272
  • 我被黑心中介騙來泰國打工莱衩, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留爵嗅,地道東北人。 一個月前我還...
    沈念sama閱讀 48,377評論 3 373
  • 正文 我出身青樓笨蚁,卻偏偏與公主長得像睹晒,于是被迫代替她去往敵國和親趟庄。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 45,060評論 2 355

推薦閱讀更多精彩內(nèi)容