From fe0fcaf43ef3aab81541dad2a71b46254dc4cf6a Mon Sep 17 00:00:00 2001 From: Matt Madison Date: Sat, 17 Feb 2018 10:03:48 -0800 Subject: [PATCH] cmd/dist: separate host and target builds Change the dist tool to allow for OE-style cross- and cross-canadian builds: - command flags --host-only and --target only are added; if one is present, the other changes mentioned below take effect, and arguments may also be specified on the command line to enumerate the package(s) to be built. - for OE cross builds, go_bootstrap is always built for the current build host, and is moved, along with the supporting toolchain (asm, compile, etc.) to a separate 'native_native' directory under GOROOT/pkg/tool. - go_bootstrap is not automatically removed after the build, so it can be reused later (e.g., building both static and shared runtime). Note that for --host-only builds, it would be nice to specify just the "cmd" package to build only the go commands/tools, the staleness checks in the dist tool will fail if the "std" library has not also been built. So host-only builds have to build everything anyway. Upstream-Status: Inappropriate [OE specific] Signed-off-by: Matt Madison more dist cleanup --- src/cmd/dist/build.go | 153 ++++++++++++++++++++++++++++++------------ 1 file changed, 111 insertions(+), 42 deletions(-) Index: go/src/cmd/dist/build.go =================================================================== --- go.orig/src/cmd/dist/build.go +++ go/src/cmd/dist/build.go @@ -39,6 +39,7 @@ var ( goldflags string workdir string tooldir string + build_tooldir string oldgoos string oldgoarch string exe string @@ -50,6 +51,7 @@ var ( rebuildall bool defaultclang bool + crossBuild bool vflag int // verbosity ) @@ -231,6 +233,8 @@ func xinit() { if tooldir = os.Getenv("GOTOOLDIR"); tooldir == "" { tooldir = pathf("%s/pkg/tool/%s_%s", goroot, gohostos, gohostarch) } + build_tooldir = pathf("%s/pkg/tool/native_native", goroot) + } // compilerEnv returns a map from "goos/goarch" to the @@ -260,7 +264,6 @@ func compilerEnv(envName, def string) ma if gohostos != goos || gohostarch != goarch { m[gohostos+"/"+gohostarch] = m[""] } - m[""] = env } for _, goos := range okgoos { @@ -487,8 +490,10 @@ func setup() { // We keep it in pkg/, just like the object directory above. if rebuildall { xremoveall(tooldir) + xremoveall(build_tooldir) } xmkdirall(tooldir) + xmkdirall(build_tooldir) // Remove tool binaries from before the tool/gohostos_gohostarch xremoveall(pathf("%s/bin/tool", goroot)) @@ -1155,11 +1160,29 @@ func cmdbootstrap() { var noBanner bool var debug bool + var hostOnly bool + var targetOnly bool + var toBuild = []string { "std", "cmd" } + flag.BoolVar(&rebuildall, "a", rebuildall, "rebuild all") flag.BoolVar(&debug, "d", debug, "enable debugging of bootstrap process") flag.BoolVar(&noBanner, "no-banner", noBanner, "do not print banner") + flag.BoolVar(&hostOnly, "host-only", hostOnly, "build only host binaries, not target") + flag.BoolVar(&targetOnly, "target-only", targetOnly, "build only target binaries, not host") - xflagparse(0) + xflagparse(-1) + + if (hostOnly && targetOnly) { + fatalf("specify only one of --host-only or --target-only\n") + } + crossBuild = hostOnly || targetOnly + if flag.NArg() > 0 { + if crossBuild { + toBuild = flag.Args() + } else { + fatalf("package names not permitted without --host-only or --target-only\n") + } + } if debug { // cmd/buildid is used in debug mode. @@ -1207,8 +1230,13 @@ func cmdbootstrap() { xprintf("\n") } - gogcflags = os.Getenv("GO_GCFLAGS") // we were using $BOOT_GO_GCFLAGS until now - goldflags = os.Getenv("GO_LDFLAGS") + // For split host/target cross/cross-canadian builds, we don't + // want to be setting these flags until after we have compiled + // the toolchain that runs on the build host. + if ! crossBuild { + gogcflags = os.Getenv("GO_GCFLAGS") // we were using $BOOT_GO_GCFLAGS until now + goldflags = os.Getenv("GO_LDFLAGS") + } goBootstrap := pathf("%s/go_bootstrap", tooldir) cmdGo := pathf("%s/go", gobin) if debug { @@ -1237,7 +1265,11 @@ func cmdbootstrap() { xprintf("\n") } xprintf("Building Go toolchain2 using go_bootstrap and Go toolchain1.\n") - os.Setenv("CC", compilerEnvLookup(defaultcc, goos, goarch)) + if crossBuild { + os.Setenv("CC", defaultcc[""]) + } else { + os.Setenv("CC", compilerEnvLookup(defaultcc, goos, goarch)) + } goInstall(goBootstrap, append([]string{"-i"}, toolchain...)...) if debug { run("", ShowOutput|CheckExit, pathf("%s/compile", tooldir), "-V=full") @@ -1274,50 +1306,84 @@ func cmdbootstrap() { } checkNotStale(goBootstrap, append(toolchain, "runtime/internal/sys")...) - if goos == oldgoos && goarch == oldgoarch { - // Common case - not setting up for cross-compilation. - timelog("build", "toolchain") - if vflag > 0 { - xprintf("\n") + if crossBuild { + gogcflags = os.Getenv("GO_GCFLAGS") + goldflags = os.Getenv("GO_LDFLAGS") + tool_files, _ := filepath.Glob(pathf("%s/*", tooldir)) + for _, f := range tool_files { + copyfile(pathf("%s/%s", build_tooldir, filepath.Base(f)), f, writeExec) + xremove(f) + } + os.Setenv("GOTOOLDIR", build_tooldir) + goBootstrap = pathf("%s/go_bootstrap", build_tooldir) + if hostOnly { + timelog("build", "host toolchain") + if vflag > 0 { + xprintf("\n") + } + xprintf("Building %s for host, %s/%s.\n", strings.Join(toBuild, ","), goos, goarch) + goInstall(goBootstrap, toBuild...) + checkNotStale(goBootstrap, toBuild...) + // Skip cmdGo staleness checks here, since we can't necessarily run the cmdGo binary + + timelog("build", "target toolchain") + if vflag > 0 { + xprintf("\n") + } + } else if targetOnly { + goos = oldgoos + goarch = oldgoarch + os.Setenv("GOOS", goos) + os.Setenv("GOARCH", goarch) + os.Setenv("CC", compilerEnvLookup(defaultcc, goos, goarch)) + xprintf("Building %s for target, %s/%s.\n", strings.Join(toBuild, ","), goos, goarch) + goInstall(goBootstrap, toBuild...) + checkNotStale(goBootstrap, toBuild...) + // Skip cmdGo staleness checks here, since we can't run the target's cmdGo binary } - xprintf("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") - if vflag > 0 { - xprintf("\n") + + if goos == oldgoos && goarch == oldgoarch { + // Common case - not setting up for cross-compilation. + timelog("build", "toolchain") + if vflag > 0 { + xprintf("\n") + } + xprintf("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") + if vflag > 0 { + xprintf("\n") + } + xprintf("Building packages and commands for host, %s/%s.\n", goos, goarch) + goInstall(goBootstrap, "std", "cmd") + checkNotStale(goBootstrap, "std", "cmd") + checkNotStale(cmdGo, "std", "cmd") + + timelog("build", "target toolchain") + if vflag > 0 { + xprintf("\n") + } + goos = oldgoos + goarch = oldgoarch + os.Setenv("GOOS", goos) + os.Setenv("GOARCH", goarch) + os.Setenv("CC", compilerEnvLookup(defaultcc, goos, goarch)) + xprintf("Building packages and commands for target, %s/%s.\n", goos, goarch) } - xprintf("Building packages and commands for host, %s/%s.\n", goos, goarch) goInstall(goBootstrap, "std", "cmd") checkNotStale(goBootstrap, "std", "cmd") checkNotStale(cmdGo, "std", "cmd") - timelog("build", "target toolchain") - if vflag > 0 { - xprintf("\n") - } - goos = oldgoos - goarch = oldgoarch - os.Setenv("GOOS", goos) - os.Setenv("GOARCH", goarch) - os.Setenv("CC", compilerEnvLookup(defaultcc, goos, goarch)) - xprintf("Building packages and commands for target, %s/%s.\n", goos, goarch) - } - targets := []string{"std", "cmd"} - if goos == "js" && goarch == "wasm" { - // Skip the cmd tools for js/wasm. They're not usable. - targets = targets[:1] - } - goInstall(goBootstrap, targets...) - checkNotStale(goBootstrap, targets...) - checkNotStale(cmdGo, targets...) - if debug { - run("", ShowOutput|CheckExit, pathf("%s/compile", tooldir), "-V=full") - run("", ShowOutput|CheckExit, pathf("%s/buildid", tooldir), pathf("%s/pkg/%s_%s/runtime/internal/sys.a", goroot, goos, goarch)) - checkNotStale(goBootstrap, append(toolchain, "runtime/internal/sys")...) - copyfile(pathf("%s/compile4", tooldir), pathf("%s/compile", tooldir), writeExec) + if debug { + run("", ShowOutput|CheckExit, pathf("%s/compile", tooldir), "-V=full") + run("", ShowOutput|CheckExit, pathf("%s/buildid", tooldir), pathf("%s/pkg/%s_%s/runtime/internal/sys.a", goroot, goos, goarch)) + checkNotStale(goBootstrap, append(toolchain, "runtime/internal/sys")...) + copyfile(pathf("%s/compile4", tooldir), pathf("%s/compile", tooldir), writeExec) + } } // Check that there are no new files in $GOROOT/bin other than @@ -1335,7 +1401,11 @@ func cmdbootstrap() { } // Remove go_bootstrap now that we're done. - xremove(pathf("%s/go_bootstrap", tooldir)) + // Except that for split host/target cross-builds, we need to + // keep it. + if ! crossBuild { + xremove(pathf("%s/go_bootstrap", tooldir)) + } // Print trailing banner unless instructed otherwise. if !noBanner {