mirror of
https://github.com/tinygo-org/tinygo.git
synced 2026-08-04 02:57:46 +00:00
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:
committed by
Ron Evans
parent
a79edf416c
commit
141a70f401
@@ -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
@@ -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 {
|
||||
|
||||
@@ -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,
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user