github.com/gopherjs/gopherjs@v1.19.0-beta1.0.20240506212314-27071a8796e4/compiler/version_check.go (about) 1 //go:build go1.19 2 3 package compiler 4 5 import ( 6 "fmt" 7 "os" 8 "os/exec" 9 "path/filepath" 10 "strconv" 11 "strings" 12 ) 13 14 // Version is the GopherJS compiler version string. 15 const Version = "1.19.0-beta1+go1.19.13" 16 17 // GoVersion is the current Go 1.x version that GopherJS is compatible with. 18 const GoVersion = 19 19 20 // CheckGoVersion checks the version of the Go distribution 21 // at goroot, and reports an error if it's not compatible 22 // with this version of the GopherJS compiler. 23 func CheckGoVersion(goroot string) error { 24 if nvc, err := strconv.ParseBool(os.Getenv("GOPHERJS_SKIP_VERSION_CHECK")); err == nil && nvc { 25 return nil 26 } 27 v, err := goRootVersion(goroot) 28 if err != nil { 29 return fmt.Errorf("unable to detect Go version for %q: %w", goroot, err) 30 } 31 if !strings.HasPrefix(v, "go1."+strconv.Itoa(GoVersion)) { 32 return fmt.Errorf("GopherJS %s requires a Go 1.%d.x distribution, but found version %s", Version, GoVersion, v) 33 } 34 return nil 35 } 36 37 // goRootVersion determines the Go release for the given GOROOT installation. 38 func goRootVersion(goroot string) (string, error) { 39 if b, err := os.ReadFile(filepath.Join(goroot, "VERSION")); err == nil { 40 // Standard Go distribution has a VERSION file inside its GOROOT, 41 // checking its first line is the most efficient option. 42 v, _, _ := strings.Cut(string(b), "\n") 43 return v, nil 44 } 45 46 // Fall back to the "go version" command. 47 cmd := exec.Command(filepath.Join(goroot, "bin", "go"), "version") 48 out, err := cmd.Output() 49 if err != nil { 50 return "", fmt.Errorf("`go version` command failed: %w", err) 51 } 52 // Expected output: go version go1.18.1 linux/amd64 53 parts := strings.Split(string(out), " ") 54 if len(parts) != 4 { 55 return "", fmt.Errorf("unexpected `go version` output %q, expected 4 words", string(out)) 56 } 57 return parts[2], nil 58 } 59 60 // GoRelease does a best-effort to identify the Go release we are building with. 61 // If unable to determine the precise version for the given GOROOT, falls back 62 // to the best guess available. 63 func GoRelease(goroot string) string { 64 v, err := goRootVersion(goroot) 65 if err == nil { 66 // Prefer using the actual version of the GOROOT we are working with. 67 return v 68 } 69 70 // Use Go version GopherJS release was tested against as a fallback. By 71 // convention, it is included in the GopherJS version after the plus sign. 72 parts := strings.Split(Version, "+") 73 if len(parts) == 2 { 74 return parts[1] 75 } 76 77 // If everything else fails, return just the Go version without patch level. 78 return fmt.Sprintf("go1.%d", GoVersion) 79 }