func buildGoPackage(ctx blueprint.ModuleContext, pkgRoot string, pkgPath string, archiveFile string, srcs []string, genSrcs []string, orderDeps []string) { srcDir := moduleSrcDir(ctx) srcFiles := pathtools.PrefixPaths(srcs, srcDir) srcFiles = append(srcFiles, genSrcs...) var incFlags []string deps := []string{"$compileCmd"} ctx.VisitDepsDepthFirstIf(isGoPackageProducer, func(module blueprint.Module) { dep := module.(goPackageProducer) incDir := dep.GoPkgRoot() target := dep.GoPackageTarget() incFlags = append(incFlags, "-I "+incDir) deps = append(deps, target) }) compileArgs := map[string]string{ "pkgPath": pkgPath, } if len(incFlags) > 0 { compileArgs["incFlags"] = strings.Join(incFlags, " ") } ctx.Build(pctx, blueprint.BuildParams{ Rule: compile, Outputs: []string{archiveFile}, Inputs: srcFiles, OrderOnly: orderDeps, Implicits: deps, Args: compileArgs, }) }
func writeDocs(ctx *blueprint.Context, srcDir, filename string) error { // Find the module that's marked as the "primary builder", which means it's // creating the binary that we'll use to generate the non-bootstrap // build.ninja file. var primaryBuilders []*goBinary var minibp *goBinary ctx.VisitAllModulesIf(isBootstrapBinaryModule, func(module blueprint.Module) { binaryModule := module.(*goBinary) if binaryModule.properties.PrimaryBuilder { primaryBuilders = append(primaryBuilders, binaryModule) } if ctx.ModuleName(binaryModule) == "minibp" { minibp = binaryModule } }) if minibp == nil { panic("missing minibp") } var primaryBuilder *goBinary switch len(primaryBuilders) { case 0: // If there's no primary builder module then that means we'll use minibp // as the primary builder. primaryBuilder = minibp case 1: primaryBuilder = primaryBuilders[0] default: return fmt.Errorf("multiple primary builder modules present") } pkgFiles := make(map[string][]string) ctx.VisitDepsDepthFirst(primaryBuilder, func(module blueprint.Module) { switch m := module.(type) { case (*goPackage): pkgFiles[m.properties.PkgPath] = pathtools.PrefixPaths(m.properties.Srcs, filepath.Join(srcDir, ctx.ModuleDir(m))) default: panic(fmt.Errorf("unknown dependency type %T", module)) } }) return bpdoc.Write(filename, pkgFiles, ctx.ModuleTypePropertyStructs()) }
func phonyGoTarget(ctx blueprint.ModuleContext, target string, srcs []string, gensrcs []string, intermediates []string) { var depTargets []string ctx.VisitDepsDepthFirstIf(isGoPackageProducer, func(module blueprint.Module) { dep := module.(goPackageProducer) target := dep.GoPackageTarget() depTargets = append(depTargets, target) }) moduleDir := ctx.ModuleDir() srcs = pathtools.PrefixPaths(srcs, filepath.Join("$srcDir", moduleDir)) srcs = append(srcs, gensrcs...) ctx.Build(pctx, blueprint.BuildParams{ Rule: phony, Outputs: []string{target}, Inputs: srcs, Implicits: depTargets, }) // If one of the source files gets deleted or renamed that will prevent the // re-bootstrapping happening because it depends on the missing source file. // To get around this we add a build statement using the built-in phony rule // for each source file, which will cause Ninja to treat it as dirty if its // missing. for _, src := range srcs { ctx.Build(pctx, blueprint.BuildParams{ Rule: blueprint.Phony, Outputs: []string{src}, }) } // If there is no rule to build the intermediate files of a bootstrap go package // the cleanup phase of the primary builder will delete the intermediate files, // forcing an unnecessary rebuild. Add phony rules for all of them. for _, intermediate := range intermediates { ctx.Build(pctx, blueprint.BuildParams{ Rule: blueprint.Phony, Outputs: []string{intermediate}, }) } }
func buildGoTest(ctx blueprint.ModuleContext, testRoot, testPkgArchive, pkgPath string, srcs, genSrcs, testSrcs []string) []string { if len(testSrcs) == 0 { return nil } srcDir := moduleSrcDir(ctx) testFiles := pathtools.PrefixPaths(testSrcs, srcDir) mainFile := filepath.Join(testRoot, "test.go") testArchive := filepath.Join(testRoot, "test.a") testFile := filepath.Join(testRoot, "test") testPassed := filepath.Join(testRoot, "test.passed") buildGoPackage(ctx, testRoot, pkgPath, testPkgArchive, append(srcs, testSrcs...), genSrcs, nil) ctx.Build(pctx, blueprint.BuildParams{ Rule: goTestMain, Outputs: []string{mainFile}, Inputs: testFiles, Implicits: []string{"$goTestMainCmd"}, Args: map[string]string{ "pkg": pkgPath, }, }) libDirFlags := []string{"-L " + testRoot} ctx.VisitDepsDepthFirstIf(isGoPackageProducer, func(module blueprint.Module) { dep := module.(goPackageProducer) libDir := dep.GoPkgRoot() libDirFlags = append(libDirFlags, "-L "+libDir) }) ctx.Build(pctx, blueprint.BuildParams{ Rule: compile, Outputs: []string{testArchive}, Inputs: []string{mainFile}, Implicits: []string{"$compileCmd", testPkgArchive}, Args: map[string]string{ "pkgPath": "main", "incFlags": "-I " + testRoot, }, }) ctx.Build(pctx, blueprint.BuildParams{ Rule: link, Outputs: []string{testFile}, Inputs: []string{testArchive}, Implicits: []string{"$linkCmd"}, Args: map[string]string{ "libDirFlags": strings.Join(libDirFlags, " "), }, }) ctx.Build(pctx, blueprint.BuildParams{ Rule: test, Outputs: []string{testPassed}, Inputs: []string{testFile}, Args: map[string]string{ "pkg": pkgPath, "pkgSrcDir": filepath.Dir(testFiles[0]), }, }) return []string{testPassed} }