diff mbox series

libgo patch committed: Update go tool to match recent upstream changes

Message ID CAOyqgcW2EUJ94dU73mDWHGcLy=vk5gyLVRJZ+MpRSoY_3LxOkQ@mail.gmail.com
State New
Headers show
Series libgo patch committed: Update go tool to match recent upstream changes | expand

Commit Message

Ian Lance Taylor May 9, 2018, 9:49 p.m. UTC
Several recent changes to the master version of cmd/go improve the
gofrontend support. These changes are partially copies of existing
gofrontend differences, and partially new code. This libgo patch 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 master 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 master 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.

Bootstrapped and ran Go testsuite on x86_64-pc-linux-gnu.  Committed
to mainline.

Ian

2018-05-09  Ian Lance Taylor  <iant@golang.org>

* Makefile.am (check-go-tool): Don't copy zstdpkglist.go.
* Makefile.in: Rebuild.
diff mbox series

Patch

Index: gcc/go/gofrontend/MERGE
===================================================================
--- gcc/go/gofrontend/MERGE	(revision 260048)
+++ gcc/go/gofrontend/MERGE	(working copy)
@@ -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: libgo/Makefile.am
===================================================================
--- libgo/Makefile.am	(revision 260048)
+++ libgo/Makefile.am	(working copy)
@@ -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-l
 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_f
 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: libgo/go/cmd/go/internal/load/pkg.go
===================================================================
--- libgo/go/cmd/go/internal/load/pkg.go	(revision 260048)
+++ libgo/go/cmd/go/internal/load/pkg.go	(working copy)
@@ -223,9 +223,6 @@  func (p *Package) copyBuild(pp *build.Pa
 	// 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,
 			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, forc
 	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, forc
 	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: libgo/go/cmd/go/internal/test/test.go
===================================================================
--- libgo/go/cmd/go/internal/test/test.go	(revision 260048)
+++ libgo/go/cmd/go/internal/test/test.go	(working copy)
@@ -633,6 +633,8 @@  func runTest(cmd *base.Command, args []s
 		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 *loa
 			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: libgo/go/cmd/go/internal/work/buildid.go
===================================================================
--- libgo/go/cmd/go/internal/work/buildid.go	(revision 260048)
+++ libgo/go/cmd/go/internal/work/buildid.go	(working copy)
@@ -234,18 +234,9 @@  func (b *Builder) gccgoToolID(name, lang
 	// 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: libgo/go/cmd/go/internal/work/exec.go
===================================================================
--- libgo/go/cmd/go/internal/work/exec.go	(revision 260048)
+++ libgo/go/cmd/go/internal/work/exec.go	(working copy)
@@ -1545,6 +1545,8 @@  func joinUnambiguously(a []string) strin
 			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) erro
 
 // 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: libgo/go/go/build/build.go
===================================================================
--- libgo/go/go/build/build.go	(revision 260048)
+++ libgo/go/go/build/build.go	(working copy)
@@ -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,
 		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,
 				// 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,
 				}
 				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,
 		// 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: libgo/go/go/build/gc.go
===================================================================
--- libgo/go/go/build/gc.go	(revision 260048)
+++ libgo/go/go/build/gc.go	(working copy)
@@ -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
+}
Index: libgo/go/go/build/gccgo.go
===================================================================
--- libgo/go/go/build/gccgo.go	(revision 260048)
+++ libgo/go/go/build/gccgo.go	(working copy)
@@ -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]
+}
Index: gotools/Makefile.am
===================================================================
--- gotools/Makefile.am	(revision 260048)
+++ gotools/Makefile.am	(working copy)
@@ -232,7 +232,6 @@  check-go-tool: go$(EXEEXT) $(noinst_PROG
 	$(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/