mirror of https://github.com/golang/go.git
go/build, cmd/go: don't expect gccgo to have GOROOT packages
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>
This commit is contained in:
parent
814c749c8f
commit
d540da105c
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -7,11 +7,131 @@
|
|||
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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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]
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue