"encoding/json"
"flag"
"fmt"
+ "log"
"os"
"os/exec"
"path/filepath"
"sort"
"strings"
"sync"
+ "time"
)
// Initialization for any invocation.
}
}
+var (
+ timeLogEnabled = os.Getenv("GOBUILDTIMELOGFILE") != ""
+ timeLogMu sync.Mutex
+ timeLogFile *os.File
+ timeLogStart time.Time
+)
+
+func timelog(op, name string) {
+ if !timeLogEnabled {
+ return
+ }
+ timeLogMu.Lock()
+ defer timeLogMu.Unlock()
+ if timeLogFile == nil {
+ f, err := os.OpenFile(os.Getenv("GOBUILDTIMELOGFILE"), os.O_RDWR|os.O_APPEND, 0666)
+ if err != nil {
+ log.Fatal(err)
+ }
+ buf := make([]byte, 100)
+ n, _ := f.Read(buf)
+ s := string(buf[:n])
+ if i := strings.Index(s, "\n"); i >= 0 {
+ s = s[:i]
+ }
+ i := strings.Index(s, " start")
+ if i < 0 {
+ log.Fatalf("time log %s does not begin with start line", os.Getenv("GOBULDTIMELOGFILE"))
+ }
+ t, err := time.Parse(time.UnixDate, s[:i])
+ if err != nil {
+ log.Fatalf("cannot parse time log line %q: %v", s, err)
+ }
+ timeLogStart = t
+ timeLogFile = f
+ }
+ t := time.Now()
+ fmt.Fprintf(timeLogFile, "%s %+.1fs %s %s\n", t.Format(time.UnixDate), t.Sub(timeLogStart).Seconds(), op, name)
+}
+
// The bootstrap command runs a build from scratch,
// stopping at having installed the go_bootstrap command.
//
// if $X was already present in os.Environ(), most systems preferred
// that setting, not the new one.
func cmdbootstrap() {
+ timelog("start", "dist bootstrap")
+ defer timelog("end", "dist bootstrap")
+
var noBanner bool
var debug bool
flag.BoolVar(&rebuildall, "a", rebuildall, "rebuild all")
setup()
+ timelog("build", "toolchain1")
checkCC()
bootstrapBuildTools()
os.Setenv("GOARCH", goarch)
os.Setenv("GOOS", goos)
+ timelog("build", "go_bootstrap")
xprintf("##### Building go_bootstrap.\n")
for _, dir := range buildlist {
installed[dir] = make(chan struct{})
//
// toolchain2 = mk(new toolchain, toolchain1, go_bootstrap)
//
+ timelog("build", "toolchain2")
xprintf("\n##### Building Go toolchain2 using go_bootstrap and Go toolchain1.\n")
os.Setenv("CC", defaultcc)
if goos == oldgoos && goarch == oldgoarch {
//
// toolchain3 = mk(new toolchain, toolchain2, go_bootstrap)
//
+ timelog("build", "toolchain3")
xprintf("\n##### Building Go toolchain3 using go_bootstrap and Go toolchain2.\n")
goInstall(append([]string{"-a"}, toolchain...)...)
if debug {
if goos == oldgoos && goarch == oldgoarch {
// Common case - not setting up for cross-compilation.
+ timelog("build", "toolchain")
xprintf("\n##### Building packages and commands for %s/%s\n", goos, goarch)
} else {
// GOOS/GOARCH does not match GOHOSTOS/GOHOSTARCH.
// Finish GOHOSTOS/GOHOSTARCH installation and then
// run GOOS/GOARCH installation.
+ timelog("build", "host toolchain")
xprintf("\n##### Building packages and commands for host, %s/%s\n", goos, goarch)
goInstall("std", "cmd")
checkNotStale(goBootstrap, "std", "cmd")
checkNotStale(cmdGo, "std", "cmd")
+ timelog("build", "target toolchain")
xprintf("\n##### Building packages and commands for target, %s/%s\n", goos, goarch)
goos = oldgoos
goarch = oldgoarch
}
func (t *tester) run() {
+ timelog("start", "dist test")
+
var exeSuffix string
if goos == "windows" {
exeSuffix = ".exe"
}
}
t.runPending(nil)
+ timelog("end", "dist test")
if t.failed {
fmt.Println("\nFAILED")
os.Exit(1)
return nil
}
t.runPending(dt)
+ timelog("start", dt.name)
+ defer timelog("end", dt.name)
ranGoTest = true
args := []string{
"test",
return nil
}
t.runPending(dt)
+ timelog("start", dt.name)
+ defer timelog("end", dt.name)
ranGoBench = true
args := []string{
"test",
heading: "cmd/go terminal test",
fn: func(dt *distTest) error {
t.runPending(dt)
+ timelog("start", dt.name)
+ defer timelog("end", dt.name)
if !stdOutErrAreTerminals() {
fmt.Println("skipping terminal test; stdout/stderr not terminals")
return nil
heading: "moved GOROOT",
fn: func(dt *distTest) error {
t.runPending(dt)
+ timelog("start", dt.name)
+ defer timelog("end", dt.name)
moved := goroot + "-moved"
if err := os.Rename(goroot, moved); err != nil {
if goos == "windows" {
fn: func(dt *distTest) error {
if seq {
t.runPending(dt)
+ timelog("start", name)
+ defer timelog("end", name)
return t.dirCmd(filepath.Join(goroot, "src", dirBanner), bin, args...).Run()
}
t.addCmd(dt, filepath.Join(goroot, "src", dirBanner), bin, args...)
heading: heading,
fn: func(dt *distTest) error {
t.runPending(dt)
+ timelog("start", name)
+ defer timelog("end", name)
return t.runHostTest(dir, pkg)
},
})
w.end = make(chan bool)
go func(w *work) {
if !<-w.start {
+ timelog("skip", w.dt.name)
w.out = []byte(fmt.Sprintf("skipped due to earlier error\n"))
} else {
+ timelog("start", w.dt.name)
w.out, w.err = w.cmd.CombinedOutput()
}
+ timelog("end", w.dt.name)
w.end <- true
}(w)
}
func (t *tester) cgoTestSO(dt *distTest, testpath string) error {
t.runPending(dt)
+ timelog("start", dt.name)
+ defer timelog("end", dt.name)
+
dir := filepath.Join(goroot, testpath)
// build shared object