Repository: magefile/mage
Pull request #144 (2018-09-01 13:26:21)

Use go/build from 1.11 to support modules
This updates the magefile/build code to use go/build from 1.11, which has some needed
tweaks to fully support modules

natefinch: fixes #140 

Patch:
diff --git a/build/build.go b/build-1.10/build.go
similarity index 97%
rename from build/build.go
rename to build-1.10/build.go
index 64198e6..922af7b 100644
--- a/build/build.go
+++ b/build-1.10/build.go
@@ -145,7 +145,7 @@ func (ctxt *Context) hasSubdir(root, dir string) (rel string, ok bool) {
 
 	// Try using paths we received.
 	if rel, ok = hasSubdir(root, dir); ok {
-		return rel, ok
+		return
 	}
 
 	// Try expanding symlinks and comparing
@@ -155,10 +155,10 @@ func (ctxt *Context) hasSubdir(root, dir string) (rel string, ok bool) {
 	dirSym, _ := filepath.EvalSymlinks(dir)
 
 	if rel, ok = hasSubdir(rootSym, dir); ok {
-		return rel, ok
+		return
 	}
 	if rel, ok = hasSubdir(root, dirSym); ok {
-		return rel, ok
+		return
 	}
 	return hasSubdir(rootSym, dirSym)
 }
@@ -300,7 +300,10 @@ func defaultContext() Context {
 	// say "+build go1.x", and code that should only be built before Go 1.x
 	// (perhaps it is the stub to use in that case) should say "+build !go1.x".
 	// NOTE: If you add to this list, also update the doc comment in doc.go.
-	c.ReleaseTags = []string{"go1.1", "go1.2", "go1.3", "go1.4", "go1.5", "go1.6", "go1.7", "go1.8", "go1.9"}
+	const version = 10 // go1.10
+	for i := 1; i <= version; i++ {
+		c.ReleaseTags = append(c.ReleaseTags, "go1."+strconv.Itoa(i))
+	}
 
 	env := os.Getenv("CGO_ENABLED")
 	if env == "" {
@@ -549,6 +552,7 @@ func (ctxt *Context) Import(path string, srcDir string, mode ImportMode) (*Packa
 				p.Goroot = true
 				p.ImportPath = sub
 				p.Root = ctxt.GOROOT
+				setPkga() // p.ImportPath changed
 				goto Found
 			}
 		}
@@ -576,6 +580,7 @@ func (ctxt *Context) Import(path string, srcDir string, mode ImportMode) (*Packa
 				// Record it.
 				p.ImportPath = sub
 				p.Root = root
+				setPkga() // p.ImportPath changed
 				goto Found
 			}
 		}
@@ -1052,8 +1057,7 @@ func parseWord(data []byte) (word, rest []byte) {
 // read some or all of the file's content.
 func (ctxt *Context) MatchFile(dir, name string) (match bool, err error) {
 	match, _, _, err = ctxt.matchFile(dir, name, nil, nil)
-	return match, err
-
+	return
 }
 
 // matchFile determines whether the file with the given name in the given directory
@@ -1067,7 +1071,7 @@ func (ctxt *Context) MatchFile(dir, name string) (match bool, err error) {
 func (ctxt *Context) matchFile(dir, name string, allTags map[string]bool, binaryOnly *bool) (match bool, data []byte, filename string, err error) {
 	if strings.HasPrefix(name, "_") ||
 		strings.HasPrefix(name, ".") {
-		return match, data, filename, err
+		return
 	}
 
 	i := strings.LastIndex(name, ".")
@@ -1077,7 +1081,7 @@ func (ctxt *Context) matchFile(dir, name string, allTags map[string]bool, binary
 	ext := name[i:]
 
 	if !ctxt.goodOSArchFile(name, allTags) && !ctxt.UseAllFiles {
-		return match, data, filename, err
+		return
 	}
 
 	switch ext {
@@ -1086,16 +1090,16 @@ func (ctxt *Context) matchFile(dir, name string, allTags map[string]bool, binary
 	case ".syso":
 		// binary, no reading
 		match = true
-		return match, data, filename, err
+		return
 	default:
 		// skip
-		return match, data, filename, err
+		return
 	}
 
 	filename = ctxt.joinPath(dir, name)
 	f, err := ctxt.openFile(filename)
 	if err != nil {
-		return match, data, filename, err
+		return
 	}
 
 	if strings.HasSuffix(filename, ".go") {
@@ -1110,20 +1114,20 @@ func (ctxt *Context) matchFile(dir, name string, allTags map[string]bool, binary
 	f.Close()
 	if err != nil {
 		err = fmt.Errorf("read %s: %v", filename, err)
-		return match, data, filename, err
+		return
 	}
 
 	// Look for +build comments to accept or reject the file.
 	var sawBinaryOnly bool
 	if !ctxt.shouldBuild(data, allTags, &sawBinaryOnly) && !ctxt.UseAllFiles {
-		return match, data, filename, err
+		return
 	}
 
 	if binaryOnly != nil && sawBinaryOnly {
 		*binaryOnly = true
 	}
 	match = true
-	return match, data, filename, err
+	return
 }
 
 func cleanImports(m map[string][]token.Position) ([]string, map[string][]token.Position) {
@@ -1205,33 +1209,34 @@ func (ctxt *Context) shouldBuild(content []byte, allTags map[string]bool, binary
 			p = p[len(p):]
 		}
 		line = bytes.TrimSpace(line)
-		if bytes.HasPrefix(line, slashslash) {
-			if bytes.Equal(line, binaryOnlyComment) {
-				sawBinaryOnly = true
-			}
-			line = bytes.TrimSpace(line[len(slashslash):])
-			if len(line) > 0 && line[0] == '+' {
-				// Looks like a comment +line.
-				f := strings.Fields(string(line))
-				if f[0] == "+build" {
-					ok := false
-					for _, tok := range f[1:] {
-						tags := map[string]bool{}
-						if ctxt.match(tok, tags) {
-							if containsAll(tags, ctxt.RequiredTags) {
-								ok = true
-							}
+		if !bytes.HasPrefix(line, slashslash) {
+			continue
+		}
+		if bytes.Equal(line, binaryOnlyComment) {
+			sawBinaryOnly = true
+		}
+		line = bytes.TrimSpace(line[len(slashslash):])
+		if len(line) > 0 && line[0] == '+' {
+			// Looks like a comment +line.
+			f := strings.Fields(string(line))
+			if f[0] == "+build" {
+				ok := false
+				for _, tok := range f[1:] {
+					tags := map[string]bool{}
+					if ctxt.match(tok, tags) {
+						if containsAll(tags, ctxt.RequiredTags) {
+							ok = true
 						}
-						merge(allTags, tags)
 					}
-					if !hasReq {
-						if !ok {
-							allok = false
-						}
-					} else {
-						if ok {
-							allok = true
-						}
+					merge(allTags, tags)
+				}
+				if !hasReq {
+					if !ok {
+						allok = false
+					}
+				} else {
+					if ok {
+						allok = true
 					}
 				}
 			}
@@ -1264,15 +1269,6 @@ func containsAll(m map[string]bool, vals []string) bool {
 	return true
 }
 
-func contains(list []string, s string) bool {
-	for _, l := range list {
-		if l == s {
-			return true
-		}
-	}
-	return false
-}
-
 // saveCgo saves the information from the #cgo lines in the import "C" comment.
 // These lines set CFLAGS, CPPFLAGS, CXXFLAGS and LDFLAGS and pkg-config directives
 // that affect the way cgo's C code is built.
diff --git a/build/doc.go b/build-1.10/doc.go
similarity index 99%
rename from build/doc.go
rename to build-1.10/doc.go
index 422e1a5..daa9a75 100644
--- a/build/doc.go
+++ b/build-1.10/doc.go
@@ -106,6 +106,7 @@
 //	- "go1.7", from Go version 1.7 onward
 //	- "go1.8", from Go version 1.8 onward
 //	- "go1.9", from Go version 1.9 onward
+//	- "go1.10", from Go version 1.10 onward
 //	- any additional words listed in ctxt.BuildTags
 //
 // If a file's name, after stripping the extension and a possible _test suffix,
diff --git a/build/read.go b/build-1.10/read.go
similarity index 100%
rename from build/read.go
rename to build-1.10/read.go
diff --git a/build/read_test.go b/build-1.10/read_test.go
similarity index 100%
rename from build/read_test.go
rename to build-1.10/read_test.go
diff --git a/build/syslist.go b/build-1.10/syslist.go
similarity index 100%
rename from build/syslist.go
rename to build-1.10/syslist.go
diff --git a/build/syslist_test.go b/build-1.10/syslist_test.go
similarity index 100%
rename from build/syslist_test.go
rename to build-1.10/syslist_test.go
diff --git a/build/testdata/empty/dummy b/build-1.10/testdata/empty/dummy
similarity index 100%
rename from build/testdata/empty/dummy
rename to build-1.10/testdata/empty/dummy
diff --git a/build/testdata/multi/file.go b/build-1.10/testdata/multi/file.go
similarity index 100%
rename from build/testdata/multi/file.go
rename to build-1.10/testdata/multi/file.go
diff --git a/build/testdata/multi/file_appengine.go b/build-1.10/testdata/multi/file_appengine.go
similarity index 100%
rename from build/testdata/multi/file_appengine.go
rename to build-1.10/testdata/multi/file_appengine.go
diff --git a/build/testdata/other/file/file.go b/build-1.10/testdata/other/file/file.go
similarity index 100%
rename from build/testdata/other/file/file.go
rename to build-1.10/testdata/other/file/file.go
diff --git a/build/testdata/other/main.go b/build-1.10/testdata/other/main.go
similarity index 100%
rename from build/testdata/other/main.go
rename to build-1.10/testdata/other/main.go
diff --git a/build-1.10/zcgo.go b/build-1.10/zcgo.go
new file mode 100644
index 0000000..7cb5f97
--- /dev/null
+++ b/build-1.10/zcgo.go
@@ -0,0 +1,38 @@
+// Code generated by go tool dist; DO NOT EDIT.
+
+package build
+
+const defaultCGO_ENABLED = ""
+
+var cgoEnabled = map[string]bool{
+	"android/386": true,
+	"android/amd64": true,
+	"android/arm": true,
+	"android/arm64": true,
+	"darwin/386": true,
+	"darwin/amd64": true,
+	"darwin/arm": true,
+	"darwin/arm64": true,
+	"dragonfly/amd64": true,
+	"freebsd/386": true,
+	"freebsd/amd64": true,
+	"linux/386": true,
+	"linux/amd64": true,
+	"linux/arm": true,
+	"linux/arm64": true,
+	"linux/mips": true,
+	"linux/mips64": true,
+	"linux/mips64le": true,
+	"linux/mipsle": true,
+	"linux/ppc64le": true,
+	"linux/riscv64": true,
+	"linux/s390x": true,
+	"netbsd/386": true,
+	"netbsd/amd64": true,
+	"netbsd/arm": true,
+	"openbsd/386": true,
+	"openbsd/amd64": true,
+	"solaris/amd64": true,
+	"windows/386": true,
+	"windows/amd64": true,
+}
diff --git a/build-1.11/build.go b/build-1.11/build.go
new file mode 100644
index 0000000..3141106
--- /dev/null
+++ b/build-1.11/build.go
@@ -0,0 +1,1765 @@
+// Copyright 2011 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.
+
+package build
+
+import (
+	"bytes"
+	"errors"
+	"fmt"
+	"go/ast"
+	"go/doc"
+	"go/parser"
+	"go/token"
+	"io"
+	"io/ioutil"
+	"log"
+	"os"
+	"os/exec"
+	pathpkg "path"
+	"path/filepath"
+	"runtime"
+	"sort"
+	"strconv"
+	"strings"
+	"unicode"
+	"unicode/utf8"
+)
+
+// A Context specifies the supporting context for a build.
+type Context struct {
+	GOARCH      string // target architecture
+	GOOS        string // target operating system
+	GOROOT      string // Go root
+	GOPATH      string // Go path
+	CgoEnabled  bool   // whether cgo can be used
+	UseAllFiles bool   // use files regardless of +build lines, file names
+	Compiler    string // compiler to assume when computing target paths
+
+	// RequiredTags lists tags that the must exist in a build tag in order for
+	// the file to be included in the build.  If RequiredTags is empty, no tags
+	// are required.  Note that this is mostly useful in filtering the list of
+	// files in a single directory.  Using required tags across an entire
+	// compile step will likely exclude much, if not all of the standard library
+	// files.
+	RequiredTags []string
+
+	// The build and release tags specify build constraints
+	// that should be considered satisfied when processing +build lines.
+	// Clients creating a new context may customize BuildTags, which
+	// defaults to empty, but it is usually an error to customize ReleaseTags,
+	// which defaults to the list of Go releases the current release is compatible with.
+	// In addition to the BuildTags and ReleaseTags, build constraints
+	// consider the values of GOARCH and GOOS as satisfied tags.
+	BuildTags   []string
+	ReleaseTags []string
+
+	// The install suffix specifies a suffix to use in the name of the installation
+	// directory. By default it is empty, but custom builds that need to keep
+	// their outputs separate can set InstallSuffix to do so. For example, when
+	// using the race detector, the go command uses InstallSuffix = "race", so
+	// that on a Linux/386 system, packages are written to a directory named
+	// "linux_386_race" instead of the usual "linux_386".
+	InstallSuffix string
+
+	// By default, Import uses the operating system's file system calls
+	// to read directories and files. To read from other sources,
+	// callers can set the following functions. They all have default
+	// behaviors that use the local file system, so clients need only set
+	// the functions whose behaviors they wish to change.
+
+	// JoinPath joins the sequence of path fragments into a single path.
+	// If JoinPath is nil, Import uses filepath.Join.
+	JoinPath func(elem ...string) string
+
+	// SplitPathList splits the path list into a slice of individual paths.
+	// If SplitPathList is nil, Import uses filepath.SplitList.
+	SplitPathList func(list string) []string
+
+	// IsAbsPath reports whether path is an absolute path.
+	// If IsAbsPath is nil, Import uses filepath.IsAbs.
+	IsAbsPath func(path string) bool
+
+	// IsDir reports whether the path names a directory.
+	// If IsDir is nil, Import calls os.Stat and uses the result's IsDir method.
+	IsDir func(path string) bool
+
+	// HasSubdir reports whether dir is lexically a subdirectory of
+	// root, perhaps multiple levels below. It does not try to check
+	// whether dir exists.
+	// If so, HasSubdir sets rel to a slash-separated path that
+	// can be joined to root to produce a path equivalent to dir.
+	// If HasSubdir is nil, Import uses an implementation built on
+	// filepath.EvalSymlinks.
+	HasSubdir func(root, dir string) (rel string, ok bool)
+
+	// ReadDir returns a slice of os.FileInfo, sorted by Name,
+	// describing the content of the named directory.
+	// If ReadDir is nil, Import uses ioutil.ReadDir.
+	ReadDir func(dir string) ([]os.FileInfo, error)
+
+	// OpenFile opens a file (not a directory) for reading.
+	// If OpenFile is nil, Import uses os.Open.
+	OpenFile func(path string) (io.ReadCloser, error)
+}
+
+// joinPath calls ctxt.JoinPath (if not nil) or else filepath.Join.
+func (ctxt *Context) joinPath(elem ...string) string {
+	if f := ctxt.JoinPath; f != nil {
+		return f(elem...)
+	}
+	return filepath.Join(elem...)
+}
+
+// splitPathList calls ctxt.SplitPathList (if not nil) or else filepath.SplitList.
+func (ctxt *Context) splitPathList(s string) []string {
+	if f := ctxt.SplitPathList; f != nil {
+		return f(s)
+	}
+	return filepath.SplitList(s)
+}
+
+// isAbsPath calls ctxt.IsAbsPath (if not nil) or else filepath.IsAbs.
+func (ctxt *Context) isAbsPath(path string) bool {
+	if f := ctxt.IsAbsPath; f != nil {
+		return f(path)
+	}
+	return filepath.IsAbs(path)
+}
+
+// isDir calls ctxt.IsDir (if not nil) or else uses os.Stat.
+func (ctxt *Context) isDir(path string) bool {
+	if f := ctxt.IsDir; f != nil {
+		return f(path)
+	}
+	fi, err := os.Stat(path)
+	return err == nil && fi.IsDir()
+}
+
+// hasSubdir calls ctxt.HasSubdir (if not nil) or else uses
+// the local file system to answer the question.
+func (ctxt *Context) hasSubdir(root, dir string) (rel string, ok bool) {
+	if f := ctxt.HasSubdir; f != nil {
+		return f(root, dir)
+	}
+
+	// Try using paths we received.
+	if rel, ok = hasSubdir(root, dir); ok {
+		return
+	}
+
+	// Try expanding symlinks and comparing
+	// expanded against unexpanded and
+	// expanded against expanded.
+	rootSym, _ := filepath.EvalSymlinks(root)
+	dirSym, _ := filepath.EvalSymlinks(dir)
+
+	if rel, ok = hasSubdir(rootSym, dir); ok {
+		return
+	}
+	if rel, ok = hasSubdir(root, dirSym); ok {
+		return
+	}
+	return hasSubdir(rootSym, dirSym)
+}
+
+// hasSubdir reports if dir is within root by performing lexical analysis only.
+func hasSubdir(root, dir string) (rel string, ok bool) {
+	const sep = string(filepath.Separator)
+	root = filepath.Clean(root)
+	if !strings.HasSuffix(root, sep) {
+		root += sep
+	}
+	dir = filepath.Clean(dir)
+	if !strings.HasPrefix(dir, root) {
+		return "", false
+	}
+	return filepath.ToSlash(dir[len(root):]), true
+}
+
+// readDir calls ctxt.ReadDir (if not nil) or else ioutil.ReadDir.
+func (ctxt *Context) readDir(path string) ([]os.FileInfo, error) {
+	if f := ctxt.ReadDir; f != nil {
+		return f(path)
+	}
+	return ioutil.ReadDir(path)
+}
+
+// openFile calls ctxt.OpenFile (if not nil) or else os.Open.
+func (ctxt *Context) openFile(path string) (io.ReadCloser, error) {
+	if fn := ctxt.OpenFile; fn != nil {
+		return fn(path)
+	}
+
+	f, err := os.Open(path)
+	if err != nil {
+		return nil, err // nil interface
+	}
+	return f, nil
+}
+
+// isFile determines whether path is a file by trying to open it.
+// It reuses openFile instead of adding another function to the
+// list in Context.
+func (ctxt *Context) isFile(path string) bool {
+	f, err := ctxt.openFile(path)
+	if err != nil {
+		return false
+	}
+	f.Close()
+	return true
+}
+
+// gopath returns the list of Go path directories.
+func (ctxt *Context) gopath() []string {
+	var all []string
+	for _, p := range ctxt.splitPathList(ctxt.GOPATH) {
+		if p == "" || p == ctxt.GOROOT {
+			// Empty paths are uninteresting.
+			// If the path is the GOROOT, ignore it.
+			// People sometimes set GOPATH=$GOROOT.
+			// Do not get confused by this common mistake.
+			continue
+		}
+		if strings.HasPrefix(p, "~") {
+			// Path segments starting with ~ on Unix are almost always
+			// users who have incorrectly quoted ~ while setting GOPATH,
+			// preventing it from expanding to $HOME.
+			// The situation is made more confusing by the fact that
+			// bash allows quoted ~ in $PATH (most shells do not).
+			// Do not get confused by this, and do not try to use the path.
+			// It does not exist, and printing errors about it confuses
+			// those users even more, because they think "sure ~ exists!".
+			// The go command diagnoses this situation and prints a
+			// useful error.
+			// On Windows, ~ is used in short names, such as c:\progra~1
+			// for c:\program files.
+			continue
+		}
+		all = append(all, p)
+	}
+	return all
+}
+
+// SrcDirs returns a list of package source root directories.
+// It draws from the current Go root and Go path but omits directories
+// that do not exist.
+func (ctxt *Context) SrcDirs() []string {
+	var all []string
+	if ctxt.GOROOT != "" && ctxt.Compiler != "gccgo" {
+		dir := ctxt.joinPath(ctxt.GOROOT, "src")
+		if ctxt.isDir(dir) {
+			all = append(all, dir)
+		}
+	}
+	for _, p := range ctxt.gopath() {
+		dir := ctxt.joinPath(p, "src")
+		if ctxt.isDir(dir) {
+			all = append(all, dir)
+		}
+	}
+	return all
+}
+
+// Default is the default Context for builds.
+// It uses the GOARCH, GOOS, GOROOT, and GOPATH environment variables
+// if set, or else the compiled code's GOARCH, GOOS, and GOROOT.
+var Default Context = defaultContext()
+
+func defaultGOPATH() string {
+	env := "HOME"
+	if runtime.GOOS == "windows" {
+		env = "USERPROFILE"
+	} else if runtime.GOOS == "plan9" {
+		env = "home"
+	}
+	if home := os.Getenv(env); home != "" {
+		def := filepath.Join(home, "go")
+		if filepath.Clean(def) == filepath.Clean(runtime.GOROOT()) {
+			// Don't set the default GOPATH to GOROOT,
+			// as that will trigger warnings from the go tool.
+			return ""
+		}
+		return def
+	}
+	return ""
+}
+
+var defaultReleaseTags []string
+
+func defaultContext() Context {
+	var c Context
+
+	c.GOARCH = envOr("GOARCH", runtime.GOARCH)
+	c.GOOS = envOr("GOOS", runtime.GOOS)
+	c.GOROOT = pathpkg.Clean(runtime.GOROOT())
+	c.GOPATH = envOr("GOPATH", defaultGOPATH())
+	c.Compiler = runtime.Compiler
+
+	// Each major Go release in the Go 1.x series should add a tag here.
+	// Old tags should not be removed. That is, the go1.x tag is present
+	// in all releases >= Go 1.x. Code that requires Go 1.x or later should
+	// say "+build go1.x", and code that should only be built before Go 1.x
+	// (perhaps it is the stub to use in that case) should say "+build !go1.x".
+	// NOTE: If you add to this list, also update the doc comment in doc.go.
+	const version = 11 // go1.11
+	for i := 1; i <= version; i++ {
+		c.ReleaseTags = append(c.ReleaseTags, "go1."+strconv.Itoa(i))
+	}
+
+	defaultReleaseTags = append([]string{}, c.ReleaseTags...) // our own private copy
+
+	env := os.Getenv("CGO_ENABLED")
+	if env == "" {
+		env = defaultCGO_ENABLED
+	}
+	switch env {
+	case "1":
+		c.CgoEnabled = true
+	case "0":
+		c.CgoEnabled = false
+	default:
+		// cgo must be explicitly enabled for cross compilation builds
+		if runtime.GOARCH == c.GOARCH && runtime.GOOS == c.GOOS {
+			c.CgoEnabled = cgoEnabled[c.GOOS+"/"+c.GOARCH]
+			break
+		}
+		c.CgoEnabled = false
+	}
+
+	return c
+}
+
+func envOr(name, def string) string {
+	s := os.Getenv(name)
+	if s == "" {
+		return def
+	}
+	return s
+}
+
+// An ImportMode controls the behavior of the Import method.
+type ImportMode uint
+
+const (
+	// If FindOnly is set, Import stops after locating the directory
+	// that should contain the sources for a package. It does not
+	// read any files in the directory.
+	FindOnly ImportMode = 1 << iota
+
+	// If AllowBinary is set, Import can be satisfied by a compiled
+	// package object without corresponding sources.
+	//
+	// Deprecated:
+	// The supported way to create a compiled-only package is to
+	// write source code containing a //go:binary-only-package comment at
+	// the top of the file. Such a package will be recognized
+	// regardless of this flag setting (because it has source code)
+	// and will have BinaryOnly set to true in the returned Package.
+	AllowBinary
+
+	// If ImportComment is set, parse import comments on package statements.
+	// Import returns an error if it finds a comment it cannot understand
+	// or finds conflicting comments in multiple source files.
+	// See golang.org/s/go14customimport for more information.
+	ImportComment
+
+	// By default, Import searches vendor directories
+	// that apply in the given source directory before searching
+	// the GOROOT and GOPATH roots.
+	// If an Import finds and returns a package using a vendor
+	// directory, the resulting ImportPath is the complete path
+	// to the package, including the path elements leading up
+	// to and including "vendor".
+	// For example, if Import("y", "x/subdir", 0) finds
+	// "x/vendor/y", the returned package's ImportPath is "x/vendor/y",
+	// not plain "y".
+	// See golang.org/s/go15vendor for more information.
+	//
+	// Setting IgnoreVendor ignores vendor directories.
+	//
+	// In contrast to the package's ImportPath,
+	// the returned package's Imports, TestImports, and XTestImports
+	// are always the exact import paths from the source files:
+	// Import makes no attempt to resolve or check those paths.
+	IgnoreVendor
+)
+
+// A Package describes the Go package found in a directory.
+type Package struct {
+	Dir           string   // directory containing package sources
+	Name          string   // package name
+	ImportComment string   // path in import comment on package statement
+	Doc           string   // documentation synopsis
+	ImportPath    string   // import path of package ("" if unknown)
+	Root          string   // root of Go tree where this package lives
+	SrcRoot       string   // package source root directory ("" if unknown)
+	PkgRoot       string   // package install root directory ("" if unknown)
+	PkgTargetRoot string   // architecture dependent install root directory ("" if unknown)
+	BinDir        string   // command install directory ("" if unknown)
+	Goroot        bool     // package found in Go root
+	PkgObj        string   // installed .a file
+	AllTags       []string // tags that can influence file selection in this directory
+	ConflictDir   string   // this directory shadows Dir in $GOPATH
+	BinaryOnly    bool     // cannot be rebuilt from source (has //go:binary-only-package comment)
+
+	// Source files
+	GoFiles        []string // .go source files (excluding CgoFiles, TestGoFiles, XTestGoFiles)
+	CgoFiles       []string // .go source files that import "C"
+	IgnoredGoFiles []string // .go source files ignored for this build
+	InvalidGoFiles []string // .go source files with detected problems (parse error, wrong package name, and so on)
+	CFiles         []string // .c source files
+	CXXFiles       []string // .cc, .cpp and .cxx source files
+	MFiles         []string // .m (Objective-C) source files
+	HFiles         []string // .h, .hh, .hpp and .hxx source files
+	FFiles         []string // .f, .F, .for and .f90 Fortran source files
+	SFiles         []string // .s source files
+	SwigFiles      []string // .swig files
+	SwigCXXFiles   []string // .swigcxx files
+	SysoFiles      []string // .syso system object files to add to archive
+
+	// Cgo directives
+	CgoCFLAGS    []string // Cgo CFLAGS directives
+	CgoCPPFLAGS  []string // Cgo CPPFLAGS directives
+	CgoCXXFLAGS  []string // Cgo CXXFLAGS directives
+	CgoFFLAGS    []string // Cgo FFLAGS directives
+	CgoLDFLAGS   []string // Cgo LDFLAGS directives
+	CgoPkgConfig []string // Cgo pkg-config directives
+
+	// Dependency information
+	Imports   []string                    // import paths from GoFiles, CgoFiles
+	ImportPos map[string][]token.Position // line information for Imports
+
+	// Test information
+	TestGoFiles    []string                    // _test.go files in package
+	TestImports    []string                    // import paths from TestGoFiles
+	TestImportPos  map[string][]token.Position // line information for TestImports
+	XTestGoFiles   []string                    // _test.go files outside package
+	XTestImports   []string                    // import paths from XTestGoFiles
+	XTestImportPos map[string][]token.Position // line information for XTestImports
+}
+
+// IsCommand reports whether the package is considered a
+// command to be installed (not just a library).
+// Packages named "main" are treated as commands.
+func (p *Package) IsCommand() bool {
+	return p.Name == "main"
+}
+
+// ImportDir is like Import but processes the Go package found in
+// the named directory.
+func (ctxt *Context) ImportDir(dir string, mode ImportMode) (*Package, error) {
+	return ctxt.Import(".", dir, mode)
+}
+
+// NoGoError is the error used by Import to describe a directory
+// containing no buildable Go source files. (It may still contain
+// test files, files hidden by build tags, and so on.)
+type NoGoError struct {
+	Dir string
+}
+
+func (e *NoGoError) Error() string {
+	return "no buildable Go source files in " + e.Dir
+}
+
+// MultiplePackageError describes a directory containing
+// multiple buildable Go source files for multiple packages.
+type MultiplePackageError struct {
+	Dir      string   // directory containing files
+	Packages []string // package names found
+	Files    []string // corresponding files: Files[i] declares package Packages[i]
+}
+
+func (e *MultiplePackageError) Error() string {
+	// Error string limited to two entries for compatibility.
+	return fmt.Sprintf("found packages %s (%s) and %s (%s) in %s", e.Packages[0], e.Files[0], e.Packages[1], e.Files[1], e.Dir)
+}
+
+func nameExt(name string) string {
+	i := strings.LastIndex(name, ".")
+	if i < 0 {
+		return ""
+	}
+	return name[i:]
+}
+
+// Import returns details about the Go package named by the import path,
+// interpreting local import paths relative to the srcDir directory.
+// If the path is a local import path naming a package that can be imported
+// using a standard import path, the returned package will set p.ImportPath
+// to that path.
+//
+// In the directory containing the package, .go, .c, .h, and .s files are
+// considered part of the package except for:
+//
+//	- .go files in package documentation
+//	- files starting with _ or . (likely editor temporary files)
+//	- files with build constraints not satisfied by the context
+//
+// If an error occurs, Import returns a non-nil error and a non-nil
+// *Package containing partial information.
+//
+func (ctxt *Context) Import(path string, srcDir string, mode ImportMode) (*Package, error) {
+	p := &Package{
+		ImportPath: path,
+	}
+	if path == "" {
+		return p, fmt.Errorf("import %q: invalid import path", path)
+	}
+
+	var pkgtargetroot string
+	var pkga string
+	var pkgerr error
+	suffix := ""
+	if ctxt.InstallSuffix != "" {
+		suffix = "_" + ctxt.InstallSuffix
+	}
+	switch ctxt.Compiler {
+	case "gccgo":
+		pkgtargetroot = "pkg/gccgo_" + ctxt.GOOS + "_" + ctxt.GOARCH + suffix
+	case "gc":
+		pkgtargetroot = "pkg/" + ctxt.GOOS + "_" + ctxt.GOARCH + suffix
+	default:
+		// Save error for end of function.
+		pkgerr = fmt.Errorf("import %q: unknown compiler %q", path, ctxt.Compiler)
+	}
+	setPkga := func() {
+		switch ctxt.Compiler {
+		case "gccgo":
+			dir, elem := pathpkg.Split(p.ImportPath)
+			pkga = pkgtargetroot + "/" + dir + "lib" + elem + ".a"
+		case "gc":
+			pkga = pkgtargetroot + "/" + p.ImportPath + ".a"
+		}
+	}
+	setPkga()
+
+	binaryOnly := false
+	if IsLocalImport(path) {
+		pkga = "" // local imports have no installed path
+		if srcDir == "" {
+			return p, fmt.Errorf("import %q: import relative to unknown directory", path)
+		}
+		if !ctxt.isAbsPath(path) {
+			p.Dir = ctxt.joinPath(srcDir, path)
+		}
+		// p.Dir directory may or may not exist. Gather partial information first, check if it exists later.
+		// Determine canonical import path, if any.
+		// Exclude results where the import path would include /testdata/.
+		inTestdata := func(sub string) bool {
+			return strings.Contains(sub, "/testdata/") || strings.HasSuffix(sub, "/testdata") || strings.HasPrefix(sub, "testdata/") || sub == "testdata"
+		}
+		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
+				p.ImportPath = sub
+				p.Root = ctxt.GOROOT
+				setPkga() // p.ImportPath changed
+				goto Found
+			}
+		}
+		all := ctxt.gopath()
+		for i, root := range all {
+			rootsrc := ctxt.joinPath(root, "src")
+			if sub, ok := ctxt.hasSubdir(rootsrc, p.Dir); ok && !inTestdata(sub) {
+				// We found a potential import path for dir,
+				// but check that using it wouldn't find something
+				// else first.
+				if ctxt.GOROOT != "" && ctxt.Compiler != "gccgo" {
+					if dir := ctxt.joinPath(ctxt.GOROOT, "src", sub); ctxt.isDir(dir) {
+						p.ConflictDir = dir
+						goto Found
+					}
+				}
+				for _, earlyRoot := range all[:i] {
+					if dir := ctxt.joinPath(earlyRoot, "src", sub); ctxt.isDir(dir) {
+						p.ConflictDir = dir
+						goto Found
+					}
+				}
+
+				// sub would not name some other directory instead of this one.
+				// Record it.
+				p.ImportPath = sub
+				p.Root = root
+				setPkga() // p.ImportPath changed
+				goto Found
+			}
+		}
+		// It's okay that we didn't find a root containing dir.
+		// Keep going with the information we have.
+	} else {
+		if strings.HasPrefix(path, "/") {
+			return p, fmt.Errorf("import %q: cannot import absolute path", path)
+		}
+
+		gopath := ctxt.gopath() // needed by both importGo and below; avoid computing twice
+		if err := ctxt.importGo(p, path, srcDir, mode, gopath); err == nil {
+			goto Found
+		} else if err != errNoModules {
+			return p, err
+		}
+
+		// tried records the location of unsuccessful package lookups
+		var tried struct {
+			vendor []string
+			goroot string
+			gopath []string
+		}
+
+		// Vendor directories get first chance to satisfy import.
+		if mode&IgnoreVendor == 0 && srcDir != "" {
+			searchVendor := func(root string, isGoroot bool) bool {
+				sub, ok := ctxt.hasSubdir(root, srcDir)
+				if !ok || !strings.HasPrefix(sub, "src/") || strings.Contains(sub, "/testdata/") {
+					return false
+				}
+				for {
+					vendor := ctxt.joinPath(root, sub, "vendor")
+					if ctxt.isDir(vendor) {
+						dir := ctxt.joinPath(vendor, path)
+						if ctxt.isDir(dir) && hasGoFiles(ctxt, dir) {
+							p.Dir = dir
+							p.ImportPath = strings.TrimPrefix(pathpkg.Join(sub, "vendor", path), "src/")
+							p.Goroot = isGoroot
+							p.Root = root
+							setPkga() // p.ImportPath changed
+							return true
+						}
+						tried.vendor = append(tried.vendor, dir)
+					}
+					i := strings.LastIndex(sub, "/")
+					if i < 0 {
+						break
+					}
+					sub = sub[:i]
+				}
+				return false
+			}
+			if ctxt.Compiler != "gccgo" && searchVendor(ctxt.GOROOT, true) {
+				goto Found
+			}
+			for _, root := range gopath {
+				if searchVendor(root, false) {
+					goto Found
+				}
+			}
+		}
+
+		// Determine directory from import path.
+		if ctxt.GOROOT != "" {
+			dir := ctxt.joinPath(ctxt.GOROOT, "src", path)
+			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)
+			binaryOnly = !isDir && mode&AllowBinary != 0 && pkga != "" && ctxt.isFile(ctxt.joinPath(root, pkga))
+			if isDir || binaryOnly {
+				p.Dir = dir
+				p.Root = root
+				goto Found
+			}
+			tried.gopath = append(tried.gopath, dir)
+		}
+
+		// package was not found
+		var paths []string
+		format := "\t%s (vendor tree)"
+		for _, dir := range tried.vendor {
+			paths = append(paths, fmt.Sprintf(format, dir))
+			format = "\t%s"
+		}
+		if tried.goroot != "" {
+			paths = append(paths, fmt.Sprintf("\t%s (from $GOROOT)", tried.goroot))
+		} else {
+			paths = append(paths, "\t($GOROOT not set)")
+		}
+		format = "\t%s (from $GOPATH)"
+		for _, dir := range tried.gopath {
+			paths = append(paths, fmt.Sprintf(format, dir))
+			format = "\t%s"
+		}
+		if len(tried.gopath) == 0 {
+			paths = append(paths, "\t($GOPATH not set. For more details see: 'go help gopath')")
+		}
+		return p, fmt.Errorf("cannot find package %q in any of:\n%s", path, strings.Join(paths, "\n"))
+	}
+
+Found:
+	if p.Root != "" {
+		p.SrcRoot = ctxt.joinPath(p.Root, "src")
+		p.PkgRoot = ctxt.joinPath(p.Root, "pkg")
+		p.BinDir = ctxt.joinPath(p.Root, "bin")
+		if pkga != "" {
+			p.PkgTargetRoot = ctxt.joinPath(p.Root, pkgtargetroot)
+			p.PkgObj = ctxt.joinPath(p.Root, pkga)
+		}
+	}
+
+	// If it's a local import path, by the time we get here, we still haven't checked
+	// that p.Dir directory exists. This is the right time to do that check.
+	// We can't do it earlier, because we want to gather partial information for the
+	// non-nil *Package returned when an error occurs.
+	// We need to do this before we return early on FindOnly flag.
+	if IsLocalImport(path) && !ctxt.isDir(p.Dir) {
+		// package was not found
+		return p, fmt.Errorf("cannot find package %q in:\n\t%s", path, p.Dir)
+	}
+
+	if mode&FindOnly != 0 {
+		return p, pkgerr
+	}
+	if binaryOnly && (mode&AllowBinary) != 0 {
+		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
+	}
+
+	var badGoError error
+	var Sfiles []string // files with ".S" (capital S)
+	var firstFile, firstCommentFile string
+	imported := make(map[string][]token.Position)
+	testImported := make(map[string][]token.Position)
+	xTestImported := make(map[string][]token.Position)
+	allTags := make(map[string]bool)
+	fset := token.NewFileSet()
+	for _, d := range dirs {
+		if d.IsDir() {
+			continue
+		}
+
+		name := d.Name()
+		ext := nameExt(name)
+
+		badFile := func(err error) {
+			if badGoError == nil {
+				badGoError = err
+			}
+			p.InvalidGoFiles = append(p.InvalidGoFiles, name)
+		}
+
+		match, data, filename, err := ctxt.matchFile(p.Dir, name, allTags, &p.BinaryOnly)
+		if err != nil {
+			badFile(err)
+			continue
+		}
+		if !match {
+			if ext == ".go" {
+				p.IgnoredGoFiles = append(p.IgnoredGoFiles, name)
+			}
+			continue
+		}
+
+		// Going to save the file. For non-Go files, can stop here.
+		switch ext {
+		case ".c":
+			p.CFiles = append(p.CFiles, name)
+			continue
+		case ".cc", ".cpp", ".cxx":
+			p.CXXFiles = append(p.CXXFiles, name)
+			continue
+		case ".m":
+			p.MFiles = append(p.MFiles, name)
+			continue
+		case ".h", ".hh", ".hpp", ".hxx":
+			p.HFiles = append(p.HFiles, name)
+			continue
+		case ".f", ".F", ".for", ".f90":
+			p.FFiles = append(p.FFiles, name)
+			continue
+		case ".s":
+			p.SFiles = append(p.SFiles, name)
+			continue
+		case ".S":
+			Sfiles = append(Sfiles, name)
+			continue
+		case ".swig":
+			p.SwigFiles = append(p.SwigFiles, name)
+			continue
+		case ".swigcxx":
+			p.SwigCXXFiles = append(p.SwigCXXFiles, name)
+			continue
+		case ".syso":
+			// binary objects to add to package archive
+			// Likely of the form foo_windows.syso, but
+			// the name was vetted above with goodOSArchFile.
+			p.SysoFiles = append(p.SysoFiles, name)
+			continue
+		}
+
+		pf, err := parser.ParseFile(fset, filename, data, parser.ImportsOnly|parser.ParseComments)
+		if err != nil {
+			badFile(err)
+			continue
+		}
+
+		pkg := pf.Name.Name
+		if pkg == "documentation" {
+			p.IgnoredGoFiles = append(p.IgnoredGoFiles, name)
+			continue
+		}
+
+		isTest := strings.HasSuffix(name, "_test.go")
+		isXTest := false
+		if isTest && strings.HasSuffix(pkg, "_test") {
+			isXTest = true
+			pkg = pkg[:len(pkg)-len("_test")]
+		}
+
+		if p.Name == "" {
+			p.Name = pkg
+			firstFile = name
+		} else if pkg != p.Name {
+			badFile(&MultiplePackageError{
+				Dir:      p.Dir,
+				Packages: []string{p.Name, pkg},
+				Files:    []string{firstFile, name},
+			})
+			p.InvalidGoFiles = append(p.InvalidGoFiles, name)
+		}
+		// Grab the first package comment as docs, provided it is not from a test file.
+		if pf.Doc != nil && p.Doc == "" && !isTest && !isXTest {
+			p.Doc = doc.Synopsis(pf.Doc.Text())
+		}
+
+		if mode&ImportComment != 0 {
+			qcom, line := findImportComment(data)
+			if line != 0 {
+				com, err := strconv.Unquote(qcom)
+				if err != nil {
+					badFile(fmt.Errorf("%s:%d: cannot parse import comment", filename, line))
+				} else if p.ImportComment == "" {
+					p.ImportComment = com
+					firstCommentFile = name
+				} else if p.ImportComment != com {
+					badFile(fmt.Errorf("found import comments %q (%s) and %q (%s) in %s", p.ImportComment, firstCommentFile, com, name, p.Dir))
+				}
+			}
+		}
+
+		// Record imports and information about cgo.
+		isCgo := false
+		for _, decl := range pf.Decls {
+			d, ok := decl.(*ast.GenDecl)
+			if !ok {
+				continue
+			}
+			for _, dspec := range d.Specs {
+				spec, ok := dspec.(*ast.ImportSpec)
+				if !ok {
+					continue
+				}
+				quoted := spec.Path.Value
+				path, err := strconv.Unquote(quoted)
+				if err != nil {
+					log.Panicf("%s: parser returned invalid quoted string: <%s>", filename, quoted)
+				}
+				if isXTest {
+					xTestImported[path] = append(xTestImported[path], fset.Position(spec.Pos()))
+				} else if isTest {
+					testImported[path] = append(testImported[path], fset.Position(spec.Pos()))
+				} else {
+					imported[path] = append(imported[path], fset.Position(spec.Pos()))
+				}
+				if path == "C" {
+					if isTest {
+						badFile(fmt.Errorf("use of cgo in test %s not supported", filename))
+					} else {
+						cg := spec.Doc
+						if cg == nil && len(d.Specs) == 1 {
+							cg = d.Doc
+						}
+						if cg != nil {
+							if err := ctxt.saveCgo(filename, p, cg); err != nil {
+								badFile(err)
+							}
+						}
+						isCgo = true
+					}
+				}
+			}
+		}
+		if isCgo {
+			allTags["cgo"] = true
+			if ctxt.CgoEnabled {
+				p.CgoFiles = append(p.CgoFiles, name)
+			} else {
+				p.IgnoredGoFiles = append(p.IgnoredGoFiles, name)
+			}
+		} else if isXTest {
+			p.XTestGoFiles = append(p.XTestGoFiles, name)
+		} else if isTest {
+			p.TestGoFiles = append(p.TestGoFiles, name)
+		} else {
+			p.GoFiles = append(p.GoFiles, name)
+		}
+	}
+	if badGoError != nil {
+		return p, badGoError
+	}
+	if len(p.GoFiles)+len(p.CgoFiles)+len(p.TestGoFiles)+len(p.XTestGoFiles) == 0 {
+		return p, &NoGoError{p.Dir}
+	}
+
+	for tag := range allTags {
+		p.AllTags = append(p.AllTags, tag)
+	}
+	sort.Strings(p.AllTags)
+
+	p.Imports, p.ImportPos = cleanImports(imported)
+	p.TestImports, p.TestImportPos = cleanImports(testImported)
+	p.XTestImports, p.XTestImportPos = cleanImports(xTestImported)
+
+	// add the .S files only if we are using cgo
+	// (which means gcc will compile them).
+	// The standard assemblers expect .s files.
+	if len(p.CgoFiles) > 0 {
+		p.SFiles = append(p.SFiles, Sfiles...)
+		sort.Strings(p.SFiles)
+	}
+
+	return p, pkgerr
+}
+
+var errNoModules = errors.New("not using modules")
+
+// importGo checks whether it can use the go command to find the directory for path.
+// If using the go command is not appopriate, importGo returns errNoModules.
+// Otherwise, importGo tries using the go command and reports whether that succeeded.
+// Using the go command lets build.Import and build.Context.Import find code
+// in Go modules. In the long term we want tools to use go/packages (currently golang.org/x/tools/go/packages),
+// which will also use the go command.
+// Invoking the go command here is not very efficient in that it computes information
+// about the requested package and all dependencies and then only reports about the requested package.
+// Then we reinvoke it for every dependency. But this is still better than not working at all.
+// See golang.org/issue/26504.
+func (ctxt *Context) importGo(p *Package, path, srcDir string, mode ImportMode, gopath []string) error {
+	const debugImportGo = false
+
+	// To invoke the go command, we must know the source directory,
+	// we must not being doing special things like AllowBinary or IgnoreVendor,
+	// and all the file system callbacks must be nil (we're meant to use the local file system).
+	if srcDir == "" || mode&AllowBinary != 0 || mode&IgnoreVendor != 0 ||
+		ctxt.JoinPath != nil || ctxt.SplitPathList != nil || ctxt.IsAbsPath != nil || ctxt.IsDir != nil || ctxt.HasSubdir != nil || ctxt.ReadDir != nil || ctxt.OpenFile != nil || !equal(ctxt.ReleaseTags, defaultReleaseTags) {
+		return errNoModules
+	}
+
+	// If modules are not enabled, then the in-process code works fine and we should keep using it.
+	switch os.Getenv("GO111MODULE") {
+	case "off":
+		return errNoModules
+	case "on":
+		// ok
+	default: // "", "auto", anything else
+		// Automatic mode: no module use in $GOPATH/src.
+		for _, root := range gopath {
+			sub, ok := ctxt.hasSubdir(root, srcDir)
+			if ok && strings.HasPrefix(sub, "src/") {
+				return errNoModules
+			}
+		}
+	}
+
+	// For efficiency, if path is a standard library package, let the usual lookup code handle it.
+	if ctxt.GOROOT != "" {
+		dir := ctxt.joinPath(ctxt.GOROOT, "src", path)
+		if ctxt.isDir(dir) {
+			return errNoModules
+		}
+	}
+
+	// Look to see if there is a go.mod.
+	abs, err := filepath.Abs(srcDir)
+	if err != nil {
+		return errNoModules
+	}
+	for {
+		info, err := os.Stat(filepath.Join(abs, "go.mod"))
+		if err == nil && !info.IsDir() {
+			break
+		}
+		d := filepath.Dir(abs)
+		if len(d) >= len(abs) {
+			return errNoModules // reached top of file system, no go.mod
+		}
+		abs = d
+	}
+
+	cmd := exec.Command("go", "list", "-compiler="+ctxt.Compiler, "-tags="+strings.Join(ctxt.BuildTags, ","), "-installsuffix="+ctxt.InstallSuffix, "-f={{.Dir}}\n{{.ImportPath}}\n{{.Root}}\n{{.Goroot}}\n", path)
+	cmd.Dir = srcDir
+	var stdout, stderr bytes.Buffer
+	cmd.Stdout = &stdout
+	cmd.Stderr = &stderr
+
+	cgo := "0"
+	if ctxt.CgoEnabled {
+		cgo = "1"
+	}
+	cmd.Env = append(os.Environ(),
+		"GOOS="+ctxt.GOOS,
+		"GOARCH="+ctxt.GOARCH,
+		"GOROOT="+ctxt.GOROOT,
+		"GOPATH="+ctxt.GOPATH,
+		"CGO_ENABLED="+cgo,
+	)
+
+	if err := cmd.Run(); err != nil {
+		return fmt.Errorf("go/build: importGo %s: %v\n%s\n", path, err, stderr.String())
+	}
+
+	f := strings.Split(stdout.String(), "\n")
+	if len(f) != 5 || f[4] != "" {
+		return fmt.Errorf("go/build: importGo %s: unexpected output:\n%s\n", path, stdout.String())
+	}
+
+	p.Dir = f[0]
+	p.ImportPath = f[1]
+	p.Root = f[2]
+	p.Goroot = f[3] == "true"
+	return nil
+}
+
+func equal(x, y []string) bool {
+	if len(x) != len(y) {
+		return false
+	}
+	for i, xi := range x {
+		if xi != y[i] {
+			return false
+		}
+	}
+	return true
+}
+
+// hasGoFiles reports whether dir contains any files with names ending in .go.
+// For a vendor check we must exclude directories that contain no .go files.
+// Otherwise it is not possible to vendor just a/b/c and still import the
+// non-vendored a/b. See golang.org/issue/13832.
+func hasGoFiles(ctxt *Context, dir string) bool {
+	ents, _ := ctxt.readDir(dir)
+	for _, ent := range ents {
+		if !ent.IsDir() && strings.HasSuffix(ent.Name(), ".go") {
+			return true
+		}
+	}
+	return false
+}
+
+func findImportComment(data []byte) (s string, line int) {
+	// expect keyword package
+	word, data := parseWord(data)
+	if string(word) != "package" {
+		return "", 0
+	}
+
+	// expect package name
+	_, data = parseWord(data)
+
+	// now ready for import comment, a // or /* */ comment
+	// beginning and ending on the current line.
+	for len(data) > 0 && (data[0] == ' ' || data[0] == '\t' || data[0] == '\r') {
+		data = data[1:]
+	}
+
+	var comment []byte
+	switch {
+	case bytes.HasPrefix(data, slashSlash):
+		i := bytes.Index(data, newline)
+		if i < 0 {
+			i = len(data)
+		}
+		comment = data[2:i]
+	case bytes.HasPrefix(data, slashStar):
+		data = data[2:]
+		i := bytes.Index(data, starSlash)
+		if i < 0 {
+			// malformed comment
+			return "", 0
+		}
+		comment = data[:i]
+		if bytes.Contains(comment, newline) {
+			return "", 0
+		}
+	}
+	comment = bytes.TrimSpace(comment)
+
+	// split comment into `import`, `"pkg"`
+	word, arg := parseWord(comment)
+	if string(word) != "import" {
+		return "", 0
+	}
+
+	line = 1 + bytes.Count(data[:cap(data)-cap(arg)], newline)
+	return strings.TrimSpace(string(arg)), line
+}
+
+var (
+	slashSlash = []byte("//")
+	slashStar  = []byte("/*")
+	starSlash  = []byte("*/")
+	newline    = []byte("\n")
+)
+
+// skipSpaceOrComment returns data with any leading spaces or comments removed.
+func skipSpaceOrComment(data []byte) []byte {
+	for len(data) > 0 {
+		switch data[0] {
+		case ' ', '\t', '\r', '\n':
+			data = data[1:]
+			continue
+		case '/':
+			if bytes.HasPrefix(data, slashSlash) {
+				i := bytes.Index(data, newline)
+				if i < 0 {
+					return nil
+				}
+				data = data[i+1:]
+				continue
+			}
+			if bytes.HasPrefix(data, slashStar) {
+				data = data[2:]
+				i := bytes.Index(data, starSlash)
+				if i < 0 {
+					return nil
+				}
+				data = data[i+2:]
+				continue
+			}
+		}
+		break
+	}
+	return data
+}
+
+// parseWord skips any leading spaces or comments in data
+// and then parses the beginning of data as an identifier or keyword,
+// returning that word and what remains after the word.
+func parseWord(data []byte) (word, rest []byte) {
+	data = skipSpaceOrComment(data)
+
+	// Parse past leading word characters.
+	rest = data
+	for {
+		r, size := utf8.DecodeRune(rest)
+		if unicode.IsLetter(r) || '0' <= r && r <= '9' || r == '_' {
+			rest = rest[size:]
+			continue
+		}
+		break
+	}
+
+	word = data[:len(data)-len(rest)]
+	if len(word) == 0 {
+		return nil, nil
+	}
+
+	return word, rest
+}
+
+// MatchFile reports whether the file with the given name in the given directory
+// matches the context and would be included in a Package created by ImportDir
+// of that directory.
+//
+// MatchFile considers the name of the file and may use ctxt.OpenFile to
+// read some or all of the file's content.
+func (ctxt *Context) MatchFile(dir, name string) (match bool, err error) {
+	match, _, _, err = ctxt.matchFile(dir, name, nil, nil)
+	return
+}
+
+// matchFile determines whether the file with the given name in the given directory
+// should be included in the package being constructed.
+// It returns the data read from the file.
+// If name denotes a Go program, matchFile reads until the end of the
+// imports (and returns that data) even though it only considers text
+// until the first non-comment.
+// If allTags is non-nil, matchFile records any encountered build tag
+// by setting allTags[tag] = true.
+func (ctxt *Context) matchFile(dir, name string, allTags map[string]bool, binaryOnly *bool) (match bool, data []byte, filename string, err error) {
+	if strings.HasPrefix(name, "_") ||
+		strings.HasPrefix(name, ".") {
+		return
+	}
+
+	i := strings.LastIndex(name, ".")
+	if i < 0 {
+		i = len(name)
+	}
+	ext := name[i:]
+
+	if !ctxt.goodOSArchFile(name, allTags) && !ctxt.UseAllFiles {
+		return
+	}
+
+	switch ext {
+	case ".go", ".c", ".cc", ".cxx", ".cpp", ".m", ".s", ".h", ".hh", ".hpp", ".hxx", ".f", ".F", ".f90", ".S", ".swig", ".swigcxx":
+		// tentatively okay - read to make sure
+	case ".syso":
+		// binary, no reading
+		match = true
+		return
+	default:
+		// skip
+		return
+	}
+
+	filename = ctxt.joinPath(dir, name)
+	f, err := ctxt.openFile(filename)
+	if err != nil {
+		return
+	}
+
+	if strings.HasSuffix(filename, ".go") {
+		data, err = readImports(f, false, nil)
+		if strings.HasSuffix(filename, "_test.go") {
+			binaryOnly = nil // ignore //go:binary-only-package comments in _test.go files
+		}
+	} else {
+		binaryOnly = nil // ignore //go:binary-only-package comments in non-Go sources
+		data, err = readComments(f)
+	}
+	f.Close()
+	if err != nil {
+		err = fmt.Errorf("read %s: %v", filename, err)
+		return
+	}
+
+	// Look for +build comments to accept or reject the file.
+	var sawBinaryOnly bool
+	if !ctxt.shouldBuild(data, allTags, &sawBinaryOnly) && !ctxt.UseAllFiles {
+		return
+	}
+
+	if binaryOnly != nil && sawBinaryOnly {
+		*binaryOnly = true
+	}
+	match = true
+	return
+}
+
+func cleanImports(m map[string][]token.Position) ([]string, map[string][]token.Position) {
+	all := make([]string, 0, len(m))
+	for path := range m {
+		all = append(all, path)
+	}
+	sort.Strings(all)
+	return all, m
+}
+
+// Import is shorthand for Default.Import.
+func Import(path, srcDir string, mode ImportMode) (*Package, error) {
+	return Default.Import(path, srcDir, mode)
+}
+
+// ImportDir is shorthand for Default.ImportDir.
+func ImportDir(dir string, mode ImportMode) (*Package, error) {
+	return Default.ImportDir(dir, mode)
+}
+
+var slashslash = []byte("//")
+
+// Special comment denoting a binary-only package.
+// See https://golang.org/design/2775-binary-only-packages
+// for more about the design of binary-only packages.
+var binaryOnlyComment = []byte("//go:binary-only-package")
+
+// shouldBuild reports whether it is okay to use this file,
+// The rule is that in the file's leading run of // comments
+// and blank lines, which must be followed by a blank line
+// (to avoid including a Go package clause doc comment),
+// lines beginning with '// +build' are taken as build directives.
+//
+// The file is accepted only if each such line lists something
+// matching the file. For example:
+//
+//	// +build windows linux
+//
+// marks the file as applicable only on Windows and Linux.
+//
+// If shouldBuild finds a //go:binary-only-package comment in the file,
+// it sets *binaryOnly to true. Otherwise it does not change *binaryOnly.
+//
+func (ctxt *Context) shouldBuild(content []byte, allTags map[string]bool, binaryOnly *bool) bool {
+	sawBinaryOnly := false
+
+	// Pass 1. Identify leading run of // comments and blank lines,
+	// which must be followed by a blank line.
+	end := 0
+	p := content
+	for len(p) > 0 {
+		line := p
+		if i := bytes.IndexByte(line, '\n'); i >= 0 {
+			line, p = line[:i], p[i+1:]
+		} else {
+			p = p[len(p):]
+		}
+		line = bytes.TrimSpace(line)
+		if len(line) == 0 { // Blank line
+			end = len(content) - len(p)
+			continue
+		}
+		if !bytes.HasPrefix(line, slashslash) { // Not comment line
+			break
+		}
+	}
+	content = content[:end]
+
+	// Pass 2.  Process each line in the run.
+	p = content
+	hasReq := len(ctxt.RequiredTags) > 0
+	allok := !hasReq
+	for len(p) > 0 {
+		line := p
+		if i := bytes.IndexByte(line, '\n'); i >= 0 {
+			line, p = line[:i], p[i+1:]
+		} else {
+			p = p[len(p):]
+		}
+		line = bytes.TrimSpace(line)
+		if !bytes.HasPrefix(line, slashslash) {
+			continue
+		}
+		if bytes.Equal(line, binaryOnlyComment) {
+			sawBinaryOnly = true
+		}
+		line = bytes.TrimSpace(line[len(slashslash):])
+		if len(line) > 0 && line[0] == '+' {
+			// Looks like a comment +line.
+			f := strings.Fields(string(line))
+			if f[0] == "+build" {
+				ok := false
+				for _, tok := range f[1:] {
+					tags := map[string]bool{}
+					if ctxt.match(tok, tags) {
+						if containsAll(tags, ctxt.RequiredTags) {
+							ok = true
+						}
+					}
+					merge(allTags, tags)
+				}
+				if !hasReq {
+					if !ok {
+						allok = false
+					}
+				} else {
+					if ok {
+						allok = true
+					}
+				}
+			}
+		}
+	}
+
+	if binaryOnly != nil && sawBinaryOnly {
+		*binaryOnly = true
+	}
+
+	return allok
+}
+
+func merge(to, from map[string]bool) {
+	if to == nil {
+		return
+	}
+	for k, v := range from {
+		to[k] = v
+	}
+}
+
+func containsAll(m map[string]bool, vals []string) bool {
+	// yes this is N^2,  but N is small.
+	for _, v := range vals {
+		if !m[v] {
+			return false
+		}
+	}
+	return true
+}
+
+// saveCgo saves the information from the #cgo lines in the import "C" comment.
+// These lines set CFLAGS, CPPFLAGS, CXXFLAGS and LDFLAGS and pkg-config directives
+// that affect the way cgo's C code is built.
+func (ctxt *Context) saveCgo(filename string, di *Package, cg *ast.CommentGroup) error {
+	text := cg.Text()
+	for _, line := range strings.Split(text, "\n") {
+		orig := line
+
+		// Line is
+		//	#cgo [GOOS/GOARCH...] LDFLAGS: stuff
+		//
+		line = strings.TrimSpace(line)
+		if len(line) < 5 || line[:4] != "#cgo" || (line[4] != ' ' && line[4] != '\t') {
+			continue
+		}
+
+		// Split at colon.
+		line = strings.TrimSpace(line[4:])
+		i := strings.Index(line, ":")
+		if i < 0 {
+			return fmt.Errorf("%s: invalid #cgo line: %s", filename, orig)
+		}
+		line, argstr := line[:i], line[i+1:]
+
+		// Parse GOOS/GOARCH stuff.
+		f := strings.Fields(line)
+		if len(f) < 1 {
+			return fmt.Errorf("%s: invalid #cgo line: %s", filename, orig)
+		}
+
+		cond, verb := f[:len(f)-1], f[len(f)-1]
+		if len(cond) > 0 {
+			ok := false
+			for _, c := range cond {
+				if ctxt.match(c, nil) {
+					ok = true
+					break
+				}
+			}
+			if !ok {
+				continue
+			}
+		}
+
+		args, err := splitQuoted(argstr)
+		if err != nil {
+			return fmt.Errorf("%s: invalid #cgo line: %s", filename, orig)
+		}
+		var ok bool
+		for i, arg := range args {
+			if arg, ok = expandSrcDir(arg, di.Dir); !ok {
+				return fmt.Errorf("%s: malformed #cgo argument: %s", filename, arg)
+			}
+			args[i] = arg
+		}
+
+		switch verb {
+		case "CFLAGS", "CPPFLAGS", "CXXFLAGS", "FFLAGS", "LDFLAGS":
+			// Change relative paths to absolute.
+			ctxt.makePathsAbsolute(args, di.Dir)
+		}
+
+		switch verb {
+		case "CFLAGS":
+			di.CgoCFLAGS = append(di.CgoCFLAGS, args...)
+		case "CPPFLAGS":
+			di.CgoCPPFLAGS = append(di.CgoCPPFLAGS, args...)
+		case "CXXFLAGS":
+			di.CgoCXXFLAGS = append(di.CgoCXXFLAGS, args...)
+		case "FFLAGS":
+			di.CgoFFLAGS = append(di.CgoFFLAGS, args...)
+		case "LDFLAGS":
+			di.CgoLDFLAGS = append(di.CgoLDFLAGS, args...)
+		case "pkg-config":
+			di.CgoPkgConfig = append(di.CgoPkgConfig, args...)
+		default:
+			return fmt.Errorf("%s: invalid #cgo verb: %s", filename, orig)
+		}
+	}
+	return nil
+}
+
+// expandSrcDir expands any occurrence of ${SRCDIR}, making sure
+// the result is safe for the shell.
+func expandSrcDir(str string, srcdir string) (string, bool) {
+	// "\" delimited paths cause safeCgoName to fail
+	// so convert native paths with a different delimiter
+	// to "/" before starting (eg: on windows).
+	srcdir = filepath.ToSlash(srcdir)
+
+	chunks := strings.Split(str, "${SRCDIR}")
+	if len(chunks) < 2 {
+		return str, safeCgoName(str)
+	}
+	ok := true
+	for _, chunk := range chunks {
+		ok = ok && (chunk == "" || safeCgoName(chunk))
+	}
+	ok = ok && (srcdir == "" || safeCgoName(srcdir))
+	res := strings.Join(chunks, srcdir)
+	return res, ok && res != ""
+}
+
+// makePathsAbsolute looks for compiler options that take paths and
+// makes them absolute. We do this because through the 1.8 release we
+// ran the compiler in the package directory, so any relative -I or -L
+// options would be relative to that directory. In 1.9 we changed to
+// running the compiler in the build directory, to get consistent
+// build results (issue #19964). To keep builds working, we change any
+// relative -I or -L options to be absolute.
+//
+// Using filepath.IsAbs and filepath.Join here means the results will be
+// different on different systems, but that's OK: -I and -L options are
+// inherently system-dependent.
+func (ctxt *Context) makePathsAbsolute(args []string, srcDir string) {
+	nextPath := false
+	for i, arg := range args {
+		if nextPath {
+			if !filepath.IsAbs(arg) {
+				args[i] = filepath.Join(srcDir, arg)
+			}
+			nextPath = false
+		} else if strings.HasPrefix(arg, "-I") || strings.HasPrefix(arg, "-L") {
+			if len(arg) == 2 {
+				nextPath = true
+			} else {
+				if !filepath.IsAbs(arg[2:]) {
+					args[i] = arg[:2] + filepath.Join(srcDir, arg[2:])
+				}
+			}
+		}
+	}
+}
+
+// NOTE: $ is not safe for the shell, but it is allowed here because of linker options like -Wl,$ORIGIN.
+// We never pass these arguments to a shell (just to programs we construct argv for), so this should be okay.
+// See golang.org/issue/6038.
+// The @ is for OS X. See golang.org/issue/13720.
+// The % is for Jenkins. See golang.org/issue/16959.
+// The ! is because module paths may use them. See golang.org/issue/26716.
+const safeString = "+-.,/0123456789=ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz:$@%! "
+
+func safeCgoName(s string) bool {
+	if s == "" {
+		return false
+	}
+	for i := 0; i < len(s); i++ {
+		if c := s[i]; c < utf8.RuneSelf && strings.IndexByte(safeString, c) < 0 {
+			return false
+		}
+	}
+	return true
+}
+
+// splitQuoted splits the string s around each instance of one or more consecutive
+// white space characters while taking into account quotes and escaping, and
+// returns an array of substrings of s or an empty list if s contains only white space.
+// Single quotes and double quotes are recognized to prevent splitting within the
+// quoted region, and are removed from the resulting substrings. If a quote in s
+// isn't closed err will be set and r will have the unclosed argument as the
+// last element. The backslash is used for escaping.
+//
+// For example, the following string:
+//
+//     a b:"c d" 'e''f'  "g\""
+//
+// Would be parsed as:
+//
+//     []string{"a", "b:c d", "ef", `g"`}
+//
+func splitQuoted(s string) (r []string, err error) {
+	var args []string
+	arg := make([]rune, len(s))
+	escaped := false
+	quoted := false
+	quote := '\x00'
+	i := 0
+	for _, rune := range s {
+		switch {
+		case escaped:
+			escaped = false
+		case rune == '\\':
+			escaped = true
+			continue
+		case quote != '\x00':
+			if rune == quote {
+				quote = '\x00'
+				continue
+			}
+		case rune == '"' || rune == '\'':
+			quoted = true
+			quote = rune
+			continue
+		case unicode.IsSpace(rune):
+			if quoted || i > 0 {
+				quoted = false
+				args = append(args, string(arg[:i]))
+				i = 0
+			}
+			continue
+		}
+		arg[i] = rune
+		i++
+	}
+	if quoted || i > 0 {
+		args = append(args, string(arg[:i]))
+	}
+	if quote != 0 {
+		err = errors.New("unclosed quote")
+	} else if escaped {
+		err = errors.New("unfinished escaping")
+	}
+	return args, err
+}
+
+// match reports whether the name is one of:
+//
+//	$GOOS
+//	$GOARCH
+//	cgo (if cgo is enabled)
+//	!cgo (if cgo is disabled)
+//	ctxt.Compiler
+//	!ctxt.Compiler
+//	tag (if tag is listed in ctxt.BuildTags or ctxt.ReleaseTags)
+//	!tag (if tag is not listed in ctxt.BuildTags or ctxt.ReleaseTags)
+//	a comma-separated list of any of these
+//
+func (ctxt *Context) match(name string, allTags map[string]bool) bool {
+	if name == "" {
+		if allTags != nil {
+			allTags[name] = true
+		}
+		return false
+	}
+	if i := strings.Index(name, ","); i >= 0 {
+		// comma-separated list
+		ok1 := ctxt.match(name[:i], allTags)
+		ok2 := ctxt.match(name[i+1:], allTags)
+		return ok1 && ok2
+	}
+	if strings.HasPrefix(name, "!!") { // bad syntax, reject always
+		return false
+	}
+	if strings.HasPrefix(name, "!") { // negation
+		return len(name) > 1 && !ctxt.match(name[1:], allTags)
+	}
+
+	if allTags != nil {
+		allTags[name] = true
+	}
+
+	// Tags must be letters, digits, underscores or dots.
+	// Unlike in Go identifiers, all digits are fine (e.g., "386").
+	for _, c := range name {
+		if !unicode.IsLetter(c) && !unicode.IsDigit(c) && c != '_' && c != '.' {
+			return false
+		}
+	}
+
+	// special tags
+	if ctxt.CgoEnabled && name == "cgo" {
+		return true
+	}
+	if name == ctxt.GOOS || name == ctxt.GOARCH || name == ctxt.Compiler {
+		return true
+	}
+	if ctxt.GOOS == "android" && name == "linux" {
+		return true
+	}
+
+	// other tags
+	for _, tag := range ctxt.BuildTags {
+		if tag == name {
+			return true
+		}
+	}
+	for _, tag := range ctxt.ReleaseTags {
+		if tag == name {
+			return true
+		}
+	}
+
+	return false
+}
+
+// goodOSArchFile returns false if the name contains a $GOOS or $GOARCH
+// suffix which does not match the current system.
+// The recognized name formats are:
+//
+//     name_$(GOOS).*
+//     name_$(GOARCH).*
+//     name_$(GOOS)_$(GOARCH).*
+//     name_$(GOOS)_test.*
+//     name_$(GOARCH)_test.*
+//     name_$(GOOS)_$(GOARCH)_test.*
+//
+// An exception: if GOOS=android, then files with GOOS=linux are also matched.
+func (ctxt *Context) goodOSArchFile(name string, allTags map[string]bool) bool {
+	if dot := strings.Index(name, "."); dot != -1 {
+		name = name[:dot]
+	}
+
+	// Before Go 1.4, a file called "linux.go" would be equivalent to having a
+	// build tag "linux" in that file. For Go 1.4 and beyond, we require this
+	// auto-tagging to apply only to files with a non-empty prefix, so
+	// "foo_linux.go" is tagged but "linux.go" is not. This allows new operating
+	// systems, such as android, to arrive without breaking existing code with
+	// innocuous source code in "android.go". The easiest fix: cut everything
+	// in the name before the initial _.
+	i := strings.Index(name, "_")
+	if i < 0 {
+		return true
+	}
+	name = name[i:] // ignore everything before first _
+
+	l := strings.Split(name, "_")
+	if n := len(l); n > 0 && l[n-1] == "test" {
+		l = l[:n-1]
+	}
+	n := len(l)
+	if n >= 2 && knownOS[l[n-2]] && knownArch[l[n-1]] {
+		return ctxt.match(l[n-1], allTags) && ctxt.match(l[n-2], allTags)
+	}
+	if n >= 1 && (knownOS[l[n-1]] || knownArch[l[n-1]]) {
+		return ctxt.match(l[n-1], allTags)
+	}
+	return true
+}
+
+var knownOS = make(map[string]bool)
+var knownArch = make(map[string]bool)
+
+func init() {
+	for _, v := range strings.Fields(goosList) {
+		knownOS[v] = true
+	}
+	for _, v := range strings.Fields(goarchList) {
+		knownArch[v] = true
+	}
+}
+
+// ToolDir is the directory containing build tools.
+var ToolDir = getToolDir()
+
+// IsLocalImport reports whether the import path is
+// a local import path, like ".", "..", "./foo", or "../foo".
+func IsLocalImport(path string) bool {
+	return path == "." || path == ".." ||
+		strings.HasPrefix(path, "./") || strings.HasPrefix(path, "../")
+}
+
+// ArchChar returns "?" and an error.
+// In earlier versions of Go, the returned string was used to derive
+// the compiler and linker tool names, the default object file suffix,
+// and the default linker output name. As of Go 1.5, those strings
+// no longer vary by architecture; they are compile, link, .o, and a.out, respectively.
+func ArchChar(goarch string) (string, error) {
+	return "?", errors.New("architecture letter no longer used")
+}
diff --git a/build-1.11/doc.go b/build-1.11/doc.go
new file mode 100644
index 0000000..69613e3
--- /dev/null
+++ b/build-1.11/doc.go
@@ -0,0 +1,168 @@
+// Copyright 2011 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.
+
+// Package build gathers information about Go packages.
+//
+// Go Path
+//
+// The Go path is a list of directory trees containing Go source code.
+// It is consulted to resolve imports that cannot be found in the standard
+// Go tree. The default path is the value of the GOPATH environment
+// variable, interpreted as a path list appropriate to the operating system
+// (on Unix, the variable is a colon-separated string;
+// on Windows, a semicolon-separated string;
+// on Plan 9, a list).
+//
+// Each directory listed in the Go path must have a prescribed structure:
+//
+// The src/ directory holds source code. The path below 'src' determines
+// the import path or executable name.
+//
+// The pkg/ directory holds installed package objects.
+// As in the Go tree, each target operating system and
+// architecture pair has its own subdirectory of pkg
+// (pkg/GOOS_GOARCH).
+//
+// If DIR is a directory listed in the Go path, a package with
+// source in DIR/src/foo/bar can be imported as "foo/bar" and
+// has its compiled form installed to "DIR/pkg/GOOS_GOARCH/foo/bar.a"
+// (or, for gccgo, "DIR/pkg/gccgo/foo/libbar.a").
+//
+// The bin/ directory holds compiled commands.
+// Each command is named for its source directory, but only
+// using the final element, not the entire path. That is, the
+// command with source in DIR/src/foo/quux is installed into
+// DIR/bin/quux, not DIR/bin/foo/quux. The foo/ is stripped
+// so that you can add DIR/bin to your PATH to get at the
+// installed commands.
+//
+// Here's an example directory layout:
+//
+//	GOPATH=/home/user/gocode
+//
+//	/home/user/gocode/
+//	    src/
+//	        foo/
+//	            bar/               (go code in package bar)
+//	                x.go
+//	            quux/              (go code in package main)
+//	                y.go
+//	    bin/
+//	        quux                   (installed command)
+//	    pkg/
+//	        linux_amd64/
+//	            foo/
+//	                bar.a          (installed package object)
+//
+// Build Constraints
+//
+// A build constraint, also known as a build tag, is a line comment that begins
+//
+//	// +build
+//
+// that lists the conditions under which a file should be included in the package.
+// Constraints may appear in any kind of source file (not just Go), but
+// they must appear near the top of the file, preceded
+// only by blank lines and other line comments. These rules mean that in Go
+// files a build constraint must appear before the package clause.
+//
+// To distinguish build constraints from package documentation, a series of
+// build constraints must be followed by a blank line.
+//
+// A build constraint is evaluated as the OR of space-separated options;
+// each option evaluates as the AND of its comma-separated terms;
+// and each term is an alphanumeric word or, preceded by !, its negation.
+// That is, the build constraint:
+//
+//	// +build linux,386 darwin,!cgo
+//
+// corresponds to the boolean formula:
+//
+//	(linux AND 386) OR (darwin AND (NOT cgo))
+//
+// A file may have multiple build constraints. The overall constraint is the AND
+// of the individual constraints. That is, the build constraints:
+//
+//	// +build linux darwin
+//	// +build 386
+//
+// corresponds to the boolean formula:
+//
+//	(linux OR darwin) AND 386
+//
+// During a particular build, the following words are satisfied:
+//
+//	- the target operating system, as spelled by runtime.GOOS
+//	- the target architecture, as spelled by runtime.GOARCH
+//	- the compiler being used, either "gc" or "gccgo"
+//	- "cgo", if ctxt.CgoEnabled is true
+//	- "go1.1", from Go version 1.1 onward
+//	- "go1.2", from Go version 1.2 onward
+//	- "go1.3", from Go version 1.3 onward
+//	- "go1.4", from Go version 1.4 onward
+//	- "go1.5", from Go version 1.5 onward
+//	- "go1.6", from Go version 1.6 onward
+//	- "go1.7", from Go version 1.7 onward
+//	- "go1.8", from Go version 1.8 onward
+//	- "go1.9", from Go version 1.9 onward
+//	- "go1.10", from Go version 1.10 onward
+//	- "go1.11", from Go version 1.11 onward
+//	- any additional words listed in ctxt.BuildTags
+//
+// If a file's name, after stripping the extension and a possible _test suffix,
+// matches any of the following patterns:
+//	*_GOOS
+// 	*_GOARCH
+// 	*_GOOS_GOARCH
+// (example: source_windows_amd64.go) where GOOS and GOARCH represent
+// any known operating system and architecture values respectively, then
+// the file is considered to have an implicit build constraint requiring
+// those terms (in addition to any explicit constraints in the file).
+//
+// To keep a file from being considered for the build:
+//
+//	// +build ignore
+//
+// (any other unsatisfied word will work as well, but ``ignore'' is conventional.)
+//
+// To build a file only when using cgo, and only on Linux and OS X:
+//
+//	// +build linux,cgo darwin,cgo
+//
+// Such a file is usually paired with another file implementing the
+// default functionality for other systems, which in this case would
+// carry the constraint:
+//
+//	// +build !linux,!darwin !cgo
+//
+// Naming a file dns_windows.go will cause it to be included only when
+// building the package for Windows; similarly, math_386.s will be included
+// only when building the package for 32-bit x86.
+//
+// Using GOOS=android matches build tags and files as for GOOS=linux
+// in addition to android tags and files.
+//
+// Binary-Only Packages
+//
+// It is possible to distribute packages in binary form without including the
+// source code used for compiling the package. To do this, the package must
+// be distributed with a source file not excluded by build constraints and
+// containing a "//go:binary-only-package" comment.
+// Like a build constraint, this comment must appear near the top of the file,
+// preceded only by blank lines and other line comments and with a blank line
+// following the comment, to separate it from the package documentation.
+// Unlike build constraints, this comment is only recognized in non-test
+// Go source files.
+//
+// The minimal source code for a binary-only package is therefore:
+//
+//	//go:binary-only-package
+//
+//	package mypkg
+//
+// The source code may include additional Go code. That code is never compiled
+// but will be processed by tools like godoc and might be useful as end-user
+// documentation.
+//
+package build
diff --git a/build-1.11/gc.go b/build-1.11/gc.go
new file mode 100644
index 0000000..e2be2cb
--- /dev/null
+++ b/build-1.11/gc.go
@@ -0,0 +1,137 @@
+// 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 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
+}
diff --git a/build-1.11/gccgo.go b/build-1.11/gccgo.go
new file mode 100644
index 0000000..59e089d
--- /dev/null
+++ b/build-1.11/gccgo.go
@@ -0,0 +1,20 @@
+// 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 build
+
+import "runtime"
+
+// getToolDir returns the default value of ToolDir.
+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]
+}
diff --git a/build-1.11/read.go b/build-1.11/read.go
new file mode 100644
index 0000000..29b8cdc
--- /dev/null
+++ b/build-1.11/read.go
@@ -0,0 +1,247 @@
+// Copyright 2012 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.
+
+package build
+
+import (
+	"bufio"
+	"errors"
+	"io"
+	"unicode/utf8"
+)
+
+type importReader struct {
+	b    *bufio.Reader
+	buf  []byte
+	peek byte
+	err  error
+	eof  bool
+	nerr int
+}
+
+func isIdent(c byte) bool {
+	return 'A' <= c && c <= 'Z' || 'a' <= c && c <= 'z' || '0' <= c && c <= '9' || c == '_' || c >= utf8.RuneSelf
+}
+
+var (
+	errSyntax = errors.New("syntax error")
+	errNUL    = errors.New("unexpected NUL in input")
+)
+
+// syntaxError records a syntax error, but only if an I/O error has not already been recorded.
+func (r *importReader) syntaxError() {
+	if r.err == nil {
+		r.err = errSyntax
+	}
+}
+
+// readByte reads the next byte from the input, saves it in buf, and returns it.
+// If an error occurs, readByte records the error in r.err and returns 0.
+func (r *importReader) readByte() byte {
+	c, err := r.b.ReadByte()
+	if err == nil {
+		r.buf = append(r.buf, c)
+		if c == 0 {
+			err = errNUL
+		}
+	}
+	if err != nil {
+		if err == io.EOF {
+			r.eof = true
+		} else if r.err == nil {
+			r.err = err
+		}
+		c = 0
+	}
+	return c
+}
+
+// peekByte returns the next byte from the input reader but does not advance beyond it.
+// If skipSpace is set, peekByte skips leading spaces and comments.
+func (r *importReader) peekByte(skipSpace bool) byte {
+	if r.err != nil {
+		if r.nerr++; r.nerr > 10000 {
+			panic("go/build: import reader looping")
+		}
+		return 0
+	}
+
+	// Use r.peek as first input byte.
+	// Don't just return r.peek here: it might have been left by peekByte(false)
+	// and this might be peekByte(true).
+	c := r.peek
+	if c == 0 {
+		c = r.readByte()
+	}
+	for r.err == nil && !r.eof {
+		if skipSpace {
+			// For the purposes of this reader, semicolons are never necessary to
+			// understand the input and are treated as spaces.
+			switch c {
+			case ' ', '\f', '\t', '\r', '\n', ';':
+				c = r.readByte()
+				continue
+
+			case '/':
+				c = r.readByte()
+				if c == '/' {
+					for c != '\n' && r.err == nil && !r.eof {
+						c = r.readByte()
+					}
+				} else if c == '*' {
+					var c1 byte
+					for (c != '*' || c1 != '/') && r.err == nil {
+						if r.eof {
+							r.syntaxError()
+						}
+						c, c1 = c1, r.readByte()
+					}
+				} else {
+					r.syntaxError()
+				}
+				c = r.readByte()
+				continue
+			}
+		}
+		break
+	}
+	r.peek = c
+	return r.peek
+}
+
+// nextByte is like peekByte but advances beyond the returned byte.
+func (r *importReader) nextByte(skipSpace bool) byte {
+	c := r.peekByte(skipSpace)
+	r.peek = 0
+	return c
+}
+
+// readKeyword reads the given keyword from the input.
+// If the keyword is not present, readKeyword records a syntax error.
+func (r *importReader) readKeyword(kw string) {
+	r.peekByte(true)
+	for i := 0; i < len(kw); i++ {
+		if r.nextByte(false) != kw[i] {
+			r.syntaxError()
+			return
+		}
+	}
+	if isIdent(r.peekByte(false)) {
+		r.syntaxError()
+	}
+}
+
+// readIdent reads an identifier from the input.
+// If an identifier is not present, readIdent records a syntax error.
+func (r *importReader) readIdent() {
+	c := r.peekByte(true)
+	if !isIdent(c) {
+		r.syntaxError()
+		return
+	}
+	for isIdent(r.peekByte(false)) {
+		r.peek = 0
+	}
+}
+
+// readString reads a quoted string literal from the input.
+// If an identifier is not present, readString records a syntax error.
+func (r *importReader) readString(save *[]string) {
+	switch r.nextByte(true) {
+	case '`':
+		start := len(r.buf) - 1
+		for r.err == nil {
+			if r.nextByte(false) == '`' {
+				if save != nil {
+					*save = append(*save, string(r.buf[start:]))
+				}
+				break
+			}
+			if r.eof {
+				r.syntaxError()
+			}
+		}
+	case '"':
+		start := len(r.buf) - 1
+		for r.err == nil {
+			c := r.nextByte(false)
+			if c == '"' {
+				if save != nil {
+					*save = append(*save, string(r.buf[start:]))
+				}
+				break
+			}
+			if r.eof || c == '\n' {
+				r.syntaxError()
+			}
+			if c == '\\' {
+				r.nextByte(false)
+			}
+		}
+	default:
+		r.syntaxError()
+	}
+}
+
+// readImport reads an import clause - optional identifier followed by quoted string -
+// from the input.
+func (r *importReader) readImport(imports *[]string) {
+	c := r.peekByte(true)
+	if c == '.' {
+		r.peek = 0
+	} else if isIdent(c) {
+		r.readIdent()
+	}
+	r.readString(imports)
+}
+
+// readComments is like ioutil.ReadAll, except that it only reads the leading
+// block of comments in the file.
+func readComments(f io.Reader) ([]byte, error) {
+	r := &importReader{b: bufio.NewReader(f)}
+	r.peekByte(true)
+	if r.err == nil && !r.eof {
+		// Didn't reach EOF, so must have found a non-space byte. Remove it.
+		r.buf = r.buf[:len(r.buf)-1]
+	}
+	return r.buf, r.err
+}
+
+// readImports is like ioutil.ReadAll, except that it expects a Go file as input
+// and stops reading the input once the imports have completed.
+func readImports(f io.Reader, reportSyntaxError bool, imports *[]string) ([]byte, error) {
+	r := &importReader{b: bufio.NewReader(f)}
+
+	r.readKeyword("package")
+	r.readIdent()
+	for r.peekByte(true) == 'i' {
+		r.readKeyword("import")
+		if r.peekByte(true) == '(' {
+			r.nextByte(false)
+			for r.peekByte(true) != ')' && r.err == nil {
+				r.readImport(imports)
+			}
+			r.nextByte(false)
+		} else {
+			r.readImport(imports)
+		}
+	}
+
+	// If we stopped successfully before EOF, we read a byte that told us we were done.
+	// Return all but that last byte, which would cause a syntax error if we let it through.
+	if r.err == nil && !r.eof {
+		return r.buf[:len(r.buf)-1], nil
+	}
+
+	// If we stopped for a syntax error, consume the whole file so that
+	// we are sure we don't change the errors that go/parser returns.
+	if r.err == errSyntax && !reportSyntaxError {
+		r.err = nil
+		for r.err == nil && !r.eof {
+			r.readByte()
+		}
+	}
+
+	return r.buf, r.err
+}
diff --git a/build-1.11/syslist.go b/build-1.11/syslist.go
new file mode 100644
index 0000000..d7938fa
--- /dev/null
+++ b/build-1.11/syslist.go
@@ -0,0 +1,8 @@
+// Copyright 2011 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.
+
+package build
+
+const goosList = "android darwin dragonfly freebsd js linux nacl netbsd openbsd plan9 solaris windows zos "
+const goarchList = "386 amd64 amd64p32 arm armbe arm64 arm64be ppc64 ppc64le mips mipsle mips64 mips64le mips64p32 mips64p32le ppc riscv riscv64 s390 s390x sparc sparc64 wasm "
diff --git a/build-1.11/zcgo.go b/build-1.11/zcgo.go
new file mode 100644
index 0000000..7cb5f97
--- /dev/null
+++ b/build-1.11/zcgo.go
@@ -0,0 +1,38 @@
+// Code generated by go tool dist; DO NOT EDIT.
+
+package build
+
+const defaultCGO_ENABLED = ""
+
+var cgoEnabled = map[string]bool{
+	"android/386": true,
+	"android/amd64": true,
+	"android/arm": true,
+	"android/arm64": true,
+	"darwin/386": true,
+	"darwin/amd64": true,
+	"darwin/arm": true,
+	"darwin/arm64": true,
+	"dragonfly/amd64": true,
+	"freebsd/386": true,
+	"freebsd/amd64": true,
+	"linux/386": true,
+	"linux/amd64": true,
+	"linux/arm": true,
+	"linux/arm64": true,
+	"linux/mips": true,
+	"linux/mips64": true,
+	"linux/mips64le": true,
+	"linux/mipsle": true,
+	"linux/ppc64le": true,
+	"linux/riscv64": true,
+	"linux/s390x": true,
+	"netbsd/386": true,
+	"netbsd/amd64": true,
+	"netbsd/arm": true,
+	"openbsd/386": true,
+	"openbsd/amd64": true,
+	"solaris/amd64": true,
+	"windows/386": true,
+	"windows/amd64": true,
+}
diff --git a/build/zcgo.go b/build/zcgo.go
deleted file mode 100644
index 86e2a2d..0000000
--- a/build/zcgo.go
+++ /dev/null
@@ -1,37 +0,0 @@
-// auto generated by go tool dist
-
-package build
-
-const defaultCGO_ENABLED = ""
-
-var cgoEnabled = map[string]bool{
-	"android/386":     true,
-	"android/amd64":   true,
-	"android/arm":     true,
-	"android/arm64":   true,
-	"darwin/386":      true,
-	"darwin/amd64":    true,
-	"darwin/arm":      true,
-	"darwin/arm64":    true,
-	"dragonfly/amd64": true,
-	"freebsd/386":     true,
-	"freebsd/amd64":   true,
-	"linux/386":       true,
-	"linux/amd64":     true,
-	"linux/arm":       true,
-	"linux/arm64":     true,
-	"linux/mips":      true,
-	"linux/mips64":    true,
-	"linux/mips64le":  true,
-	"linux/mipsle":    true,
-	"linux/ppc64le":   true,
-	"linux/s390x":     true,
-	"netbsd/386":      true,
-	"netbsd/amd64":    true,
-	"netbsd/arm":      true,
-	"openbsd/386":     true,
-	"openbsd/amd64":   true,
-	"solaris/amd64":   true,
-	"windows/386":     true,
-	"windows/amd64":   true,
-}
diff --git a/mage/main.go b/mage/main.go
index ee70706..6b4cc24 100644
--- a/mage/main.go
+++ b/mage/main.go
@@ -12,15 +12,18 @@ import (
 	"os"
 	"os/exec"
 	"path/filepath"
+	"regexp"
 	"runtime"
 	"sort"
+	"strconv"
 	"strings"
 	"text/tabwriter"
 	"text/template"
 	"time"
 	"unicode"
 
-	"github.com/magefile/mage/build"
+	build "github.com/magefile/mage/build-1.10"
+	buildmod "github.com/magefile/mage/build-1.11"
 	"github.com/magefile/mage/mg"
 	"github.com/magefile/mage/parse"
 	"github.com/magefile/mage/sh"
@@ -62,6 +65,7 @@ var (
 // Command tracks invocations of mage that run without targets or other flags.
 type Command int
 
+// The various command types
 const (
 	None          Command = iota
 	Version               // report the current version of mage
@@ -361,14 +365,57 @@ type data struct {
 	Aliases      map[string]string
 }
 
+// Yeah, if we get to go2, this will need to be revisited. I think that's ok.
+var goVerReg = regexp.MustCompile(`1\.[0-9]+`)
+
 // Magefiles returns the list of magefiles in dir.
 func Magefiles(dir string) ([]string, error) {
-	ctx := build.Default
+	// use the build directory for the specific go binary we're running.  We
+	// divide the world into two epochs - 1.11 and later, where we have go
+	// modules, and 1.10 and prior, where there are no modules.
+	cmd := exec.Command("go", "version")
+	out, stderr := &bytes.Buffer{}, &bytes.Buffer{}
+	cmd.Stdout = out
+	cmd.Stderr = stderr
+	if err := cmd.Run(); err != nil {
+		return nil, fmt.Errorf("failed to run `go version`: %s", stderr)
+	}
+	v := goVerReg.FindString(out.String())
+	if v == "" {
+		return nil, fmt.Errorf("failed to get version from go version output: %s", out)
+	}
+	minor, err := strconv.Atoi(v[2:])
+	if err != nil {
+		return nil, fmt.Errorf("failed to parse minor version from go version output: %s", out)
+	}
+	// yes, these two blocks are exactly the same aside from the build context,
+	// but we need to access struct fields so... let's just copy and paste and
+	// move on.
+	if minor < 11 {
+		// go 1.10 and before
+		ctx := build.Default
+		ctx.RequiredTags = []string{"mage"}
+		ctx.BuildTags = []string{"mage"}
+		p, err := ctx.ImportDir(dir, 0)
+		if err != nil {
+			if _, ok := err.(*build.NoGoError); ok {
+				debug.Print("no go files found by build")
+				return []string{}, nil
+			}
+			return nil, err
+		}
+		for i := range p.GoFiles {
+			p.GoFiles[i] = filepath.Join(dir, p.GoFiles[i])
+		}
+		return p.GoFiles, nil
+	}
+	// Go 1.11+
+	ctx := buildmod.Default
 	ctx.RequiredTags = []string{"mage"}
 	ctx.BuildTags = []string{"mage"}
 	p, err := ctx.ImportDir(dir, 0)
 	if err != nil {
-		if _, ok := err.(*build.NoGoError); ok {
+		if _, ok := err.(*buildmod.NoGoError); ok {
 			debug.Print("no go files found by build")
 			return []string{}, nil
 		}


Test patch:
diff --git a/build/build_test.go b/build-1.10/build_test.go
similarity index 90%
rename from build/build_test.go
rename to build-1.10/build_test.go
index 89b2c09..7110179 100644
--- a/build/build_test.go
+++ b/build-1.10/build_test.go
@@ -108,27 +108,27 @@ func TestMultiplePackageImport(t *testing.T) {
 	}
 }
 
-func TestLocalDirectory(t *testing.T) {
-	if runtime.GOOS == "darwin" {
-		switch runtime.GOARCH {
-		case "arm", "arm64":
-			t.Skipf("skipping on %s/%s, no valid GOROOT", runtime.GOOS, runtime.GOARCH)
-		}
-	}
-
-	cwd, err := os.Getwd()
-	if err != nil {
-		t.Fatal(err)
-	}
-
-	p, err := ImportDir(cwd, 0)
-	if err != nil {
-		t.Fatal(err)
-	}
-	if p.ImportPath != "github.com/magefile/mage/build" {
-		t.Fatalf("ImportPath=%q, want %q", p.ImportPath, "github.com/magefile/mage/build")
-	}
-}
+// func TestLocalDirectory(t *testing.T) {
+// 	if runtime.GOOS == "darwin" {
+// 		switch runtime.GOARCH {
+// 		case "arm", "arm64":
+// 			t.Skipf("skipping on %s/%s, no valid GOROOT", runtime.GOOS, runtime.GOARCH)
+// 		}
+// 	}
+
+// 	cwd, err := os.Getwd()
+// 	if err != nil {
+// 		t.Fatal(err)
+// 	}
+
+// 	p, err := ImportDir(cwd, 0)
+// 	if err != nil {
+// 		t.Fatal(err)
+// 	}
+// 	if p.ImportPath != "go/build" {
+// 		t.Fatalf("ImportPath=%q, want %q", p.ImportPath, "go/build")
+// 	}
+// }
 
 func TestShouldBuild(t *testing.T) {
 	const file1 = "// +build tag1\n\n" +
@@ -175,46 +175,6 @@ func TestShouldBuild(t *testing.T) {
 	}
 }
 
-func TestRequiredTags(t *testing.T) {
-	tests := []struct {
-		name   string
-		file   string
-		should bool
-	}{
-		{
-			"no req tag",
-			"package main",
-			false,
-		},
-		{
-			"has req tag",
-			`// +build req
-			
-			package main`,
-			true,
-		},
-		{
-			"OR with req",
-			`// +build no req
-			
-			package main`,
-			true,
-		},
-	}
-
-	ctx := &Context{
-		BuildTags:    []string{"req"},
-		RequiredTags: []string{"req"},
-	}
-	for _, tst := range tests {
-		t.Run(tst.name, func(t *testing.T) {
-			if tst.should != ctx.shouldBuild([]byte(tst.file), nil, nil) {
-				t.Errorf("shouldBuild = %v, want %v", !tst.should, tst.should)
-			}
-		})
-	}
-}
-
 type readNopCloser struct {
 	io.Reader
 }
@@ -422,11 +382,45 @@ func TestImportVendorParentFailure(t *testing.T) {
 	}
 }
 
+func TestImportDirTarget(t *testing.T) {
+	MustHaveGoBuild(t) // really must just have source
+	ctxt := Default
+	ctxt.GOPATH = ""
+	p, err := ctxt.ImportDir(filepath.Join(ctxt.GOROOT, "src/path"), 0)
+	if err != nil {
+		t.Fatal(err)
+	}
+	if p.PkgTargetRoot == "" || p.PkgObj == "" {
+		t.Errorf("p.PkgTargetRoot == %q, p.PkgObj == %q, want non-empty", p.PkgTargetRoot, p.PkgObj)
+	}
+}
+
+// the following copied from go/src/internal/testenv
+
+// MustHaveGoBuild checks that the current system can build programs with ``go build''
+// and then run them with os.StartProcess or exec.Command.
+// If not, MustHaveGoBuild calls t.Skip with an explanation.
+func MustHaveGoBuild(t testing.TB) {
+	if os.Getenv("GO_GCFLAGS") != "" {
+		t.Skipf("skipping test: 'go build' not compatible with setting $GO_GCFLAGS")
+	}
+	if !HasGoBuild() {
+		t.Skipf("skipping test: 'go build' not available on %s/%s", runtime.GOOS, runtime.GOARCH)
+	}
+}
+
 // HasGoBuild reports whether the current system can build programs with ``go build''
 // and then run them with os.StartProcess or exec.Command.
 func HasGoBuild() bool {
+	if os.Getenv("GO_GCFLAGS") != "" {
+		// It's too much work to require every caller of the go command
+		// to pass along "-gcflags="+os.Getenv("GO_GCFLAGS").
+		// For now, if $GO_GCFLAGS is set, report that we simply can't
+		// run go build.
+		return false
+	}
 	switch runtime.GOOS {
-	case "android", "nacl":
+	case "android", "nacl", "js":
 		return false
 	case "darwin":
 		if strings.HasPrefix(runtime.GOARCH, "arm") {
@@ -435,12 +429,3 @@ func HasGoBuild() bool {
 	}
 	return true
 }
-
-// MustHaveGoBuild checks that the current system can build programs with ``go build''
-// and then run them with os.StartProcess or exec.Command.
-// If not, MustHaveGoBuild calls t.Skip with an explanation.
-func MustHaveGoBuild(t *testing.T) {
-	if !HasGoBuild() {
-		t.Skipf("skipping test: 'go build' not available on %s/%s", runtime.GOOS, runtime.GOARCH)
-	}
-}
diff --git a/build/deps_test.go b/build-1.10/deps_test.go
similarity index 93%
rename from build/deps_test.go
rename to build-1.10/deps_test.go
index 1e64d0c..f0cc697 100644
--- a/build/deps_test.go
+++ b/build-1.10/deps_test.go
@@ -33,7 +33,7 @@ import (
 var pkgDeps = map[string][]string{
 	// L0 is the lowest level, core, nearly unavoidable packages.
 	"errors":                  {},
-	"io":                      {"errors", "sync"},
+	"io":                      {"errors", "sync", "sync/atomic"},
 	"runtime":                 {"unsafe", "runtime/internal/atomic", "runtime/internal/sys"},
 	"runtime/internal/sys":    {},
 	"runtime/internal/atomic": {"unsafe", "runtime/internal/sys"},
@@ -99,7 +99,7 @@ var pkgDeps = map[string][]string{
 	"crypto/cipher":       {"L2", "crypto/subtle"},
 	"crypto/subtle":       {},
 	"encoding/base32":     {"L2"},
-	"encoding/base64":     {"L2"},
+	"encoding/base64":     {"L2", "encoding/binary"},
 	"encoding/binary":     {"L2", "reflect"},
 	"hash":                {"L2"}, // interfaces
 	"hash/adler32":        {"L2", "hash"},
@@ -152,12 +152,13 @@ var pkgDeps = map[string][]string{
 		"syscall",
 	},
 
-	"internal/poll": {"L0", "internal/race", "syscall", "time", "unicode/utf16", "unicode/utf8"},
-	"os":            {"L1", "os", "syscall", "time", "internal/poll", "internal/syscall/windows"},
-	"path/filepath": {"L2", "os", "syscall"},
-	"io/ioutil":     {"L2", "os", "path/filepath", "time"},
-	"os/exec":       {"L2", "os", "context", "path/filepath", "syscall"},
-	"os/signal":     {"L2", "os", "syscall"},
+	"internal/poll":    {"L0", "internal/race", "syscall", "time", "unicode/utf16", "unicode/utf8", "internal/syscall/windows"},
+	"internal/testlog": {"L0"},
+	"os":               {"L1", "os", "syscall", "time", "internal/poll", "internal/syscall/windows", "internal/testlog"},
+	"path/filepath":    {"L2", "os", "syscall", "internal/syscall/windows"},
+	"io/ioutil":        {"L2", "os", "path/filepath", "time"},
+	"os/exec":          {"L2", "os", "context", "path/filepath", "syscall"},
+	"os/signal":        {"L2", "os", "syscall"},
 
 	// OS enables basic operating system functionality,
 	// but not direct use of package syscall, nor os/signal.
@@ -224,7 +225,7 @@ var pkgDeps = map[string][]string{
 	"go/types":                  {"L4", "GOPARSER", "container/heap", "go/constant"},
 
 	// One of a kind.
-	"archive/tar":              {"L4", "OS", "syscall"},
+	"archive/tar":              {"L4", "OS", "syscall", "os/user"},
 	"archive/zip":              {"L4", "OS", "compress/flate"},
 	"container/heap":           {"sort"},
 	"compress/bzip2":           {"L4"},
@@ -264,11 +265,11 @@ var pkgDeps = map[string][]string{
 	"math/big":                 {"L4"},
 	"mime":                     {"L4", "OS", "syscall", "internal/syscall/windows/registry"},
 	"mime/quotedprintable":     {"L4"},
-	"net/internal/socktest":    {"L4", "OS", "syscall"},
+	"net/internal/socktest":    {"L4", "OS", "syscall", "internal/syscall/windows"},
 	"net/url":                  {"L4"},
 	"plugin":                   {"L0", "OS", "CGO"},
 	"runtime/pprof/internal/profile": {"L4", "OS", "compress/gzip", "regexp"},
-	"testing/internal/testdeps":      {"L4", "runtime/pprof", "regexp"},
+	"testing/internal/testdeps":      {"L4", "internal/testlog", "runtime/pprof", "regexp"},
 	"text/scanner":                   {"L4", "OS"},
 	"text/template/parse":            {"L4"},
 
@@ -297,6 +298,9 @@ var pkgDeps = map[string][]string{
 	// Plan 9 alone needs io/ioutil and os.
 	"os/user": {"L4", "CGO", "io/ioutil", "os", "syscall"},
 
+	// Internal package used only for testing.
+	"os/signal/internal/pty": {"CGO", "fmt", "os", "syscall"},
+
 	// Basic networking.
 	// Because net must be used by any package that wants to
 	// do networking portably, it must have a small dependency set: just L0+basic os.
@@ -375,9 +379,10 @@ var pkgDeps = map[string][]string{
 	},
 	"crypto/x509": {
 		"L4", "CRYPTO-MATH", "OS", "CGO",
-		"crypto/x509/pkix", "encoding/pem", "encoding/hex", "net", "os/user", "syscall",
+		"crypto/x509/pkix", "encoding/pem", "encoding/hex", "net", "os/user", "syscall", "net/url",
+		"golang_org/x/crypto/cryptobyte", "golang_org/x/crypto/cryptobyte/asn1",
 	},
-	"crypto/x509/pkix": {"L4", "CRYPTO-MATH"},
+	"crypto/x509/pkix": {"L4", "CRYPTO-MATH", "encoding/hex"},
 
 	// Simple net+crypto-aware packages.
 	"mime/multipart": {"L4", "OS", "mime", "crypto/rand", "net/textproto", "mime/quotedprintable"},
@@ -476,8 +481,6 @@ func listStdPkgs(goroot string) ([]string, error) {
 	return pkgs, nil
 }
 
-// This test does not function well in travis under different go versions for some reason.
-//
 // func TestDependencies(t *testing.T) {
 // 	iOS := runtime.GOOS == "darwin" && (runtime.GOARCH == "arm" || runtime.GOARCH == "arm64")
 // 	if runtime.GOOS == "nacl" || iOS {
diff --git a/build-1.11/build_test.go b/build-1.11/build_test.go
new file mode 100644
index 0000000..c2d9f6a
--- /dev/null
+++ b/build-1.11/build_test.go
@@ -0,0 +1,459 @@
+// Copyright 2011 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.
+
+package build
+
+import (
+	"io"
+	"os"
+	"path/filepath"
+	"reflect"
+	"runtime"
+	"strings"
+	"testing"
+)
+
+func TestMatch(t *testing.T) {
+	ctxt := Default
+	what := "default"
+	match := func(tag string, want map[string]bool) {
+		m := make(map[string]bool)
+		if !ctxt.match(tag, m) {
+			t.Errorf("%s context should match %s, does not", what, tag)
+		}
+		if !reflect.DeepEqual(m, want) {
+			t.Errorf("%s tags = %v, want %v", tag, m, want)
+		}
+	}
+	nomatch := func(tag string, want map[string]bool) {
+		m := make(map[string]bool)
+		if ctxt.match(tag, m) {
+			t.Errorf("%s context should NOT match %s, does", what, tag)
+		}
+		if !reflect.DeepEqual(m, want) {
+			t.Errorf("%s tags = %v, want %v", tag, m, want)
+		}
+	}
+
+	match(runtime.GOOS+","+runtime.GOARCH, map[string]bool{runtime.GOOS: true, runtime.GOARCH: true})
+	match(runtime.GOOS+","+runtime.GOARCH+",!foo", map[string]bool{runtime.GOOS: true, runtime.GOARCH: true, "foo": true})
+	nomatch(runtime.GOOS+","+runtime.GOARCH+",foo", map[string]bool{runtime.GOOS: true, runtime.GOARCH: true, "foo": true})
+
+	what = "modified"
+	ctxt.BuildTags = []string{"foo"}
+	match(runtime.GOOS+","+runtime.GOARCH, map[string]bool{runtime.GOOS: true, runtime.GOARCH: true})
+	match(runtime.GOOS+","+runtime.GOARCH+",foo", map[string]bool{runtime.GOOS: true, runtime.GOARCH: true, "foo": true})
+	nomatch(runtime.GOOS+","+runtime.GOARCH+",!foo", map[string]bool{runtime.GOOS: true, runtime.GOARCH: true, "foo": true})
+	match(runtime.GOOS+","+runtime.GOARCH+",!bar", map[string]bool{runtime.GOOS: true, runtime.GOARCH: true, "bar": true})
+	nomatch(runtime.GOOS+","+runtime.GOARCH+",bar", map[string]bool{runtime.GOOS: true, runtime.GOARCH: true, "bar": true})
+	nomatch("!", map[string]bool{})
+}
+
+func TestDotSlashImport(t *testing.T) {
+	p, err := ImportDir("testdata/other", 0)
+	if err != nil {
+		t.Fatal(err)
+	}
+	if len(p.Imports) != 1 || p.Imports[0] != "./file" {
+		t.Fatalf("testdata/other: Imports=%v, want [./file]", p.Imports)
+	}
+
+	p1, err := Import("./file", "testdata/other", 0)
+	if err != nil {
+		t.Fatal(err)
+	}
+	if p1.Name != "file" {
+		t.Fatalf("./file: Name=%q, want %q", p1.Name, "file")
+	}
+	dir := filepath.Clean("testdata/other/file") // Clean to use \ on Windows
+	if p1.Dir != dir {
+		t.Fatalf("./file: Dir=%q, want %q", p1.Name, dir)
+	}
+}
+
+func TestEmptyImport(t *testing.T) {
+	p, err := Import("", Default.GOROOT, FindOnly)
+	if err == nil {
+		t.Fatal(`Import("") returned nil error.`)
+	}
+	if p == nil {
+		t.Fatal(`Import("") returned nil package.`)
+	}
+	if p.ImportPath != "" {
+		t.Fatalf("ImportPath=%q, want %q.", p.ImportPath, "")
+	}
+}
+
+func TestEmptyFolderImport(t *testing.T) {
+	_, err := Import(".", "testdata/empty", 0)
+	if _, ok := err.(*NoGoError); !ok {
+		t.Fatal(`Import("testdata/empty") did not return NoGoError.`)
+	}
+}
+
+func TestMultiplePackageImport(t *testing.T) {
+	_, err := Import(".", "testdata/multi", 0)
+	mpe, ok := err.(*MultiplePackageError)
+	if !ok {
+		t.Fatal(`Import("testdata/multi") did not return MultiplePackageError.`)
+	}
+	want := &MultiplePackageError{
+		Dir:      filepath.FromSlash("testdata/multi"),
+		Packages: []string{"main", "test_package"},
+		Files:    []string{"file.go", "file_appengine.go"},
+	}
+	if !reflect.DeepEqual(mpe, want) {
+		t.Errorf("got %#v; want %#v", mpe, want)
+	}
+}
+
+// func TestLocalDirectory(t *testing.T) {
+// 	if runtime.GOOS == "darwin" {
+// 		switch runtime.GOARCH {
+// 		case "arm", "arm64":
+// 			t.Skipf("skipping on %s/%s, no valid GOROOT", runtime.GOOS, runtime.GOARCH)
+// 		}
+// 	}
+
+// 	cwd, err := os.Getwd()
+// 	if err != nil {
+// 		t.Fatal(err)
+// 	}
+
+// 	p, err := ImportDir(cwd, 0)
+// 	if err != nil {
+// 		t.Fatal(err)
+// 	}
+// 	if p.ImportPath != "go/build" {
+// 		t.Fatalf("ImportPath=%q, want %q", p.ImportPath, "go/build")
+// 	}
+// }
+
+func TestShouldBuild(t *testing.T) {
+	const file1 = "// +build tag1\n\n" +
+		"package main\n"
+	want1 := map[string]bool{"tag1": true}
+
+	const file2 = "// +build cgo\n\n" +
+		"// This package implements parsing of tags like\n" +
+		"// +build tag1\n" +
+		"package build"
+	want2 := map[string]bool{"cgo": true}
+
+	const file3 = "// Copyright The Go Authors.\n\n" +
+		"package build\n\n" +
+		"// shouldBuild checks tags given by lines of the form\n" +
+		"// +build tag\n" +
+		"func shouldBuild(content []byte)\n"
+	want3 := map[string]bool{}
+
+	ctx := &Context{BuildTags: []string{"tag1"}}
+	m := map[string]bool{}
+	if !ctx.shouldBuild([]byte(file1), m, nil) {
+		t.Errorf("shouldBuild(file1) = false, want true")
+	}
+	if !reflect.DeepEqual(m, want1) {
+		t.Errorf("shouldBuild(file1) tags = %v, want %v", m, want1)
+	}
+
+	m = map[string]bool{}
+	if ctx.shouldBuild([]byte(file2), m, nil) {
+		t.Errorf("shouldBuild(file2) = true, want false")
+	}
+	if !reflect.DeepEqual(m, want2) {
+		t.Errorf("shouldBuild(file2) tags = %v, want %v", m, want2)
+	}
+
+	m = map[string]bool{}
+	ctx = &Context{BuildTags: nil}
+	if !ctx.shouldBuild([]byte(file3), m, nil) {
+		t.Errorf("shouldBuild(file3) = false, want true")
+	}
+	if !reflect.DeepEqual(m, want3) {
+		t.Errorf("shouldBuild(file3) tags = %v, want %v", m, want3)
+	}
+}
+
+func TestGoodOSArchFile(t *testing.T) {
+	ctx := &Context{BuildTags: []string{"linux"}, GOOS: "darwin"}
+	m := map[string]bool{}
+	want := map[string]bool{"linux": true}
+	if !ctx.goodOSArchFile("hello_linux.go", m) {
+		t.Errorf("goodOSArchFile(hello_linux.go) = false, want true")
+	}
+	if !reflect.DeepEqual(m, want) {
+		t.Errorf("goodOSArchFile(hello_linux.go) tags = %v, want %v", m, want)
+	}
+}
+
+type readNopCloser struct {
+	io.Reader
+}
+
+func (r readNopCloser) Close() error {
+	return nil
+}
+
+var (
+	ctxtP9      = Context{GOARCH: "arm", GOOS: "plan9"}
+	ctxtAndroid = Context{GOARCH: "arm", GOOS: "android"}
+)
+
+var matchFileTests = []struct {
+	ctxt  Context
+	name  string
+	data  string
+	match bool
+}{
+	{ctxtP9, "foo_arm.go", "", true},
+	{ctxtP9, "foo1_arm.go", "// +build linux\n\npackage main\n", false},
+	{ctxtP9, "foo_darwin.go", "", false},
+	{ctxtP9, "foo.go", "", true},
+	{ctxtP9, "foo1.go", "// +build linux\n\npackage main\n", false},
+	{ctxtP9, "foo.badsuffix", "", false},
+	{ctxtAndroid, "foo_linux.go", "", true},
+	{ctxtAndroid, "foo_android.go", "", true},
+	{ctxtAndroid, "foo_plan9.go", "", false},
+	{ctxtAndroid, "android.go", "", true},
+	{ctxtAndroid, "plan9.go", "", true},
+	{ctxtAndroid, "plan9_test.go", "", true},
+	{ctxtAndroid, "arm.s", "", true},
+	{ctxtAndroid, "amd64.s", "", true},
+}
+
+func TestMatchFile(t *testing.T) {
+	for _, tt := range matchFileTests {
+		ctxt := tt.ctxt
+		ctxt.OpenFile = func(path string) (r io.ReadCloser, err error) {
+			if path != "x+"+tt.name {
+				t.Fatalf("OpenFile asked for %q, expected %q", path, "x+"+tt.name)
+			}
+			return &readNopCloser{strings.NewReader(tt.data)}, nil
+		}
+		ctxt.JoinPath = func(elem ...string) string {
+			return strings.Join(elem, "+")
+		}
+		match, err := ctxt.MatchFile("x", tt.name)
+		if match != tt.match || err != nil {
+			t.Fatalf("MatchFile(%q) = %v, %v, want %v, nil", tt.name, match, err, tt.match)
+		}
+	}
+}
+
+func TestImportCmd(t *testing.T) {
+	if runtime.GOOS == "darwin" {
+		switch runtime.GOARCH {
+		case "arm", "arm64":
+			t.Skipf("skipping on %s/%s, no valid GOROOT", runtime.GOOS, runtime.GOARCH)
+		}
+	}
+
+	p, err := Import("cmd/internal/objfile", "", 0)
+	if err != nil {
+		t.Fatal(err)
+	}
+	if !strings.HasSuffix(filepath.ToSlash(p.Dir), "src/cmd/internal/objfile") {
+		t.Fatalf("Import cmd/internal/objfile returned Dir=%q, want %q", filepath.ToSlash(p.Dir), ".../src/cmd/internal/objfile")
+	}
+}
+
+var (
+	expandSrcDirPath = filepath.Join(string(filepath.Separator)+"projects", "src", "add")
+)
+
+var expandSrcDirTests = []struct {
+	input, expected string
+}{
+	{"-L ${SRCDIR}/libs -ladd", "-L /projects/src/add/libs -ladd"},
+	{"${SRCDIR}/add_linux_386.a -pthread -lstdc++", "/projects/src/add/add_linux_386.a -pthread -lstdc++"},
+	{"Nothing to expand here!", "Nothing to expand here!"},
+	{"$", "$"},
+	{"$$", "$$"},
+	{"${", "${"},
+	{"$}", "$}"},
+	{"$FOO ${BAR}", "$FOO ${BAR}"},
+	{"Find me the $SRCDIRECTORY.", "Find me the $SRCDIRECTORY."},
+	{"$SRCDIR is missing braces", "$SRCDIR is missing braces"},
+}
+
+func TestExpandSrcDir(t *testing.T) {
+	for _, test := range expandSrcDirTests {
+		output, _ := expandSrcDir(test.input, expandSrcDirPath)
+		if output != test.expected {
+			t.Errorf("%q expands to %q with SRCDIR=%q when %q is expected", test.input, output, expandSrcDirPath, test.expected)
+		} else {
+			t.Logf("%q expands to %q with SRCDIR=%q", test.input, output, expandSrcDirPath)
+		}
+	}
+}
+
+func TestShellSafety(t *testing.T) {
+	tests := []struct {
+		input, srcdir, expected string
+		result                  bool
+	}{
+		{"-I${SRCDIR}/../include", "/projects/src/issue 11868", "-I/projects/src/issue 11868/../include", true},
+		{"-I${SRCDIR}", "wtf$@%", "-Iwtf$@%", true},
+		{"-X${SRCDIR}/1,${SRCDIR}/2", "/projects/src/issue 11868", "-X/projects/src/issue 11868/1,/projects/src/issue 11868/2", true},
+		{"-I/tmp -I/tmp", "/tmp2", "-I/tmp -I/tmp", true},
+		{"-I/tmp", "/tmp/[0]", "-I/tmp", true},
+		{"-I${SRCDIR}/dir", "/tmp/[0]", "-I/tmp/[0]/dir", false},
+		{"-I${SRCDIR}/dir", "/tmp/go go", "-I/tmp/go go/dir", true},
+		{"-I${SRCDIR}/dir dir", "/tmp/go", "-I/tmp/go/dir dir", true},
+	}
+	for _, test := range tests {
+		output, ok := expandSrcDir(test.input, test.srcdir)
+		if ok != test.result {
+			t.Errorf("Expected %t while %q expands to %q with SRCDIR=%q; got %t", test.result, test.input, output, test.srcdir, ok)
+		}
+		if output != test.expected {
+			t.Errorf("Expected %q while %q expands with SRCDIR=%q; got %q", test.expected, test.input, test.srcdir, output)
+		}
+	}
+}
+
+// Want to get a "cannot find package" error when directory for package does not exist.
+// There should be valid partial information in the returned non-nil *Package.
+func TestImportDirNotExist(t *testing.T) {
+	MustHaveGoBuild(t) // really must just have source
+	ctxt := Default
+	ctxt.GOPATH = ""
+
+	tests := []struct {
+		label        string
+		path, srcDir string
+		mode         ImportMode
+	}{
+		{"Import(full, 0)", "go/build/doesnotexist", "", 0},
+		{"Import(local, 0)", "./doesnotexist", filepath.Join(ctxt.GOROOT, "src/go/build"), 0},
+		{"Import(full, FindOnly)", "go/build/doesnotexist", "", FindOnly},
+		{"Import(local, FindOnly)", "./doesnotexist", filepath.Join(ctxt.GOROOT, "src/go/build"), FindOnly},
+	}
+	for _, test := range tests {
+		p, err := ctxt.Import(test.path, test.srcDir, test.mode)
+		if err == nil || !strings.HasPrefix(err.Error(), "cannot find package") {
+			t.Errorf(`%s got error: %q, want "cannot find package" error`, test.label, err)
+		}
+		// If an error occurs, build.Import is documented to return
+		// a non-nil *Package containing partial information.
+		if p == nil {
+			t.Fatalf(`%s got nil p, want non-nil *Package`, test.label)
+		}
+		// Verify partial information in p.
+		if p.ImportPath != "go/build/doesnotexist" {
+			t.Errorf(`%s got p.ImportPath: %q, want "go/build/doesnotexist"`, test.label, p.ImportPath)
+		}
+	}
+}
+
+func TestImportVendor(t *testing.T) {
+	MustHaveGoBuild(t) // really must just have source
+	ctxt := Default
+	ctxt.GOPATH = ""
+	p, err := ctxt.Import("golang_org/x/net/http2/hpack", filepath.Join(ctxt.GOROOT, "src/net/http"), 0)
+	if err != nil {
+		t.Fatalf("cannot find vendored golang_org/x/net/http2/hpack from net/http directory: %v", err)
+	}
+	want := "vendor/golang_org/x/net/http2/hpack"
+	if p.ImportPath != want {
+		t.Fatalf("Import succeeded but found %q, want %q", p.ImportPath, want)
+	}
+}
+
+func TestImportVendorFailure(t *testing.T) {
+	MustHaveGoBuild(t) // really must just have source
+	ctxt := Default
+	ctxt.GOPATH = ""
+	p, err := ctxt.Import("x.com/y/z", filepath.Join(ctxt.GOROOT, "src/net/http"), 0)
+	if err == nil {
+		t.Fatalf("found made-up package x.com/y/z in %s", p.Dir)
+	}
+
+	e := err.Error()
+	if !strings.Contains(e, " (vendor tree)") {
+		t.Fatalf("error on failed import does not mention GOROOT/src/vendor directory:\n%s", e)
+	}
+}
+
+func TestImportVendorParentFailure(t *testing.T) {
+	MustHaveGoBuild(t) // really must just have source
+	ctxt := Default
+	ctxt.GOPATH = ""
+	// This import should fail because the vendor/golang.org/x/net/http2 directory has no source code.
+	p, err := ctxt.Import("golang_org/x/net/http2", filepath.Join(ctxt.GOROOT, "src/net/http"), 0)
+	if err == nil {
+		t.Fatalf("found empty parent in %s", p.Dir)
+	}
+	if p != nil && p.Dir != "" {
+		t.Fatalf("decided to use %s", p.Dir)
+	}
+	e := err.Error()
+	if !strings.Contains(e, " (vendor tree)") {
+		t.Fatalf("error on failed import does not mention GOROOT/src/vendor directory:\n%s", e)
+	}
+}
+
+func TestImportDirTarget(t *testing.T) {
+	MustHaveGoBuild(t) // really must just have source
+	ctxt := Default
+	ctxt.GOPATH = ""
+	p, err := ctxt.ImportDir(filepath.Join(ctxt.GOROOT, "src/path"), 0)
+	if err != nil {
+		t.Fatal(err)
+	}
+	if p.PkgTargetRoot == "" || p.PkgObj == "" {
+		t.Errorf("p.PkgTargetRoot == %q, p.PkgObj == %q, want non-empty", p.PkgTargetRoot, p.PkgObj)
+	}
+}
+
+// TestIssue23594 prevents go/build from regressing and populating Package.Doc
+// from comments in test files.
+func TestIssue23594(t *testing.T) {
+	// Package testdata/doc contains regular and external test files
+	// with comments attached to their package declarations. The names of the files
+	// ensure that we see the comments from the test files first.
+	p, err := ImportDir("testdata/doc", 0)
+	if err != nil {
+		t.Fatalf("could not import testdata: %v", err)
+	}
+
+	if p.Doc != "Correct" {
+		t.Fatalf("incorrectly set .Doc to %q", p.Doc)
+	}
+}
+
+// the following copied from go/src/internal/testenv
+
+// MustHaveGoBuild checks that the current system can build programs with ``go build''
+// and then run them with os.StartProcess or exec.Command.
+// If not, MustHaveGoBuild calls t.Skip with an explanation.
+func MustHaveGoBuild(t testing.TB) {
+	if os.Getenv("GO_GCFLAGS") != "" {
+		t.Skipf("skipping test: 'go build' not compatible with setting $GO_GCFLAGS")
+	}
+	if !HasGoBuild() {
+		t.Skipf("skipping test: 'go build' not available on %s/%s", runtime.GOOS, runtime.GOARCH)
+	}
+}
+
+// HasGoBuild reports whether the current system can build programs with ``go build''
+// and then run them with os.StartProcess or exec.Command.
+func HasGoBuild() bool {
+	if os.Getenv("GO_GCFLAGS") != "" {
+		// It's too much work to require every caller of the go command
+		// to pass along "-gcflags="+os.Getenv("GO_GCFLAGS").
+		// For now, if $GO_GCFLAGS is set, report that we simply can't
+		// run go build.
+		return false
+	}
+	switch runtime.GOOS {
+	case "android", "nacl", "js":
+		return false
+	case "darwin":
+		if strings.HasPrefix(runtime.GOARCH, "arm") {
+			return false
+		}
+	}
+	return true
+}
diff --git a/build-1.11/deps_test.go b/build-1.11/deps_test.go
new file mode 100644
index 0000000..5c18ff2
--- /dev/null
+++ b/build-1.11/deps_test.go
@@ -0,0 +1,569 @@
+// Copyright 2012 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.
+
+// This file exercises the import parser but also checks that
+// some low-level packages do not have new dependencies added.
+
+package build
+
+import (
+	"bytes"
+	"fmt"
+	"io/ioutil"
+	"os"
+	"path/filepath"
+	"sort"
+	"strconv"
+	"strings"
+)
+
+// pkgDeps defines the expected dependencies between packages in
+// the Go source tree. It is a statement of policy.
+// Changes should not be made to this map without prior discussion.
+//
+// The map contains two kinds of entries:
+// 1) Lower-case keys are standard import paths and list the
+// allowed imports in that package.
+// 2) Upper-case keys define aliases for package sets, which can then
+// be used as dependencies by other rules.
+//
+// DO NOT CHANGE THIS DATA TO FIX BUILDS.
+//
+var pkgDeps = map[string][]string{
+	// L0 is the lowest level, core, nearly unavoidable packages.
+	"errors":                  {},
+	"io":                      {"errors", "sync", "sync/atomic"},
+	"runtime":                 {"unsafe", "runtime/internal/atomic", "runtime/internal/sys", "internal/cpu", "internal/bytealg"},
+	"runtime/internal/sys":    {},
+	"runtime/internal/atomic": {"unsafe", "runtime/internal/sys"},
+	"internal/race":           {"runtime", "unsafe"},
+	"sync":                    {"internal/race", "runtime", "sync/atomic", "unsafe"},
+	"sync/atomic":             {"unsafe"},
+	"unsafe":                  {},
+	"internal/cpu":            {},
+	"internal/bytealg":        {"unsafe", "internal/cpu"},
+
+	"L0": {
+		"errors",
+		"io",
+		"runtime",
+		"runtime/internal/atomic",
+		"sync",
+		"sync/atomic",
+		"unsafe",
+		"internal/cpu",
+		"internal/bytealg",
+	},
+
+	// L1 adds simple functions and strings processing,
+	// but not Unicode tables.
+	"math":          {"internal/cpu", "unsafe"},
+	"math/bits":     {},
+	"math/cmplx":    {"math"},
+	"math/rand":     {"L0", "math"},
+	"strconv":       {"L0", "unicode/utf8", "math", "math/bits"},
+	"unicode/utf16": {},
+	"unicode/utf8":  {},
+
+	"L1": {
+		"L0",
+		"math",
+		"math/bits",
+		"math/cmplx",
+		"math/rand",
+		"sort",
+		"strconv",
+		"unicode/utf16",
+		"unicode/utf8",
+	},
+
+	// L2 adds Unicode and strings processing.
+	"bufio":   {"L0", "unicode/utf8", "bytes"},
+	"bytes":   {"L0", "unicode", "unicode/utf8"},
+	"path":    {"L0", "unicode/utf8", "strings"},
+	"strings": {"L0", "unicode", "unicode/utf8"},
+	"unicode": {},
+
+	"L2": {
+		"L1",
+		"bufio",
+		"bytes",
+		"path",
+		"strings",
+		"unicode",
+	},
+
+	// L3 adds reflection and some basic utility packages
+	// and interface definitions, but nothing that makes
+	// system calls.
+	"crypto":                 {"L2", "hash"}, // interfaces
+	"crypto/cipher":          {"L2", "crypto/subtle", "crypto/internal/subtle"},
+	"crypto/internal/subtle": {"unsafe", "reflect"}, // reflect behind a appengine tag
+	"crypto/subtle":          {},
+	"encoding/base32":        {"L2"},
+	"encoding/base64":        {"L2", "encoding/binary"},
+	"encoding/binary":        {"L2", "reflect"},
+	"hash":                   {"L2"}, // interfaces
+	"hash/adler32":           {"L2", "hash"},
+	"hash/crc32":             {"L2", "hash"},
+	"hash/crc64":             {"L2", "hash"},
+	"hash/fnv":               {"L2", "hash"},
+	"image":                  {"L2", "image/color"}, // interfaces
+	"image/color":            {"L2"},                // interfaces
+	"image/color/palette":    {"L2", "image/color"},
+	"reflect":                {"L2"},
+	"sort":                   {"reflect"},
+
+	"L3": {
+		"L2",
+		"crypto",
+		"crypto/cipher",
+		"crypto/internal/subtle",
+		"crypto/subtle",
+		"encoding/base32",
+		"encoding/base64",
+		"encoding/binary",
+		"hash",
+		"hash/adler32",
+		"hash/crc32",
+		"hash/crc64",
+		"hash/fnv",
+		"image",
+		"image/color",
+		"image/color/palette",
+		"reflect",
+	},
+
+	// End of linear dependency definitions.
+
+	// Operating system access.
+	"syscall":                           {"L0", "internal/race", "internal/syscall/windows/sysdll", "syscall/js", "unicode/utf16"},
+	"syscall/js":                        {"L0"},
+	"internal/syscall/unix":             {"L0", "syscall"},
+	"internal/syscall/windows":          {"L0", "syscall", "internal/syscall/windows/sysdll"},
+	"internal/syscall/windows/registry": {"L0", "syscall", "internal/syscall/windows/sysdll", "unicode/utf16"},
+	"time": {
+		// "L0" without the "io" package:
+		"errors",
+		"runtime",
+		"runtime/internal/atomic",
+		"sync",
+		"sync/atomic",
+		"unsafe",
+		// Other time dependencies:
+		"internal/syscall/windows/registry",
+		"syscall",
+	},
+
+	"internal/poll":    {"L0", "internal/race", "syscall", "time", "unicode/utf16", "unicode/utf8", "internal/syscall/windows"},
+	"internal/testlog": {"L0"},
+	"os":               {"L1", "os", "syscall", "time", "internal/poll", "internal/syscall/windows", "internal/syscall/unix", "internal/testlog"},
+	"path/filepath":    {"L2", "os", "syscall", "internal/syscall/windows"},
+	"io/ioutil":        {"L2", "os", "path/filepath", "time"},
+	"os/exec":          {"L2", "os", "context", "path/filepath", "syscall"},
+	"os/signal":        {"L2", "os", "syscall"},
+
+	// OS enables basic operating system functionality,
+	// but not direct use of package syscall, nor os/signal.
+	"OS": {
+		"io/ioutil",
+		"os",
+		"os/exec",
+		"path/filepath",
+		"time",
+	},
+
+	// Formatted I/O: few dependencies (L1) but we must add reflect.
+	"fmt": {"L1", "os", "reflect"},
+	"log": {"L1", "os", "fmt", "time"},
+
+	// Packages used by testing must be low-level (L2+fmt).
+	"regexp":         {"L2", "regexp/syntax"},
+	"regexp/syntax":  {"L2"},
+	"runtime/debug":  {"L2", "fmt", "io/ioutil", "os", "time"},
+	"runtime/pprof":  {"L2", "compress/gzip", "context", "encoding/binary", "fmt", "io/ioutil", "os", "text/tabwriter", "time"},
+	"runtime/trace":  {"L0", "context", "fmt"},
+	"text/tabwriter": {"L2"},
+
+	"testing":          {"L2", "flag", "fmt", "internal/race", "os", "runtime/debug", "runtime/pprof", "runtime/trace", "time"},
+	"testing/iotest":   {"L2", "log"},
+	"testing/quick":    {"L2", "flag", "fmt", "reflect", "time"},
+	"internal/testenv": {"L2", "OS", "flag", "testing", "syscall"},
+
+	// L4 is defined as L3+fmt+log+time, because in general once
+	// you're using L3 packages, use of fmt, log, or time is not a big deal.
+	"L4": {
+		"L3",
+		"fmt",
+		"log",
+		"time",
+	},
+
+	// Go parser.
+	"go/ast":     {"L4", "OS", "go/scanner", "go/token"},
+	"go/doc":     {"L4", "go/ast", "go/token", "regexp", "text/template"},
+	"go/parser":  {"L4", "OS", "go/ast", "go/scanner", "go/token"},
+	"go/printer": {"L4", "OS", "go/ast", "go/scanner", "go/token", "text/tabwriter"},
+	"go/scanner": {"L4", "OS", "go/token"},
+	"go/token":   {"L4"},
+
+	"GOPARSER": {
+		"go/ast",
+		"go/doc",
+		"go/parser",
+		"go/printer",
+		"go/scanner",
+		"go/token",
+	},
+
+	"go/format":       {"L4", "GOPARSER", "internal/format"},
+	"internal/format": {"L4", "GOPARSER"},
+
+	// Go type checking.
+	"go/constant":               {"L4", "go/token", "math/big"},
+	"go/importer":               {"L4", "go/build", "go/internal/gccgoimporter", "go/internal/gcimporter", "go/internal/srcimporter", "go/token", "go/types"},
+	"go/internal/gcimporter":    {"L4", "OS", "go/build", "go/constant", "go/token", "go/types", "text/scanner"},
+	"go/internal/gccgoimporter": {"L4", "OS", "debug/elf", "go/constant", "go/token", "go/types", "text/scanner"},
+	"go/internal/srcimporter":   {"L4", "OS", "fmt", "go/ast", "go/build", "go/parser", "go/token", "go/types", "path/filepath"},
+	"go/types":                  {"L4", "GOPARSER", "container/heap", "go/constant"},
+
+	// One of a kind.
+	"archive/tar":              {"L4", "OS", "syscall", "os/user"},
+	"archive/zip":              {"L4", "OS", "compress/flate"},
+	"container/heap":           {"sort"},
+	"compress/bzip2":           {"L4"},
+	"compress/flate":           {"L4"},
+	"compress/gzip":            {"L4", "compress/flate"},
+	"compress/lzw":             {"L4"},
+	"compress/zlib":            {"L4", "compress/flate"},
+	"context":                  {"errors", "fmt", "reflect", "sync", "time"},
+	"database/sql":             {"L4", "container/list", "context", "database/sql/driver", "database/sql/internal"},
+	"database/sql/driver":      {"L4", "context", "time", "database/sql/internal"},
+	"debug/dwarf":              {"L4"},
+	"debug/elf":                {"L4", "OS", "debug/dwarf", "compress/zlib"},
+	"debug/gosym":              {"L4"},
+	"debug/macho":              {"L4", "OS", "debug/dwarf", "compress/zlib"},
+	"debug/pe":                 {"L4", "OS", "debug/dwarf", "compress/zlib"},
+	"debug/plan9obj":           {"L4", "OS"},
+	"encoding":                 {"L4"},
+	"encoding/ascii85":         {"L4"},
+	"encoding/asn1":            {"L4", "math/big"},
+	"encoding/csv":             {"L4"},
+	"encoding/gob":             {"L4", "OS", "encoding"},
+	"encoding/hex":             {"L4"},
+	"encoding/json":            {"L4", "encoding"},
+	"encoding/pem":             {"L4"},
+	"encoding/xml":             {"L4", "encoding"},
+	"flag":                     {"L4", "OS"},
+	"go/build":                 {"L4", "OS", "GOPARSER"},
+	"html":                     {"L4"},
+	"image/draw":               {"L4", "image/internal/imageutil"},
+	"image/gif":                {"L4", "compress/lzw", "image/color/palette", "image/draw"},
+	"image/internal/imageutil": {"L4"},
+	"image/jpeg":               {"L4", "image/internal/imageutil"},
+	"image/png":                {"L4", "compress/zlib"},
+	"index/suffixarray":        {"L4", "regexp"},
+	"internal/singleflight":    {"sync"},
+	"internal/trace":           {"L4", "OS"},
+	"math/big":                 {"L4"},
+	"mime":                     {"L4", "OS", "syscall", "internal/syscall/windows/registry"},
+	"mime/quotedprintable":     {"L4"},
+	"net/internal/socktest":    {"L4", "OS", "syscall", "internal/syscall/windows"},
+	"net/url":                  {"L4"},
+	"plugin":                   {"L0", "OS", "CGO"},
+	"runtime/pprof/internal/profile": {"L4", "OS", "compress/gzip", "regexp"},
+	"testing/internal/testdeps":      {"L4", "internal/testlog", "runtime/pprof", "regexp"},
+	"text/scanner":                   {"L4", "OS"},
+	"text/template/parse":            {"L4"},
+
+	"html/template": {
+		"L4", "OS", "encoding/json", "html", "text/template",
+		"text/template/parse",
+	},
+	"text/template": {
+		"L4", "OS", "net/url", "text/template/parse",
+	},
+
+	// Cgo.
+	// If you add a dependency on CGO, you must add the package to
+	// cgoPackages in cmd/dist/test.go.
+	"runtime/cgo": {"L0", "C"},
+	"CGO":         {"C", "runtime/cgo"},
+
+	// Fake entry to satisfy the pseudo-import "C"
+	// that shows up in programs that use cgo.
+	"C": {},
+
+	// Race detector/MSan uses cgo.
+	"runtime/race": {"C"},
+	"runtime/msan": {"C"},
+
+	// Plan 9 alone needs io/ioutil and os.
+	"os/user": {"L4", "CGO", "io/ioutil", "os", "syscall", "internal/syscall/windows", "internal/syscall/windows/registry"},
+
+	// Internal package used only for testing.
+	"os/signal/internal/pty": {"CGO", "fmt", "os", "syscall"},
+
+	// Basic networking.
+	// Because net must be used by any package that wants to
+	// do networking portably, it must have a small dependency set: just L0+basic os.
+	"net": {
+		"L0", "CGO",
+		"context", "math/rand", "os", "reflect", "sort", "syscall", "time",
+		"internal/nettrace", "internal/poll",
+		"internal/syscall/windows", "internal/singleflight", "internal/race",
+		"golang_org/x/net/dns/dnsmessage", "golang_org/x/net/lif", "golang_org/x/net/route",
+	},
+
+	// NET enables use of basic network-related packages.
+	"NET": {
+		"net",
+		"mime",
+		"net/textproto",
+		"net/url",
+	},
+
+	// Uses of networking.
+	"log/syslog":    {"L4", "OS", "net"},
+	"net/mail":      {"L4", "NET", "OS", "mime"},
+	"net/textproto": {"L4", "OS", "net"},
+
+	// Core crypto.
+	"crypto/aes":               {"L3"},
+	"crypto/des":               {"L3"},
+	"crypto/hmac":              {"L3"},
+	"crypto/internal/randutil": {"io", "sync"},
+	"crypto/md5":               {"L3"},
+	"crypto/rc4":               {"L3"},
+	"crypto/sha1":              {"L3"},
+	"crypto/sha256":            {"L3"},
+	"crypto/sha512":            {"L3"},
+
+	"CRYPTO": {
+		"crypto/aes",
+		"crypto/des",
+		"crypto/hmac",
+		"crypto/internal/randutil",
+		"crypto/md5",
+		"crypto/rc4",
+		"crypto/sha1",
+		"crypto/sha256",
+		"crypto/sha512",
+		"golang_org/x/crypto/chacha20poly1305",
+		"golang_org/x/crypto/curve25519",
+		"golang_org/x/crypto/poly1305",
+	},
+
+	// Random byte, number generation.
+	// This would be part of core crypto except that it imports
+	// math/big, which imports fmt.
+	"crypto/rand": {"L4", "CRYPTO", "OS", "math/big", "syscall", "syscall/js", "internal/syscall/unix"},
+
+	// Mathematical crypto: dependencies on fmt (L4) and math/big.
+	// We could avoid some of the fmt, but math/big imports fmt anyway.
+	"crypto/dsa":      {"L4", "CRYPTO", "math/big"},
+	"crypto/ecdsa":    {"L4", "CRYPTO", "crypto/elliptic", "math/big", "encoding/asn1"},
+	"crypto/elliptic": {"L4", "CRYPTO", "math/big"},
+	"crypto/rsa":      {"L4", "CRYPTO", "crypto/rand", "math/big"},
+
+	"CRYPTO-MATH": {
+		"CRYPTO",
+		"crypto/dsa",
+		"crypto/ecdsa",
+		"crypto/elliptic",
+		"crypto/rand",
+		"crypto/rsa",
+		"encoding/asn1",
+		"math/big",
+	},
+
+	// SSL/TLS.
+	"crypto/tls": {
+		"L4", "CRYPTO-MATH", "OS",
+		"container/list", "crypto/x509", "encoding/pem", "net", "syscall",
+	},
+	"crypto/x509": {
+		"L4", "CRYPTO-MATH", "OS", "CGO",
+		"crypto/x509/pkix", "encoding/pem", "encoding/hex", "net", "os/user", "syscall", "net/url",
+		"golang_org/x/crypto/cryptobyte", "golang_org/x/crypto/cryptobyte/asn1",
+	},
+	"crypto/x509/pkix": {"L4", "CRYPTO-MATH", "encoding/hex"},
+
+	// Simple net+crypto-aware packages.
+	"mime/multipart": {"L4", "OS", "mime", "crypto/rand", "net/textproto", "mime/quotedprintable"},
+	"net/smtp":       {"L4", "CRYPTO", "NET", "crypto/tls"},
+
+	// HTTP, kingpin of dependencies.
+	"net/http": {
+		"L4", "NET", "OS",
+		"compress/gzip",
+		"container/list",
+		"context",
+		"crypto/rand",
+		"crypto/tls",
+		"golang_org/x/net/http/httpguts",
+		"golang_org/x/net/http/httpproxy",
+		"golang_org/x/net/http2/hpack",
+		"golang_org/x/net/idna",
+		"golang_org/x/text/unicode/norm",
+		"golang_org/x/text/width",
+		"internal/nettrace",
+		"mime/multipart",
+		"net/http/httptrace",
+		"net/http/internal",
+		"runtime/debug",
+		"syscall/js",
+	},
+	"net/http/internal":  {"L4"},
+	"net/http/httptrace": {"context", "crypto/tls", "internal/nettrace", "net", "net/textproto", "reflect", "time"},
+
+	// HTTP-using packages.
+	"expvar":             {"L4", "OS", "encoding/json", "net/http"},
+	"net/http/cgi":       {"L4", "NET", "OS", "crypto/tls", "net/http", "regexp"},
+	"net/http/cookiejar": {"L4", "NET", "net/http"},
+	"net/http/fcgi":      {"L4", "NET", "OS", "context", "net/http", "net/http/cgi"},
+	"net/http/httptest": {
+		"L4", "NET", "OS", "crypto/tls", "flag", "net/http", "net/http/internal", "crypto/x509",
+		"golang_org/x/net/http/httpguts",
+	},
+	"net/http/httputil": {"L4", "NET", "OS", "context", "net/http", "net/http/internal"},
+	"net/http/pprof":    {"L4", "OS", "html/template", "net/http", "runtime/pprof", "runtime/trace"},
+	"net/rpc":           {"L4", "NET", "encoding/gob", "html/template", "net/http"},
+	"net/rpc/jsonrpc":   {"L4", "NET", "encoding/json", "net/rpc"},
+}
+
+// isMacro reports whether p is a package dependency macro
+// (uppercase name).
+func isMacro(p string) bool {
+	return 'A' <= p[0] && p[0] <= 'Z'
+}
+
+func allowed(pkg string) map[string]bool {
+	m := map[string]bool{}
+	var allow func(string)
+	allow = func(p string) {
+		if m[p] {
+			return
+		}
+		m[p] = true // set even for macros, to avoid loop on cycle
+
+		// Upper-case names are macro-expanded.
+		if isMacro(p) {
+			for _, pp := range pkgDeps[p] {
+				allow(pp)
+			}
+		}
+	}
+	for _, pp := range pkgDeps[pkg] {
+		allow(pp)
+	}
+	return m
+}
+
+// listStdPkgs returns the same list of packages as "go list std".
+func listStdPkgs(goroot string) ([]string, error) {
+	// Based on cmd/go's matchPackages function.
+	var pkgs []string
+
+	src := filepath.Join(goroot, "src") + string(filepath.Separator)
+	walkFn := func(path string, fi os.FileInfo, err error) error {
+		if err != nil || !fi.IsDir() || path == src {
+			return nil
+		}
+
+		base := filepath.Base(path)
+		if strings.HasPrefix(base, ".") || strings.HasPrefix(base, "_") || base == "testdata" {
+			return filepath.SkipDir
+		}
+
+		name := filepath.ToSlash(path[len(src):])
+		if name == "builtin" || name == "cmd" || strings.Contains(name, "golang_org") {
+			return filepath.SkipDir
+		}
+
+		pkgs = append(pkgs, name)
+		return nil
+	}
+	if err := filepath.Walk(src, walkFn); err != nil {
+		return nil, err
+	}
+	return pkgs, nil
+}
+
+// func TestDependencies(t *testing.T) {
+// 	iOS := runtime.GOOS == "darwin" && (runtime.GOARCH == "arm" || runtime.GOARCH == "arm64")
+// 	if runtime.GOOS == "nacl" || iOS {
+// 		// Tests run in a limited file system and we do not
+// 		// provide access to every source file.
+// 		t.Skipf("skipping on %s/%s, missing full GOROOT", runtime.GOOS, runtime.GOARCH)
+// 	}
+
+// 	ctxt := Default
+// 	all, err := listStdPkgs(ctxt.GOROOT)
+// 	if err != nil {
+// 		t.Fatal(err)
+// 	}
+// 	sort.Strings(all)
+
+// 	for _, pkg := range all {
+// 		imports, err := findImports(pkg)
+// 		if err != nil {
+// 			t.Error(err)
+// 			continue
+// 		}
+// 		ok := allowed(pkg)
+// 		var bad []string
+// 		for _, imp := range imports {
+// 			if !ok[imp] {
+// 				bad = append(bad, imp)
+// 			}
+// 		}
+// 		if bad != nil {
+// 			t.Errorf("unexpected dependency: %s imports %v", pkg, bad)
+// 		}
+// 	}
+// }
+
+var buildIgnore = []byte("\n// +build ignore")
+
+func findImports(pkg string) ([]string, error) {
+	dir := filepath.Join(Default.GOROOT, "src", pkg)
+	files, err := ioutil.ReadDir(dir)
+	if err != nil {
+		return nil, err
+	}
+	var imports []string
+	var haveImport = map[string]bool{}
+	for _, file := range files {
+		name := file.Name()
+		if !strings.HasSuffix(name, ".go") || strings.HasSuffix(name, "_test.go") {
+			continue
+		}
+		f, err := os.Open(filepath.Join(dir, name))
+		if err != nil {
+			return nil, err
+		}
+		var imp []string
+		data, err := readImports(f, false, &imp)
+		f.Close()
+		if err != nil {
+			return nil, fmt.Errorf("reading %v: %v", name, err)
+		}
+		if bytes.Contains(data, buildIgnore) {
+			continue
+		}
+		for _, quoted := range imp {
+			path, err := strconv.Unquote(quoted)
+			if err != nil {
+				continue
+			}
+			if !haveImport[path] {
+				haveImport[path] = true
+				imports = append(imports, path)
+			}
+		}
+	}
+	sort.Strings(imports)
+	return imports, nil
+}
diff --git a/build-1.11/read_test.go b/build-1.11/read_test.go
new file mode 100644
index 0000000..9cef657
--- /dev/null
+++ b/build-1.11/read_test.go
@@ -0,0 +1,226 @@
+// Copyright 2012 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.
+
+package build
+
+import (
+	"io"
+	"strings"
+	"testing"
+)
+
+const quote = "`"
+
+type readTest struct {
+	// Test input contains ℙ where readImports should stop.
+	in  string
+	err string
+}
+
+var readImportsTests = []readTest{
+	{
+		`package p`,
+		"",
+	},
+	{
+		`package p; import "x"`,
+		"",
+	},
+	{
+		`package p; import . "x"`,
+		"",
+	},
+	{
+		`package p; import "x";ℙvar x = 1`,
+		"",
+	},
+	{
+		`package p
+		
+		// comment
+		
+		import "x"
+		import _ "x"
+		import a "x"
+		
+		/* comment */
+		
+		import (
+			"x" /* comment */
+			_ "x"
+			a "x" // comment
+			` + quote + `x` + quote + `
+			_ /*comment*/ ` + quote + `x` + quote + `
+			a ` + quote + `x` + quote + `
+		)
+		import (
+		)
+		import ()
+		import()import()import()
+		import();import();import()
+		
+		ℙvar x = 1
+		`,
+		"",
+	},
+}
+
+var readCommentsTests = []readTest{
+	{
+		`ℙpackage p`,
+		"",
+	},
+	{
+		`ℙpackage p; import "x"`,
+		"",
+	},
+	{
+		`ℙpackage p; import . "x"`,
+		"",
+	},
+	{
+		`// foo
+
+		/* bar */
+
+		/* quux */ // baz
+		
+		/*/ zot */
+
+		// asdf
+		ℙHello, world`,
+		"",
+	},
+}
+
+func testRead(t *testing.T, tests []readTest, read func(io.Reader) ([]byte, error)) {
+	for i, tt := range tests {
+		var in, testOut string
+		j := strings.Index(tt.in, "ℙ")
+		if j < 0 {
+			in = tt.in
+			testOut = tt.in
+		} else {
+			in = tt.in[:j] + tt.in[j+len("ℙ"):]
+			testOut = tt.in[:j]
+		}
+		r := strings.NewReader(in)
+		buf, err := read(r)
+		if err != nil {
+			if tt.err == "" {
+				t.Errorf("#%d: err=%q, expected success (%q)", i, err, string(buf))
+				continue
+			}
+			if !strings.Contains(err.Error(), tt.err) {
+				t.Errorf("#%d: err=%q, expected %q", i, err, tt.err)
+				continue
+			}
+			continue
+		}
+		if err == nil && tt.err != "" {
+			t.Errorf("#%d: success, expected %q", i, tt.err)
+			continue
+		}
+
+		out := string(buf)
+		if out != testOut {
+			t.Errorf("#%d: wrong output:\nhave %q\nwant %q\n", i, out, testOut)
+		}
+	}
+}
+
+func TestReadImports(t *testing.T) {
+	testRead(t, readImportsTests, func(r io.Reader) ([]byte, error) { return readImports(r, true, nil) })
+}
+
+func TestReadComments(t *testing.T) {
+	testRead(t, readCommentsTests, readComments)
+}
+
+var readFailuresTests = []readTest{
+	{
+		`package`,
+		"syntax error",
+	},
+	{
+		"package p\n\x00\nimport `math`\n",
+		"unexpected NUL in input",
+	},
+	{
+		`package p; import`,
+		"syntax error",
+	},
+	{
+		`package p; import "`,
+		"syntax error",
+	},
+	{
+		"package p; import ` \n\n",
+		"syntax error",
+	},
+	{
+		`package p; import "x`,
+		"syntax error",
+	},
+	{
+		`package p; import _`,
+		"syntax error",
+	},
+	{
+		`package p; import _ "`,
+		"syntax error",
+	},
+	{
+		`package p; import _ "x`,
+		"syntax error",
+	},
+	{
+		`package p; import .`,
+		"syntax error",
+	},
+	{
+		`package p; import . "`,
+		"syntax error",
+	},
+	{
+		`package p; import . "x`,
+		"syntax error",
+	},
+	{
+		`package p; import (`,
+		"syntax error",
+	},
+	{
+		`package p; import ("`,
+		"syntax error",
+	},
+	{
+		`package p; import ("x`,
+		"syntax error",
+	},
+	{
+		`package p; import ("x"`,
+		"syntax error",
+	},
+}
+
+func TestReadFailures(t *testing.T) {
+	// Errors should be reported (true arg to readImports).
+	testRead(t, readFailuresTests, func(r io.Reader) ([]byte, error) { return readImports(r, true, nil) })
+}
+
+func TestReadFailuresIgnored(t *testing.T) {
+	// Syntax errors should not be reported (false arg to readImports).
+	// Instead, entire file should be the output and no error.
+	// Convert tests not to return syntax errors.
+	tests := make([]readTest, len(readFailuresTests))
+	copy(tests, readFailuresTests)
+	for i := range tests {
+		tt := &tests[i]
+		if !strings.Contains(tt.err, "NUL") {
+			tt.err = ""
+		}
+	}
+	testRead(t, tests, func(r io.Reader) ([]byte, error) { return readImports(r, false, nil) })
+}
diff --git a/build-1.11/syslist_test.go b/build-1.11/syslist_test.go
new file mode 100644
index 0000000..7973ff4
--- /dev/null
+++ b/build-1.11/syslist_test.go
@@ -0,0 +1,62 @@
+// Copyright 2011 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.
+
+package build
+
+import (
+	"runtime"
+	"testing"
+)
+
+var (
+	thisOS    = runtime.GOOS
+	thisArch  = runtime.GOARCH
+	otherOS   = anotherOS()
+	otherArch = anotherArch()
+)
+
+func anotherOS() string {
+	if thisOS != "darwin" {
+		return "darwin"
+	}
+	return "linux"
+}
+
+func anotherArch() string {
+	if thisArch != "amd64" {
+		return "amd64"
+	}
+	return "386"
+}
+
+type GoodFileTest struct {
+	name   string
+	result bool
+}
+
+var tests = []GoodFileTest{
+	{"file.go", true},
+	{"file.c", true},
+	{"file_foo.go", true},
+	{"file_" + thisArch + ".go", true},
+	{"file_" + otherArch + ".go", false},
+	{"file_" + thisOS + ".go", true},
+	{"file_" + otherOS + ".go", false},
+	{"file_" + thisOS + "_" + thisArch + ".go", true},
+	{"file_" + otherOS + "_" + thisArch + ".go", false},
+	{"file_" + thisOS + "_" + otherArch + ".go", false},
+	{"file_" + otherOS + "_" + otherArch + ".go", false},
+	{"file_foo_" + thisArch + ".go", true},
+	{"file_foo_" + otherArch + ".go", false},
+	{"file_" + thisOS + ".c", true},
+	{"file_" + otherOS + ".c", false},
+}
+
+func TestGoodOSArch(t *testing.T) {
+	for _, test := range tests {
+		if Default.goodOSArchFile(test.name, make(map[string]bool)) != test.result {
+			t.Fatalf("goodOSArchFile(%q) != %v", test.name, test.result)
+		}
+	}
+}
diff --git a/build-1.11/testdata/doc/a_test.go b/build-1.11/testdata/doc/a_test.go
new file mode 100644
index 0000000..1c07b56
--- /dev/null
+++ b/build-1.11/testdata/doc/a_test.go
@@ -0,0 +1,2 @@
+// Doc from xtests
+package doc_test
diff --git a/build-1.11/testdata/doc/b_test.go b/build-1.11/testdata/doc/b_test.go
new file mode 100644
index 0000000..0cf1605
--- /dev/null
+++ b/build-1.11/testdata/doc/b_test.go
@@ -0,0 +1,1 @@
+package doc_test
diff --git a/build-1.11/testdata/doc/c_test.go b/build-1.11/testdata/doc/c_test.go
new file mode 100644
index 0000000..1025707
--- /dev/null
+++ b/build-1.11/testdata/doc/c_test.go
@@ -0,0 +1,1 @@
+package doc
diff --git a/build-1.11/testdata/doc/d_test.go b/build-1.11/testdata/doc/d_test.go
new file mode 100644
index 0000000..ec19564
--- /dev/null
+++ b/build-1.11/testdata/doc/d_test.go
@@ -0,0 +1,2 @@
+// Doc from regular tests.
+package doc
diff --git a/build-1.11/testdata/doc/e.go b/build-1.11/testdata/doc/e.go
new file mode 100644
index 0000000..1025707
--- /dev/null
+++ b/build-1.11/testdata/doc/e.go
@@ -0,0 +1,1 @@
+package doc
diff --git a/build-1.11/testdata/doc/f.go b/build-1.11/testdata/doc/f.go
new file mode 100644
index 0000000..ab1d0bc
--- /dev/null
+++ b/build-1.11/testdata/doc/f.go
@@ -0,0 +1,2 @@
+// Correct
+package doc
diff --git a/build-1.11/testdata/empty/dummy b/build-1.11/testdata/empty/dummy
new file mode 100644
index 0000000..e69de29
diff --git a/build-1.11/testdata/multi/file.go b/build-1.11/testdata/multi/file.go
new file mode 100644
index 0000000..ee946eb
--- /dev/null
+++ b/build-1.11/testdata/multi/file.go
@@ -0,0 +1,5 @@
+// Test data - not compiled.
+
+package main
+
+func main() {}
diff --git a/build-1.11/testdata/multi/file_appengine.go b/build-1.11/testdata/multi/file_appengine.go
new file mode 100644
index 0000000..4ea31e7
--- /dev/null
+++ b/build-1.11/testdata/multi/file_appengine.go
@@ -0,0 +1,5 @@
+// Test data - not compiled.
+
+package test_package
+
+func init() {}
diff --git a/build-1.11/testdata/other/file/file.go b/build-1.11/testdata/other/file/file.go
new file mode 100644
index 0000000..bbfd3e9
--- /dev/null
+++ b/build-1.11/testdata/other/file/file.go
@@ -0,0 +1,5 @@
+// Test data - not compiled.
+
+package file
+
+func F() {}
diff --git a/build-1.11/testdata/other/main.go b/build-1.11/testdata/other/main.go
new file mode 100644
index 0000000..e090435
--- /dev/null
+++ b/build-1.11/testdata/other/main.go
@@ -0,0 +1,11 @@
+// Test data - not compiled.
+
+package main
+
+import (
+	"./file"
+)
+
+func main() {
+	file.F()
+}
diff --git a/mage/main_test.go b/mage/main_test.go
index 7ab7fa5..977a015 100644
--- a/mage/main_test.go
+++ b/mage/main_test.go
@@ -15,7 +15,7 @@ import (
 	"testing"
 	"time"
 
-	"github.com/magefile/mage/build"
+	"github.com/magefile/mage/build-1.10"
 	"github.com/magefile/mage/mg"
 )