| // Copyright 2012 The Go Authors. All rights reserved. | |
| // Use of this source code is governed by a BSD-style | |
| // license that can be found in the LICENSE file. | |
| package main | |
| import ( | |
| "flag" | |
| "fmt" | |
| "os" | |
| "runtime" | |
| "strings" | |
| ) | |
| func usage() { | |
| xprintf(`usage: go tool dist [command] | |
| Commands are: | |
| banner print installation banner | |
| bootstrap rebuild everything | |
| clean deletes all built files | |
| env [-p] print environment (-p: include $PATH) | |
| list [-json] [-broken] list all supported platforms | |
| test [-h] run Go test(s) | |
| version print Go version | |
| All commands take -v flags to emit extra information. | |
| `) | |
| xexit(2) | |
| } | |
| // commands records the available commands. | |
| var commands = map[string]func(){ | |
| "banner": cmdbanner, | |
| "bootstrap": cmdbootstrap, | |
| "clean": cmdclean, | |
| "env": cmdenv, | |
| "list": cmdlist, | |
| "test": cmdtest, | |
| "version": cmdversion, | |
| } | |
| // main takes care of OS-specific startup and dispatches to xmain. | |
| func main() { | |
| os.Setenv("TERM", "dumb") // disable escape codes in clang errors | |
| // provide -check-armv6k first, before checking for $GOROOT so that | |
| // it is possible to run this check without having $GOROOT available. | |
| if len(os.Args) > 1 && os.Args[1] == "-check-armv6k" { | |
| useARMv6K() // might fail with SIGILL | |
| println("ARMv6K supported.") | |
| os.Exit(0) | |
| } | |
| gohostos = runtime.GOOS | |
| switch gohostos { | |
| case "aix": | |
| // uname -m doesn't work under AIX | |
| gohostarch = "ppc64" | |
| case "plan9": | |
| gohostarch = os.Getenv("objtype") | |
| if gohostarch == "" { | |
| fatalf("$objtype is unset") | |
| } | |
| case "solaris", "illumos": | |
| // Solaris and illumos systems have multi-arch userlands, and | |
| // "uname -m" reports the machine hardware name; e.g., | |
| // "i86pc" on both 32- and 64-bit x86 systems. Check for the | |
| // native (widest) instruction set on the running kernel: | |
| out := run("", CheckExit, "isainfo", "-n") | |
| if strings.Contains(out, "amd64") { | |
| gohostarch = "amd64" | |
| } | |
| if strings.Contains(out, "i386") { | |
| gohostarch = "386" | |
| } | |
| case "windows": | |
| exe = ".exe" | |
| } | |
| sysinit() | |
| if gohostarch == "" { | |
| // Default Unix system. | |
| out := run("", CheckExit, "uname", "-m") | |
| outAll := run("", CheckExit, "uname", "-a") | |
| switch { | |
| case strings.Contains(outAll, "RELEASE_ARM64"): | |
| // MacOS prints | |
| // Darwin p1.local 21.1.0 Darwin Kernel Version 21.1.0: Wed Oct 13 17:33:01 PDT 2021; root:xnu-8019.41.5~1/RELEASE_ARM64_T6000 x86_64 | |
| // on ARM64 laptops when there is an x86 parent in the | |
| // process tree. Look for the RELEASE_ARM64 to avoid being | |
| // confused into building an x86 toolchain. | |
| gohostarch = "arm64" | |
| case strings.Contains(out, "x86_64"), strings.Contains(out, "amd64"): | |
| gohostarch = "amd64" | |
| case strings.Contains(out, "86"): | |
| gohostarch = "386" | |
| if gohostos == "darwin" { | |
| // Even on 64-bit platform, some versions of macOS uname -m prints i386. | |
| // We don't support any of the OS X versions that run on 32-bit-only hardware anymore. | |
| gohostarch = "amd64" | |
| } | |
| case strings.Contains(out, "aarch64"), strings.Contains(out, "arm64"): | |
| gohostarch = "arm64" | |
| case strings.Contains(out, "arm"): | |
| gohostarch = "arm" | |
| if gohostos == "netbsd" && strings.Contains(run("", CheckExit, "uname", "-p"), "aarch64") { | |
| gohostarch = "arm64" | |
| } | |
| case strings.Contains(out, "ppc64le"): | |
| gohostarch = "ppc64le" | |
| case strings.Contains(out, "ppc64"): | |
| gohostarch = "ppc64" | |
| case strings.Contains(out, "mips64"): | |
| gohostarch = "mips64" | |
| if elfIsLittleEndian(os.Args[0]) { | |
| gohostarch = "mips64le" | |
| } | |
| case strings.Contains(out, "mips"): | |
| gohostarch = "mips" | |
| if elfIsLittleEndian(os.Args[0]) { | |
| gohostarch = "mipsle" | |
| } | |
| case strings.Contains(out, "loongarch64"): | |
| gohostarch = "loong64" | |
| case strings.Contains(out, "riscv64"): | |
| gohostarch = "riscv64" | |
| case strings.Contains(out, "s390x"): | |
| gohostarch = "s390x" | |
| case gohostos == "darwin", gohostos == "ios": | |
| if strings.Contains(run("", CheckExit, "uname", "-v"), "RELEASE_ARM64_") { | |
| gohostarch = "arm64" | |
| } | |
| case gohostos == "freebsd": | |
| if strings.Contains(run("", CheckExit, "uname", "-p"), "riscv64") { | |
| gohostarch = "riscv64" | |
| } | |
| case gohostos == "openbsd" && strings.Contains(out, "powerpc64"): | |
| gohostarch = "ppc64" | |
| default: | |
| fatalf("unknown architecture: %s", out) | |
| } | |
| } | |
| if gohostarch == "arm" || gohostarch == "mips64" || gohostarch == "mips64le" { | |
| maxbg = min(maxbg, runtime.NumCPU()) | |
| } | |
| if runtime.GOMAXPROCS(0) == 1 { | |
| maxbg = 1 | |
| } | |
| if len(os.Args) > 1 && os.Args[1] == "-check-goarm" { | |
| useVFPv1() // might fail with SIGILL | |
| println("VFPv1 OK.") | |
| useVFPv3() // might fail with SIGILL | |
| println("VFPv3 OK.") | |
| os.Exit(0) | |
| } | |
| xinit() | |
| xmain() | |
| xexit(0) | |
| } | |
| // The OS-specific main calls into the portable code here. | |
| func xmain() { | |
| if len(os.Args) < 2 { | |
| usage() | |
| } | |
| cmd := os.Args[1] | |
| os.Args = os.Args[1:] // for flag parsing during cmd | |
| flag.Usage = func() { | |
| fmt.Fprintf(os.Stderr, "usage: go tool dist %s [options]\n", cmd) | |
| flag.PrintDefaults() | |
| os.Exit(2) | |
| } | |
| if f, ok := commands[cmd]; ok { | |
| f() | |
| } else { | |
| xprintf("unknown command %s\n", cmd) | |
| usage() | |
| } | |
| } |