1*4882a593SmuzhiyunFrom 7bc891e00be4263311d75aa2b2ee6a3b7b75355f Mon Sep 17 00:00:00 2001 2*4882a593SmuzhiyunFrom: Alex Kube <alexander.j.kube@gmail.com> 3*4882a593SmuzhiyunDate: Wed, 23 Oct 2019 21:18:12 +0430 4*4882a593SmuzhiyunSubject: [PATCH] cmd/dist: separate host and target builds 5*4882a593Smuzhiyun 6*4882a593SmuzhiyunUpstream-Status: Inappropriate [OE specific] 7*4882a593Smuzhiyun 8*4882a593SmuzhiyunChange the dist tool to allow for OE-style cross- 9*4882a593Smuzhiyunand cross-canadian builds: 10*4882a593Smuzhiyun 11*4882a593Smuzhiyun - command flags --host-only and --target only are added; 12*4882a593Smuzhiyun if one is present, the other changes mentioned below 13*4882a593Smuzhiyun take effect, and arguments may also be specified on 14*4882a593Smuzhiyun the command line to enumerate the package(s) to be 15*4882a593Smuzhiyun built. 16*4882a593Smuzhiyun 17*4882a593Smuzhiyun - for OE cross builds, go_bootstrap is always built for 18*4882a593Smuzhiyun the current build host, and is moved, along with the supporting 19*4882a593Smuzhiyun toolchain (asm, compile, etc.) to a separate 'native_native' 20*4882a593Smuzhiyun directory under GOROOT/pkg/tool. 21*4882a593Smuzhiyun 22*4882a593Smuzhiyun - go_bootstrap is not automatically removed after the build, 23*4882a593Smuzhiyun so it can be reused later (e.g., building both static and 24*4882a593Smuzhiyun shared runtime). 25*4882a593Smuzhiyun 26*4882a593SmuzhiyunNote that for --host-only builds, it would be nice to specify 27*4882a593Smuzhiyunjust the "cmd" package to build only the go commands/tools, 28*4882a593Smuzhiyunthe staleness checks in the dist tool will fail if the "std" 29*4882a593Smuzhiyunlibrary has not also been built. So host-only builds have to 30*4882a593Smuzhiyunbuild everything anyway. 31*4882a593Smuzhiyun 32*4882a593SmuzhiyunAdapted to Go 1.13 from patches originally submitted to 33*4882a593Smuzhiyunthe meta/recipes-devtools/go tree by 34*4882a593SmuzhiyunMatt Madison <matt@madison.systems>. 35*4882a593Smuzhiyun 36*4882a593SmuzhiyunSigned-off-by: Alexander J Kube <alexander.j.kube@gmail.com> 37*4882a593Smuzhiyun 38*4882a593Smuzhiyun--- 39*4882a593Smuzhiyun src/cmd/dist/build.go | 156 ++++++++++++++++++++++++++++++------------ 40*4882a593Smuzhiyun 1 file changed, 113 insertions(+), 43 deletions(-) 41*4882a593Smuzhiyun 42*4882a593Smuzhiyundiff --git a/src/cmd/dist/build.go b/src/cmd/dist/build.go 43*4882a593Smuzhiyunindex d82f612..5c8459c 100644 44*4882a593Smuzhiyun--- a/src/cmd/dist/build.go 45*4882a593Smuzhiyun+++ b/src/cmd/dist/build.go 46*4882a593Smuzhiyun@@ -43,6 +43,7 @@ var ( 47*4882a593Smuzhiyun goexperiment string 48*4882a593Smuzhiyun workdir string 49*4882a593Smuzhiyun tooldir string 50*4882a593Smuzhiyun+ build_tooldir string 51*4882a593Smuzhiyun oldgoos string 52*4882a593Smuzhiyun oldgoarch string 53*4882a593Smuzhiyun exe string 54*4882a593Smuzhiyun@@ -55,6 +56,7 @@ var ( 55*4882a593Smuzhiyun 56*4882a593Smuzhiyun rebuildall bool 57*4882a593Smuzhiyun defaultclang bool 58*4882a593Smuzhiyun+ crossBuild bool 59*4882a593Smuzhiyun 60*4882a593Smuzhiyun vflag int // verbosity 61*4882a593Smuzhiyun ) 62*4882a593Smuzhiyun@@ -251,6 +253,8 @@ func xinit() { 63*4882a593Smuzhiyun if tooldir = os.Getenv("GOTOOLDIR"); tooldir == "" { 64*4882a593Smuzhiyun tooldir = pathf("%s/pkg/tool/%s_%s", goroot, gohostos, gohostarch) 65*4882a593Smuzhiyun } 66*4882a593Smuzhiyun+ 67*4882a593Smuzhiyun+ build_tooldir = pathf("%s/pkg/tool/native_native", goroot) 68*4882a593Smuzhiyun } 69*4882a593Smuzhiyun 70*4882a593Smuzhiyun // compilerEnv returns a map from "goos/goarch" to the 71*4882a593Smuzhiyun@@ -496,8 +500,10 @@ func setup() { 72*4882a593Smuzhiyun p := pathf("%s/pkg/%s_%s", goroot, gohostos, gohostarch) 73*4882a593Smuzhiyun if rebuildall { 74*4882a593Smuzhiyun xremoveall(p) 75*4882a593Smuzhiyun+ xremoveall(build_tooldir) 76*4882a593Smuzhiyun } 77*4882a593Smuzhiyun xmkdirall(p) 78*4882a593Smuzhiyun+ xmkdirall(build_tooldir) 79*4882a593Smuzhiyun 80*4882a593Smuzhiyun if goos != gohostos || goarch != gohostarch { 81*4882a593Smuzhiyun p := pathf("%s/pkg/%s_%s", goroot, goos, goarch) 82*4882a593Smuzhiyun@@ -1267,17 +1273,35 @@ func cmdbootstrap() { 83*4882a593Smuzhiyun 84*4882a593Smuzhiyun var noBanner, noClean bool 85*4882a593Smuzhiyun var debug bool 86*4882a593Smuzhiyun+ var hostOnly bool 87*4882a593Smuzhiyun+ var targetOnly bool 88*4882a593Smuzhiyun+ var toBuild = []string{"std", "cmd"} 89*4882a593Smuzhiyun+ 90*4882a593Smuzhiyun flag.BoolVar(&rebuildall, "a", rebuildall, "rebuild all") 91*4882a593Smuzhiyun flag.BoolVar(&debug, "d", debug, "enable debugging of bootstrap process") 92*4882a593Smuzhiyun flag.BoolVar(&noBanner, "no-banner", noBanner, "do not print banner") 93*4882a593Smuzhiyun flag.BoolVar(&noClean, "no-clean", noClean, "print deprecation warning") 94*4882a593Smuzhiyun+ flag.BoolVar(&hostOnly, "host-only", hostOnly, "build only host binaries, not target") 95*4882a593Smuzhiyun+ flag.BoolVar(&targetOnly, "target-only", targetOnly, "build only target binaries, not host") 96*4882a593Smuzhiyun 97*4882a593Smuzhiyun- xflagparse(0) 98*4882a593Smuzhiyun+ xflagparse(-1) 99*4882a593Smuzhiyun 100*4882a593Smuzhiyun if noClean { 101*4882a593Smuzhiyun xprintf("warning: --no-clean is deprecated and has no effect; use 'go install std cmd' instead\n") 102*4882a593Smuzhiyun } 103*4882a593Smuzhiyun 104*4882a593Smuzhiyun+ if hostOnly && targetOnly { 105*4882a593Smuzhiyun+ fatalf("specify only one of --host-only or --target-only\n") 106*4882a593Smuzhiyun+ } 107*4882a593Smuzhiyun+ crossBuild = hostOnly || targetOnly 108*4882a593Smuzhiyun+ if flag.NArg() > 0 { 109*4882a593Smuzhiyun+ if crossBuild { 110*4882a593Smuzhiyun+ toBuild = flag.Args() 111*4882a593Smuzhiyun+ } else { 112*4882a593Smuzhiyun+ fatalf("package names not permitted without --host-only or --target-only\n") 113*4882a593Smuzhiyun+ } 114*4882a593Smuzhiyun+ } 115*4882a593Smuzhiyun+ 116*4882a593Smuzhiyun // Set GOPATH to an internal directory. We shouldn't actually 117*4882a593Smuzhiyun // need to store files here, since the toolchain won't 118*4882a593Smuzhiyun // depend on modules outside of vendor directories, but if 119*4882a593Smuzhiyun@@ -1345,8 +1369,13 @@ func cmdbootstrap() { 120*4882a593Smuzhiyun xprintf("\n") 121*4882a593Smuzhiyun } 122*4882a593Smuzhiyun 123*4882a593Smuzhiyun- gogcflags = os.Getenv("GO_GCFLAGS") // we were using $BOOT_GO_GCFLAGS until now 124*4882a593Smuzhiyun- goldflags = os.Getenv("GO_LDFLAGS") // we were using $BOOT_GO_LDFLAGS until now 125*4882a593Smuzhiyun+ // For split host/target cross/cross-canadian builds, we don't 126*4882a593Smuzhiyun+ // want to be setting these flags until after we have compiled 127*4882a593Smuzhiyun+ // the toolchain that runs on the build host. 128*4882a593Smuzhiyun+ if !crossBuild { 129*4882a593Smuzhiyun+ gogcflags = os.Getenv("GO_GCFLAGS") // we were using $BOOT_GO_GCFLAGS until now 130*4882a593Smuzhiyun+ goldflags = os.Getenv("GO_LDFLAGS") // we were using $BOOT_GO_LDFLAGS until now 131*4882a593Smuzhiyun+ } 132*4882a593Smuzhiyun goBootstrap := pathf("%s/go_bootstrap", tooldir) 133*4882a593Smuzhiyun cmdGo := pathf("%s/go", gobin) 134*4882a593Smuzhiyun if debug { 135*4882a593Smuzhiyun@@ -1375,7 +1404,11 @@ func cmdbootstrap() { 136*4882a593Smuzhiyun xprintf("\n") 137*4882a593Smuzhiyun } 138*4882a593Smuzhiyun xprintf("Building Go toolchain2 using go_bootstrap and Go toolchain1.\n") 139*4882a593Smuzhiyun- os.Setenv("CC", compilerEnvLookup(defaultcc, goos, goarch)) 140*4882a593Smuzhiyun+ if crossBuild { 141*4882a593Smuzhiyun+ os.Setenv("CC", defaultcc[""]) 142*4882a593Smuzhiyun+ } else { 143*4882a593Smuzhiyun+ os.Setenv("CC", compilerEnvLookup(defaultcc, goos, goarch)) 144*4882a593Smuzhiyun+ } 145*4882a593Smuzhiyun // Now that cmd/go is in charge of the build process, enable GOEXPERIMENT. 146*4882a593Smuzhiyun os.Setenv("GOEXPERIMENT", goexperiment) 147*4882a593Smuzhiyun goInstall(goBootstrap, append([]string{"-i"}, toolchain...)...) 148*4882a593Smuzhiyun@@ -1414,50 +1447,84 @@ func cmdbootstrap() { 149*4882a593Smuzhiyun } 150*4882a593Smuzhiyun checkNotStale(goBootstrap, append(toolchain, "runtime/internal/sys")...) 151*4882a593Smuzhiyun 152*4882a593Smuzhiyun- if goos == oldgoos && goarch == oldgoarch { 153*4882a593Smuzhiyun- // Common case - not setting up for cross-compilation. 154*4882a593Smuzhiyun- timelog("build", "toolchain") 155*4882a593Smuzhiyun- if vflag > 0 { 156*4882a593Smuzhiyun- xprintf("\n") 157*4882a593Smuzhiyun+ if crossBuild { 158*4882a593Smuzhiyun+ gogcflags = os.Getenv("GO_GCFLAGS") 159*4882a593Smuzhiyun+ goldflags = os.Getenv("GO_LDFLAGS") 160*4882a593Smuzhiyun+ tool_files, _ := filepath.Glob(pathf("%s/*", tooldir)) 161*4882a593Smuzhiyun+ for _, f := range tool_files { 162*4882a593Smuzhiyun+ copyfile(pathf("%s/%s", build_tooldir, filepath.Base(f)), f, writeExec) 163*4882a593Smuzhiyun+ xremove(f) 164*4882a593Smuzhiyun+ } 165*4882a593Smuzhiyun+ os.Setenv("GOTOOLDIR", build_tooldir) 166*4882a593Smuzhiyun+ goBootstrap = pathf("%s/go_bootstrap", build_tooldir) 167*4882a593Smuzhiyun+ if hostOnly { 168*4882a593Smuzhiyun+ timelog("build", "host toolchain") 169*4882a593Smuzhiyun+ if vflag > 0 { 170*4882a593Smuzhiyun+ xprintf("\n") 171*4882a593Smuzhiyun+ } 172*4882a593Smuzhiyun+ xprintf("Building %s for host, %s/%s.\n", strings.Join(toBuild, ","), goos, goarch) 173*4882a593Smuzhiyun+ goInstall(goBootstrap, toBuild...) 174*4882a593Smuzhiyun+ checkNotStale(goBootstrap, toBuild...) 175*4882a593Smuzhiyun+ // Skip cmdGo staleness checks here, since we can't necessarily run the cmdGo binary 176*4882a593Smuzhiyun+ 177*4882a593Smuzhiyun+ timelog("build", "target toolchain") 178*4882a593Smuzhiyun+ if vflag > 0 { 179*4882a593Smuzhiyun+ xprintf("\n") 180*4882a593Smuzhiyun+ } 181*4882a593Smuzhiyun+ } else if targetOnly { 182*4882a593Smuzhiyun+ goos = oldgoos 183*4882a593Smuzhiyun+ goarch = oldgoarch 184*4882a593Smuzhiyun+ os.Setenv("GOOS", goos) 185*4882a593Smuzhiyun+ os.Setenv("GOARCH", goarch) 186*4882a593Smuzhiyun+ os.Setenv("CC", compilerEnvLookup(defaultcc, goos, goarch)) 187*4882a593Smuzhiyun+ xprintf("Building %s for target, %s/%s.\n", strings.Join(toBuild, ","), goos, goarch) 188*4882a593Smuzhiyun+ goInstall(goBootstrap, toBuild...) 189*4882a593Smuzhiyun+ checkNotStale(goBootstrap, toBuild...) 190*4882a593Smuzhiyun+ // Skip cmdGo staleness checks here, since we can't run the target's cmdGo binary 191*4882a593Smuzhiyun } 192*4882a593Smuzhiyun- xprintf("Building packages and commands for %s/%s.\n", goos, goarch) 193*4882a593Smuzhiyun } else { 194*4882a593Smuzhiyun- // GOOS/GOARCH does not match GOHOSTOS/GOHOSTARCH. 195*4882a593Smuzhiyun- // Finish GOHOSTOS/GOHOSTARCH installation and then 196*4882a593Smuzhiyun- // run GOOS/GOARCH installation. 197*4882a593Smuzhiyun- timelog("build", "host toolchain") 198*4882a593Smuzhiyun- if vflag > 0 { 199*4882a593Smuzhiyun- xprintf("\n") 200*4882a593Smuzhiyun- } 201*4882a593Smuzhiyun- xprintf("Building packages and commands for host, %s/%s.\n", goos, goarch) 202*4882a593Smuzhiyun+ 203*4882a593Smuzhiyun+ if goos == oldgoos && goarch == oldgoarch { 204*4882a593Smuzhiyun+ // Common case - not setting up for cross-compilation. 205*4882a593Smuzhiyun+ timelog("build", "toolchain") 206*4882a593Smuzhiyun+ if vflag > 0 { 207*4882a593Smuzhiyun+ xprintf("\n") 208*4882a593Smuzhiyun+ } 209*4882a593Smuzhiyun+ xprintf("Building packages and commands for %s/%s.\n", goos, goarch) 210*4882a593Smuzhiyun+ } else { 211*4882a593Smuzhiyun+ // GOOS/GOARCH does not match GOHOSTOS/GOHOSTARCH. 212*4882a593Smuzhiyun+ // Finish GOHOSTOS/GOHOSTARCH installation and then 213*4882a593Smuzhiyun+ // run GOOS/GOARCH installation. 214*4882a593Smuzhiyun+ timelog("build", "host toolchain") 215*4882a593Smuzhiyun+ if vflag > 0 { 216*4882a593Smuzhiyun+ xprintf("\n") 217*4882a593Smuzhiyun+ } 218*4882a593Smuzhiyun+ xprintf("Building packages and commands for host, %s/%s.\n", goos, goarch) 219*4882a593Smuzhiyun+ goInstall(goBootstrap, "std", "cmd") 220*4882a593Smuzhiyun+ checkNotStale(goBootstrap, "std", "cmd") 221*4882a593Smuzhiyun+ checkNotStale(cmdGo, "std", "cmd") 222*4882a593Smuzhiyun+ 223*4882a593Smuzhiyun+ timelog("build", "target toolchain") 224*4882a593Smuzhiyun+ if vflag > 0 { 225*4882a593Smuzhiyun+ xprintf("\n") 226*4882a593Smuzhiyun+ } 227*4882a593Smuzhiyun+ goos = oldgoos 228*4882a593Smuzhiyun+ goarch = oldgoarch 229*4882a593Smuzhiyun+ os.Setenv("GOOS", goos) 230*4882a593Smuzhiyun+ os.Setenv("GOARCH", goarch) 231*4882a593Smuzhiyun+ os.Setenv("CC", compilerEnvLookup(defaultcc, goos, goarch)) 232*4882a593Smuzhiyun+ xprintf("Building packages and commands for target, %s/%s.\n", goos, goarch) 233*4882a593Smuzhiyun+ } 234*4882a593Smuzhiyun goInstall(goBootstrap, "std", "cmd") 235*4882a593Smuzhiyun checkNotStale(goBootstrap, "std", "cmd") 236*4882a593Smuzhiyun checkNotStale(cmdGo, "std", "cmd") 237*4882a593Smuzhiyun 238*4882a593Smuzhiyun- timelog("build", "target toolchain") 239*4882a593Smuzhiyun- if vflag > 0 { 240*4882a593Smuzhiyun- xprintf("\n") 241*4882a593Smuzhiyun+ if debug { 242*4882a593Smuzhiyun+ run("", ShowOutput|CheckExit, pathf("%s/compile", tooldir), "-V=full") 243*4882a593Smuzhiyun+ run("", ShowOutput|CheckExit, pathf("%s/buildid", tooldir), pathf("%s/pkg/%s_%s/runtime/internal/sys.a", goroot, goos, goarch)) 244*4882a593Smuzhiyun+ checkNotStale(goBootstrap, append(toolchain, "runtime/internal/sys")...) 245*4882a593Smuzhiyun+ copyfile(pathf("%s/compile4", tooldir), pathf("%s/compile", tooldir), writeExec) 246*4882a593Smuzhiyun } 247*4882a593Smuzhiyun- goos = oldgoos 248*4882a593Smuzhiyun- goarch = oldgoarch 249*4882a593Smuzhiyun- os.Setenv("GOOS", goos) 250*4882a593Smuzhiyun- os.Setenv("GOARCH", goarch) 251*4882a593Smuzhiyun- os.Setenv("CC", compilerEnvLookup(defaultcc, goos, goarch)) 252*4882a593Smuzhiyun- xprintf("Building packages and commands for target, %s/%s.\n", goos, goarch) 253*4882a593Smuzhiyun- } 254*4882a593Smuzhiyun- targets := []string{"std", "cmd"} 255*4882a593Smuzhiyun- if goos == "js" && goarch == "wasm" { 256*4882a593Smuzhiyun- // Skip the cmd tools for js/wasm. They're not usable. 257*4882a593Smuzhiyun- targets = targets[:1] 258*4882a593Smuzhiyun- } 259*4882a593Smuzhiyun- goInstall(goBootstrap, targets...) 260*4882a593Smuzhiyun- checkNotStale(goBootstrap, targets...) 261*4882a593Smuzhiyun- checkNotStale(cmdGo, targets...) 262*4882a593Smuzhiyun- if debug { 263*4882a593Smuzhiyun- run("", ShowOutput|CheckExit, pathf("%s/compile", tooldir), "-V=full") 264*4882a593Smuzhiyun- run("", ShowOutput|CheckExit, pathf("%s/buildid", tooldir), pathf("%s/pkg/%s_%s/runtime/internal/sys.a", goroot, goos, goarch)) 265*4882a593Smuzhiyun- checkNotStale(goBootstrap, append(toolchain, "runtime/internal/sys")...) 266*4882a593Smuzhiyun- copyfile(pathf("%s/compile4", tooldir), pathf("%s/compile", tooldir), writeExec) 267*4882a593Smuzhiyun } 268*4882a593Smuzhiyun 269*4882a593Smuzhiyun // Check that there are no new files in $GOROOT/bin other than 270*4882a593Smuzhiyun@@ -1474,8 +1541,11 @@ func cmdbootstrap() { 271*4882a593Smuzhiyun } 272*4882a593Smuzhiyun } 273*4882a593Smuzhiyun 274*4882a593Smuzhiyun- // Remove go_bootstrap now that we're done. 275*4882a593Smuzhiyun- xremove(pathf("%s/go_bootstrap", tooldir)) 276*4882a593Smuzhiyun+ // Except that for split host/target cross-builds, we need to 277*4882a593Smuzhiyun+ // keep it. 278*4882a593Smuzhiyun+ if !crossBuild { 279*4882a593Smuzhiyun+ xremove(pathf("%s/go_bootstrap", tooldir)) 280*4882a593Smuzhiyun+ } 281*4882a593Smuzhiyun 282*4882a593Smuzhiyun if goos == "android" { 283*4882a593Smuzhiyun // Make sure the exec wrapper will sync a fresh $GOROOT to the device. 284