"os"
        "os/exec"
        "path/filepath"
+       "sort"
        "strings"
+       "sync"
 )
 
 // Initialization for any invocation.
        {"anames9.c", nil},
 }
 
+// installed maps from a dir name (as given to install) to a chan
+// closed when the dir's package is installed.
+var installed = make(map[string]chan struct{})
+
 // install installs the library, package, or binary associated with dir,
 // which is relative to $GOROOT/src.
 func install(dir string) {
+       if ch, ok := installed[dir]; ok {
+               defer close(ch)
+       }
+       for _, dep := range builddeps[dir] {
+               <-installed[dep]
+       }
+
        if vflag > 0 {
                if goos != gohostos || goarch != gohostarch {
                        errprintf("%s (%s/%s)\n", dir, goos, goarch)
                }
        }
 
+       workdir := pathf("%s/%s", workdir, dir)
+       xmkdirall(workdir)
+
        var clean []string
        defer func() {
                for _, name := range clean {
        run(path, CheckExit|ShowOutput, compile...)
 
        // Compile the files.
+       var wg sync.WaitGroup
        for _, p := range files {
                if !strings.HasSuffix(p, ".s") {
                        continue
                // Change the last character of the output file (which was c or s).
                b = b[:len(b)-1] + "o"
                compile = append(compile, "-o", b, p)
-               bgrun(path, compile...)
+               bgrun(&wg, path, compile...)
 
                link = append(link, b)
                if doclean {
                        clean = append(clean, b)
                }
        }
-       bgwait()
+       bgwait(&wg)
 
        if ispackcmd {
                xremove(link[targ])
        writefile(bdst.String(), dst, 0)
 }
 
-// buildorder records the order of builds for the 'go bootstrap' command.
-// The Go packages and commands must be in dependency order,
-// maintained by hand, but the order doesn't change often.
-var buildorder = []string{
-       // Go libraries and programs for bootstrap.
-       "runtime",
-       "errors",
-       "sync/atomic",
-       "sync",
-       "internal/singleflight",
-       "io",
-       "unicode",
-       "unicode/utf8",
-       "unicode/utf16",
-       "bytes",
-       "math",
-       "strings",
-       "strconv",
-       "bufio",
-       "sort",
-       "container/heap",
-       "encoding/base64",
-       "syscall",
-       "internal/syscall/windows/registry",
-       "time",
-       "internal/syscall/windows",
-       "os",
-       "reflect",
-       "fmt",
-       "encoding",
-       "encoding/binary",
-       "encoding/json",
-       "flag",
-       "path/filepath",
-       "path",
-       "io/ioutil",
-       "log",
-       "regexp/syntax",
-       "regexp",
-       "go/token",
-       "go/scanner",
-       "go/ast",
-       "go/parser",
-       "os/exec",
-       "os/signal",
-       "net/url",
-       "text/template/parse",
-       "text/template",
-       "go/doc",
-       "go/build",
-       "hash",
-       "crypto",
-       "crypto/sha1",
-       "debug/dwarf",
-       "debug/elf",
-       "cmd/go",
+// builddeps records the build dependencies for the 'go bootstrap' command.
+// It is a map[string][]string and generated by mkdeps.bash into deps.go.
+
+// buildlist is the list of directories being built, sorted by name.
+var buildlist = makeBuildlist()
+
+func makeBuildlist() []string {
+       var all []string
+       for dir := range builddeps {
+               all = append(all, dir)
+       }
+       sort.Strings(all)
+       return all
 }
 
 var runtimegen = []string{
 }
 
 func clean() {
-       for _, name := range buildorder {
+       for _, name := range buildlist {
                path := pathf("%s/src/%s", goroot, name)
                // Remove generated files.
                for _, elem := range xreaddir(path) {
        // than in a standard release like Go 1.4, so don't do this rebuild by default.
        if false {
                xprintf("##### Building Go toolchain using itself.\n")
-               for _, dir := range buildorder {
-                       if dir == "cmd/go" {
-                               break
-                       }
-                       install(dir)
+               for _, dir := range buildlist {
+                       installed[dir] = make(chan struct{})
                }
+               var wg sync.WaitGroup
+               for _, dir := range builddeps["cmd/go"] {
+                       wg.Add(1)
+                       dir := dir
+                       go func() {
+                               defer wg.Done()
+                               install(dir)
+                       }()
+               }
+               wg.Wait()
                xprintf("\n")
        }
 
        xprintf("##### Building go_bootstrap for host, %s/%s.\n", gohostos, gohostarch)
-       for _, dir := range buildorder {
-               install(dir)
+       for _, dir := range buildlist {
+               installed[dir] = make(chan struct{})
+       }
+       for _, dir := range buildlist {
+               go install(dir)
        }
+       <-installed["cmd/go"]
 
        goos = oldgoos
        goarch = oldgoarch
 
        // Build runtime for actual goos/goarch too.
        if goos != gohostos || goarch != gohostarch {
+               installed["runtime"] = make(chan struct{})
                install("runtime")
        }
 }
 
--- /dev/null
+// generated by mkdeps.bash
+
+package main
+
+var builddeps = map[string][]string{
+       "bufio":                             {"bytes", "errors", "io", "runtime", "sync", "sync/atomic", "unicode", "unicode/utf8"},
+       "bytes":                             {"errors", "io", "runtime", "sync", "sync/atomic", "unicode", "unicode/utf8"},
+       "container/heap":                    {"runtime", "sort"},
+       "crypto":                            {"errors", "hash", "io", "math", "runtime", "strconv", "sync", "sync/atomic", "unicode/utf8"},
+       "crypto/sha1":                       {"crypto", "errors", "hash", "io", "math", "runtime", "strconv", "sync", "sync/atomic", "unicode/utf8"},
+       "debug/dwarf":                       {"encoding/binary", "errors", "fmt", "internal/syscall/windows", "internal/syscall/windows/registry", "io", "math", "os", "path", "reflect", "runtime", "sort", "strconv", "strings", "sync", "sync/atomic", "syscall", "time", "unicode", "unicode/utf16", "unicode/utf8"},
+       "debug/elf":                         {"bytes", "debug/dwarf", "encoding/binary", "errors", "fmt", "internal/syscall/windows", "internal/syscall/windows/registry", "io", "math", "os", "path", "reflect", "runtime", "sort", "strconv", "strings", "sync", "sync/atomic", "syscall", "time", "unicode", "unicode/utf16", "unicode/utf8"},
+       "encoding":                          {"runtime"},
+       "encoding/base64":                   {"errors", "io", "math", "runtime", "strconv", "sync", "sync/atomic", "unicode/utf8"},
+       "encoding/binary":                   {"errors", "io", "math", "reflect", "runtime", "strconv", "sync", "sync/atomic", "unicode/utf8"},
+       "encoding/json":                     {"bytes", "encoding", "encoding/base64", "errors", "fmt", "internal/syscall/windows", "internal/syscall/windows/registry", "io", "math", "os", "reflect", "runtime", "sort", "strconv", "strings", "sync", "sync/atomic", "syscall", "time", "unicode", "unicode/utf16", "unicode/utf8"},
+       "errors":                            {"runtime"},
+       "flag":                              {"errors", "fmt", "internal/syscall/windows", "internal/syscall/windows/registry", "io", "math", "os", "reflect", "runtime", "sort", "strconv", "sync", "sync/atomic", "syscall", "time", "unicode/utf16", "unicode/utf8"},
+       "fmt":                               {"errors", "internal/syscall/windows", "internal/syscall/windows/registry", "io", "math", "os", "reflect", "runtime", "strconv", "sync", "sync/atomic", "syscall", "time", "unicode/utf16", "unicode/utf8"},
+       "go/ast":                            {"bytes", "errors", "fmt", "go/scanner", "go/token", "internal/syscall/windows", "internal/syscall/windows/registry", "io", "math", "os", "path/filepath", "reflect", "runtime", "sort", "strconv", "strings", "sync", "sync/atomic", "syscall", "time", "unicode", "unicode/utf16", "unicode/utf8"},
+       "go/build":                          {"bufio", "bytes", "errors", "fmt", "go/ast", "go/doc", "go/parser", "go/scanner", "go/token", "internal/syscall/windows", "internal/syscall/windows/registry", "io", "io/ioutil", "log", "math", "net/url", "os", "path", "path/filepath", "reflect", "regexp", "regexp/syntax", "runtime", "sort", "strconv", "strings", "sync", "sync/atomic", "syscall", "text/template", "text/template/parse", "time", "unicode", "unicode/utf16", "unicode/utf8"},
+       "go/doc":                            {"bytes", "errors", "fmt", "go/ast", "go/scanner", "go/token", "internal/syscall/windows", "internal/syscall/windows/registry", "io", "io/ioutil", "math", "net/url", "os", "path", "path/filepath", "reflect", "regexp", "regexp/syntax", "runtime", "sort", "strconv", "strings", "sync", "sync/atomic", "syscall", "text/template", "text/template/parse", "time", "unicode", "unicode/utf16", "unicode/utf8"},
+       "go/parser":                         {"bytes", "errors", "fmt", "go/ast", "go/scanner", "go/token", "internal/syscall/windows", "internal/syscall/windows/registry", "io", "io/ioutil", "math", "os", "path/filepath", "reflect", "runtime", "sort", "strconv", "strings", "sync", "sync/atomic", "syscall", "time", "unicode", "unicode/utf16", "unicode/utf8"},
+       "go/scanner":                        {"bytes", "errors", "fmt", "go/token", "internal/syscall/windows", "internal/syscall/windows/registry", "io", "math", "os", "path/filepath", "reflect", "runtime", "sort", "strconv", "strings", "sync", "sync/atomic", "syscall", "time", "unicode", "unicode/utf16", "unicode/utf8"},
+       "go/token":                          {"errors", "fmt", "internal/syscall/windows", "internal/syscall/windows/registry", "io", "math", "os", "reflect", "runtime", "sort", "strconv", "sync", "sync/atomic", "syscall", "time", "unicode/utf16", "unicode/utf8"},
+       "hash":                              {"errors", "io", "runtime", "sync", "sync/atomic"},
+       "internal/singleflight":             {"runtime", "sync", "sync/atomic"},
+       "internal/syscall/windows":          {"errors", "runtime", "sync", "sync/atomic", "syscall", "unicode/utf16"},
+       "internal/syscall/windows/registry": {"errors", "io", "runtime", "sync", "sync/atomic", "syscall", "unicode/utf16"},
+       "io":                  {"errors", "runtime", "sync", "sync/atomic"},
+       "io/ioutil":           {"bytes", "errors", "internal/syscall/windows", "internal/syscall/windows/registry", "io", "math", "os", "path/filepath", "runtime", "sort", "strconv", "strings", "sync", "sync/atomic", "syscall", "time", "unicode", "unicode/utf16", "unicode/utf8"},
+       "log":                 {"errors", "fmt", "internal/syscall/windows", "internal/syscall/windows/registry", "io", "math", "os", "reflect", "runtime", "strconv", "sync", "sync/atomic", "syscall", "time", "unicode/utf16", "unicode/utf8"},
+       "math":                {"runtime"},
+       "net/url":             {"bytes", "errors", "fmt", "internal/syscall/windows", "internal/syscall/windows/registry", "io", "math", "os", "reflect", "runtime", "sort", "strconv", "strings", "sync", "sync/atomic", "syscall", "time", "unicode", "unicode/utf16", "unicode/utf8"},
+       "os":                  {"errors", "internal/syscall/windows", "internal/syscall/windows/registry", "io", "runtime", "sync", "sync/atomic", "syscall", "time", "unicode/utf16", "unicode/utf8"},
+       "os/exec":             {"bytes", "errors", "internal/syscall/windows", "internal/syscall/windows/registry", "io", "math", "os", "path/filepath", "runtime", "sort", "strconv", "strings", "sync", "sync/atomic", "syscall", "time", "unicode", "unicode/utf16", "unicode/utf8"},
+       "os/signal":           {"errors", "internal/syscall/windows", "internal/syscall/windows/registry", "io", "os", "runtime", "sync", "sync/atomic", "syscall", "time", "unicode/utf16", "unicode/utf8"},
+       "path":                {"errors", "io", "runtime", "strings", "sync", "sync/atomic", "unicode", "unicode/utf8"},
+       "path/filepath":       {"bytes", "errors", "internal/syscall/windows", "internal/syscall/windows/registry", "io", "os", "runtime", "sort", "strings", "sync", "sync/atomic", "syscall", "time", "unicode", "unicode/utf16", "unicode/utf8"},
+       "reflect":             {"errors", "math", "runtime", "strconv", "sync", "sync/atomic", "unicode/utf8"},
+       "regexp":              {"bytes", "errors", "io", "math", "regexp/syntax", "runtime", "sort", "strconv", "strings", "sync", "sync/atomic", "unicode", "unicode/utf8"},
+       "regexp/syntax":       {"bytes", "errors", "io", "math", "runtime", "sort", "strconv", "strings", "sync", "sync/atomic", "unicode", "unicode/utf8"},
+       "runtime":             {},
+       "sort":                {"runtime"},
+       "strconv":             {"errors", "math", "runtime", "unicode/utf8"},
+       "strings":             {"errors", "io", "runtime", "sync", "sync/atomic", "unicode", "unicode/utf8"},
+       "sync":                {"runtime", "sync/atomic"},
+       "sync/atomic":         {"runtime"},
+       "syscall":             {"errors", "runtime", "sync", "sync/atomic", "unicode/utf16"},
+       "text/template":       {"bytes", "errors", "fmt", "internal/syscall/windows", "internal/syscall/windows/registry", "io", "io/ioutil", "math", "net/url", "os", "path/filepath", "reflect", "runtime", "sort", "strconv", "strings", "sync", "sync/atomic", "syscall", "text/template/parse", "time", "unicode", "unicode/utf16", "unicode/utf8"},
+       "text/template/parse": {"bytes", "errors", "fmt", "internal/syscall/windows", "internal/syscall/windows/registry", "io", "math", "os", "reflect", "runtime", "strconv", "strings", "sync", "sync/atomic", "syscall", "time", "unicode", "unicode/utf16", "unicode/utf8"},
+       "time":                {"errors", "internal/syscall/windows/registry", "io", "runtime", "sync", "sync/atomic", "syscall", "unicode/utf16"},
+       "unicode":             {"runtime"},
+       "unicode/utf16":       {"runtime"},
+       "unicode/utf8":        {"runtime"},
+       "cmd/go":              {"bufio", "bytes", "container/heap", "crypto", "crypto/sha1", "debug/dwarf", "debug/elf", "encoding", "encoding/base64", "encoding/binary", "encoding/json", "errors", "flag", "fmt", "go/ast", "go/build", "go/doc", "go/parser", "go/scanner", "go/token", "hash", "internal/singleflight", "internal/syscall/windows", "internal/syscall/windows/registry", "io", "io/ioutil", "log", "math", "net/url", "os", "os/exec", "os/signal", "path", "path/filepath", "reflect", "regexp", "regexp/syntax", "runtime", "sort", "strconv", "strings", "sync", "sync/atomic", "syscall", "text/template", "text/template/parse", "time", "unicode", "unicode/utf16", "unicode/utf8"},
+}