diff --git a/builder/config.go b/builder/config.go index aabf82ac..3a83f7f7 100644 --- a/builder/config.go +++ b/builder/config.go @@ -21,7 +21,7 @@ func NewConfig(options *compileopts.Options) (*compileopts.Config, error) { if goroot == "" { return nil, errors.New("cannot locate $GOROOT, please set it manually") } - major, minor, err := getGorootVersion(goroot) + major, minor, err := goenv.GetGorootVersion(goroot) if err != nil { return nil, fmt.Errorf("could not read version from GOROOT (%v): %v", goroot, err) } diff --git a/builder/env.go b/builder/env.go index 995ad2ad..c59f5df4 100644 --- a/builder/env.go +++ b/builder/env.go @@ -1,71 +1,13 @@ package builder import ( - "errors" - "fmt" - "io" "io/ioutil" "os" "os/exec" "path/filepath" - "regexp" "sort" - "strings" ) -// getGorootVersion returns the major and minor version for a given GOROOT path. -// If the goroot cannot be determined, (0, 0) is returned. -func getGorootVersion(goroot string) (major, minor int, err error) { - s, err := GorootVersionString(goroot) - if err != nil { - return 0, 0, err - } - - if s == "" || s[:2] != "go" { - return 0, 0, errors.New("could not parse Go version: version does not start with 'go' prefix") - } - - parts := strings.Split(s[2:], ".") - if len(parts) < 2 { - return 0, 0, errors.New("could not parse Go version: version has less than two parts") - } - - // Ignore the errors, we don't really handle errors here anyway. - var trailing string - n, err := fmt.Sscanf(s, "go%d.%d%s", &major, &minor, &trailing) - if n == 2 && err == io.EOF { - // Means there were no trailing characters (i.e., not an alpha/beta) - err = nil - } - if err != nil { - return 0, 0, fmt.Errorf("failed to parse version: %s", err) - } - return -} - -// GorootVersionString returns the version string as reported by the Go -// toolchain for the given GOROOT path. It is usually of the form `go1.x.y` but -// can have some variations (for beta releases, for example). -func GorootVersionString(goroot string) (string, error) { - if data, err := ioutil.ReadFile(filepath.Join( - goroot, "src", "runtime", "internal", "sys", "zversion.go")); err == nil { - - r := regexp.MustCompile("const TheVersion = `(.*)`") - matches := r.FindSubmatch(data) - if len(matches) != 2 { - return "", errors.New("Invalid go version output:\n" + string(data)) - } - - return string(matches[1]), nil - - } else if data, err := ioutil.ReadFile(filepath.Join(goroot, "VERSION")); err == nil { - return string(data), nil - - } else { - return "", err - } -} - // getClangHeaderPath returns the path to the built-in Clang headers. It tries // multiple locations, which should make it find the directory when installed in // various ways. diff --git a/goenv/version.go b/goenv/version.go new file mode 100644 index 00000000..7c0d10f6 --- /dev/null +++ b/goenv/version.go @@ -0,0 +1,64 @@ +package goenv + +import ( + "errors" + "fmt" + "io" + "io/ioutil" + "path/filepath" + "regexp" + "strings" +) + +// GetGorootVersion returns the major and minor version for a given GOROOT path. +// If the goroot cannot be determined, (0, 0) is returned. +func GetGorootVersion(goroot string) (major, minor int, err error) { + s, err := GorootVersionString(goroot) + if err != nil { + return 0, 0, err + } + + if s == "" || s[:2] != "go" { + return 0, 0, errors.New("could not parse Go version: version does not start with 'go' prefix") + } + + parts := strings.Split(s[2:], ".") + if len(parts) < 2 { + return 0, 0, errors.New("could not parse Go version: version has less than two parts") + } + + // Ignore the errors, we don't really handle errors here anyway. + var trailing string + n, err := fmt.Sscanf(s, "go%d.%d%s", &major, &minor, &trailing) + if n == 2 && err == io.EOF { + // Means there were no trailing characters (i.e., not an alpha/beta) + err = nil + } + if err != nil { + return 0, 0, fmt.Errorf("failed to parse version: %s", err) + } + return +} + +// GorootVersionString returns the version string as reported by the Go +// toolchain for the given GOROOT path. It is usually of the form `go1.x.y` but +// can have some variations (for beta releases, for example). +func GorootVersionString(goroot string) (string, error) { + if data, err := ioutil.ReadFile(filepath.Join( + goroot, "src", "runtime", "internal", "sys", "zversion.go")); err == nil { + + r := regexp.MustCompile("const TheVersion = `(.*)`") + matches := r.FindSubmatch(data) + if len(matches) != 2 { + return "", errors.New("Invalid go version output:\n" + string(data)) + } + + return string(matches[1]), nil + + } else if data, err := ioutil.ReadFile(filepath.Join(goroot, "VERSION")); err == nil { + return string(data), nil + + } else { + return "", err + } +} diff --git a/main.go b/main.go index 1d203212..27836d1a 100644 --- a/main.go +++ b/main.go @@ -897,7 +897,7 @@ func main() { usage() case "version": goversion := "" - if s, err := builder.GorootVersionString(goenv.Get("GOROOT")); err == nil { + if s, err := goenv.GorootVersionString(goenv.Get("GOROOT")); err == nil { goversion = s } fmt.Printf("tinygo version %s %s/%s (using go version %s and LLVM version %s)\n", version, runtime.GOOS, runtime.GOARCH, goversion, llvm.Version) diff --git a/main_test.go b/main_test.go index ec7f7085..f3f10fd2 100644 --- a/main_test.go +++ b/main_test.go @@ -73,7 +73,7 @@ func TestCompiler(t *testing.T) { t.Run("ARM64Linux", func(t *testing.T) { runPlatTests("aarch64--linux-gnu", matches, t) }) - goVersion, err := builder.GorootVersionString(goenv.Get("GOROOT")) + goVersion, err := goenv.GorootVersionString(goenv.Get("GOROOT")) if err != nil { t.Error("could not get Go version:", err) return