platform_build_blueprint/bootstrap/config.go
Dan Willemsen 7d0dddd84d Simplify bootstrap
tl;dr: Read if you don't use the wrapper or use SKIP_NINJA

Previously, we were relying on the ninja behavior of restarting the
build when the build.ninja file was updated to switch between different
bootstrap stages. But that means that every step that could produce a
build.ninja must pass in order to switch to a different stage. That
wasn't a big problem when we had a two stage build -- there was very
little that could fail in the second stage before we chose to go back to
the first stage. But when we had a three stage build, it was possible to
get into a state (usually during development) where you were in the
second stage, but the build was failing because the first stage needed
to be run. This was fixed in d79f1af742
by adding a wrapper that always started building at the first stage.

But this kept all of the complexity of using ninja restarts without any
of the benefits, so this change removes that complexity and just runs
each stage sequentially in the wrapper. So the wrapper is now required.

Since we're no longer going through choosestage, we can also skip the
template parsing for the later stages that don't need to be templated --
this can save a couple of seconds for large files.

In addition to all of the above, this also lets Soong reduce the number
of times the main ninja file is loaded. We had been running the wrapper
once (3 stages), then running ninja again after combining the
Soong-generated build.ninja with the Kati-generated build.ninja. This
change lets us removing the intermediate parsing of Soong's build.ninja,
so that we only execute ninja 3 times per build. It also lets us have
dependencies on pools or rules from Kati in the primary builder, since
we're never executing the main build.ninja without the Kati build.ninja.

The wrapper has a new option, NINJA to provide the path to ninja. This
used to be hardcoded to `ninja`, and will still default to that. But
we'll be running the first two bootstrap stages with $NINJA even if
SKIP_NINJA is set.

The wrapper passes "-w dupbuild=err" to ninja now -- this really should
always be turned on if you care about reliable builds.

Change-Id: I6f656b74eb3d064b8b9e69d1d6dac1129d72b747
2016-08-30 17:26:56 -07:00

95 lines
3 KiB
Go

// 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.
package bootstrap
import (
"runtime"
"github.com/google/blueprint"
)
func bootstrapVariable(name, template string, value func() string) blueprint.Variable {
return pctx.VariableFunc(name, func(config interface{}) (string, error) {
if c, ok := config.(ConfigInterface); ok && c.GeneratingBootstrapper() {
return template, nil
}
return value(), nil
})
}
var (
// These variables are the only configuration needed by the boostrap
// modules. For the first bootstrap stage, they are set to the
// variable name enclosed in "@@" so that their values can be easily
// replaced in the generated Ninja file.
srcDir = bootstrapVariable("srcDir", "@@SrcDir@@", func() string {
return SrcDir
})
buildDir = bootstrapVariable("buildDir", "@@BuildDir@@", func() string {
return BuildDir
})
goRoot = bootstrapVariable("goRoot", "@@GoRoot@@", func() string {
return runtime.GOROOT()
})
compileCmd = bootstrapVariable("compileCmd", "@@GoCompile@@", func() string {
return "$goRoot/pkg/tool/" + runtime.GOOS + "_" + runtime.GOARCH + "/compile"
})
linkCmd = bootstrapVariable("linkCmd", "@@GoLink@@", func() string {
return "$goRoot/pkg/tool/" + runtime.GOOS + "_" + runtime.GOARCH + "/link"
})
bootstrapCmd = bootstrapVariable("bootstrapCmd", "@@Bootstrap@@", func() string {
panic("bootstrapCmd is only available for minibootstrap")
})
)
type ConfigInterface interface {
// GeneratingBootstrapper should return true if this build invocation is
// creating a .minibootstrap/build.ninja file to be used in a build
// bootstrapping sequence.
GeneratingBootstrapper() bool
// GeneratingPrimaryBuilder should return true if this build invocation is
// creating a .bootstrap/build.ninja file to be used to build the
// primary builder
GeneratingPrimaryBuilder() bool
}
type ConfigRemoveAbandonedFiles interface {
// RemoveAbandonedFiles should return true if files listed in the
// .ninja_log but not the output build.ninja file should be deleted.
RemoveAbandonedFiles() bool
}
type ConfigBlueprintToolLocation interface {
// BlueprintToolLocation can return a path name to install blueprint tools
// designed for end users (bpfmt, bpmodify, and anything else using
// blueprint_go_binary).
BlueprintToolLocation() string
}
type Stage int
const (
StageBootstrap Stage = iota
StagePrimary
StageMain
)
type Config struct {
stage Stage
topLevelBlueprintsFile string
runGoTests bool
}