main: make $GOROOT more robust and configurable

Check various locations that $GOROOT may live, including the location of
the go binary. But make it possible to override this autodetection by
setting GOROOT manually as an environment variable.
This commit is contained in:
Ayke van Laethem
2019-05-05 17:24:36 +02:00
committed by Ron Evans
parent a79edf416c
commit 141a70f401
4 changed files with 75 additions and 12 deletions
+7 -7
View File
@@ -9,7 +9,6 @@ import (
"go/types"
"os"
"path/filepath"
"runtime"
"strconv"
"strings"
@@ -39,7 +38,8 @@ type Config struct {
LDFlags []string // ldflags to pass to cgo
DumpSSA bool // dump Go SSA, for compiler debugging
Debug bool // add debug symbols for gdb
RootDir string // GOROOT for TinyGo
GOROOT string // GOROOT
TINYGOROOT string // GOROOT for TinyGo
GOPATH string // GOPATH, like `go env GOPATH`
BuildTags []string // build tags for TinyGo (empty means {Config.GOOS/Config.GOARCH})
}
@@ -165,9 +165,9 @@ func (c *Compiler) Compile(mainPath string) []error {
// the TinyGo root.
overlayGopath := c.GOPATH
if overlayGopath == "" {
overlayGopath = runtime.GOROOT()
overlayGopath = c.GOROOT
} else {
overlayGopath = runtime.GOROOT() + string(filepath.ListSeparator) + overlayGopath
overlayGopath = c.GOROOT + string(filepath.ListSeparator) + overlayGopath
}
wd, err := os.Getwd()
@@ -178,7 +178,7 @@ func (c *Compiler) Compile(mainPath string) []error {
Build: &build.Context{
GOARCH: c.GOARCH,
GOOS: c.GOOS,
GOROOT: runtime.GOROOT(),
GOROOT: c.GOROOT,
GOPATH: c.GOPATH,
CgoEnabled: true,
UseAllFiles: false,
@@ -188,7 +188,7 @@ func (c *Compiler) Compile(mainPath string) []error {
OverlayBuild: &build.Context{
GOARCH: c.GOARCH,
GOOS: c.GOOS,
GOROOT: c.RootDir,
GOROOT: c.TINYGOROOT,
GOPATH: overlayGopath,
CgoEnabled: true,
UseAllFiles: false,
@@ -220,7 +220,7 @@ func (c *Compiler) Compile(mainPath string) []error {
},
},
Dir: wd,
TinyGoRoot: c.RootDir,
TINYGOROOT: c.TINYGOROOT,
CFlags: c.CFlags,
}
if strings.HasSuffix(mainPath, ".go") {
+4 -4
View File
@@ -22,7 +22,7 @@ type Program struct {
fset *token.FileSet
TypeChecker types.Config
Dir string // current working directory (for error reporting)
TinyGoRoot string // root of the TinyGo installation or root of the source code
TINYGOROOT string // root of the TinyGo installation or root of the source code
CFlags []string
}
@@ -297,12 +297,12 @@ func (p *Package) parseFiles() ([]*ast.File, error) {
}
clangIncludes := ""
if len(p.CgoFiles) != 0 {
if _, err := os.Stat(filepath.Join(p.TinyGoRoot, "llvm", "tools", "clang", "lib", "Headers")); !os.IsNotExist(err) {
if _, err := os.Stat(filepath.Join(p.TINYGOROOT, "llvm", "tools", "clang", "lib", "Headers")); !os.IsNotExist(err) {
// Running from the source directory.
clangIncludes = filepath.Join(p.TinyGoRoot, "llvm", "tools", "clang", "lib", "Headers")
clangIncludes = filepath.Join(p.TINYGOROOT, "llvm", "tools", "clang", "lib", "Headers")
} else {
// Running from the installation directory.
clangIncludes = filepath.Join(p.TinyGoRoot, "lib", "clang", "include")
clangIncludes = filepath.Join(p.TINYGOROOT, "lib", "clang", "include")
}
}
for _, file := range p.CgoFiles {
+6 -1
View File
@@ -76,6 +76,10 @@ func Compile(pkgName, outpath string, spec *TargetSpec, config *BuildConfig, act
ldflags = append(ldflags, strings.Replace(flag, "{root}", root, -1))
}
goroot := getGoroot()
if goroot == "" {
return errors.New("cannot locate $GOROOT, please set it manually")
}
compilerConfig := compiler.Config{
Triple: spec.Triple,
CPU: spec.CPU,
@@ -87,7 +91,8 @@ func Compile(pkgName, outpath string, spec *TargetSpec, config *BuildConfig, act
LDFlags: ldflags,
Debug: config.debug,
DumpSSA: config.dumpSSA,
RootDir: root,
TINYGOROOT: root,
GOROOT: goroot,
GOPATH: getGopath(),
BuildTags: spec.BuildTags,
}
+58
View File
@@ -6,6 +6,7 @@ import (
"fmt"
"io"
"os"
"os/exec"
"os/user"
"path/filepath"
"runtime"
@@ -310,3 +311,60 @@ func getHomeDir() string {
}
return u.HomeDir
}
// getGoroot returns an appropriate GOROOT from various sources. If it can't be
// found, it returns an empty string.
func getGoroot() string {
goroot := os.Getenv("GOROOT")
if goroot != "" {
// An explicitly set GOROOT always has preference.
return goroot
}
// Check for the location of the 'go' binary and base GOROOT on that.
binpath, err := exec.LookPath("go")
if err == nil {
binpath, err = filepath.EvalSymlinks(binpath)
if err == nil {
goroot := filepath.Dir(filepath.Dir(binpath))
if isGoroot(goroot) {
return goroot
}
}
}
// Check what GOROOT was at compile time.
if isGoroot(runtime.GOROOT()) {
return runtime.GOROOT()
}
// Check for some standard locations, as a last resort.
var candidates []string
switch runtime.GOOS {
case "linux":
candidates = []string{
"/usr/local/go", // manually installed
"/usr/lib/go", // from the distribution
}
case "darwin":
candidates = []string{
"/usr/local/go", // manually installed
"/usr/local/opt/go/libexec", // from Homebrew
}
}
for _, candidate := range candidates {
if isGoroot(candidate) {
return candidate
}
}
// Can't find GOROOT...
return ""
}
// isGoroot checks whether the given path looks like a GOROOT.
func isGoroot(goroot string) bool {
_, err := os.Stat(filepath.Join(goroot, "src", "runtime", "internal", "sys", "zversion.go"))
return err == nil
}