]> Cypherpunks repositories - gostls13.git/commitdiff
go/build, cmd/go: don't expect gccgo to have GOROOT packages
authorIan Lance Taylor <iant@golang.org>
Fri, 4 May 2018 22:15:47 +0000 (15:15 -0700)
committerIan Lance Taylor <iant@golang.org>
Wed, 9 May 2018 16:42:20 +0000 (16:42 +0000)
When using gccgo the standard library sources are not available in
GOROOT. Don't expect them to be there. In the gccgo build, use a set
of standard library packages generated at build time.

Change-Id: Id133022604d9b7e778e73e8512f9080c61462fba
Reviewed-on: https://go-review.googlesource.com/111595
Run-TryBot: Ian Lance Taylor <iant@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Than McIntosh <thanm@google.com>
src/cmd/go/internal/test/test.go
src/go/build/build.go
src/go/build/gc.go
src/go/build/gccgo.go

index 31cb51794312edac8dd8ea54f96fa2c92178ba90..bcff5ff3b164dd3194663aeef1416bacf7062172 100644 (file)
@@ -626,6 +626,11 @@ func runTest(cmd *base.Command, args []string) {
 
                a := &work.Action{Mode: "go test -i"}
                for _, p := range load.PackagesForBuild(all) {
+                       if cfg.BuildToolchainName == "gccgo" && p.Standard {
+                               // gccgo's standard library packages
+                               // can not be reinstalled.
+                               continue
+                       }
                        a.Deps = append(a.Deps, b.CompileAction(work.ModeInstall, work.ModeInstall, p))
                }
                b.Do(a)
index ef43888fc544cf16b9d960b8dd45ee768c66869f..38380d323d244b24b630e0ca6ca2da40db4c93a1 100644 (file)
@@ -238,7 +238,7 @@ func (ctxt *Context) gopath() []string {
 // that do not exist.
 func (ctxt *Context) SrcDirs() []string {
        var all []string
-       if ctxt.GOROOT != "" {
+       if ctxt.GOROOT != "" && ctxt.Compiler != "gccgo" {
                dir := ctxt.joinPath(ctxt.GOROOT, "src")
                if ctxt.isDir(dir) {
                        all = append(all, dir)
@@ -538,7 +538,7 @@ func (ctxt *Context) Import(path string, srcDir string, mode ImportMode) (*Packa
                inTestdata := func(sub string) bool {
                        return strings.Contains(sub, "/testdata/") || strings.HasSuffix(sub, "/testdata") || strings.HasPrefix(sub, "testdata/") || sub == "testdata"
                }
-               if ctxt.GOROOT != "" {
+               if ctxt.GOROOT != "" && ctxt.Compiler != "gccgo" {
                        root := ctxt.joinPath(ctxt.GOROOT, "src")
                        if sub, ok := ctxt.hasSubdir(root, p.Dir); ok && !inTestdata(sub) {
                                p.Goroot = true
@@ -555,7 +555,7 @@ func (ctxt *Context) Import(path string, srcDir string, mode ImportMode) (*Packa
                                // We found a potential import path for dir,
                                // but check that using it wouldn't find something
                                // else first.
-                               if ctxt.GOROOT != "" {
+                               if ctxt.GOROOT != "" && ctxt.Compiler != "gccgo" {
                                        if dir := ctxt.joinPath(ctxt.GOROOT, "src", sub); ctxt.isDir(dir) {
                                                p.ConflictDir = dir
                                                goto Found
@@ -620,7 +620,7 @@ func (ctxt *Context) Import(path string, srcDir string, mode ImportMode) (*Packa
                                }
                                return false
                        }
-                       if searchVendor(ctxt.GOROOT, true) {
+                       if ctxt.Compiler != "gccgo" && searchVendor(ctxt.GOROOT, true) {
                                goto Found
                        }
                        for _, root := range gopath {
@@ -633,16 +633,24 @@ func (ctxt *Context) Import(path string, srcDir string, mode ImportMode) (*Packa
                // Determine directory from import path.
                if ctxt.GOROOT != "" {
                        dir := ctxt.joinPath(ctxt.GOROOT, "src", path)
-                       isDir := ctxt.isDir(dir)
-                       binaryOnly = !isDir && mode&AllowBinary != 0 && pkga != "" && ctxt.isFile(ctxt.joinPath(ctxt.GOROOT, pkga))
-                       if isDir || binaryOnly {
-                               p.Dir = dir
-                               p.Goroot = true
-                               p.Root = ctxt.GOROOT
-                               goto Found
+                       if ctxt.Compiler != "gccgo" {
+                               isDir := ctxt.isDir(dir)
+                               binaryOnly = !isDir && mode&AllowBinary != 0 && pkga != "" && ctxt.isFile(ctxt.joinPath(ctxt.GOROOT, pkga))
+                               if isDir || binaryOnly {
+                                       p.Dir = dir
+                                       p.Goroot = true
+                                       p.Root = ctxt.GOROOT
+                                       goto Found
+                               }
                        }
                        tried.goroot = dir
                }
+               if ctxt.Compiler == "gccgo" && isStandardPackage(path) {
+                       p.Dir = ctxt.joinPath(ctxt.GOROOT, "src", path)
+                       p.Goroot = true
+                       p.Root = ctxt.GOROOT
+                       goto Found
+               }
                for _, root := range gopath {
                        dir := ctxt.joinPath(root, "src", path)
                        isDir := ctxt.isDir(dir)
@@ -706,6 +714,11 @@ Found:
                return p, pkgerr
        }
 
+       if ctxt.Compiler == "gccgo" && p.Goroot {
+               // gccgo has no sources for GOROOT packages.
+               return p, nil
+       }
+
        dirs, err := ctxt.readDir(p.Dir)
        if err != nil {
                return p, err
index 3025cd5681591f0c2f0aaee701786be344dcdcc5..e2be2cbb1d18ff158849714caa3f19725a8ffc8f 100644 (file)
 package build
 
 import (
+       "os"
+       "os/exec"
        "path/filepath"
        "runtime"
+       "strings"
+       "sync"
 )
 
 // getToolDir returns the default value of ToolDir.
 func getToolDir() string {
        return filepath.Join(runtime.GOROOT(), "pkg/tool/"+runtime.GOOS+"_"+runtime.GOARCH)
 }
+
+// isStandardPackage is not used for the gc toolchain.
+// However, this function may be called when using `go build -compiler=gccgo`.
+func isStandardPackage(path string) bool {
+       return gccgoSearch.isStandard(path)
+}
+
+// gccgoSearch holds the gccgo search directories.
+type gccgoDirs struct {
+       once sync.Once
+       dirs []string
+}
+
+// gccgoSearch is used to check whether a gccgo package exists in the
+// standard library.
+var gccgoSearch gccgoDirs
+
+// init finds the gccgo search directories. If this fails it leaves dirs == nil.
+func (gd *gccgoDirs) init() {
+       gccgo := os.Getenv("GCCGO")
+       if gccgo == "" {
+               gccgo = "gccgo"
+       }
+       bin, err := exec.LookPath(gccgo)
+       if err != nil {
+               return
+       }
+
+       allDirs, err := exec.Command(bin, "-print-search-dirs").Output()
+       if err != nil {
+               return
+       }
+       versionB, err := exec.Command(bin, "-dumpversion").Output()
+       if err != nil {
+               return
+       }
+       version := strings.TrimSpace(string(versionB))
+       machineB, err := exec.Command(bin, "-dumpmachine").Output()
+       if err != nil {
+               return
+       }
+       machine := strings.TrimSpace(string(machineB))
+
+       dirsEntries := strings.Split(string(allDirs), "\n")
+       const prefix = "libraries: ="
+       var dirs []string
+       for _, dirEntry := range dirsEntries {
+               if strings.HasPrefix(dirEntry, prefix) {
+                       dirs = filepath.SplitList(strings.TrimPrefix(dirEntry, prefix))
+                       break
+               }
+       }
+       if len(dirs) == 0 {
+               return
+       }
+
+       var lastDirs []string
+       for _, dir := range dirs {
+               goDir := filepath.Join(dir, "go", version)
+               if fi, err := os.Stat(goDir); err == nil && fi.IsDir() {
+                       gd.dirs = append(gd.dirs, goDir)
+                       goDir = filepath.Join(goDir, machine)
+                       if fi, err = os.Stat(goDir); err == nil && fi.IsDir() {
+                               gd.dirs = append(gd.dirs, goDir)
+                       }
+               }
+               if fi, err := os.Stat(dir); err == nil && fi.IsDir() {
+                       lastDirs = append(lastDirs, dir)
+               }
+       }
+       gd.dirs = append(gd.dirs, lastDirs...)
+}
+
+// isStandard returns whether path is a standard library for gccgo.
+func (gd *gccgoDirs) isStandard(path string) bool {
+       // Quick check: if the first path component has a '.', it's not
+       // in the standard library. This skips most GOPATH directories.
+       i := strings.Index(path, "/")
+       if i < 0 {
+               i = len(path)
+       }
+       if strings.Contains(path[:i], ".") {
+               return false
+       }
+
+       if path == "unsafe" {
+               // Special case.
+               return true
+       }
+
+       gd.once.Do(gd.init)
+       if gd.dirs == nil {
+               // We couldn't find the gccgo search directories.
+               // Best guess, since the first component did not contain
+               // '.', is that this is a standard library package.
+               return true
+       }
+
+       for _, dir := range gd.dirs {
+               full := filepath.Join(dir, path)
+               pkgdir, pkg := filepath.Split(full)
+               for _, p := range [...]string{
+                       full,
+                       full + ".gox",
+                       pkgdir + "lib" + pkg + ".so",
+                       pkgdir + "lib" + pkg + ".a",
+                       full + ".o",
+               } {
+                       if fi, err := os.Stat(p); err == nil && !fi.IsDir() {
+                               return true
+                       }
+               }
+       }
+
+       return false
+}
index c6aac9aa1bc2d6fb5eec8749a220f4b69ced5036..59e089d69db2cee93077b7ea20d075389ae836c0 100644 (file)
@@ -12,3 +12,9 @@ import "runtime"
 func getToolDir() string {
        return envOr("GCCGOTOOLDIR", runtime.GCCGOTOOLDIR)
 }
+
+// isStandardPackage returns whether path names a standard library package.
+// This uses a list generated at build time.
+func isStandardPackage(path string) bool {
+       return stdpkg[path]
+}