"go/doc"
"go/parser"
"go/token"
+ "internal/goroot"
"io"
"io/ioutil"
"log"
}
tried.goroot = dir
}
- if ctxt.Compiler == "gccgo" && isStandardPackage(path) {
+ if ctxt.Compiler == "gccgo" && goroot.IsStandardPackage(ctxt.GOROOT, ctxt.Compiler, path) {
p.Dir = ctxt.joinPath(ctxt.GOROOT, "src", path)
p.Goroot = true
p.Root = ctxt.GOROOT
"encoding/pem": {"L4"},
"encoding/xml": {"L4", "encoding"},
"flag": {"L4", "OS"},
- "go/build": {"L4", "OS", "GOPARSER"},
+ "go/build": {"L4", "OS", "GOPARSER", "internal/goroot"},
"html": {"L4"},
"image/draw": {"L4", "image/internal/imageutil"},
"image/gif": {"L4", "compress/lzw", "image/color/palette", "image/draw"},
"image/jpeg": {"L4", "image/internal/imageutil"},
"image/png": {"L4", "compress/zlib"},
"index/suffixarray": {"L4", "regexp"},
+ "internal/goroot": {"L4", "OS"},
"internal/singleflight": {"sync"},
"internal/trace": {"L4", "OS"},
"math/big": {"L4"},
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
-}
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]
-}
--- /dev/null
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build gc
+
+package goroot
+
+import (
+ "os"
+ "os/exec"
+ "path/filepath"
+ "strings"
+ "sync"
+)
+
+// IsStandardPackage returns whether path is a standard package,
+// given goroot and compiler.
+func IsStandardPackage(goroot, compiler, path string) bool {
+ switch compiler {
+ case "gc":
+ dir := filepath.Join(goroot, "src", path)
+ _, err := os.Stat(dir)
+ return err == nil
+ case "gccgo":
+ return gccgoSearch.isStandard(path)
+ default:
+ panic("unknown compiler " + compiler)
+ }
+}
+
+// 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
+}
--- /dev/null
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build gccgo
+
+package goroot
+
+import (
+ "os"
+ "path/filepath"
+)
+
+// IsStandardPackage returns whether path is a standard package,
+// given goroot and compiler.
+func IsStandardPackage(goroot, compiler, path string) bool {
+ switch compiler {
+ case "gc":
+ dir := filepath.Join(goroot, "src", path)
+ _, err := os.Stat(dir)
+ return err == nil
+ case "gccgo":
+ return stdpkg[path]
+ default:
+ panic("unknown compiler " + compiler)
+ }
+}