aboutsummaryrefslogtreecommitdiffstats
path: root/bootstrap/command.go
diff options
context:
space:
mode:
authorDan Willemsen <dwillemsen@google.com>2015-07-22 17:05:59 -0700
committerDan Willemsen <dwillemsen@google.com>2015-07-23 22:06:02 -0700
commit91a657e219aa226df400ac30c0982820912051fa (patch)
tree1a074f9126d2f730bf67fc873e78c0526339f0a0 /bootstrap/command.go
parentf04c55172fb4810fc8aa463322a40ac130375df7 (diff)
downloadandroid_build_blueprint-91a657e219aa226df400ac30c0982820912051fa.tar.gz
android_build_blueprint-91a657e219aa226df400ac30c0982820912051fa.tar.bz2
android_build_blueprint-91a657e219aa226df400ac30c0982820912051fa.zip
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
Diffstat (limited to 'bootstrap/command.go')
-rw-r--r--bootstrap/command.go70
1 files changed, 30 insertions, 40 deletions
diff --git a/bootstrap/command.go b/bootstrap/command.go
index 932cfd7..4fb9c51 100644
--- a/bootstrap/command.go
+++ b/bootstrap/command.go
@@ -29,19 +29,21 @@ import (
)
var (
- outFile string
- depFile string
- checkFile string
- manifestFile string
- docFile string
- cpuprofile string
- runGoTests bool
+ outFile string
+ depFile string
+ timestampFile string
+ timestampDepFile string
+ manifestFile string
+ docFile string
+ cpuprofile string
+ runGoTests bool
)
func init() {
flag.StringVar(&outFile, "o", "build.ninja.in", "the Ninja file to output")
flag.StringVar(&depFile, "d", "", "the dependency file to output")
- flag.StringVar(&checkFile, "c", "", "the existing file to check against")
+ flag.StringVar(&timestampFile, "timestamp", "", "file to write before the output file")
+ flag.StringVar(&timestampDepFile, "timestampdep", "", "the dependency file for the timestamp file")
flag.StringVar(&manifestFile, "m", "", "the bootstrap manifest file")
flag.StringVar(&docFile, "docs", "", "build documentation file to output")
flag.StringVar(&cpuprofile, "cpuprofile", "", "write cpu profile to file")
@@ -69,13 +71,15 @@ func Main(ctx *blueprint.Context, config interface{}, extraNinjaFileDeps ...stri
fatalf("no Blueprints file specified")
}
- generatingBootstrapper := false
+ stage := StageMain
if c, ok := config.(ConfigInterface); ok {
- generatingBootstrapper = c.GeneratingBootstrapper()
+ if c.GeneratingBootstrapper() {
+ stage = StageBootstrap
+ }
}
bootstrapConfig := &Config{
- generatingBootstrapper: generatingBootstrapper,
+ stage: stage,
topLevelBlueprintsFile: flag.Arg(0),
runGoTests: runGoTests,
}
@@ -118,48 +122,34 @@ func Main(ctx *blueprint.Context, config interface{}, extraNinjaFileDeps ...stri
}
const outFilePermissions = 0666
- err = ioutil.WriteFile(outFile, buf.Bytes(), outFilePermissions)
- if err != nil {
- fatalf("error writing %s: %s", outFile, err)
- }
-
- if checkFile != "" {
- checkData, err := ioutil.ReadFile(checkFile)
+ if timestampFile != "" {
+ err := ioutil.WriteFile(timestampFile, []byte{}, outFilePermissions)
if err != nil {
- fatalf("error reading %s: %s", checkFile, err)
+ fatalf("error writing %s: %s", timestampFile, err)
}
- matches := buf.Len() == len(checkData)
- if matches {
- for i, value := range buf.Bytes() {
- if value != checkData[i] {
- matches = false
- break
- }
- }
- }
-
- if matches {
- // The new file content matches the check-file content, so we set
- // the new file's mtime and atime to match that of the check-file.
- checkFileInfo, err := os.Stat(checkFile)
- if err != nil {
- fatalf("error stat'ing %s: %s", checkFile, err)
- }
-
- time := checkFileInfo.ModTime()
- err = os.Chtimes(outFile, time, time)
+ if timestampDepFile != "" {
+ err := deptools.WriteDepFile(timestampDepFile, timestampFile, deps)
if err != nil {
- fatalf("error setting timestamps for %s: %s", outFile, err)
+ fatalf("error writing depfile: %s", err)
}
}
}
+ err = ioutil.WriteFile(outFile, buf.Bytes(), outFilePermissions)
+ if err != nil {
+ fatalf("error writing %s: %s", outFile, err)
+ }
+
if depFile != "" {
err := deptools.WriteDepFile(depFile, outFile, deps)
if err != nil {
fatalf("error writing depfile: %s", err)
}
+ err = deptools.WriteDepFile(depFile+".timestamp", outFile+".timestamp", deps)
+ if err != nil {
+ fatalf("error writing depfile: %s", err)
+ }
}
srcDir := filepath.Dir(bootstrapConfig.topLevelBlueprintsFile)