go/build, cmd/go: update to match recent changes to gc
authorIan Lance Taylor <iant@golang.org>
Wed, 9 May 2018 21:49:47 +0000 (21:49 +0000)
committerIan Lance Taylor <ian@gcc.gnu.org>
Wed, 9 May 2018 21:49:47 +0000 (21:49 +0000)
    Several recent changes to the gc version of cmd/go improve the
    gofrontend support. These changes are partially copies of existing
    gofrontend differences, and partially new code. This CL makes the
    gofrontend match the upstream code.

    The changes included here come from:
        https://golang.org/cl/111575
        https://golang.org/cl/111595
        https://golang.org/cl/111635
        https://golang.org/cl/111636

    For the record, the following recent gc changes are based on code
    already present in the gofrontend repo:
        https://golang.org/cl/110915
        https://golang.org/cl/111615

    For the record, a gc change, partially based on earlier gofrontend
    work, also with new gc code, was already copied to gofrontend repo in
    CL 111099:
        https://golang.org/cl/111097

    This moves the generated list of standard library packages from
    cmd/go/internal/load to go/build.

    Reviewed-on: https://go-review.googlesource.com/112475

gotools/:
* Makefile.am (check-go-tool): Don't copy zstdpkglist.go.
* Makefile.in: Rebuild.

From-SVN: r260097

13 files changed:
gcc/go/gofrontend/MERGE
gotools/ChangeLog
gotools/Makefile.am
gotools/Makefile.in
libgo/Makefile.am
libgo/Makefile.in
libgo/go/cmd/go/internal/load/pkg.go
libgo/go/cmd/go/internal/test/test.go
libgo/go/cmd/go/internal/work/buildid.go
libgo/go/cmd/go/internal/work/exec.go
libgo/go/go/build/build.go
libgo/go/go/build/gc.go
libgo/go/go/build/gccgo.go

index 05ecf265d74d02ba64809171f39bd59eeba44d16..319d2f5a49c86aa5b01f88a4a831821987d9e823 100644 (file)
@@ -1,4 +1,4 @@
-6b0355769edd9543e6c5f2270b26b140bb96e9aa
+290c93f08f4456f0552b0764e28573164e47f259
 
 The first line of this file holds the git revision number of the last
 merge done from the gofrontend repository.
index cac11df05acf3abff9115c3bce90e0de24a79563..0e671860435e87eaabd58b46e2d5d235225db32b 100644 (file)
@@ -1,3 +1,8 @@
+2018-05-09  Ian Lance Taylor  <iant@golang.org>
+
+       * Makefile.am (check-go-tool): Don't copy zstdpkglist.go.
+       * Makefile.in: Rebuild.
+
 2018-05-04  Ian Lance Taylor  <iant@golang.org>
 
        PR go/85630
