2015-01-23 23:15:10 +01:00
|
|
|
// Copyright 2014 Google Inc. All rights reserved.
|
|
|
|
//
|
|
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
// you may not use this file except in compliance with the License.
|
|
|
|
// You may obtain a copy of the License at
|
|
|
|
//
|
|
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
//
|
|
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
// See the License for the specific language governing permissions and
|
|
|
|
// limitations under the License.
|
|
|
|
|
2014-05-28 01:34:41 +02:00
|
|
|
package bootstrap
|
|
|
|
|
|
|
|
import (
|
2024-04-17 18:35:55 +02:00
|
|
|
"encoding/json"
|
2014-05-28 01:34:41 +02:00
|
|
|
"fmt"
|
2024-04-17 18:35:55 +02:00
|
|
|
"os"
|
2014-05-28 01:34:41 +02:00
|
|
|
"path/filepath"
|
2017-02-06 23:00:10 +01:00
|
|
|
"runtime"
|
2014-05-28 01:34:41 +02:00
|
|
|
"strings"
|
2015-05-13 23:36:24 +02:00
|
|
|
|
|
|
|
"github.com/google/blueprint"
|
|
|
|
"github.com/google/blueprint/pathtools"
|
2014-05-28 01:34:41 +02:00
|
|
|
)
|
|
|
|
|
|
|
|
var (
|
2015-03-21 03:39:29 +01:00
|
|
|
pctx = blueprint.NewPackageContext("github.com/google/blueprint/bootstrap")
|
2014-05-28 01:34:41 +02:00
|
|
|
|
2021-09-01 08:58:07 +02:00
|
|
|
goTestMainCmd = pctx.StaticVariable("goTestMainCmd", filepath.Join("$ToolDir", "gotestmain"))
|
|
|
|
goTestRunnerCmd = pctx.StaticVariable("goTestRunnerCmd", filepath.Join("$ToolDir", "gotestrunner"))
|
|
|
|
pluginGenSrcCmd = pctx.StaticVariable("pluginGenSrcCmd", filepath.Join("$ToolDir", "loadplugins"))
|
2014-10-03 11:49:58 +02:00
|
|
|
|
2017-07-25 05:28:41 +02:00
|
|
|
parallelCompile = pctx.StaticVariable("parallelCompile", func() string {
|
2023-03-03 21:31:12 +01:00
|
|
|
numCpu := runtime.NumCPU()
|
|
|
|
// This will cause us to recompile all go programs if the
|
|
|
|
// number of cpus changes. We don't get a lot of benefit from
|
|
|
|
// higher values, so cap this to make it cheaper to move trees
|
|
|
|
// between machines.
|
|
|
|
if numCpu > 8 {
|
|
|
|
numCpu = 8
|
2017-07-25 05:28:41 +02:00
|
|
|
}
|
2023-03-03 21:31:12 +01:00
|
|
|
return fmt.Sprintf("-c %d", numCpu)
|
2017-07-25 05:28:41 +02:00
|
|
|
}())
|
|
|
|
|
2015-08-02 00:07:27 +02:00
|
|
|
compile = pctx.StaticRule("compile",
|
2014-05-28 01:34:41 +02:00
|
|
|
blueprint.RuleParams{
|
2018-09-29 01:15:58 +02:00
|
|
|
Command: "GOROOT='$goRoot' $compileCmd $parallelCompile -o $out.tmp " +
|
2024-04-17 18:35:55 +02:00
|
|
|
"$debugFlags -p $pkgPath -complete $incFlags $embedFlags -pack $in && " +
|
2018-09-29 01:15:58 +02:00
|
|
|
"if cmp --quiet $out.tmp $out; then rm $out.tmp; else mv -f $out.tmp $out; fi",
|
2015-11-17 23:21:45 +01:00
|
|
|
CommandDeps: []string{"$compileCmd"},
|
2015-08-02 00:07:27 +02:00
|
|
|
Description: "compile $out",
|
2018-09-29 01:15:58 +02:00
|
|
|
Restat: true,
|
2014-05-28 01:34:41 +02:00
|
|
|
},
|
2024-04-17 18:35:55 +02:00
|
|
|
"pkgPath", "incFlags", "embedFlags")
|
2014-05-28 01:34:41 +02:00
|
|
|
|
2014-10-03 11:49:58 +02:00
|
|
|
link = pctx.StaticRule("link",
|
2014-05-28 01:34:41 +02:00
|
|
|
blueprint.RuleParams{
|
2018-09-29 01:15:58 +02:00
|
|
|
Command: "GOROOT='$goRoot' $linkCmd -o $out.tmp $libDirFlags $in && " +
|
|
|
|
"if cmp --quiet $out.tmp $out; then rm $out.tmp; else mv -f $out.tmp $out; fi",
|
2015-11-17 23:21:45 +01:00
|
|
|
CommandDeps: []string{"$linkCmd"},
|
2015-08-02 00:07:27 +02:00
|
|
|
Description: "link $out",
|
2018-09-29 01:15:58 +02:00
|
|
|
Restat: true,
|
2014-05-28 01:34:41 +02:00
|
|
|
},
|
|
|
|
"libDirFlags")
|
|
|
|
|
2015-06-24 02:21:00 +02:00
|
|
|
goTestMain = pctx.StaticRule("gotestmain",
|
|
|
|
blueprint.RuleParams{
|
|
|
|
Command: "$goTestMainCmd -o $out -pkg $pkg $in",
|
2015-11-17 23:21:45 +01:00
|
|
|
CommandDeps: []string{"$goTestMainCmd"},
|
2015-06-24 02:21:00 +02:00
|
|
|
Description: "gotestmain $out",
|
|
|
|
},
|
|
|
|
"pkg")
|
|
|
|
|
2015-07-25 01:53:27 +02:00
|
|
|
pluginGenSrc = pctx.StaticRule("pluginGenSrc",
|
|
|
|
blueprint.RuleParams{
|
|
|
|
Command: "$pluginGenSrcCmd -o $out -p $pkg $plugins",
|
2015-11-17 23:21:45 +01:00
|
|
|
CommandDeps: []string{"$pluginGenSrcCmd"},
|
2015-07-25 01:53:27 +02:00
|
|
|
Description: "create $out",
|
|
|
|
},
|
|
|
|
"pkg", "plugins")
|
|
|
|
|
2015-06-24 02:21:00 +02:00
|
|
|
test = pctx.StaticRule("test",
|
|
|
|
blueprint.RuleParams{
|
2015-09-18 05:59:51 +02:00
|
|
|
Command: "$goTestRunnerCmd -p $pkgSrcDir -f $out -- $in -test.short",
|
2015-11-17 23:21:45 +01:00
|
|
|
CommandDeps: []string{"$goTestRunnerCmd"},
|
2015-06-24 02:21:00 +02:00
|
|
|
Description: "test $pkg",
|
|
|
|
},
|
|
|
|
"pkg", "pkgSrcDir")
|
|
|
|
|
2014-10-03 11:49:58 +02:00
|
|
|
cp = pctx.StaticRule("cp",
|
2014-05-28 01:34:41 +02:00
|
|
|
blueprint.RuleParams{
|
|
|
|
Command: "cp $in $out",
|
|
|
|
Description: "cp $out",
|
2014-06-06 05:00:22 +02:00
|
|
|
},
|
|
|
|
"generator")
|
2014-05-28 01:34:41 +02:00
|
|
|
|
2014-10-03 11:49:58 +02:00
|
|
|
bootstrap = pctx.StaticRule("bootstrap",
|
2014-05-28 01:34:41 +02:00
|
|
|
blueprint.RuleParams{
|
2021-08-26 15:08:09 +02:00
|
|
|
Command: "BUILDDIR=$soongOutDir $bootstrapCmd -i $in",
|
2015-11-17 23:21:45 +01:00
|
|
|
CommandDeps: []string{"$bootstrapCmd"},
|
2014-05-28 01:34:41 +02:00
|
|
|
Description: "bootstrap $in",
|
|
|
|
Generator: true,
|
|
|
|
})
|
|
|
|
|
Enhance bootstrap stage selection
This simplifies the bootstrap process while making it more flexible by
moving the stage selection into a go binary(choosestage). It will now be
possible to have more than two build stages.
Now each stage has a ninja template(main.ninja.in) and a timestamp
file(main.ninja.in.timestamp). The timestamp file may be updated by any
build stage that wishes to regenerate the ninja template. If the
choosestage binaries sees that the timestamp is newer than the template,
it will choose the prior stage.
The main stage no longer writes to the source tree to update the
build.ninja.in file. This was a problem for read-only source trees.
Instead, the choosestage binary first checks to see if that file is
newer than the last bootstrap.ninja.in, copies it in place, and starts
the boostrap stage.
The bootstrap stage regenerates it's own ninja template, but that
required a loop through the main stage to actually run it. The
choosestage binary now detects if the template has changed for the
current stage, and will restart the stage.
One change is that if dependencies do get messed up, instead of silently
failing, there's a higher chance that the bootstrap step will just
continue looping, doing nothing. This can happen if the main stage
has a dependency that triggers the bootstrap stage, but the bootstrap
stage doesn't see anything required to rebuild the main ninja file. A
side effect of this requirement is that changes to test code will now
rebuild the main ninja file.
Change-Id: I9965cfba79dc0dbbd3af05f5944f7653054455a2
2015-07-23 02:05:59 +02:00
|
|
|
touch = pctx.StaticRule("touch",
|
|
|
|
blueprint.RuleParams{
|
|
|
|
Command: "touch $out",
|
|
|
|
Description: "touch $out",
|
|
|
|
},
|
|
|
|
"depfile", "generator")
|
|
|
|
|
2016-11-02 01:12:28 +01:00
|
|
|
generateBuildNinja = pctx.StaticRule("build.ninja",
|
|
|
|
blueprint.RuleParams{
|
2021-02-17 11:59:10 +01:00
|
|
|
// TODO: it's kinda ugly that some parameters are computed from
|
|
|
|
// environment variables and some from Ninja parameters, but it's probably
|
|
|
|
// better to not to touch that while Blueprint and Soong are separate
|
2021-03-08 13:09:19 +01:00
|
|
|
// NOTE: The spaces at EOL are important because otherwise Ninja would
|
|
|
|
// omit all spaces between the different options.
|
|
|
|
Command: `cd "$$(dirname "$builder")" && ` +
|
|
|
|
`BUILDER="$$PWD/$$(basename "$builder")" && ` +
|
|
|
|
`cd / && ` +
|
2022-01-05 10:26:53 +01:00
|
|
|
`env -i $env "$$BUILDER" ` +
|
2021-03-08 13:09:19 +01:00
|
|
|
` --top "$$TOP" ` +
|
2021-09-01 16:25:38 +02:00
|
|
|
` --soong_out "$soongOutDir" ` +
|
|
|
|
` --out "$outDir" ` +
|
2021-04-12 12:07:02 +02:00
|
|
|
` $extra`,
|
2016-11-02 01:12:28 +01:00
|
|
|
CommandDeps: []string{"$builder"},
|
|
|
|
Description: "$builder $out",
|
2017-12-18 18:14:16 +01:00
|
|
|
Deps: blueprint.DepsGCC,
|
2016-11-02 01:12:28 +01:00
|
|
|
Depfile: "$out.d",
|
|
|
|
Restat: true,
|
|
|
|
},
|
2022-01-05 10:26:53 +01:00
|
|
|
"builder", "env", "extra", "pool")
|
2016-11-02 01:12:28 +01:00
|
|
|
|
2014-05-28 01:34:41 +02:00
|
|
|
// Work around a Ninja issue. See https://github.com/martine/ninja/pull/634
|
2014-10-03 11:49:58 +02:00
|
|
|
phony = pctx.StaticRule("phony",
|
2014-05-28 01:34:41 +02:00
|
|
|
blueprint.RuleParams{
|
|
|
|
Command: "# phony $out",
|
|
|
|
Description: "phony $out",
|
|
|
|
Generator: true,
|
|
|
|
},
|
|
|
|
"depfile")
|
|
|
|
|
2022-11-04 04:19:48 +01:00
|
|
|
_ = pctx.VariableFunc("ToolDir", func(ctx blueprint.VariableFuncContext, config interface{}) (string, error) {
|
2021-09-01 08:58:07 +02:00
|
|
|
return config.(BootstrapConfig).HostToolDir(), nil
|
2016-05-26 19:07:59 +02:00
|
|
|
})
|
2014-05-28 01:34:41 +02:00
|
|
|
)
|
|
|
|
|
2017-09-14 00:19:22 +02:00
|
|
|
type GoBinaryTool interface {
|
|
|
|
InstallPath() string
|
|
|
|
|
|
|
|
// So that other packages can't implement this interface
|
|
|
|
isGoBinary()
|
|
|
|
}
|
|
|
|
|
2015-07-25 01:53:27 +02:00
|
|
|
func pluginDeps(ctx blueprint.BottomUpMutatorContext) {
|
2023-06-08 23:03:45 +02:00
|
|
|
if pkg, ok := ctx.Module().(*GoPackage); ok {
|
2020-09-09 22:03:57 +02:00
|
|
|
if ctx.PrimaryModule() == ctx.Module() {
|
|
|
|
for _, plugin := range pkg.properties.PluginFor {
|
|
|
|
ctx.AddReverseDependency(ctx.Module(), nil, plugin)
|
|
|
|
}
|
2015-07-25 01:53:27 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-05-28 01:34:41 +02:00
|
|
|
type goPackageProducer interface {
|
|
|
|
GoPkgRoot() string
|
|
|
|
GoPackageTarget() string
|
2016-11-02 08:43:00 +01:00
|
|
|
GoTestTargets() []string
|
2014-05-28 01:34:41 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
func isGoPackageProducer(module blueprint.Module) bool {
|
|
|
|
_, ok := module.(goPackageProducer)
|
|
|
|
return ok
|
|
|
|
}
|
|
|
|
|
2015-07-25 01:53:27 +02:00
|
|
|
type goPluginProvider interface {
|
|
|
|
GoPkgPath() string
|
|
|
|
IsPluginFor(string) bool
|
|
|
|
}
|
|
|
|
|
|
|
|
func isGoPluginFor(name string) func(blueprint.Module) bool {
|
|
|
|
return func(module blueprint.Module) bool {
|
|
|
|
if plugin, ok := module.(goPluginProvider); ok {
|
|
|
|
return plugin.IsPluginFor(name)
|
|
|
|
}
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-09-09 22:03:57 +02:00
|
|
|
func IsBootstrapModule(module blueprint.Module) bool {
|
2023-06-08 23:03:45 +02:00
|
|
|
_, isPackage := module.(*GoPackage)
|
|
|
|
_, isBinary := module.(*GoBinary)
|
2014-05-28 01:34:41 +02:00
|
|
|
return isPackage || isBinary
|
|
|
|
}
|
|
|
|
|
|
|
|
func isBootstrapBinaryModule(module blueprint.Module) bool {
|
2023-06-08 23:03:45 +02:00
|
|
|
_, isBinary := module.(*GoBinary)
|
2014-05-28 01:34:41 +02:00
|
|
|
return isBinary
|
|
|
|
}
|
|
|
|
|
2023-06-08 23:03:45 +02:00
|
|
|
// A GoPackage is a module for building Go packages.
|
|
|
|
type GoPackage struct {
|
2016-05-17 23:58:05 +02:00
|
|
|
blueprint.SimpleName
|
2014-05-28 01:34:41 +02:00
|
|
|
properties struct {
|
2016-05-17 23:58:05 +02:00
|
|
|
Deps []string
|
2015-07-25 01:53:27 +02:00
|
|
|
PkgPath string
|
|
|
|
Srcs []string
|
|
|
|
TestSrcs []string
|
2023-06-23 01:51:22 +02:00
|
|
|
TestData []string
|
2015-07-25 01:53:27 +02:00
|
|
|
PluginFor []string
|
2024-04-17 18:35:55 +02:00
|
|
|
EmbedSrcs []string
|
2016-04-12 00:41:52 +02:00
|
|
|
|
2017-02-06 23:00:10 +01:00
|
|
|
Darwin struct {
|
|
|
|
Srcs []string
|
|
|
|
TestSrcs []string
|
|
|
|
}
|
|
|
|
Linux struct {
|
|
|
|
Srcs []string
|
|
|
|
TestSrcs []string
|
|
|
|
}
|
2014-05-28 01:34:41 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// The root dir in which the package .a file is located. The full .a file
|
|
|
|
// path will be "packageRoot/PkgPath.a"
|
|
|
|
pkgRoot string
|
|
|
|
|
|
|
|
// The path of the .a file that is to be built.
|
|
|
|
archiveFile string
|
2015-06-25 04:21:21 +02:00
|
|
|
|
2016-11-02 08:43:00 +01:00
|
|
|
// The path of the test result file.
|
|
|
|
testResultFile []string
|
2014-05-28 01:34:41 +02:00
|
|
|
}
|
|
|
|
|
2023-06-08 23:03:45 +02:00
|
|
|
var _ goPackageProducer = (*GoPackage)(nil)
|
2014-05-28 01:34:41 +02:00
|
|
|
|
2021-09-02 09:57:30 +02:00
|
|
|
func newGoPackageModuleFactory() func() (blueprint.Module, []interface{}) {
|
2015-06-25 04:21:21 +02:00
|
|
|
return func() (blueprint.Module, []interface{}) {
|
2023-06-08 23:03:45 +02:00
|
|
|
module := &GoPackage{}
|
2016-05-17 23:58:05 +02:00
|
|
|
return module, []interface{}{&module.properties, &module.SimpleName.Properties}
|
2015-06-25 04:21:21 +02:00
|
|
|
}
|
2014-05-28 01:34:41 +02:00
|
|
|
}
|
|
|
|
|
2023-06-08 23:03:45 +02:00
|
|
|
func (g *GoPackage) DynamicDependencies(ctx blueprint.DynamicDependerModuleContext) []string {
|
2020-09-09 22:03:57 +02:00
|
|
|
if ctx.Module() != ctx.PrimaryModule() {
|
|
|
|
return nil
|
|
|
|
}
|
2016-05-17 23:58:05 +02:00
|
|
|
return g.properties.Deps
|
|
|
|
}
|
|
|
|
|
2023-06-08 23:03:45 +02:00
|
|
|
func (g *GoPackage) GoPkgPath() string {
|
2015-07-25 01:53:27 +02:00
|
|
|
return g.properties.PkgPath
|
|
|
|
}
|
|
|
|
|
2023-06-08 23:03:45 +02:00
|
|
|
func (g *GoPackage) GoPkgRoot() string {
|
2014-05-28 01:34:41 +02:00
|
|
|
return g.pkgRoot
|
|
|
|
}
|
|
|
|
|
2023-06-08 23:03:45 +02:00
|
|
|
func (g *GoPackage) GoPackageTarget() string {
|
2014-05-28 01:34:41 +02:00
|
|
|
return g.archiveFile
|
|
|
|
}
|
|
|
|
|
2023-06-08 23:03:45 +02:00
|
|
|
func (g *GoPackage) GoTestTargets() []string {
|
2016-11-02 08:43:00 +01:00
|
|
|
return g.testResultFile
|
2015-06-24 02:21:00 +02:00
|
|
|
}
|
|
|
|
|
2023-06-08 23:03:45 +02:00
|
|
|
func (g *GoPackage) IsPluginFor(name string) bool {
|
2015-07-25 01:53:27 +02:00
|
|
|
for _, plugin := range g.properties.PluginFor {
|
|
|
|
if plugin == name {
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
2023-06-08 23:03:45 +02:00
|
|
|
func (g *GoPackage) GenerateBuildActions(ctx blueprint.ModuleContext) {
|
2020-09-09 22:03:57 +02:00
|
|
|
// Allow the primary builder to create multiple variants. Any variants after the first
|
|
|
|
// will copy outputs from the first.
|
|
|
|
if ctx.Module() != ctx.PrimaryModule() {
|
2023-06-08 23:03:45 +02:00
|
|
|
primary := ctx.PrimaryModule().(*GoPackage)
|
2020-09-09 22:03:57 +02:00
|
|
|
g.pkgRoot = primary.pkgRoot
|
|
|
|
g.archiveFile = primary.archiveFile
|
|
|
|
g.testResultFile = primary.testResultFile
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2015-07-25 01:53:27 +02:00
|
|
|
var (
|
|
|
|
name = ctx.ModuleName()
|
|
|
|
hasPlugins = false
|
|
|
|
pluginSrc = ""
|
|
|
|
genSrcs = []string{}
|
|
|
|
)
|
2014-05-28 01:34:41 +02:00
|
|
|
|
|
|
|
if g.properties.PkgPath == "" {
|
|
|
|
ctx.ModuleErrorf("module %s did not specify a valid pkgPath", name)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2021-08-19 16:26:36 +02:00
|
|
|
g.pkgRoot = packageRoot(ctx)
|
2015-06-24 02:21:00 +02:00
|
|
|
g.archiveFile = filepath.Join(g.pkgRoot,
|
|
|
|
filepath.FromSlash(g.properties.PkgPath)+".a")
|
2014-05-28 01:34:41 +02:00
|
|
|
|
2015-07-25 01:53:27 +02:00
|
|
|
ctx.VisitDepsDepthFirstIf(isGoPluginFor(name),
|
|
|
|
func(module blueprint.Module) { hasPlugins = true })
|
|
|
|
if hasPlugins {
|
2021-08-26 15:08:09 +02:00
|
|
|
pluginSrc = filepath.Join(moduleGenSrcDir(ctx), "plugin.go")
|
2015-07-25 01:53:27 +02:00
|
|
|
genSrcs = append(genSrcs, pluginSrc)
|
|
|
|
}
|
|
|
|
|
2017-07-20 04:22:34 +02:00
|
|
|
if hasPlugins && !buildGoPluginLoader(ctx, g.properties.PkgPath, pluginSrc) {
|
|
|
|
return
|
|
|
|
}
|
2017-02-06 23:00:10 +01:00
|
|
|
|
2017-07-20 04:22:34 +02:00
|
|
|
var srcs, testSrcs []string
|
|
|
|
if runtime.GOOS == "darwin" {
|
|
|
|
srcs = append(g.properties.Srcs, g.properties.Darwin.Srcs...)
|
|
|
|
testSrcs = append(g.properties.TestSrcs, g.properties.Darwin.TestSrcs...)
|
|
|
|
} else if runtime.GOOS == "linux" {
|
|
|
|
srcs = append(g.properties.Srcs, g.properties.Linux.Srcs...)
|
|
|
|
testSrcs = append(g.properties.TestSrcs, g.properties.Linux.TestSrcs...)
|
|
|
|
}
|
2015-06-24 02:21:00 +02:00
|
|
|
|
2023-10-24 20:05:56 +02:00
|
|
|
testArchiveFile := filepath.Join(testRoot(ctx),
|
|
|
|
filepath.FromSlash(g.properties.PkgPath)+".a")
|
|
|
|
g.testResultFile = buildGoTest(ctx, testRoot(ctx), testArchiveFile,
|
2024-04-17 18:35:55 +02:00
|
|
|
g.properties.PkgPath, srcs, genSrcs, testSrcs, g.properties.EmbedSrcs)
|
2017-07-20 04:22:34 +02:00
|
|
|
|
2021-05-20 04:24:32 +02:00
|
|
|
// Don't build for test-only packages
|
|
|
|
if len(srcs) == 0 && len(genSrcs) == 0 {
|
|
|
|
ctx.Build(pctx, blueprint.BuildParams{
|
|
|
|
Rule: touch,
|
|
|
|
Outputs: []string{g.archiveFile},
|
|
|
|
Optional: true,
|
|
|
|
})
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2017-07-20 04:22:34 +02:00
|
|
|
buildGoPackage(ctx, g.pkgRoot, g.properties.PkgPath, g.archiveFile,
|
2024-04-17 18:35:55 +02:00
|
|
|
srcs, genSrcs, g.properties.EmbedSrcs)
|
2023-12-13 23:47:32 +01:00
|
|
|
blueprint.SetProvider(ctx, blueprint.SrcsFileProviderKey, blueprint.SrcsFileProviderData{SrcPaths: srcs})
|
2014-05-28 01:34:41 +02:00
|
|
|
}
|
|
|
|
|
2023-06-08 23:03:45 +02:00
|
|
|
func (g *GoPackage) Srcs() []string {
|
|
|
|
return g.properties.Srcs
|
|
|
|
}
|
|
|
|
|
|
|
|
func (g *GoPackage) LinuxSrcs() []string {
|
|
|
|
return g.properties.Linux.Srcs
|
|
|
|
}
|
|
|
|
|
|
|
|
func (g *GoPackage) DarwinSrcs() []string {
|
|
|
|
return g.properties.Darwin.Srcs
|
|
|
|
}
|
|
|
|
|
|
|
|
func (g *GoPackage) TestSrcs() []string {
|
|
|
|
return g.properties.TestSrcs
|
|
|
|
}
|
|
|
|
|
|
|
|
func (g *GoPackage) LinuxTestSrcs() []string {
|
|
|
|
return g.properties.Linux.TestSrcs
|
|
|
|
}
|
|
|
|
|
|
|
|
func (g *GoPackage) DarwinTestSrcs() []string {
|
|
|
|
return g.properties.Darwin.TestSrcs
|
|
|
|
}
|
|
|
|
|
|
|
|
func (g *GoPackage) Deps() []string {
|
|
|
|
return g.properties.Deps
|
|
|
|
}
|
|
|
|
|
2023-06-23 01:51:22 +02:00
|
|
|
func (g *GoPackage) TestData() []string {
|
|
|
|
return g.properties.TestData
|
|
|
|
}
|
|
|
|
|
2023-06-08 23:03:45 +02:00
|
|
|
// A GoBinary is a module for building executable binaries from Go sources.
|
|
|
|
type GoBinary struct {
|
2016-05-17 23:58:05 +02:00
|
|
|
blueprint.SimpleName
|
2014-05-28 01:34:41 +02:00
|
|
|
properties struct {
|
2016-05-17 23:58:05 +02:00
|
|
|
Deps []string
|
2014-05-28 01:34:41 +02:00
|
|
|
Srcs []string
|
2015-06-24 02:21:00 +02:00
|
|
|
TestSrcs []string
|
2023-06-23 01:51:22 +02:00
|
|
|
TestData []string
|
2024-04-17 18:35:55 +02:00
|
|
|
EmbedSrcs []string
|
2014-05-28 01:34:41 +02:00
|
|
|
PrimaryBuilder bool
|
2017-07-20 03:48:01 +02:00
|
|
|
Default bool
|
2016-04-12 00:41:52 +02:00
|
|
|
|
2017-02-06 23:00:10 +01:00
|
|
|
Darwin struct {
|
|
|
|
Srcs []string
|
|
|
|
TestSrcs []string
|
|
|
|
}
|
|
|
|
Linux struct {
|
|
|
|
Srcs []string
|
|
|
|
TestSrcs []string
|
|
|
|
}
|
2014-05-28 01:34:41 +02:00
|
|
|
}
|
2015-06-25 04:21:21 +02:00
|
|
|
|
2017-09-14 00:19:22 +02:00
|
|
|
installPath string
|
2014-05-28 01:34:41 +02:00
|
|
|
}
|
|
|
|
|
2023-06-08 23:03:45 +02:00
|
|
|
var _ GoBinaryTool = (*GoBinary)(nil)
|
2017-09-14 00:19:22 +02:00
|
|
|
|
2021-09-02 09:57:30 +02:00
|
|
|
func newGoBinaryModuleFactory() func() (blueprint.Module, []interface{}) {
|
2015-06-25 04:21:21 +02:00
|
|
|
return func() (blueprint.Module, []interface{}) {
|
2023-06-08 23:03:45 +02:00
|
|
|
module := &GoBinary{}
|
2016-05-17 23:58:05 +02:00
|
|
|
return module, []interface{}{&module.properties, &module.SimpleName.Properties}
|
2015-06-25 04:21:21 +02:00
|
|
|
}
|
2014-05-28 01:34:41 +02:00
|
|
|
}
|
|
|
|
|
2023-06-08 23:03:45 +02:00
|
|
|
func (g *GoBinary) DynamicDependencies(ctx blueprint.DynamicDependerModuleContext) []string {
|
2020-09-09 22:03:57 +02:00
|
|
|
if ctx.Module() != ctx.PrimaryModule() {
|
|
|
|
return nil
|
|
|
|
}
|
2016-05-17 23:58:05 +02:00
|
|
|
return g.properties.Deps
|
|
|
|
}
|
|
|
|
|
2023-06-08 23:03:45 +02:00
|
|
|
func (g *GoBinary) isGoBinary() {}
|
|
|
|
func (g *GoBinary) InstallPath() string {
|
2017-09-14 00:19:22 +02:00
|
|
|
return g.installPath
|
2016-05-26 19:07:59 +02:00
|
|
|
}
|
|
|
|
|
2023-06-08 23:03:45 +02:00
|
|
|
func (g *GoBinary) Srcs() []string {
|
|
|
|
return g.properties.Srcs
|
|
|
|
}
|
|
|
|
|
|
|
|
func (g *GoBinary) LinuxSrcs() []string {
|
|
|
|
return g.properties.Linux.Srcs
|
|
|
|
}
|
|
|
|
|
|
|
|
func (g *GoBinary) DarwinSrcs() []string {
|
|
|
|
return g.properties.Darwin.Srcs
|
|
|
|
}
|
|
|
|
|
|
|
|
func (g *GoBinary) TestSrcs() []string {
|
|
|
|
return g.properties.TestSrcs
|
|
|
|
}
|
|
|
|
|
|
|
|
func (g *GoBinary) LinuxTestSrcs() []string {
|
|
|
|
return g.properties.Linux.TestSrcs
|
|
|
|
}
|
|
|
|
|
|
|
|
func (g *GoBinary) DarwinTestSrcs() []string {
|
|
|
|
return g.properties.Darwin.TestSrcs
|
|
|
|
}
|
|
|
|
|
|
|
|
func (g *GoBinary) Deps() []string {
|
|
|
|
return g.properties.Deps
|
|
|
|
}
|
|
|
|
|
2023-06-23 01:51:22 +02:00
|
|
|
func (g *GoBinary) TestData() []string {
|
|
|
|
return g.properties.TestData
|
|
|
|
}
|
|
|
|
|
2023-06-08 23:03:45 +02:00
|
|
|
func (g *GoBinary) GenerateBuildActions(ctx blueprint.ModuleContext) {
|
2020-09-09 22:03:57 +02:00
|
|
|
// Allow the primary builder to create multiple variants. Any variants after the first
|
|
|
|
// will copy outputs from the first.
|
|
|
|
if ctx.Module() != ctx.PrimaryModule() {
|
2023-06-08 23:03:45 +02:00
|
|
|
primary := ctx.PrimaryModule().(*GoBinary)
|
2020-09-09 22:03:57 +02:00
|
|
|
g.installPath = primary.installPath
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2014-05-28 01:34:41 +02:00
|
|
|
var (
|
2016-11-02 08:43:00 +01:00
|
|
|
name = ctx.ModuleName()
|
2021-08-19 16:26:36 +02:00
|
|
|
objDir = moduleObjDir(ctx)
|
2016-11-02 08:43:00 +01:00
|
|
|
archiveFile = filepath.Join(objDir, name+".a")
|
2021-08-19 16:26:36 +02:00
|
|
|
testArchiveFile = filepath.Join(testRoot(ctx), name+".a")
|
2016-11-02 08:43:00 +01:00
|
|
|
aoutFile = filepath.Join(objDir, "a.out")
|
|
|
|
hasPlugins = false
|
|
|
|
pluginSrc = ""
|
|
|
|
genSrcs = []string{}
|
2014-05-28 01:34:41 +02:00
|
|
|
)
|
|
|
|
|
2021-09-01 08:58:07 +02:00
|
|
|
g.installPath = filepath.Join(ctx.Config().(BootstrapConfig).HostToolDir(), name)
|
2015-07-25 01:53:27 +02:00
|
|
|
ctx.VisitDepsDepthFirstIf(isGoPluginFor(name),
|
|
|
|
func(module blueprint.Module) { hasPlugins = true })
|
|
|
|
if hasPlugins {
|
2021-08-26 15:08:09 +02:00
|
|
|
pluginSrc = filepath.Join(moduleGenSrcDir(ctx), "plugin.go")
|
2015-07-25 01:53:27 +02:00
|
|
|
genSrcs = append(genSrcs, pluginSrc)
|
|
|
|
}
|
|
|
|
|
2020-07-09 23:24:56 +02:00
|
|
|
var testDeps []string
|
2017-02-06 23:00:10 +01:00
|
|
|
|
2017-07-20 04:22:34 +02:00
|
|
|
if hasPlugins && !buildGoPluginLoader(ctx, "main", pluginSrc) {
|
|
|
|
return
|
|
|
|
}
|
2015-06-24 02:21:00 +02:00
|
|
|
|
2017-07-20 04:22:34 +02:00
|
|
|
var srcs, testSrcs []string
|
|
|
|
if runtime.GOOS == "darwin" {
|
|
|
|
srcs = append(g.properties.Srcs, g.properties.Darwin.Srcs...)
|
|
|
|
testSrcs = append(g.properties.TestSrcs, g.properties.Darwin.TestSrcs...)
|
|
|
|
} else if runtime.GOOS == "linux" {
|
|
|
|
srcs = append(g.properties.Srcs, g.properties.Linux.Srcs...)
|
|
|
|
testSrcs = append(g.properties.TestSrcs, g.properties.Linux.TestSrcs...)
|
|
|
|
}
|
2014-05-28 01:34:41 +02:00
|
|
|
|
2023-10-24 20:05:56 +02:00
|
|
|
testDeps = buildGoTest(ctx, testRoot(ctx), testArchiveFile,
|
2024-04-17 18:35:55 +02:00
|
|
|
name, srcs, genSrcs, testSrcs, g.properties.EmbedSrcs)
|
2014-05-28 01:34:41 +02:00
|
|
|
|
2024-04-17 18:35:55 +02:00
|
|
|
buildGoPackage(ctx, objDir, "main", archiveFile, srcs, genSrcs, g.properties.EmbedSrcs)
|
2014-05-28 01:34:41 +02:00
|
|
|
|
2018-09-29 01:15:58 +02:00
|
|
|
var linkDeps []string
|
2017-07-20 04:22:34 +02:00
|
|
|
var libDirFlags []string
|
|
|
|
ctx.VisitDepsDepthFirstIf(isGoPackageProducer,
|
|
|
|
func(module blueprint.Module) {
|
|
|
|
dep := module.(goPackageProducer)
|
2018-09-29 01:15:58 +02:00
|
|
|
linkDeps = append(linkDeps, dep.GoPackageTarget())
|
2017-07-20 04:22:34 +02:00
|
|
|
libDir := dep.GoPkgRoot()
|
|
|
|
libDirFlags = append(libDirFlags, "-L "+libDir)
|
2020-07-09 23:24:56 +02:00
|
|
|
testDeps = append(testDeps, dep.GoTestTargets()...)
|
2014-05-28 01:34:41 +02:00
|
|
|
})
|
|
|
|
|
2017-07-20 04:22:34 +02:00
|
|
|
linkArgs := map[string]string{}
|
|
|
|
if len(libDirFlags) > 0 {
|
|
|
|
linkArgs["libDirFlags"] = strings.Join(libDirFlags, " ")
|
2014-05-28 01:34:41 +02:00
|
|
|
}
|
2017-07-20 04:22:34 +02:00
|
|
|
|
|
|
|
ctx.Build(pctx, blueprint.BuildParams{
|
2018-09-29 01:15:58 +02:00
|
|
|
Rule: link,
|
|
|
|
Outputs: []string{aoutFile},
|
|
|
|
Inputs: []string{archiveFile},
|
|
|
|
Implicits: linkDeps,
|
|
|
|
Args: linkArgs,
|
|
|
|
Optional: true,
|
2017-07-20 04:22:34 +02:00
|
|
|
})
|
|
|
|
|
2023-10-24 20:05:56 +02:00
|
|
|
var validations []string
|
|
|
|
if ctx.Config().(BootstrapConfig).RunGoTests() {
|
|
|
|
validations = testDeps
|
|
|
|
}
|
|
|
|
|
2017-07-20 04:22:34 +02:00
|
|
|
ctx.Build(pctx, blueprint.BuildParams{
|
2020-07-09 23:24:56 +02:00
|
|
|
Rule: cp,
|
|
|
|
Outputs: []string{g.installPath},
|
|
|
|
Inputs: []string{aoutFile},
|
2023-10-24 20:05:56 +02:00
|
|
|
Validations: validations,
|
2020-07-09 23:24:56 +02:00
|
|
|
Optional: !g.properties.Default,
|
2017-07-20 04:22:34 +02:00
|
|
|
})
|
2023-12-13 23:47:32 +01:00
|
|
|
blueprint.SetProvider(ctx, blueprint.SrcsFileProviderKey, blueprint.SrcsFileProviderData{SrcPaths: srcs})
|
2014-05-28 01:34:41 +02:00
|
|
|
}
|
|
|
|
|
2017-07-20 04:22:34 +02:00
|
|
|
func buildGoPluginLoader(ctx blueprint.ModuleContext, pkgPath, pluginSrc string) bool {
|
2015-07-25 01:53:27 +02:00
|
|
|
ret := true
|
|
|
|
name := ctx.ModuleName()
|
|
|
|
|
|
|
|
var pluginPaths []string
|
|
|
|
ctx.VisitDepsDepthFirstIf(isGoPluginFor(name),
|
|
|
|
func(module blueprint.Module) {
|
|
|
|
plugin := module.(goPluginProvider)
|
|
|
|
pluginPaths = append(pluginPaths, plugin.GoPkgPath())
|
|
|
|
})
|
|
|
|
|
|
|
|
ctx.Build(pctx, blueprint.BuildParams{
|
2015-11-17 23:21:45 +01:00
|
|
|
Rule: pluginGenSrc,
|
|
|
|
Outputs: []string{pluginSrc},
|
2015-07-25 01:53:27 +02:00
|
|
|
Args: map[string]string{
|
|
|
|
"pkg": pkgPath,
|
|
|
|
"plugins": strings.Join(pluginPaths, " "),
|
|
|
|
},
|
2017-07-20 03:48:01 +02:00
|
|
|
Optional: true,
|
2015-07-25 01:53:27 +02:00
|
|
|
})
|
|
|
|
|
|
|
|
return ret
|
|
|
|
}
|
|
|
|
|
2024-04-17 18:35:55 +02:00
|
|
|
func generateEmbedcfgFile(files []string, srcDir string, embedcfgFile string) {
|
|
|
|
embedcfg := struct {
|
|
|
|
Patterns map[string][]string
|
|
|
|
Files map[string]string
|
|
|
|
}{
|
|
|
|
map[string][]string{},
|
|
|
|
map[string]string{},
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, file := range files {
|
|
|
|
embedcfg.Patterns[file] = []string{file}
|
|
|
|
embedcfg.Files[file] = filepath.Join(srcDir, file)
|
|
|
|
}
|
|
|
|
|
|
|
|
embedcfgData, err := json.Marshal(&embedcfg)
|
|
|
|
if err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
os.WriteFile(embedcfgFile, []byte(embedcfgData), 0644)
|
|
|
|
}
|
|
|
|
|
2014-05-28 01:34:41 +02:00
|
|
|
func buildGoPackage(ctx blueprint.ModuleContext, pkgRoot string,
|
2024-04-17 18:35:55 +02:00
|
|
|
pkgPath string, archiveFile string, srcs []string, genSrcs []string, embedSrcs []string) {
|
2014-05-28 01:34:41 +02:00
|
|
|
|
2014-11-09 20:52:56 +01:00
|
|
|
srcDir := moduleSrcDir(ctx)
|
2014-06-06 23:37:07 +02:00
|
|
|
srcFiles := pathtools.PrefixPaths(srcs, srcDir)
|
2015-07-25 01:53:27 +02:00
|
|
|
srcFiles = append(srcFiles, genSrcs...)
|
2014-05-28 01:34:41 +02:00
|
|
|
|
|
|
|
var incFlags []string
|
2015-11-17 23:21:45 +01:00
|
|
|
var deps []string
|
2014-05-28 01:34:41 +02:00
|
|
|
ctx.VisitDepsDepthFirstIf(isGoPackageProducer,
|
|
|
|
func(module blueprint.Module) {
|
|
|
|
dep := module.(goPackageProducer)
|
|
|
|
incDir := dep.GoPkgRoot()
|
|
|
|
target := dep.GoPackageTarget()
|
|
|
|
incFlags = append(incFlags, "-I "+incDir)
|
2014-10-22 22:22:22 +02:00
|
|
|
deps = append(deps, target)
|
2014-05-28 01:34:41 +02:00
|
|
|
})
|
|
|
|
|
2015-08-02 00:07:27 +02:00
|
|
|
compileArgs := map[string]string{
|
2014-05-28 01:34:41 +02:00
|
|
|
"pkgPath": pkgPath,
|
|
|
|
}
|
|
|
|
|
|
|
|
if len(incFlags) > 0 {
|
2015-08-02 00:07:27 +02:00
|
|
|
compileArgs["incFlags"] = strings.Join(incFlags, " ")
|
2014-05-28 01:34:41 +02:00
|
|
|
}
|
|
|
|
|
2024-04-17 18:35:55 +02:00
|
|
|
if len(embedSrcs) > 0 {
|
|
|
|
embedcfgFile := archiveFile + ".embedcfg"
|
|
|
|
generateEmbedcfgFile(embedSrcs, srcDir, embedcfgFile)
|
|
|
|
compileArgs["embedFlags"] = "-embedcfg " + embedcfgFile
|
|
|
|
}
|
|
|
|
|
2014-10-03 11:49:58 +02:00
|
|
|
ctx.Build(pctx, blueprint.BuildParams{
|
2015-08-02 00:07:27 +02:00
|
|
|
Rule: compile,
|
2014-10-22 19:55:28 +02:00
|
|
|
Outputs: []string{archiveFile},
|
2014-05-28 01:34:41 +02:00
|
|
|
Inputs: srcFiles,
|
2014-10-22 22:22:22 +02:00
|
|
|
Implicits: deps,
|
2015-08-02 00:07:27 +02:00
|
|
|
Args: compileArgs,
|
2017-07-20 03:48:01 +02:00
|
|
|
Optional: true,
|
2014-05-28 01:34:41 +02:00
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2015-07-25 01:53:27 +02:00
|
|
|
func buildGoTest(ctx blueprint.ModuleContext, testRoot, testPkgArchive,
|
2024-04-17 18:35:55 +02:00
|
|
|
pkgPath string, srcs, genSrcs, testSrcs []string, embedSrcs []string) []string {
|
2015-06-24 02:21:00 +02:00
|
|
|
|
|
|
|
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,
|
2024-04-17 18:35:55 +02:00
|
|
|
append(srcs, testSrcs...), genSrcs, embedSrcs)
|
2015-06-24 02:21:00 +02:00
|
|
|
|
|
|
|
ctx.Build(pctx, blueprint.BuildParams{
|
2015-11-17 23:21:45 +01:00
|
|
|
Rule: goTestMain,
|
|
|
|
Outputs: []string{mainFile},
|
|
|
|
Inputs: testFiles,
|
2015-06-24 02:21:00 +02:00
|
|
|
Args: map[string]string{
|
|
|
|
"pkg": pkgPath,
|
|
|
|
},
|
2017-07-20 03:48:01 +02:00
|
|
|
Optional: true,
|
2015-06-24 02:21:00 +02:00
|
|
|
})
|
|
|
|
|
2018-10-24 22:11:33 +02:00
|
|
|
linkDeps := []string{testPkgArchive}
|
2015-06-24 02:21:00 +02:00
|
|
|
libDirFlags := []string{"-L " + testRoot}
|
2016-11-02 08:43:00 +01:00
|
|
|
testDeps := []string{}
|
2015-06-24 02:21:00 +02:00
|
|
|
ctx.VisitDepsDepthFirstIf(isGoPackageProducer,
|
|
|
|
func(module blueprint.Module) {
|
|
|
|
dep := module.(goPackageProducer)
|
2018-10-05 20:12:53 +02:00
|
|
|
linkDeps = append(linkDeps, dep.GoPackageTarget())
|
2015-06-24 02:21:00 +02:00
|
|
|
libDir := dep.GoPkgRoot()
|
|
|
|
libDirFlags = append(libDirFlags, "-L "+libDir)
|
2016-11-02 08:43:00 +01:00
|
|
|
testDeps = append(testDeps, dep.GoTestTargets()...)
|
2015-06-24 02:21:00 +02:00
|
|
|
})
|
|
|
|
|
|
|
|
ctx.Build(pctx, blueprint.BuildParams{
|
2015-08-02 00:07:27 +02:00
|
|
|
Rule: compile,
|
2015-06-24 02:21:00 +02:00
|
|
|
Outputs: []string{testArchive},
|
|
|
|
Inputs: []string{mainFile},
|
2015-11-17 23:21:45 +01:00
|
|
|
Implicits: []string{testPkgArchive},
|
2015-06-24 02:21:00 +02:00
|
|
|
Args: map[string]string{
|
|
|
|
"pkgPath": "main",
|
|
|
|
"incFlags": "-I " + testRoot,
|
|
|
|
},
|
2017-07-20 03:48:01 +02:00
|
|
|
Optional: true,
|
2015-06-24 02:21:00 +02:00
|
|
|
})
|
|
|
|
|
|
|
|
ctx.Build(pctx, blueprint.BuildParams{
|
2018-10-05 20:12:53 +02:00
|
|
|
Rule: link,
|
|
|
|
Outputs: []string{testFile},
|
|
|
|
Inputs: []string{testArchive},
|
|
|
|
Implicits: linkDeps,
|
2015-06-24 02:21:00 +02:00
|
|
|
Args: map[string]string{
|
|
|
|
"libDirFlags": strings.Join(libDirFlags, " "),
|
|
|
|
},
|
2017-07-20 03:48:01 +02:00
|
|
|
Optional: true,
|
2015-06-24 02:21:00 +02:00
|
|
|
})
|
|
|
|
|
|
|
|
ctx.Build(pctx, blueprint.BuildParams{
|
2020-07-09 23:24:56 +02:00
|
|
|
Rule: test,
|
|
|
|
Outputs: []string{testPassed},
|
|
|
|
Inputs: []string{testFile},
|
2021-09-08 15:32:52 +02:00
|
|
|
Validations: testDeps,
|
2015-06-24 02:21:00 +02:00
|
|
|
Args: map[string]string{
|
|
|
|
"pkg": pkgPath,
|
|
|
|
"pkgSrcDir": filepath.Dir(testFiles[0]),
|
|
|
|
},
|
2017-07-20 03:48:01 +02:00
|
|
|
Optional: true,
|
2015-06-24 02:21:00 +02:00
|
|
|
})
|
|
|
|
|
|
|
|
return []string{testPassed}
|
|
|
|
}
|
|
|
|
|
2015-06-25 04:21:21 +02:00
|
|
|
type singleton struct {
|
|
|
|
}
|
2014-05-28 01:34:41 +02:00
|
|
|
|
2021-09-02 09:57:30 +02:00
|
|
|
func newSingletonFactory() func() blueprint.Singleton {
|
2015-06-25 04:21:21 +02:00
|
|
|
return func() blueprint.Singleton {
|
2021-09-02 09:57:30 +02:00
|
|
|
return &singleton{}
|
2015-06-25 04:21:21 +02:00
|
|
|
}
|
2014-05-28 01:34:41 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
func (s *singleton) GenerateBuildActions(ctx blueprint.SingletonContext) {
|
|
|
|
// 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.
|
2023-06-08 23:03:45 +02:00
|
|
|
var primaryBuilders []*GoBinary
|
2016-05-26 19:07:59 +02:00
|
|
|
// blueprintTools contains blueprint go binaries that will be built in StageMain
|
|
|
|
var blueprintTools []string
|
2023-10-24 20:05:56 +02:00
|
|
|
// blueprintTools contains the test outputs of go tests that can be run in StageMain
|
|
|
|
var blueprintTests []string
|
2021-05-20 04:24:32 +02:00
|
|
|
// blueprintGoPackages contains all blueprint go packages that can be built in StageMain
|
|
|
|
var blueprintGoPackages []string
|
|
|
|
ctx.VisitAllModulesIf(IsBootstrapModule,
|
2020-06-12 01:22:36 +02:00
|
|
|
func(module blueprint.Module) {
|
2020-09-09 22:03:57 +02:00
|
|
|
if ctx.PrimaryModule(module) == module {
|
2023-06-08 23:03:45 +02:00
|
|
|
if binaryModule, ok := module.(*GoBinary); ok {
|
2021-09-02 09:57:30 +02:00
|
|
|
blueprintTools = append(blueprintTools, binaryModule.InstallPath())
|
2021-05-20 04:24:32 +02:00
|
|
|
if binaryModule.properties.PrimaryBuilder {
|
|
|
|
primaryBuilders = append(primaryBuilders, binaryModule)
|
|
|
|
}
|
2020-09-09 22:03:57 +02:00
|
|
|
}
|
2021-05-20 04:24:32 +02:00
|
|
|
|
2023-06-08 23:03:45 +02:00
|
|
|
if packageModule, ok := module.(*GoPackage); ok {
|
2021-05-20 04:24:32 +02:00
|
|
|
blueprintGoPackages = append(blueprintGoPackages,
|
|
|
|
packageModule.GoPackageTarget())
|
2023-10-24 20:05:56 +02:00
|
|
|
blueprintTests = append(blueprintTests,
|
2021-05-20 04:24:32 +02:00
|
|
|
packageModule.GoTestTargets()...)
|
2020-09-09 22:03:57 +02:00
|
|
|
}
|
2014-05-28 01:34:41 +02:00
|
|
|
}
|
2020-06-12 01:22:36 +02:00
|
|
|
})
|
2014-05-28 01:34:41 +02:00
|
|
|
|
2021-04-12 12:07:02 +02:00
|
|
|
var primaryBuilderCmdlinePrefix []string
|
|
|
|
var primaryBuilderName string
|
2016-11-02 01:12:28 +01:00
|
|
|
|
2021-04-12 12:07:02 +02:00
|
|
|
if len(primaryBuilders) == 0 {
|
2021-08-16 14:07:55 +02:00
|
|
|
ctx.Errorf("no primary builder module present")
|
|
|
|
return
|
2021-04-12 12:07:02 +02:00
|
|
|
} else if len(primaryBuilders) > 1 {
|
2014-05-28 01:34:41 +02:00
|
|
|
ctx.Errorf("multiple primary builder modules present:")
|
|
|
|
for _, primaryBuilder := range primaryBuilders {
|
|
|
|
ctx.ModuleErrorf(primaryBuilder, "<-- module %s",
|
|
|
|
ctx.ModuleName(primaryBuilder))
|
|
|
|
}
|
|
|
|
return
|
2021-04-12 12:07:02 +02:00
|
|
|
} else {
|
|
|
|
primaryBuilderName = ctx.ModuleName(primaryBuilders[0])
|
2014-05-28 01:34:41 +02:00
|
|
|
}
|
|
|
|
|
2021-09-01 08:58:07 +02:00
|
|
|
primaryBuilderFile := filepath.Join("$ToolDir", primaryBuilderName)
|
2021-08-26 15:08:09 +02:00
|
|
|
ctx.SetOutDir(pctx, "${outDir}")
|
Enhance bootstrap stage selection
This simplifies the bootstrap process while making it more flexible by
moving the stage selection into a go binary(choosestage). It will now be
possible to have more than two build stages.
Now each stage has a ninja template(main.ninja.in) and a timestamp
file(main.ninja.in.timestamp). The timestamp file may be updated by any
build stage that wishes to regenerate the ninja template. If the
choosestage binaries sees that the timestamp is newer than the template,
it will choose the prior stage.
The main stage no longer writes to the source tree to update the
build.ninja.in file. This was a problem for read-only source trees.
Instead, the choosestage binary first checks to see if that file is
newer than the last bootstrap.ninja.in, copies it in place, and starts
the boostrap stage.
The bootstrap stage regenerates it's own ninja template, but that
required a loop through the main stage to actually run it. The
choosestage binary now detects if the template has changed for the
current stage, and will restart the stage.
One change is that if dependencies do get messed up, instead of silently
failing, there's a higher chance that the bootstrap step will just
continue looping, doing nothing. This can happen if the main stage
has a dependency that triggers the bootstrap stage, but the bootstrap
stage doesn't see anything required to rebuild the main ninja file. A
side effect of this requirement is that changes to test code will now
rebuild the main ninja file.
Change-Id: I9965cfba79dc0dbbd3af05f5944f7653054455a2
2015-07-23 02:05:59 +02:00
|
|
|
|
2021-09-02 09:57:30 +02:00
|
|
|
for _, subninja := range ctx.Config().(BootstrapConfig).Subninjas() {
|
2021-08-12 15:29:03 +02:00
|
|
|
ctx.AddSubninja(subninja)
|
|
|
|
}
|
2015-05-13 23:36:24 +02:00
|
|
|
|
2021-09-02 09:57:30 +02:00
|
|
|
for _, i := range ctx.Config().(BootstrapConfig).PrimaryBuilderInvocations() {
|
2021-08-31 10:42:29 +02:00
|
|
|
flags := make([]string, 0)
|
|
|
|
flags = append(flags, primaryBuilderCmdlinePrefix...)
|
|
|
|
flags = append(flags, i.Args...)
|
2021-05-20 04:24:32 +02:00
|
|
|
|
2022-01-04 14:49:54 +01:00
|
|
|
pool := ""
|
|
|
|
if i.Console {
|
|
|
|
pool = "console"
|
|
|
|
}
|
|
|
|
|
2022-01-05 10:26:53 +01:00
|
|
|
envAssignments := ""
|
|
|
|
for k, v := range i.Env {
|
|
|
|
// NB: This is rife with quoting issues but we don't care because we trust
|
|
|
|
// soong_ui to not abuse this facility too much
|
|
|
|
envAssignments += k + "=" + v + " "
|
|
|
|
}
|
|
|
|
|
2021-08-31 10:42:29 +02:00
|
|
|
// Build the main build.ninja
|
2021-05-20 04:24:32 +02:00
|
|
|
ctx.Build(pctx, blueprint.BuildParams{
|
2022-10-27 10:05:27 +02:00
|
|
|
Rule: generateBuildNinja,
|
|
|
|
Outputs: i.Outputs,
|
|
|
|
Inputs: i.Inputs,
|
2024-01-03 01:58:49 +01:00
|
|
|
Implicits: i.Implicits,
|
2022-10-27 10:05:27 +02:00
|
|
|
OrderOnly: i.OrderOnlyInputs,
|
2021-08-31 10:42:29 +02:00
|
|
|
Args: map[string]string{
|
|
|
|
"builder": primaryBuilderFile,
|
2022-01-05 10:26:53 +01:00
|
|
|
"env": envAssignments,
|
2021-08-31 10:42:29 +02:00
|
|
|
"extra": strings.Join(flags, " "),
|
2022-01-04 14:49:54 +01:00
|
|
|
"pool": pool,
|
2021-08-31 10:42:29 +02:00
|
|
|
},
|
|
|
|
// soong_ui explicitly requests what it wants to be build. This is
|
|
|
|
// because the same Ninja file contains instructions to run
|
|
|
|
// soong_build, run bp2build and to generate the JSON module graph.
|
2021-12-06 14:30:18 +01:00
|
|
|
Optional: true,
|
|
|
|
Description: i.Description,
|
2021-05-20 04:24:32 +02:00
|
|
|
})
|
2014-05-28 01:34:41 +02:00
|
|
|
}
|
2021-08-31 10:42:29 +02:00
|
|
|
|
|
|
|
// Add a phony target for building various tools that are part of blueprint
|
|
|
|
ctx.Build(pctx, blueprint.BuildParams{
|
|
|
|
Rule: blueprint.Phony,
|
|
|
|
Outputs: []string{"blueprint_tools"},
|
|
|
|
Inputs: blueprintTools,
|
|
|
|
})
|
|
|
|
|
2023-10-24 20:05:56 +02:00
|
|
|
// Add a phony target for running various tests that are part of blueprint
|
|
|
|
ctx.Build(pctx, blueprint.BuildParams{
|
|
|
|
Rule: blueprint.Phony,
|
|
|
|
Outputs: []string{"blueprint_tests"},
|
|
|
|
Inputs: blueprintTests,
|
|
|
|
})
|
|
|
|
|
2021-08-31 10:42:29 +02:00
|
|
|
// Add a phony target for running go tests
|
|
|
|
ctx.Build(pctx, blueprint.BuildParams{
|
|
|
|
Rule: blueprint.Phony,
|
|
|
|
Outputs: []string{"blueprint_go_packages"},
|
|
|
|
Inputs: blueprintGoPackages,
|
|
|
|
Optional: true,
|
|
|
|
})
|
2014-05-28 01:34:41 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// packageRoot returns the module-specific package root directory path. This
|
|
|
|
// directory is where the final package .a files are output and where dependant
|
|
|
|
// modules search for this package via -I arguments.
|
2021-08-19 16:26:36 +02:00
|
|
|
func packageRoot(ctx blueprint.ModuleContext) string {
|
2021-09-01 08:58:07 +02:00
|
|
|
toolDir := ctx.Config().(BootstrapConfig).HostToolDir()
|
|
|
|
return filepath.Join(toolDir, "go", ctx.ModuleName(), "pkg")
|
2014-05-28 01:34:41 +02:00
|
|
|
}
|
|
|
|
|
2015-06-24 02:21:00 +02:00
|
|
|
// testRoot returns the module-specific package root directory path used for
|
|
|
|
// building tests. The .a files generated here will include everything from
|
|
|
|
// packageRoot, plus the test-only code.
|
2021-08-19 16:26:36 +02:00
|
|
|
func testRoot(ctx blueprint.ModuleContext) string {
|
2021-09-01 08:58:07 +02:00
|
|
|
toolDir := ctx.Config().(BootstrapConfig).HostToolDir()
|
|
|
|
return filepath.Join(toolDir, "go", ctx.ModuleName(), "test")
|
2015-06-24 02:21:00 +02:00
|
|
|
}
|
|
|
|
|
2014-11-09 20:52:56 +01:00
|
|
|
// moduleSrcDir returns the path of the directory that all source file paths are
|
2014-05-28 01:34:41 +02:00
|
|
|
// specified relative to.
|
2014-11-09 20:52:56 +01:00
|
|
|
func moduleSrcDir(ctx blueprint.ModuleContext) string {
|
2021-08-19 16:26:36 +02:00
|
|
|
return ctx.ModuleDir()
|
2014-05-28 01:34:41 +02:00
|
|
|
}
|
|
|
|
|
2014-11-09 20:52:56 +01:00
|
|
|
// moduleObjDir returns the module-specific object directory path.
|
2021-08-19 16:26:36 +02:00
|
|
|
func moduleObjDir(ctx blueprint.ModuleContext) string {
|
2021-09-01 08:58:07 +02:00
|
|
|
toolDir := ctx.Config().(BootstrapConfig).HostToolDir()
|
|
|
|
return filepath.Join(toolDir, "go", ctx.ModuleName(), "obj")
|
2014-05-28 01:34:41 +02:00
|
|
|
}
|
2015-07-25 01:53:27 +02:00
|
|
|
|
|
|
|
// moduleGenSrcDir returns the module-specific generated sources path.
|
2021-08-26 15:08:09 +02:00
|
|
|
func moduleGenSrcDir(ctx blueprint.ModuleContext) string {
|
2021-09-01 08:58:07 +02:00
|
|
|
toolDir := ctx.Config().(BootstrapConfig).HostToolDir()
|
|
|
|
return filepath.Join(toolDir, "go", ctx.ModuleName(), "gen")
|
2015-07-25 01:53:27 +02:00
|
|
|
}
|