index ba5f283e33f7d8a351be0811f9ce0e973f9be835..06be89d582a8afceaecf5c5f2221bb4132967ec7 100644 (file)
@@ -232,7 +232,6 @@ check-go-tool: go$(EXEEXT) $(noinst_PROGRAMS) check-head check-gccgo check-gcc
        $(MKDIR_P) check-go-dir/src/cmd/go
        cp $(cmdsrcdir)/go/*.go check-go-dir/src/cmd/go/
        cp -r $(cmdsrcdir)/go/internal check-go-dir/src/cmd/go/
-       cp $(libgodir)/zstdpkglist.go check-go-dir/src/cmd/go/internal/load/
        cp $(libgodir)/zdefaultcc.go check-go-dir/src/cmd/go/internal/cfg/
        cp -r $(cmdsrcdir)/go/testdata check-go-dir/src/cmd/go/
        cp -r $(cmdsrcdir)/internal check-go-dir/src/cmd/
index 8e60e9f26ef1492aca19cd715531caa3b1b2390e..503ec4eb446ea2bb8bb790f64801ce33435030f6 100644 (file)
@@ -637,8 +637,8 @@ distclean-generic:
 maintainer-clean-generic:
        @echo "This command is intended for maintainers to use"
        @echo "it deletes files that may require special tools to rebuild."
-@NATIVE_FALSE@install-exec-local:
 @NATIVE_FALSE@uninstall-local:
+@NATIVE_FALSE@install-exec-local:
 clean: clean-am
 
 clean-am: clean-binPROGRAMS clean-generic clean-noinstPROGRAMS \
@@ -811,7 +811,6 @@ mostlyclean-local:
 @NATIVE_TRUE@  $(MKDIR_P) check-go-dir/src/cmd/go
 @NATIVE_TRUE@  cp $(cmdsrcdir)/go/*.go check-go-dir/src/cmd/go/
 @NATIVE_TRUE@  cp -r $(cmdsrcdir)/go/internal check-go-dir/src/cmd/go/
-@NATIVE_TRUE@  cp $(libgodir)/zstdpkglist.go check-go-dir/src/cmd/go/internal/load/
 @NATIVE_TRUE@  cp $(libgodir)/zdefaultcc.go check-go-dir/src/cmd/go/internal/cfg/
 @NATIVE_TRUE@  cp -r $(cmdsrcdir)/go/testdata check-go-dir/src/cmd/go/
 @NATIVE_TRUE@  cp -r $(cmdsrcdir)/internal check-go-dir/src/cmd/
index 119d241aaaf5038d1972d17a4c82dc39b9bf6629..d847413d94cb31fb091705997f8d234b36bcef19 100644 (file)
@@ -602,13 +602,13 @@ s-runtime-inc: runtime.lo Makefile
        $(SHELL) $(srcdir)/mvifdiff.sh tmp-runtime.inc runtime.inc
        $(STAMP) $@
 
-noinst_DATA += zstdpkglist.go zdefaultcc.go
+noinst_DATA += zdefaultcc.go
 
 # Generate the list of go std packages that were included in libgo
 zstdpkglist.go: s-zstdpkglist; @true
 s-zstdpkglist: Makefile
        rm -f zstdpkglist.go.tmp
-       echo 'package load' > zstdpkglist.go.tmp
+       echo 'package build' > zstdpkglist.go.tmp
        echo "" >> zstdpkglist.go.tmp
        echo 'var stdpkg = map[string]bool{' >> zstdpkglist.go.tmp
        echo $(libgo_go_objs) 'unsafe.lo' 'runtime/cgo.lo' | sed 's|[a-z0-9_/]*_c\.lo||g' | sed 's|\([a-z0-9_/]*\)\.lo|"\1": true,|g' >> zstdpkglist.go.tmp
@@ -960,6 +960,9 @@ runtime_pprof_check_GOCFLAGS = -static-libgo -fno-inline
 extra_go_files_runtime_internal_sys = version.go
 runtime/internal/sys.lo.dep: $(extra_go_files_runtime_internal_sys)
 
+extra_go_files_go_build = zstdpkglist.go
+go/build.lo.dep: $(extra_go_files_go_build)
+
 extra_go_files_go_types = gccgosizes.go
 go/types.lo.dep: $(extra_go_files_go_types)
 
@@ -969,9 +972,6 @@ cmd/internal/objabi.lo.dep: $(extra_go_files_cmd_internal_objabi)
 extra_go_files_cmd_go_internal_cfg = zdefaultcc.go
 cmd/go/internal/cfg.lo.dep: $(extra_go_files_cmd_go_internal_cfg)
 
-extra_go_files_cmd_go_internal_load = zstdpkglist.go
-cmd/go/internal/load.lo.dep: $(extra_go_files_cmd_go_internal_load)
-
 extra_check_libs_cmd_go_internal_cache = $(abs_builddir)/libgotool.a
 extra_check_libs_cmd_go_internal_generate = $(abs_builddir)/libgotool.a
 extra_check_libs_cmd_go_internal_get = $(abs_builddir)/libgotool.a
index a30e427e118494f9667e2b67925de07e187acf50..6b3c59787018cc24d2a63537d6bca2aed39f391c 100644 (file)
@@ -759,7 +759,7 @@ noinst_DATA = golang_org/x/net/internal/nettest.gox \
        golang_org/x/net/nettest.gox internal/testenv.gox \
        internal/trace.gox net/internal/socktest.gox \
        os/signal/internal/pty.gox runtime/pprof/internal/profile.gox \
-       zstdpkglist.go zdefaultcc.go
+       zdefaultcc.go
 @LIBGO_IS_RTEMS_FALSE@rtems_task_variable_add_file = 
 @LIBGO_IS_RTEMS_TRUE@rtems_task_variable_add_file = runtime/rtems-task-variable-add.c
 @LIBGO_IS_AIX_FALSE@@LIBGO_IS_DARWIN_FALSE@@LIBGO_IS_FREEBSD_FALSE@@LIBGO_IS_IRIX_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_NETBSD_FALSE@@LIBGO_IS_SOLARIS_FALSE@runtime_getncpu_file = runtime/getncpu-none.c
@@ -999,10 +999,10 @@ runtime_internal_sys_lo_check_GOCFLAGS = -fgo-compiling-runtime
 # Also use -fno-inline to get better results from the memory profiler.
 runtime_pprof_check_GOCFLAGS = -static-libgo -fno-inline
 extra_go_files_runtime_internal_sys = version.go
+extra_go_files_go_build = zstdpkglist.go
 extra_go_files_go_types = gccgosizes.go
 extra_go_files_cmd_internal_objabi = objabi.go
 extra_go_files_cmd_go_internal_cfg = zdefaultcc.go
-extra_go_files_cmd_go_internal_load = zstdpkglist.go
 extra_check_libs_cmd_go_internal_cache = $(abs_builddir)/libgotool.a
 extra_check_libs_cmd_go_internal_generate = $(abs_builddir)/libgotool.a
 extra_check_libs_cmd_go_internal_get = $(abs_builddir)/libgotool.a
@@ -2816,7 +2816,7 @@ s-runtime-inc: runtime.lo Makefile
 zstdpkglist.go: s-zstdpkglist; @true
 s-zstdpkglist: Makefile
        rm -f zstdpkglist.go.tmp
-       echo 'package load' > zstdpkglist.go.tmp
+       echo 'package build' > zstdpkglist.go.tmp
        echo "" >> zstdpkglist.go.tmp
        echo 'var stdpkg = map[string]bool{' >> zstdpkglist.go.tmp
        echo $(libgo_go_objs) 'unsafe.lo' 'runtime/cgo.lo' | sed 's|[a-z0-9_/]*_c\.lo||g' | sed 's|\([a-z0-9_/]*\)\.lo|"\1": true,|g' >> zstdpkglist.go.tmp
@@ -2943,10 +2943,10 @@ $(foreach package,$(GOTOOL_PACKAGES),$(eval $(call PACKAGE_template,$(package)))
 runtime.lo.dep: $(extra_go_files_runtime)
 syscall.lo.dep: $(extra_go_files_syscall)
 runtime/internal/sys.lo.dep: $(extra_go_files_runtime_internal_sys)
+go/build.lo.dep: $(extra_go_files_go_build)
 go/types.lo.dep: $(extra_go_files_go_types)
 cmd/internal/objabi.lo.dep: $(extra_go_files_cmd_internal_objabi)
 cmd/go/internal/cfg.lo.dep: $(extra_go_files_cmd_go_internal_cfg)
-cmd/go/internal/load.lo.dep: $(extra_go_files_cmd_go_internal_load)
 
 # FIXME: The following C files may as well move to the runtime
 # directory and be treated like other C files.
index d3026072e09d5d2c3f50293c21c41f4d51782963..b2a757a7fc3d77a4edaca1ff6374a57ce47d730b 100644 (file)
@@ -223,9 +223,6 @@ func (p *Package) copyBuild(pp *build.Package) {
        // TODO? Target
        p.Goroot = pp.Goroot
        p.Standard = p.Goroot && p.ImportPath != "" && isStandardImportPath(p.ImportPath)
-       if cfg.BuildToolchainName == "gccgo" {
-               p.Standard = stdpkg[p.ImportPath]
-       }
        p.GoFiles = pp.GoFiles
        p.CgoFiles = pp.CgoFiles
        p.IgnoredGoFiles = pp.IgnoredGoFiles
@@ -894,13 +891,6 @@ var foldPath = make(map[string]string)
 func (p *Package) load(stk *ImportStack, bp *build.Package, err error) {
        p.copyBuild(bp)
 
-       // When using gccgo the go/build package will not be able to
-       // find a standard package. It would be nicer to not get that
-       // error, but go/build doesn't know stdpkg.
-       if cfg.BuildToolchainName == "gccgo" && err != nil && p.Standard {
-               err = nil
-       }
-
        // Decide whether p was listed on the command line.
        // Given that load is called while processing the command line,
        // you might think we could simply pass a flag down into load
@@ -1096,9 +1086,6 @@ func (p *Package) load(stk *ImportStack, bp *build.Package, err error) {
                        continue
                }
                p1 := LoadImport(path, p.Dir, p, stk, p.Internal.Build.ImportPos[path], UseVendor)
-               if cfg.BuildToolchainName == "gccgo" && p1.Standard {
-                       continue
-               }
                if p.Standard && p.Error == nil && !p1.Standard && p1.Error == nil {
                        p.Error = &PackageError{
                                ImportStack: stk.Copy(),
@@ -1610,9 +1597,6 @@ func GetTestPackagesFor(p *Package, forceTest bool) (ptest, pxtest *Package, err
        rawTestImports := str.StringList(p.TestImports)
        for i, path := range p.TestImports {
                p1 := LoadImport(path, p.Dir, p, &stk, p.Internal.Build.TestImportPos[path], UseVendor)
-               if cfg.BuildToolchainName == "gccgo" && p1.Standard {
-                       continue
-               }
                if p1.Error != nil {
                        return nil, nil, p1.Error
                }
@@ -1641,9 +1625,6 @@ func GetTestPackagesFor(p *Package, forceTest bool) (ptest, pxtest *Package, err
        rawXTestImports := str.StringList(p.XTestImports)
        for i, path := range p.XTestImports {
                p1 := LoadImport(path, p.Dir, p, &stk, p.Internal.Build.XTestImportPos[path], UseVendor)
-               if cfg.BuildToolchainName == "gccgo" && p1.Standard {
-                       continue
-               }
                if p1.Error != nil {
                        return nil, nil, p1.Error
                }
index 978547079644789cd14b3058d4451afed77e5720..dbf6eea8a9239d59742274b90ba8693192e8d202 100644 (file)
@@ -633,6 +633,8 @@ 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))
@@ -862,9 +864,6 @@ func builderTest(b *work.Builder, p *load.Package) (buildAction, runAction, prin
                        pmain.Internal.Imports = append(pmain.Internal.Imports, ptest)
                } else {
                        p1 := load.LoadImport(dep, "", nil, &stk, nil, 0)
-                       if cfg.BuildToolchainName == "gccgo" && p1.Standard {
-                               continue
-                       }
                        if p1.Error != nil {
                                return nil, nil, nil, p1.Error
                        }
index 2636128b1a7ec25e2dcdbd7fa956796776ab1e3b..6150bbb81a6a567bdfd9760944458d2285b20b59 100644 (file)
@@ -234,18 +234,9 @@ func (b *Builder) gccgoToolID(name, language string) (string, error) {
        // compile an empty file on standard input.
        cmdline := str.StringList(cfg.BuildToolexec, name, "-###", "-x", language, "-c", "-")
        cmd := exec.Command(cmdline[0], cmdline[1:]...)
-
-       // Strip any LANG or LC_ environment variables, and force
-       // LANG=C, so that we get the untranslated output.
-       var env []string
-       for _, e := range os.Environ() {
-               if !strings.HasPrefix(e, "LANG=") && !strings.HasPrefix(e, "LC_") {
-                       env = append(env, e)
-               }
-       }
-       env = append(env, "LANG=C")
-
-       cmd.Env = base.EnvForDir(cmd.Dir, env)
+       cmd.Env = base.EnvForDir(cmd.Dir, os.Environ())
+       // Force untranslated output so that we see the string "version".
+       cmd.Env = append(cmd.Env, "LC_ALL=C")
        out, err := cmd.CombinedOutput()
        if err != nil {
                return "", fmt.Errorf("%s: %v; output: %q", name, err, out)
index 40d46023f29b432820a929120649c8aa3456977a..85bdff8fb0c697c0308dde02742b5f8252a681a8 100644 (file)
@@ -1545,6 +1545,8 @@ func joinUnambiguously(a []string) string {
                        buf.WriteByte(' ')
                }
                q := strconv.Quote(s)
+               // A gccgo command line can contain -( and -).
+               // Make sure we quote them since they are special to the shell.
                if s == "" || strings.ContainsAny(s, " ()") || len(q) > len(s)+2 {
                        buf.WriteString(q)
                } else {
@@ -1585,13 +1587,17 @@ func (b *Builder) Mkdir(dir string) error {
 
 // symlink creates a symlink newname -> oldname.
 func (b *Builder) Symlink(oldname, newname string) error {
+       // It's not an error to try to recreate an existing symlink.
+       if link, err := os.Readlink(newname); err == nil && link == oldname {
+               return nil
+       }
+
        if cfg.BuildN || cfg.BuildX {
-               b.Showcmd("", "ln -sf %s %s", oldname, newname)
+               b.Showcmd("", "ln -s %s %s", oldname, newname)
                if cfg.BuildN {
                        return nil
                }
        }
-       os.Remove(newname)
        return os.Symlink(oldname, newname)
 }
 
index 4e779557942cf746fd2e21bd3880fe9842816cc7..9df4930dbcf69d6496ebd1f5406b08ac775c80b8 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)
@@ -540,7 +540,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
@@ -557,7 +557,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
@@ -622,7 +622,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 {
@@ -635,16 +635,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)
@@ -708,6 +716,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]
+}