import (
        "bytes"
-       "cmd/go/internal/cfg"
        "cmd/go/internal/base"
+       "cmd/go/internal/cfg"
        "fmt"
        "io"
        "io/ioutil"
 
        "cmd/go/internal/base"
        "cmd/go/internal/buildid"
        "cmd/go/internal/cfg"
+       "cmd/go/internal/load"
        "cmd/go/internal/str"
 )
 
        return "<stringsFlag>"
 }
 
-func pkgsMain(pkgs []*Package) (res []*Package) {
+func pkgsMain(pkgs []*load.Package) (res []*load.Package) {
        for _, p := range pkgs {
                if p.Name == "main" {
                        res = append(res, p)
        return res
 }
 
-func pkgsNotMain(pkgs []*Package) (res []*Package) {
+func pkgsNotMain(pkgs []*load.Package) (res []*load.Package) {
        for _, p := range pkgs {
                if p.Name != "main" {
                        res = append(res, p)
        return res
 }
 
-var pkgsFilter = func(pkgs []*Package) []*Package { return pkgs }
+var pkgsFilter = func(pkgs []*load.Package) []*load.Package { return pkgs }
 
 func buildModeInit() {
        gccgo := cfg.BuildToolchainName == "gccgo"
        case "archive":
                pkgsFilter = pkgsNotMain
        case "c-archive":
-               pkgsFilter = func(p []*Package) []*Package {
+               pkgsFilter = func(p []*load.Package) []*load.Package {
                        if len(p) != 1 || p[0].Name != "main" {
                                base.Fatalf("-buildmode=c-archive requires exactly one main package")
                        }
        var b builder
        b.init()
 
-       pkgs := packagesForBuild(args)
+       pkgs := load.PackagesForBuild(args)
 
        if len(pkgs) == 1 && pkgs[0].Name == "main" && cfg.BuildO == "" {
                _, cfg.BuildO = path.Split(pkgs[0].ImportPath)
                        base.Fatalf("no packages to build")
                }
                p := pkgs[0]
-               p.target = cfg.BuildO
+               p.Internal.Target = cfg.BuildO
                p.Stale = true // must build - not up to date
                p.StaleReason = "build -o flag in use"
                a := b.action(modeInstall, depMode, p)
 
        var a *action
        if cfg.BuildBuildmode == "shared" {
-               pkgs := pkgsFilter(packages(args))
+               pkgs := pkgsFilter(load.Packages(args))
                if libName, err := libname(args, pkgs); err != nil {
                        base.Fatalf("%s", err.Error())
                } else {
                }
        } else {
                a = &action{}
-               for _, p := range pkgsFilter(packages(args)) {
+               for _, p := range pkgsFilter(load.Packages(args)) {
                        a.deps = append(a.deps, b.action(modeBuild, depMode, p))
                }
        }
        `,
 }
 
-// isMetaPackage checks if name is a reserved package name that expands to multiple packages
-func isMetaPackage(name string) bool {
-       return name == "std" || name == "cmd" || name == "all"
-}
-
 // libname returns the filename to use for the shared library when using
 // -buildmode=shared. The rules we use are:
 // Use arguments for special 'meta' packages:
 //     gopkg.in/tomb.v2 -> libgopkg.in-tomb.v2.so
 //     a/... b/... ---> liba/c,b/d.so - all matching import paths
 // Name parts are joined with ','.
-func libname(args []string, pkgs []*Package) (string, error) {
+func libname(args []string, pkgs []*load.Package) (string, error) {
        var libname string
        appendName := func(arg string) {
                if libname == "" {
        }
        var haveNonMeta bool
        for _, arg := range args {
-               if isMetaPackage(arg) {
+               if load.IsMetaPackage(arg) {
                        appendName(arg)
                } else {
                        haveNonMeta = true
 }
 
 func installPackages(args []string, forGet bool) {
-       if gobin != "" && !filepath.IsAbs(gobin) {
+       if cfg.GOBIN != "" && !filepath.IsAbs(cfg.GOBIN) {
                base.Fatalf("cannot install, GOBIN must be an absolute path")
        }
 
        instrumentInit()
        buildModeInit()
-       pkgs := pkgsFilter(packagesForBuild(args))
+       pkgs := pkgsFilter(load.PackagesForBuild(args))
 
        for _, p := range pkgs {
                if p.Target == "" && (!p.Standard || p.ImportPath != "unsafe") {
                        switch {
-                       case p.gobinSubdir:
+                       case p.Internal.GobinSubdir:
                                base.Errorf("go install: cannot install cross-compiled binaries when GOBIN is set")
-                       case p.cmdline:
+                       case p.Internal.Cmdline:
                                base.Errorf("go install: no install location for .go files listed on command line (GOBIN not set)")
                        case p.ConflictDir != "":
                                base.Errorf("go install: no install location for %s: hidden by %s", p.Dir, p.ConflictDir)
                        // cmd/cgo is handled specially in b.action, so that we can
                        // both build and use it in the same 'go install'.
                        action := b.action(modeInstall, modeInstall, p)
-                       if goTools[p.ImportPath] == toTool && p.ImportPath != "cmd/cgo" {
+                       if load.GoTools[p.ImportPath] == load.ToTool && p.ImportPath != "cmd/cgo" {
                                a.deps = append(a.deps, action.deps...)
                                action.deps = append(action.deps, a)
                                tools = append(tools, action)
 
 // An action represents a single action in the action graph.
 type action struct {
-       p          *Package      // the package this action works on
+       p          *load.Package // the package this action works on
        deps       []*action     // actions that must happen before this one
        triggers   []*action     // inverse of deps
        cgo        *action       // action for cgo binary if needed
 // cacheKey is the key for the action cache.
 type cacheKey struct {
        mode  buildMode
-       p     *Package
+       p     *load.Package
        shlib string
 }
 
        modeInstall
 )
 
-var (
-       goroot    = filepath.Clean(runtime.GOROOT())
-       gobin     = os.Getenv("GOBIN")
-       gorootBin = filepath.Join(goroot, "bin")
-       gorootPkg = filepath.Join(goroot, "pkg")
-       gorootSrc = filepath.Join(goroot, "src")
-)
-
 func (b *builder) init() {
        var err error
        b.print = func(a ...interface{}) (int, error) {
        }
 }
 
-// goFilesPackage creates a package for building a collection of Go files
-// (typically named on the command line).  The target is named p.a for
-// package p or named after the first Go file for package main.
-func goFilesPackage(gofiles []string) *Package {
-       // TODO: Remove this restriction.
-       for _, f := range gofiles {
-               if !strings.HasSuffix(f, ".go") {
-                       base.Fatalf("named files must be .go files")
-               }
-       }
-
-       var stk importStack
-       ctxt := cfg.BuildContext
-       ctxt.UseAllFiles = true
-
-       // Synthesize fake "directory" that only shows the named files,
-       // to make it look like this is a standard package or
-       // command directory. So that local imports resolve
-       // consistently, the files must all be in the same directory.
-       var dirent []os.FileInfo
-       var dir string
-       for _, file := range gofiles {
-               fi, err := os.Stat(file)
-               if err != nil {
-                       base.Fatalf("%s", err)
-               }
-               if fi.IsDir() {
-                       base.Fatalf("%s is a directory, should be a Go file", file)
-               }
-               dir1, _ := filepath.Split(file)
-               if dir1 == "" {
-                       dir1 = "./"
-               }
-               if dir == "" {
-                       dir = dir1
-               } else if dir != dir1 {
-                       base.Fatalf("named files must all be in one directory; have %s and %s", dir, dir1)
-               }
-               dirent = append(dirent, fi)
-       }
-       ctxt.ReadDir = func(string) ([]os.FileInfo, error) { return dirent, nil }
-
-       var err error
-       if dir == "" {
-               dir = base.Cwd
-       }
-       dir, err = filepath.Abs(dir)
-       if err != nil {
-               base.Fatalf("%s", err)
-       }
-
-       bp, err := ctxt.ImportDir(dir, 0)
-       pkg := new(Package)
-       pkg.local = true
-       pkg.cmdline = true
-       stk.push("main")
-       pkg.load(&stk, bp, err)
-       stk.pop()
-       pkg.localPrefix = dirToImportPath(dir)
-       pkg.ImportPath = "command-line-arguments"
-       pkg.target = ""
-
-       if pkg.Name == "main" {
-               _, elem := filepath.Split(gofiles[0])
-               exe := elem[:len(elem)-len(".go")] + cfg.ExeSuffix
-               if cfg.BuildO == "" {
-                       cfg.BuildO = exe
-               }
-               if gobin != "" {
-                       pkg.target = filepath.Join(gobin, exe)
-               }
-       }
-
-       pkg.Target = pkg.target
-       pkg.Stale = true
-       pkg.StaleReason = "files named on command line"
-
-       computeStale(pkg)
-       return pkg
-}
-
 // readpkglist returns the list of packages that were built into the shared library
 // at shlibpath. For the native toolchain this list is stored, newline separated, in
 // an ELF note with name "Go\x00\x00" and type 1. For GCCGO it is extracted from the
 // .go_export section.
-func readpkglist(shlibpath string) (pkgs []*Package) {
-       var stk importStack
+func readpkglist(shlibpath string) (pkgs []*load.Package) {
+       var stk load.ImportStack
        if cfg.BuildToolchainName == "gccgo" {
                f, _ := elf.Open(shlibpath)
                sect := f.Section(".go_export")
                        if strings.HasPrefix(t, "pkgpath ") {
                                t = strings.TrimPrefix(t, "pkgpath ")
                                t = strings.TrimSuffix(t, ";")
-                               pkgs = append(pkgs, loadPackage(t, &stk))
+                               pkgs = append(pkgs, load.LoadPackage(t, &stk))
                        }
                }
        } else {
                scanner := bufio.NewScanner(bytes.NewBuffer(pkglistbytes))
                for scanner.Scan() {
                        t := scanner.Text()
-                       pkgs = append(pkgs, loadPackage(t, &stk))
+                       pkgs = append(pkgs, load.LoadPackage(t, &stk))
                }
        }
        return
 // depMode is the action to use when building dependencies.
 // action never looks for p in a shared library, but may find p's dependencies in a
 // shared library if buildLinkshared is true.
-func (b *builder) action(mode buildMode, depMode buildMode, p *Package) *action {
+func (b *builder) action(mode buildMode, depMode buildMode, p *load.Package) *action {
        return b.action1(mode, depMode, p, false, "")
 }
 
 // depMode is the action to use when building dependencies.
 // action1 will look for p in a shared library if lookshared is true.
 // forShlib is the shared library that p will become part of, if any.
-func (b *builder) action1(mode buildMode, depMode buildMode, p *Package, lookshared bool, forShlib string) *action {
+func (b *builder) action1(mode buildMode, depMode buildMode, p *load.Package, lookshared bool, forShlib string) *action {
        shlib := ""
        if lookshared {
                shlib = p.Shlib
                return a
        }
 
-       a = &action{p: p, pkgdir: p.build.PkgRoot}
-       if p.pkgdir != "" { // overrides p.t
-               a.pkgdir = p.pkgdir
+       a = &action{p: p, pkgdir: p.Internal.Build.PkgRoot}
+       if p.Internal.Pkgdir != "" { // overrides p.t
+               a.pkgdir = p.Internal.Pkgdir
        }
        b.actionCache[key] = a
 
-       for _, p1 := range p.imports {
+       for _, p1 := range p.Internal.Imports {
                if forShlib != "" {
                        // p is part of a shared library.
                        if p1.Shlib != "" && p1.Shlib != forShlib {
        // are writing is not the cgo we need to use.
        if cfg.Goos == runtime.GOOS && cfg.Goarch == runtime.GOARCH && !cfg.BuildRace && !cfg.BuildMSan {
                if (len(p.CgoFiles) > 0 || p.Standard && p.ImportPath == "runtime/cgo") && !cfg.BuildLinkshared && cfg.BuildBuildmode != "shared" {
-                       var stk importStack
-                       p1 := loadPackage("cmd/cgo", &stk)
+                       var stk load.ImportStack
+                       p1 := load.LoadPackage("cmd/cgo", &stk)
                        if p1.Error != nil {
                                base.Fatalf("load cmd/cgo: %v", p1.Error)
                        }
                // gccgo standard library is "fake" too.
                if cfg.BuildToolchainName == "gccgo" {
                        // the target name is needed for cgo.
-                       a.target = p.target
+                       a.target = p.Internal.Target
                        return a
                }
        }
 
-       if !p.Stale && p.target != "" {
-               // p.Stale==false implies that p.target is up-to-date.
+       if !p.Stale && p.Internal.Target != "" {
+               // p.Stale==false implies that p.Internal.Target is up-to-date.
                // Record target name for use by actions depending on this one.
-               a.target = p.target
+               a.target = p.Internal.Target
                return a
        }
 
-       if p.local && p.target == "" {
+       if p.Internal.Local && p.Internal.Target == "" {
                // Imported via local path. No permanent target.
                mode = modeBuild
        }
-       work := p.pkgdir
+       work := p.Internal.Pkgdir
        if work == "" {
                work = b.work
        }
        case modeInstall:
                a.f = (*builder).install
                a.deps = []*action{b.action1(modeBuild, depMode, p, lookshared, forShlib)}
-               a.target = a.p.target
+               a.target = a.p.Internal.Target
 
                // Install header for cgo in c-archive and c-shared modes.
-               if p.usesCgo() && (cfg.BuildBuildmode == "c-archive" || cfg.BuildBuildmode == "c-shared") {
+               if p.UsesCgo() && (cfg.BuildBuildmode == "c-archive" || cfg.BuildBuildmode == "c-shared") {
                        hdrTarget := a.target[:len(a.target)-len(filepath.Ext(a.target))] + ".h"
                        if cfg.BuildContext.Compiler == "gccgo" {
                                // For the header file, remove the "lib"
                        // naming conflicts. The only possible conflict is if we were
                        // to create a top-level package named exe.
                        name := "a.out"
-                       if p.exeName != "" {
-                               name = p.exeName
-                       } else if cfg.Goos == "darwin" && cfg.BuildBuildmode == "c-shared" && p.target != "" {
+                       if p.Internal.ExeName != "" {
+                               name = p.Internal.ExeName
+                       } else if cfg.Goos == "darwin" && cfg.BuildBuildmode == "c-shared" && p.Internal.Target != "" {
                                // On OS X, the linker output name gets recorded in the
                                // shared library's LC_ID_DYLIB load command.
                                // The code invoking the linker knows to pass only the final
                                // path element. Arrange that the path element matches what
                                // we'll install it as; otherwise the library is only loadable as "a.out".
-                               _, name = filepath.Split(p.target)
+                               _, name = filepath.Split(p.Internal.Target)
                        }
                        a.target = a.objdir + filepath.Join("exe", name) + cfg.ExeSuffix
                }
        return a
 }
 
-func (b *builder) libaction(libname string, pkgs []*Package, mode, depMode buildMode) *action {
+func (b *builder) libaction(libname string, pkgs []*load.Package, mode, depMode buildMode) *action {
        a := &action{}
        switch mode {
        default:
                a.f = (*builder).linkShared
                a.target = filepath.Join(b.work, libname)
                for _, p := range pkgs {
-                       if p.target == "" {
+                       if p.Internal.Target == "" {
                                continue
                        }
                        a.deps = append(a.deps, b.action(depMode, depMode, p))
                                seencgo = seencgo || (p.Standard && p.ImportPath == "runtime/cgo")
                        }
                        if !seencgo {
-                               var stk importStack
-                               p := loadPackage("runtime/cgo", &stk)
+                               var stk load.ImportStack
+                               p := load.LoadPackage("runtime/cgo", &stk)
                                if p.Error != nil {
                                        base.Fatalf("load runtime/cgo: %v", p.Error)
                                }
-                               computeStale(p)
+                               load.ComputeStale(p)
                                // If runtime/cgo is in another shared library, then that's
                                // also the shared library that contains runtime, so
                                // something will depend on it and so runtime/cgo's staleness
                                // will be checked when processing that library.
                                if p.Shlib == "" || p.Shlib == libname {
-                                       pkgs = append([]*Package{}, pkgs...)
+                                       pkgs = append([]*load.Package{}, pkgs...)
                                        pkgs = append(pkgs, p)
                                }
                        }
                                        seenmath = seenmath || (p.Standard && p.ImportPath == "math")
                                }
                                if !seenmath {
-                                       var stk importStack
-                                       p := loadPackage("math", &stk)
+                                       var stk load.ImportStack
+                                       p := load.LoadPackage("math", &stk)
                                        if p.Error != nil {
                                                base.Fatalf("load math: %v", p.Error)
                                        }
-                                       computeStale(p)
+                                       load.ComputeStale(p)
                                        // If math is in another shared library, then that's
                                        // also the shared library that contains runtime, so
                                        // something will depend on it and so math's staleness
                                        // will be checked when processing that library.
                                        if p.Shlib == "" || p.Shlib == libname {
-                                               pkgs = append([]*Package{}, pkgs...)
+                                               pkgs = append([]*load.Package{}, pkgs...)
                                                pkgs = append(pkgs, p)
                                        }
                                }
                // Figure out where the library will go.
                var libdir string
                for _, p := range pkgs {
-                       plibdir := p.build.PkgTargetRoot
+                       plibdir := p.Internal.Build.PkgTargetRoot
                        if gccgo {
                                plibdir = filepath.Join(plibdir, "shlibs")
                        }
                        built = fi.ModTime()
                }
                for _, p := range pkgs {
-                       if p.target == "" {
+                       if p.Internal.Target == "" {
                                continue
                        }
                        stale = stale || p.Stale
-                       lstat, err := os.Stat(p.target)
+                       lstat, err := os.Stat(p.Internal.Target)
                        if err != nil || lstat.ModTime().After(built) {
                                stale = true
                        }
                        buildAction := b.libaction(libname, pkgs, modeBuild, depMode)
                        a.deps = []*action{buildAction}
                        for _, p := range pkgs {
-                               if p.target == "" {
+                               if p.Internal.Target == "" {
                                        continue
                                }
                                shlibnameaction := &action{}
                                shlibnameaction.f = (*builder).installShlibname
-                               shlibnameaction.target = p.target[:len(p.target)-2] + ".shlibname"
+                               shlibnameaction.target = p.Internal.Target[:len(p.Internal.Target)-2] + ".shlibname"
                                a.deps = append(a.deps, shlibnameaction)
                                shlibnameaction.deps = append(shlibnameaction.deps, buildAction)
                        }
        // Return an error if the package has CXX files but it's not using
        // cgo nor SWIG, since the CXX files can only be processed by cgo
        // and SWIG.
-       if len(a.p.CXXFiles) > 0 && !a.p.usesCgo() && !a.p.usesSwig() {
+       if len(a.p.CXXFiles) > 0 && !a.p.UsesCgo() && !a.p.UsesSwig() {
                return fmt.Errorf("can't build package %s because it contains C++ files (%s) but it's not using cgo nor SWIG",
                        a.p.ImportPath, strings.Join(a.p.CXXFiles, ","))
        }
        // Same as above for Objective-C files
-       if len(a.p.MFiles) > 0 && !a.p.usesCgo() && !a.p.usesSwig() {
+       if len(a.p.MFiles) > 0 && !a.p.UsesCgo() && !a.p.UsesSwig() {
                return fmt.Errorf("can't build package %s because it contains Objective-C files (%s) but it's not using cgo nor SWIG",
                        a.p.ImportPath, strings.Join(a.p.MFiles, ","))
        }
        // Same as above for Fortran files
-       if len(a.p.FFiles) > 0 && !a.p.usesCgo() && !a.p.usesSwig() {
+       if len(a.p.FFiles) > 0 && !a.p.UsesCgo() && !a.p.UsesSwig() {
                return fmt.Errorf("can't build package %s because it contains Fortran files (%s) but it's not using cgo nor SWIG",
                        a.p.ImportPath, strings.Join(a.p.FFiles, ","))
        }
        sfiles = append(sfiles, a.p.SFiles...)
        cxxfiles = append(cxxfiles, a.p.CXXFiles...)
 
-       if a.p.usesCgo() || a.p.usesSwig() {
+       if a.p.UsesCgo() || a.p.UsesSwig() {
                if pcCFLAGS, pcLDFLAGS, err = b.getPkgConfigFlags(a.p); err != nil {
                        return
                }
        // Run SWIG on each .swig and .swigcxx file.
        // Each run will generate two files, a .go file and a .c or .cxx file.
        // The .go file will use import "C" and is to be processed by cgo.
-       if a.p.usesSwig() {
+       if a.p.UsesSwig() {
                outGo, outC, outCXX, err := b.swig(a.p, obj, pcCFLAGS)
                if err != nil {
                        return err
        }
 
        // Run cgo.
-       if a.p.usesCgo() || a.p.usesSwig() {
+       if a.p.UsesCgo() || a.p.UsesSwig() {
                // In a package using cgo, cgo compiles the C, C++ and assembly files with gcc.
                // There is one exception: runtime/cgo's job is to bridge the
                // cgo and non-cgo worlds, so it necessarily has files in both.
        }
 
        // If we're doing coverage, preprocess the .go files and put them in the work directory
-       if a.p.coverMode != "" {
+       if a.p.Internal.CoverMode != "" {
                for i, file := range gofiles {
                        var sourceFile string
                        var coverFile string
                                coverFile = filepath.Join(obj, file)
                                key = file
                        }
-                       cover := a.p.coverVars[key]
+                       cover := a.p.Internal.CoverVars[key]
                        if cover == nil || isTestFile(file) {
                                // Not covering this file.
                                continue
 }
 
 // Calls pkg-config if needed and returns the cflags/ldflags needed to build the package.
-func (b *builder) getPkgConfigFlags(p *Package) (cflags, ldflags []string, err error) {
+func (b *builder) getPkgConfigFlags(p *load.Package) (cflags, ldflags []string, err error) {
        if pkgs := p.CgoPkgConfig; len(pkgs) > 0 {
                var out []byte
                out, err = b.runOut(p.Dir, p.ImportPath, nil, b.pkgconfigCmd(), "--cflags", pkgs)
 func (b *builder) includeArgs(flag string, all []*action) []string {
        inc := []string{}
        incMap := map[string]bool{
-               b.work:    true, // handled later
-               gorootPkg: true,
-               "":        true, // ignore empty strings
+               b.work:        true, // handled later
+               cfg.GOROOTpkg: true,
+               "":            true, // ignore empty strings
        }
 
        // Look in the temporary space for results of test-specific actions.
                if a1.p == nil {
                        continue
                }
-               if dir := a1.pkgdir; dir != a1.p.build.PkgRoot && !incMap[dir] {
+               if dir := a1.pkgdir; dir != a1.p.Internal.Build.PkgRoot && !incMap[dir] {
                        incMap[dir] = true
                        inc = append(inc, flag, dir)
                }
        // in the original GOPATH order.
        need := map[string]*build.Package{}
        for _, a1 := range all {
-               if a1.p != nil && a1.pkgdir == a1.p.build.PkgRoot {
-                       need[a1.p.build.Root] = a1.p.build
+               if a1.p != nil && a1.pkgdir == a1.p.Internal.Build.PkgRoot {
+                       need[a1.p.Internal.Build.Root] = a1.p.Internal.Build
                }
        }
        for _, root := range cfg.Gopath {
                if a1.p == nil {
                        continue
                }
-               if dir := a1.pkgdir; dir == a1.p.build.PkgRoot && !incMap[dir] {
+               if dir := a1.pkgdir; dir == a1.p.Internal.Build.PkgRoot && !incMap[dir] {
                        incMap[dir] = true
-                       inc = append(inc, flag, a1.p.build.PkgTargetRoot)
+                       inc = append(inc, flag, a1.p.Internal.Build.PkgTargetRoot)
                }
        }
 
        return b.run(a.objdir, "cover "+a.p.ImportPath, nil,
                cfg.BuildToolexec,
                base.Tool("cover"),
-               "-mode", a.p.coverMode,
+               "-mode", a.p.Internal.CoverMode,
                "-var", varName,
                "-o", dst,
                src)
 type toolchain interface {
        // gc runs the compiler in a specific directory on a set of files
        // and returns the name of the generated output file.
-       gc(b *builder, p *Package, archive, obj string, asmhdr bool, importArgs []string, gofiles []string) (ofile string, out []byte, err error)
+       gc(b *builder, p *load.Package, archive, obj string, asmhdr bool, importArgs []string, gofiles []string) (ofile string, out []byte, err error)
        // cc runs the toolchain's C compiler in a directory on a C file
        // to produce an output file.
-       cc(b *builder, p *Package, objdir, ofile, cfile string) error
+       cc(b *builder, p *load.Package, objdir, ofile, cfile string) error
        // asm runs the assembler in a specific directory on specific files
        // and returns a list of named output files.
-       asm(b *builder, p *Package, obj string, sfiles []string) ([]string, error)
+       asm(b *builder, p *load.Package, obj string, sfiles []string) ([]string, error)
        // pkgpath builds an appropriate path for a temporary package file.
-       pkgpath(basedir string, p *Package) string
+       pkgpath(basedir string, p *load.Package) string
        // pack runs the archive packer in a specific directory to create
        // an archive from a set of object files.
        // typically it is run in the object directory.
-       pack(b *builder, p *Package, objDir, afile string, ofiles []string) error
+       pack(b *builder, p *load.Package, objDir, afile string, ofiles []string) error
        // ld runs the linker to create an executable starting at mainpkg.
        ld(b *builder, root *action, out string, allactions []*action, mainpkg string, ofiles []string) error
        // ldShared runs the linker to create a shared library containing the pkgs built by toplevelactions
        return ""
 }
 
-func (noToolchain) gc(b *builder, p *Package, archive, obj string, asmhdr bool, importArgs []string, gofiles []string) (ofile string, out []byte, err error) {
+func (noToolchain) gc(b *builder, p *load.Package, archive, obj string, asmhdr bool, importArgs []string, gofiles []string) (ofile string, out []byte, err error) {
        return "", nil, noCompiler()
 }
 
-func (noToolchain) asm(b *builder, p *Package, obj string, sfiles []string) ([]string, error) {
+func (noToolchain) asm(b *builder, p *load.Package, obj string, sfiles []string) ([]string, error) {
        return nil, noCompiler()
 }
 
-func (noToolchain) pkgpath(basedir string, p *Package) string {
+func (noToolchain) pkgpath(basedir string, p *load.Package) string {
        noCompiler()
        return ""
 }
 
-func (noToolchain) pack(b *builder, p *Package, objDir, afile string, ofiles []string) error {
+func (noToolchain) pack(b *builder, p *load.Package, objDir, afile string, ofiles []string) error {
        return noCompiler()
 }
 
        return noCompiler()
 }
 
-func (noToolchain) cc(b *builder, p *Package, objdir, ofile, cfile string) error {
+func (noToolchain) cc(b *builder, p *load.Package, objdir, ofile, cfile string) error {
        return noCompiler()
 }
 
        return base.Tool("link")
 }
 
-func (gcToolchain) gc(b *builder, p *Package, archive, obj string, asmhdr bool, importArgs []string, gofiles []string) (ofile string, output []byte, err error) {
+func (gcToolchain) gc(b *builder, p *load.Package, archive, obj string, asmhdr bool, importArgs []string, gofiles []string) (ofile string, output []byte, err error) {
        if archive != "" {
                ofile = archive
        } else {
        if cfg.BuildContext.InstallSuffix != "" {
                gcargs = append(gcargs, "-installsuffix", cfg.BuildContext.InstallSuffix)
        }
-       if p.buildID != "" {
-               gcargs = append(gcargs, "-buildid", p.buildID)
+       if p.Internal.BuildID != "" {
+               gcargs = append(gcargs, "-buildid", p.Internal.BuildID)
        }
 
        for _, path := range p.Imports {
                }
        }
 
-       args := []interface{}{cfg.BuildToolexec, base.Tool("compile"), "-o", ofile, "-trimpath", b.work, buildGcflags, gcargs, "-D", p.localPrefix, importArgs}
+       args := []interface{}{cfg.BuildToolexec, base.Tool("compile"), "-o", ofile, "-trimpath", b.work, buildGcflags, gcargs, "-D", p.Internal.LocalPrefix, importArgs}
        if ofile == archive {
                args = append(args, "-pack")
        }
        return ofile, output, err
 }
 
-func (gcToolchain) asm(b *builder, p *Package, obj string, sfiles []string) ([]string, error) {
+func (gcToolchain) asm(b *builder, p *load.Package, obj string, sfiles []string) ([]string, error) {
        // Add -I pkg/GOOS_GOARCH so #include "textflag.h" works in .s files.
-       inc := filepath.Join(goroot, "pkg", "include")
+       inc := filepath.Join(cfg.GOROOT, "pkg", "include")
        args := []interface{}{cfg.BuildToolexec, base.Tool("asm"), "-trimpath", b.work, "-I", obj, "-I", inc, "-D", "GOOS_" + cfg.Goos, "-D", "GOARCH_" + cfg.Goarch, buildAsmflags}
        if p.ImportPath == "runtime" && cfg.Goarch == "386" {
                for _, arg := range buildAsmflags {
 // toolVerify checks that the command line args writes the same output file
 // if run using newTool instead.
 // Unused now but kept around for future use.
-func toolVerify(b *builder, p *Package, newTool string, ofile string, args []interface{}) error {
+func toolVerify(b *builder, p *load.Package, newTool string, ofile string, args []interface{}) error {
        newArgs := make([]interface{}, len(args))
        copy(newArgs, args)
        newArgs[1] = base.Tool(newTool)
        return nil
 }
 
-func (gcToolchain) pkgpath(basedir string, p *Package) string {
+func (gcToolchain) pkgpath(basedir string, p *load.Package) string {
        end := filepath.FromSlash(p.ImportPath + ".a")
        return filepath.Join(basedir, end)
 }
 
-func (gcToolchain) pack(b *builder, p *Package, objDir, afile string, ofiles []string) error {
+func (gcToolchain) pack(b *builder, p *load.Package, objDir, afile string, ofiles []string) error {
        var absOfiles []string
        for _, f := range ofiles {
                absOfiles = append(absOfiles, mkAbs(objDir, f))
        if cfg.BuildContext.InstallSuffix != "" {
                ldflags = append(ldflags, "-installsuffix", cfg.BuildContext.InstallSuffix)
        }
-       if root.p.omitDWARF {
+       if root.p.Internal.OmitDWARF {
                ldflags = append(ldflags, "-w")
        }
        if cfg.BuildBuildmode == "plugin" {
                pluginpath := root.p.ImportPath
                if pluginpath == "command-line-arguments" {
-                       pluginpath = "plugin/unnamed-" + root.p.buildID
+                       pluginpath = "plugin/unnamed-" + root.p.Internal.BuildID
                }
                ldflags = append(ldflags, "-pluginpath", pluginpath)
        }
        }
        ldflags = setextld(ldflags, compiler)
        ldflags = append(ldflags, "-buildmode="+ldBuildmode)
-       if root.p.buildID != "" {
-               ldflags = append(ldflags, "-buildid="+root.p.buildID)
+       if root.p.Internal.BuildID != "" {
+               ldflags = append(ldflags, "-buildid="+root.p.Internal.BuildID)
        }
        ldflags = append(ldflags, cfg.BuildLdflags...)
 
        return b.run(".", out, nil, cfg.BuildToolexec, base.Tool("link"), "-o", out, importArgs, ldflags)
 }
 
-func (gcToolchain) cc(b *builder, p *Package, objdir, ofile, cfile string) error {
+func (gcToolchain) cc(b *builder, p *load.Package, objdir, ofile, cfile string) error {
        return fmt.Errorf("%s: C source files not supported without cgo", mkAbs(p.Dir, cfile))
 }
 
        return gccgoBin
 }
 
-func (tools gccgoToolchain) gc(b *builder, p *Package, archive, obj string, asmhdr bool, importArgs []string, gofiles []string) (ofile string, output []byte, err error) {
+func (tools gccgoToolchain) gc(b *builder, p *load.Package, archive, obj string, asmhdr bool, importArgs []string, gofiles []string) (ofile string, output []byte, err error) {
        out := "_go_.o"
        ofile = obj + out
        gcargs := []string{"-g"}
        if pkgpath := gccgoPkgpath(p); pkgpath != "" {
                gcargs = append(gcargs, "-fgo-pkgpath="+pkgpath)
        }
-       if p.localPrefix != "" {
-               gcargs = append(gcargs, "-fgo-relative-import-path="+p.localPrefix)
+       if p.Internal.LocalPrefix != "" {
+               gcargs = append(gcargs, "-fgo-relative-import-path="+p.Internal.LocalPrefix)
        }
        args := str.StringList(tools.compiler(), importArgs, "-c", gcargs, "-o", ofile, buildGccgoflags)
        for _, f := range gofiles {
        return ofile, output, err
 }
 
-func (tools gccgoToolchain) asm(b *builder, p *Package, obj string, sfiles []string) ([]string, error) {
+func (tools gccgoToolchain) asm(b *builder, p *load.Package, obj string, sfiles []string) ([]string, error) {
        var ofiles []string
        for _, sfile := range sfiles {
                ofile := obj + sfile[:len(sfile)-len(".s")] + ".o"
        return ofiles, nil
 }
 
-func (gccgoToolchain) pkgpath(basedir string, p *Package) string {
+func (gccgoToolchain) pkgpath(basedir string, p *load.Package) string {
        end := filepath.FromSlash(p.ImportPath + ".a")
        afile := filepath.Join(basedir, end)
        // add "lib" to the final element
        return filepath.Join(filepath.Dir(afile), "lib"+filepath.Base(afile))
 }
 
-func (gccgoToolchain) pack(b *builder, p *Package, objDir, afile string, ofiles []string) error {
+func (gccgoToolchain) pack(b *builder, p *load.Package, objDir, afile string, ofiles []string) error {
        var absOfiles []string
        for _, f := range ofiles {
                absOfiles = append(absOfiles, mkAbs(objDir, f))
                        if !apackagePathsSeen[a.p.ImportPath] {
                                apackagePathsSeen[a.p.ImportPath] = true
                                target := a.target
-                               if len(a.p.CgoFiles) > 0 || a.p.usesSwig() {
+                               if len(a.p.CgoFiles) > 0 || a.p.UsesSwig() {
                                        target, err = readAndRemoveCgoFlags(target)
                                        if err != nil {
                                                return
                if len(a.p.CgoFiles) > 0 {
                        usesCgo = true
                }
-               if a.p.usesSwig() {
+               if a.p.UsesSwig() {
                        usesCgo = true
                }
                if len(a.p.CXXFiles) > 0 || len(a.p.SwigCXXFiles) > 0 {
        return tools.link(b, fakeRoot, out, allactions, "", nil, "shared", out)
 }
 
-func (tools gccgoToolchain) cc(b *builder, p *Package, objdir, ofile, cfile string) error {
-       inc := filepath.Join(goroot, "pkg", "include")
+func (tools gccgoToolchain) cc(b *builder, p *load.Package, objdir, ofile, cfile string) error {
+       inc := filepath.Join(cfg.GOROOT, "pkg", "include")
        cfile = mkAbs(p.Dir, cfile)
        defs := []string{"-D", "GOOS_" + cfg.Goos, "-D", "GOARCH_" + cfg.Goarch}
        defs = append(defs, b.gccArchArgs()...)
        return args
 }
 
-func gccgoPkgpath(p *Package) string {
-       if p.build.IsCommand() && !p.forceLibrary {
+func gccgoPkgpath(p *load.Package) string {
+       if p.Internal.Build.IsCommand() && !p.Internal.ForceLibrary {
                return ""
        }
        return p.ImportPath
 }
 
-func gccgoCleanPkgpath(p *Package) string {
+func gccgoCleanPkgpath(p *load.Package) string {
        clean := func(r rune) rune {
                switch {
                case 'A' <= r && r <= 'Z', 'a' <= r && r <= 'z',
 }
 
 // gcc runs the gcc C compiler to create an object from a single C file.
-func (b *builder) gcc(p *Package, out string, flags []string, cfile string) error {
+func (b *builder) gcc(p *load.Package, out string, flags []string, cfile string) error {
        return b.ccompile(p, out, flags, cfile, b.gccCmd(p.Dir))
 }
 
 // gxx runs the g++ C++ compiler to create an object from a single C++ file.
-func (b *builder) gxx(p *Package, out string, flags []string, cxxfile string) error {
+func (b *builder) gxx(p *load.Package, out string, flags []string, cxxfile string) error {
        return b.ccompile(p, out, flags, cxxfile, b.gxxCmd(p.Dir))
 }
 
 // gfortran runs the gfortran Fortran compiler to create an object from a single Fortran file.
-func (b *builder) gfortran(p *Package, out string, flags []string, ffile string) error {
+func (b *builder) gfortran(p *load.Package, out string, flags []string, ffile string) error {
        return b.ccompile(p, out, flags, ffile, b.gfortranCmd(p.Dir))
 }
 
 // ccompile runs the given C or C++ compiler and creates an object from a single source file.
-func (b *builder) ccompile(p *Package, outfile string, flags []string, file string, compiler []string) error {
+func (b *builder) ccompile(p *load.Package, outfile string, flags []string, file string, compiler []string) error {
        file = mkAbs(p.Dir, file)
        desc := p.ImportPath
        output, err := b.runOut(p.Dir, desc, nil, compiler, flags, "-o", outfile, "-c", file)
 }
 
 // gccld runs the gcc linker to create an executable from a set of object files.
-func (b *builder) gccld(p *Package, out string, flags []string, obj []string) error {
+func (b *builder) gccld(p *load.Package, out string, flags []string, obj []string) error {
        var cmd []string
        if len(p.CXXFiles) > 0 || len(p.SwigCXXFiles) > 0 {
                cmd = b.gxxCmd(p.Dir)
 }
 
 // Return the flags to use when invoking the C, C++ or Fortran compilers, or cgo.
-func (b *builder) cflags(p *Package) (cppflags, cflags, cxxflags, fflags, ldflags []string) {
+func (b *builder) cflags(p *load.Package) (cppflags, cflags, cxxflags, fflags, ldflags []string) {
        defaults := "-g -O2"
 
        cppflags = str.StringList(envList("CGO_CPPFLAGS", ""), p.CgoCPPFLAGS)
 // dynimport creates a Go source file named importGo containing
 // //go:cgo_import_dynamic directives for each symbol or library
 // dynamically imported by the object files outObj.
-func (b *builder) dynimport(p *Package, obj, importGo, cgoExe string, cflags, cgoLDFLAGS, outObj []string) error {
+func (b *builder) dynimport(p *load.Package, obj, importGo, cgoExe string, cflags, cgoLDFLAGS, outObj []string) error {
        cfile := obj + "_cgo_main.c"
        ofile := obj + "_cgo_main.o"
        if err := b.gcc(p, ofile, cflags, cfile); err != nil {
 
 // collect partially links the object files outObj into a single
 // relocatable object file named ofile.
-func (b *builder) collect(p *Package, obj, ofile string, cgoLDFLAGS, outObj []string) error {
+func (b *builder) collect(p *load.Package, obj, ofile string, cgoLDFLAGS, outObj []string) error {
        // When linking relocatable objects, various flags need to be
        // filtered out as they are inapplicable and can cause some linkers
        // to fail.
 // Run SWIG on all SWIG input files.
 // TODO: Don't build a shared library, once SWIG emits the necessary
 // pragmas for external linking.
-func (b *builder) swig(p *Package, obj string, pcCFLAGS []string) (outGo, outC, outCXX []string, err error) {
+func (b *builder) swig(p *load.Package, obj string, pcCFLAGS []string) (outGo, outC, outCXX []string, err error) {
        if err := b.swigVersionCheck(); err != nil {
                return nil, nil, nil, err
        }
        }
        srcs := []string{src}
 
-       p := goFilesPackage(srcs)
+       p := load.GoFilesPackage(srcs)
 
        if _, _, e := buildToolchain.gc(b, p, "", obj, false, nil, srcs); e != nil {
                return "32", nil
 }
 
 // Run SWIG on one SWIG input file.
-func (b *builder) swigOne(p *Package, file, obj string, pcCFLAGS []string, cxx bool, intgosize string) (outGo, outC string, err error) {
+func (b *builder) swigOne(p *load.Package, file, obj string, pcCFLAGS []string, cxx bool, intgosize string) (outGo, outC string, err error) {
        cgoCPPFLAGS, cgoCFLAGS, cgoCXXFLAGS, _, _ := b.cflags(p)
        var cflags []string
        if cxx {
 
 package main
 
 import (
-       "cmd/go/internal/cfg"
        "cmd/go/internal/base"
+       "cmd/go/internal/cfg"
+       "cmd/go/internal/load"
        "fmt"
        "io/ioutil"
        "os"
 }
 
 func runClean(cmd *base.Command, args []string) {
-       for _, pkg := range packagesAndErrors(args) {
+       for _, pkg := range load.PackagesAndErrors(args) {
                clean(pkg)
        }
 }
 
-var cleaned = map[*Package]bool{}
+var cleaned = map[*load.Package]bool{}
 
 // TODO: These are dregs left by Makefile-based builds.
 // Eventually, can stop deleting these.
        ".so": true,
 }
 
-func clean(p *Package) {
+func clean(p *load.Package) {
        if cleaned[p] {
                return
        }
                }
        }
 
-       if cleanI && p.target != "" {
+       if cleanI && p.Internal.Target != "" {
                if cfg.BuildN || cfg.BuildX {
-                       b.showcmd("", "rm -f %s", p.target)
+                       b.showcmd("", "rm -f %s", p.Internal.Target)
                }
                if !cfg.BuildN {
-                       removeFile(p.target)
+                       removeFile(p.Internal.Target)
                }
        }
 
        if cleanR {
-               for _, p1 := range p.imports {
+               for _, p1 := range p.Internal.Imports {
                        clean(p1)
                }
        }
 
 package main
 
 import (
-       "cmd/go/internal/cfg"
        "cmd/go/internal/base"
+       "cmd/go/internal/cfg"
 )
 
 var cmdDoc = &base.Command{
 
 package main
 
 import (
-       "cmd/go/internal/cfg"
        "cmd/go/internal/base"
+       "cmd/go/internal/cfg"
+       "cmd/go/internal/load"
        "fmt"
        "os"
        "runtime"
 
        env := []cfg.EnvVar{
                {"GOARCH", cfg.Goarch},
-               {"GOBIN", gobin},
+               {"GOBIN", cfg.GOBIN},
                {"GOEXE", cfg.ExeSuffix},
                {"GOHOSTARCH", runtime.GOARCH},
                {"GOHOSTOS", runtime.GOOS},
                {"GOOS", cfg.Goos},
                {"GOPATH", cfg.BuildContext.GOPATH},
                {"GORACE", os.Getenv("GORACE")},
-               {"GOROOT", goroot},
+               {"GOROOT", cfg.GOROOT},
                {"GOTOOLDIR", base.ToolDir},
 
                // disable escape codes in clang errors
 func extraEnvVars() []cfg.EnvVar {
        var b builder
        b.init()
-       cppflags, cflags, cxxflags, fflags, ldflags := b.cflags(&Package{})
+       cppflags, cflags, cxxflags, fflags, ldflags := b.cflags(&load.Package{})
        return []cfg.EnvVar{
                {"PKG_CONFIG", b.pkgconfigCmd()},
                {"CGO_CFLAGS", strings.Join(cflags, " ")},
 
 package main
 
 import (
-       "cmd/go/internal/cfg"
        "cmd/go/internal/base"
+       "cmd/go/internal/cfg"
+       "cmd/go/internal/load"
        "cmd/go/internal/str"
 )
 
 }
 
 func runFix(cmd *base.Command, args []string) {
-       for _, pkg := range packages(args) {
+       for _, pkg := range load.Packages(args) {
                // Use pkg.gofiles instead of pkg.Dir so that
                // the command only applies to this package,
                // not to packages in subdirectories.
-               base.Run(str.StringList(cfg.BuildToolexec, base.Tool("fix"), base.RelPaths(pkg.allgofiles)))
+               base.Run(str.StringList(cfg.BuildToolexec, base.Tool("fix"), base.RelPaths(pkg.Internal.AllGoFiles)))
        }
 }
 
 package main
 
 import (
-       "cmd/go/internal/cfg"
        "cmd/go/internal/base"
+       "cmd/go/internal/cfg"
+       "cmd/go/internal/load"
        "cmd/go/internal/str"
        "os"
        "path/filepath"
 
 func runFmt(cmd *base.Command, args []string) {
        gofmt := gofmtPath()
-       for _, pkg := range packages(args) {
+       for _, pkg := range load.Packages(args) {
                // Use pkg.gofiles instead of pkg.Dir so that
                // the command only applies to this package,
                // not to packages in subdirectories.
-               base.Run(str.StringList(gofmt, "-l", "-w", base.RelPaths(pkg.allgofiles)))
+               base.Run(str.StringList(gofmt, "-l", "-w", base.RelPaths(pkg.Internal.AllGoFiles)))
        }
 }
 
                gofmt += base.ToolWindowsExtension
        }
 
-       gofmtPath := filepath.Join(gobin, gofmt)
+       gofmtPath := filepath.Join(cfg.GOBIN, gofmt)
        if _, err := os.Stat(gofmtPath); err == nil {
                return gofmtPath
        }
 
-       gofmtPath = filepath.Join(goroot, "bin", gofmt)
+       gofmtPath = filepath.Join(cfg.GOROOT, "bin", gofmt)
        if _, err := os.Stat(gofmtPath); err == nil {
                return gofmtPath
        }
 
 import (
        "bufio"
        "bytes"
-       "cmd/go/internal/cfg"
        "cmd/go/internal/base"
+       "cmd/go/internal/cfg"
+       "cmd/go/internal/load"
        "fmt"
        "io"
        "log"
 }
 
 func runGenerate(cmd *base.Command, args []string) {
-       ignoreImports = true
+       load.IgnoreImports = true
 
        if generateRunFlag != "" {
                var err error
                }
        }
        // Even if the arguments are .go files, this loop suffices.
-       for _, pkg := range packages(args) {
-               for _, file := range pkg.gofiles {
+       for _, pkg := range load.Packages(args) {
+               for _, file := range pkg.Internal.GoFiles {
                        if !generate(pkg.Name, file) {
                                break
                        }
 
 package main
 
 import (
-       "cmd/go/internal/cfg"
        "cmd/go/internal/base"
+       "cmd/go/internal/cfg"
+       "cmd/go/internal/load"
        "cmd/go/internal/str"
        "fmt"
        "go/build"
        }
 
        // Phase 1.  Download/update.
-       var stk importStack
+       var stk load.ImportStack
        mode := 0
        if *getT {
-               mode |= getTestDeps
+               mode |= load.GetTestDeps
        }
        args = downloadPaths(args)
        for _, arg := range args {
        // the information will be recomputed. Instead of keeping
        // track of the reverse dependency information, evict
        // everything.
-       for name := range packageCache {
-               delete(packageCache, name)
-       }
+       load.ClearPackageCache()
 
        // In order to rebuild packages information completely,
        // we need to clear commands cache. Command packages are
        // referring to evicted packages from the package cache.
        // This leads to duplicated loads of the standard packages.
-       for name := range cmdCache {
-               delete(cmdCache, name)
-       }
+       load.ClearCmdCache()
 
-       args = importPaths(args)
-       packagesForBuild(args)
+       args = load.ImportPaths(args)
+       load.PackagesForBuild(args)
 
        // Phase 3.  Install.
        if *getD {
 // in the hope that we can figure out the repository from the
 // initial ...-free prefix.
 func downloadPaths(args []string) []string {
-       args = importPathsNoDotExpansion(args)
+       args = load.ImportPathsNoDotExpansion(args)
        var out []string
        for _, a := range args {
                if strings.Contains(a, "...") {
                        // warnings. They will be printed by the
                        // eventual call to importPaths instead.
                        if build.IsLocalImport(a) {
-                               expand = matchPackagesInFS(a)
+                               expand = load.MatchPackagesInFS(a)
                        } else {
-                               expand = matchPackages(a)
+                               expand = load.MatchPackages(a)
                        }
                        if len(expand) > 0 {
                                out = append(out, expand...)
 
 // download runs the download half of the get command
 // for the package named by the argument.
-func download(arg string, parent *Package, stk *importStack, mode int) {
-       if mode&useVendor != 0 {
+func download(arg string, parent *load.Package, stk *load.ImportStack, mode int) {
+       if mode&load.UseVendor != 0 {
                // Caller is responsible for expanding vendor paths.
                panic("internal error: download mode has useVendor set")
        }
-       load := func(path string, mode int) *Package {
+       load1 := func(path string, mode int) *load.Package {
                if parent == nil {
-                       return loadPackage(path, stk)
+                       return load.LoadPackage(path, stk)
                }
-               return loadImport(path, parent.Dir, parent, stk, nil, mode)
+               return load.LoadImport(path, parent.Dir, parent, stk, nil, mode)
        }
 
-       p := load(arg, mode)
-       if p.Error != nil && p.Error.hard {
+       p := load1(arg, mode)
+       if p.Error != nil && p.Error.Hard {
                base.Errorf("%s", p.Error)
                return
        }
        // Only process each package once.
        // (Unless we're fetching test dependencies for this package,
        // in which case we want to process it again.)
-       if downloadCache[arg] && mode&getTestDeps == 0 {
+       if downloadCache[arg] && mode&load.GetTestDeps == 0 {
                return
        }
        downloadCache[arg] = true
 
-       pkgs := []*Package{p}
+       pkgs := []*load.Package{p}
        wildcardOkay := len(*stk) == 0
        isWildcard := false
 
        // Download if the package is missing, or update if we're using -u.
        if p.Dir == "" || *getU {
                // The actual download.
-               stk.push(arg)
+               stk.Push(arg)
                err := downloadPackage(p)
                if err != nil {
-                       base.Errorf("%s", &PackageError{ImportStack: stk.copy(), Err: err.Error()})
-                       stk.pop()
+                       base.Errorf("%s", &load.PackageError{ImportStack: stk.Copy(), Err: err.Error()})
+                       stk.Pop()
                        return
                }
-               stk.pop()
+               stk.Pop()
 
                args := []string{arg}
                // If the argument has a wildcard in it, re-evaluate the wildcard.
                // for p has been replaced in the package cache.
                if wildcardOkay && strings.Contains(arg, "...") {
                        if build.IsLocalImport(arg) {
-                               args = matchPackagesInFS(arg)
+                               args = load.MatchPackagesInFS(arg)
                        } else {
-                               args = matchPackages(arg)
+                               args = load.MatchPackages(arg)
                        }
                        isWildcard = true
                }
 
                // Clear all relevant package cache entries before
                // doing any new loads.
-               for _, arg := range args {
-                       p := packageCache[arg]
-                       if p != nil {
-                               delete(packageCache, p.Dir)
-                               delete(packageCache, p.ImportPath)
-                       }
-               }
+               load.ClearPackageCachePartial(args)
 
                pkgs = pkgs[:0]
                for _, arg := range args {
                        // Note: load calls loadPackage or loadImport,
                        // which push arg onto stk already.
                        // Do not push here too, or else stk will say arg imports arg.
-                       p := load(arg, mode)
+                       p := load1(arg, mode)
                        if p.Error != nil {
                                base.Errorf("%s", p.Error)
                                continue
        // due to wildcard expansion.
        for _, p := range pkgs {
                if *getFix {
-                       base.Run(cfg.BuildToolexec, str.StringList(base.Tool("fix"), base.RelPaths(p.allgofiles)))
+                       base.Run(cfg.BuildToolexec, str.StringList(base.Tool("fix"), base.RelPaths(p.Internal.AllGoFiles)))
 
                        // The imports might have changed, so reload again.
-                       p = reloadPackage(arg, stk)
+                       p = load.ReloadPackage(arg, stk)
                        if p.Error != nil {
                                base.Errorf("%s", p.Error)
                                return
                if isWildcard {
                        // Report both the real package and the
                        // wildcard in any error message.
-                       stk.push(p.ImportPath)
+                       stk.Push(p.ImportPath)
                }
 
                // Process dependencies, now that we know what they are.
                imports := p.Imports
-               if mode&getTestDeps != 0 {
+               if mode&load.GetTestDeps != 0 {
                        // Process test dependencies when -t is specified.
                        // (But don't get test dependencies for test dependencies:
                        // we always pass mode 0 to the recursive calls below.)
                        }
                        // Fail fast on import naming full vendor path.
                        // Otherwise expand path as needed for test imports.
-                       // Note that p.Imports can have additional entries beyond p.build.Imports.
+                       // Note that p.Imports can have additional entries beyond p.Internal.Build.Imports.
                        orig := path
-                       if i < len(p.build.Imports) {
-                               orig = p.build.Imports[i]
+                       if i < len(p.Internal.Build.Imports) {
+                               orig = p.Internal.Build.Imports[i]
                        }
-                       if j, ok := findVendor(orig); ok {
-                               stk.push(path)
-                               err := &PackageError{
-                                       ImportStack: stk.copy(),
+                       if j, ok := load.FindVendor(orig); ok {
+                               stk.Push(path)
+                               err := &load.PackageError{
+                                       ImportStack: stk.Copy(),
                                        Err:         "must be imported as " + path[j+len("vendor/"):],
                                }
-                               stk.pop()
+                               stk.Pop()
                                base.Errorf("%s", err)
                                continue
                        }
                        // download does caching based on the value of path,
                        // so it must be the fully qualified path already.
                        if i >= len(p.Imports) {
-                               path = vendoredImportPath(p, path)
+                               path = load.VendoredImportPath(p, path)
                        }
                        download(path, p, stk, 0)
                }
 
                if isWildcard {
-                       stk.pop()
+                       stk.Pop()
                }
        }
 }
 
 // downloadPackage runs the create or download command
 // to make the first copy of or update a copy of the given package.
-func downloadPackage(p *Package) error {
+func downloadPackage(p *load.Package) error {
        var (
                vcs            *vcsCmd
                repo, rootPath string
                security = insecure
        }
 
-       if p.build.SrcRoot != "" {
+       if p.Internal.Build.SrcRoot != "" {
                // Directory exists. Look for checkout along path to src.
-               vcs, rootPath, err = vcsFromDir(p.Dir, p.build.SrcRoot)
+               vcs, rootPath, err = vcsFromDir(p.Dir, p.Internal.Build.SrcRoot)
                if err != nil {
                        return err
                }
 
                // Double-check where it came from.
                if *getU && vcs.remoteRepo != nil {
-                       dir := filepath.Join(p.build.SrcRoot, filepath.FromSlash(rootPath))
+                       dir := filepath.Join(p.Internal.Build.SrcRoot, filepath.FromSlash(rootPath))
                        remote, err := vcs.remoteRepo(vcs, dir)
                        if err != nil {
                                return err
                return fmt.Errorf("cannot download, %v uses insecure protocol", repo)
        }
 
-       if p.build.SrcRoot == "" {
+       if p.Internal.Build.SrcRoot == "" {
                // Package not found. Put in first directory of $GOPATH.
                list := filepath.SplitList(cfg.BuildContext.GOPATH)
                if len(list) == 0 {
                        return fmt.Errorf("cannot download, $GOPATH not set. For more details see: 'go help gopath'")
                }
                // Guard against people setting GOPATH=$GOROOT.
-               if list[0] == goroot {
+               if list[0] == cfg.GOROOT {
                        return fmt.Errorf("cannot download, $GOPATH must not be set to $GOROOT. For more details see: 'go help gopath'")
                }
                if _, err := os.Stat(filepath.Join(list[0], "src/cmd/go/alldocs.go")); err == nil {
                        return fmt.Errorf("cannot download, %s is a GOROOT, not a GOPATH. For more details see: 'go help gopath'", list[0])
                }
-               p.build.Root = list[0]
-               p.build.SrcRoot = filepath.Join(list[0], "src")
-               p.build.PkgRoot = filepath.Join(list[0], "pkg")
+               p.Internal.Build.Root = list[0]
+               p.Internal.Build.SrcRoot = filepath.Join(list[0], "src")
+               p.Internal.Build.PkgRoot = filepath.Join(list[0], "pkg")
        }
-       root := filepath.Join(p.build.SrcRoot, filepath.FromSlash(rootPath))
+       root := filepath.Join(p.Internal.Build.SrcRoot, filepath.FromSlash(rootPath))
        // If we've considered this repository already, don't do it again.
        if downloadRootCache[root] {
                return nil
                        return fmt.Errorf("%s exists but %s does not - stale checkout?", root, meta)
                }
 
-               _, err := os.Stat(p.build.Root)
+               _, err := os.Stat(p.Internal.Build.Root)
                gopathExisted := err == nil
 
                // Some version control tools require the parent of the target to exist.
                if err = os.MkdirAll(parent, 0777); err != nil {
                        return err
                }
-               if cfg.BuildV && !gopathExisted && p.build.Root == cfg.BuildContext.GOPATH {
-                       fmt.Fprintf(os.Stderr, "created GOPATH=%s; see 'go help gopath'\n", p.build.Root)
+               if cfg.BuildV && !gopathExisted && p.Internal.Build.Root == cfg.BuildContext.GOPATH {
+                       fmt.Fprintf(os.Stderr, "created GOPATH=%s; see 'go help gopath'\n", p.Internal.Build.Root)
                }
 
                if err = vcs.create(root, repo); err != nil {
 
 package base
 
 import (
+       "bytes"
        "cmd/go/internal/cfg"
        "cmd/go/internal/str"
+       "errors"
        "flag"
        "fmt"
+       "go/scanner"
        "log"
        "os"
        "os/exec"
 // Usage is the usage-reporting function, filled in by package main
 // but here for reference by other packages.
 var Usage func()
+
+// ExpandScanner expands a scanner.List error into all the errors in the list.
+// The default Error method only shows the first error
+// and does not shorten paths.
+func ExpandScanner(err error) error {
+       // Look for parser errors.
+       if err, ok := err.(scanner.ErrorList); ok {
+               // Prepare error with \n before each message.
+               // When printed in something like context: %v
+               // this will put the leading file positions each on
+               // its own line. It will also show all the errors
+               // instead of just the first, as err.Error does.
+               var buf bytes.Buffer
+               for _, e := range err {
+                       e.Pos.Filename = ShortPath(e.Pos.Filename)
+                       buf.WriteString("\n")
+                       buf.WriteString(e.Error())
+               }
+               return errors.New(buf.String())
+       }
+       return err
+}
 
 import (
        "flag"
        "go/build"
+       "os"
+       "path/filepath"
        "runtime"
 )
 
        flags.BoolVar(&BuildN, "n", false, "")
        flags.BoolVar(&BuildX, "x", false, "")
 }
+
+var (
+       GOROOT    = filepath.Clean(runtime.GOROOT())
+       GOBIN     = os.Getenv("GOBIN")
+       GOROOTbin = filepath.Join(GOROOT, "bin")
+       GOROOTpkg = filepath.Join(GOROOT, "pkg")
+       GOROOTsrc = filepath.Join(GOROOT, "src")
+)
 
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-package main
+package load
 
 import "testing"
 
 
--- /dev/null
+// Copyright 2017 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 load
+
+import (
+       "path/filepath"
+       "strings"
+)
+
+// hasSubdir reports whether dir is a subdirectory of
+// (possibly multiple levels below) root.
+// If so, it sets rel to the path fragment that must be
+// appended to root to reach dir.
+func hasSubdir(root, dir string) (rel string, ok bool) {
+       if p, err := filepath.EvalSymlinks(root); err == nil {
+               root = p
+       }
+       if p, err := filepath.EvalSymlinks(dir); err == nil {
+               dir = p
+       }
+       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
+}
+
+// hasPathPrefix reports whether the path s begins with the
+// elements in prefix.
+func hasPathPrefix(s, prefix string) bool {
+       switch {
+       default:
+               return false
+       case len(s) == len(prefix):
+               return s == prefix
+       case len(s) > len(prefix):
+               if prefix != "" && prefix[len(prefix)-1] == '/' {
+                       return strings.HasPrefix(s, prefix)
+               }
+               return s[len(prefix)] == '/' && s[:len(prefix)] == prefix
+       }
+}
+
+// expandPath returns the symlink-expanded form of path.
+func expandPath(p string) string {
+       x, err := filepath.EvalSymlinks(p)
+       if err == nil {
+               return x
+       }
+       return p
+}
+
+// hasFilePathPrefix reports whether the filesystem path s begins with the
+// elements in prefix.
+func hasFilePathPrefix(s, prefix string) bool {
+       sv := strings.ToUpper(filepath.VolumeName(s))
+       pv := strings.ToUpper(filepath.VolumeName(prefix))
+       s = s[len(sv):]
+       prefix = prefix[len(pv):]
+       switch {
+       default:
+               return false
+       case sv != pv:
+               return false
+       case len(s) == len(prefix):
+               return s == prefix
+       case len(s) > len(prefix):
+               if prefix != "" && prefix[len(prefix)-1] == filepath.Separator {
+                       return strings.HasPrefix(s, prefix)
+               }
+               return s[len(prefix)] == filepath.Separator && s[:len(prefix)] == prefix
+       }
+}
 
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-package main
+// Package load loads packages.
+package load
 
 import (
-       "bytes"
        "crypto/sha1"
-       "errors"
        "fmt"
        "go/build"
-       "go/scanner"
        "go/token"
        "io/ioutil"
        "os"
        "cmd/go/internal/str"
 )
 
-var ignoreImports bool // control whether we ignore imports in packages
+var IgnoreImports bool // control whether we ignore imports in packages
 
 // A Package describes a single package found in a directory.
 type Package struct {
+       PackagePublic                 // visible in 'go list'
+       Internal      PackageInternal // for use inside go command only
+}
+
+type PackagePublic struct {
        // Note: These fields are part of the go command's public API.
        // See list.go. It is okay to add fields, but not to change or
        // remove existing ones. Keep in sync with list.go
        TestImports  []string `json:",omitempty"` // imports from TestGoFiles
        XTestGoFiles []string `json:",omitempty"` // _test.go files outside package
        XTestImports []string `json:",omitempty"` // imports from XTestGoFiles
+}
 
+type PackageInternal struct {
        // Unexported fields are not part of the public API.
-       build        *build.Package
-       pkgdir       string // overrides build.PkgDir
-       imports      []*Package
-       deps         []*Package
-       gofiles      []string // GoFiles+CgoFiles+TestGoFiles+XTestGoFiles files, absolute paths
-       sfiles       []string
-       allgofiles   []string             // gofiles + IgnoredGoFiles, absolute paths
-       target       string               // installed file for this package (may be executable)
-       fake         bool                 // synthesized package
-       external     bool                 // synthesized external test package
-       forceLibrary bool                 // this package is a library (even if named "main")
-       cmdline      bool                 // defined by files listed on command line
-       local        bool                 // imported via local path (./ or ../)
-       localPrefix  string               // interpret ./ and ../ imports relative to this prefix
-       exeName      string               // desired name for temporary executable
-       coverMode    string               // preprocess Go source files with the coverage tool in this mode
-       coverVars    map[string]*CoverVar // variables created by coverage analysis
-       omitDWARF    bool                 // tell linker not to write DWARF information
-       buildID      string               // expected build ID for generated package
-       gobinSubdir  bool                 // install target would be subdir of GOBIN
+       Build        *build.Package
+       Pkgdir       string // overrides build.PkgDir
+       Imports      []*Package
+       Deps         []*Package
+       GoFiles      []string // GoFiles+CgoFiles+TestGoFiles+XTestGoFiles files, absolute paths
+       SFiles       []string
+       AllGoFiles   []string             // gofiles + IgnoredGoFiles, absolute paths
+       Target       string               // installed file for this package (may be executable)
+       Fake         bool                 // synthesized package
+       External     bool                 // synthesized external test package
+       ForceLibrary bool                 // this package is a library (even if named "main")
+       Cmdline      bool                 // defined by files listed on command line
+       Local        bool                 // imported via local path (./ or ../)
+       LocalPrefix  string               // interpret ./ and ../ imports relative to this prefix
+       ExeName      string               // desired name for temporary executable
+       CoverMode    string               // preprocess Go source files with the coverage tool in this mode
+       CoverVars    map[string]*CoverVar // variables created by coverage analysis
+       OmitDWARF    bool                 // tell linker not to write DWARF information
+       BuildID      string               // expected build ID for generated package
+       GobinSubdir  bool                 // install target would be subdir of GOBIN
 }
 
-// vendored returns the vendor-resolved version of imports,
+// Vendored returns the vendor-resolved version of imports,
 // which should be p.TestImports or p.XTestImports, NOT p.Imports.
 // The imports in p.TestImports and p.XTestImports are not recursively
 // loaded during the initial load of p, so they list the imports found in
 // can produce better error messages if it starts with the original paths.
 // The initial load of p loads all the non-test imports and rewrites
 // the vendored paths, so nothing should ever call p.vendored(p.Imports).
-func (p *Package) vendored(imports []string) []string {
+func (p *Package) Vendored(imports []string) []string {
        if len(imports) > 0 && len(p.Imports) > 0 && &imports[0] == &p.Imports[0] {
                panic("internal error: p.vendored(p.Imports) called")
        }
        seen := make(map[string]bool)
        var all []string
        for _, path := range imports {
-               path = vendoredImportPath(p, path)
+               path = VendoredImportPath(p, path)
                if !seen[path] {
                        seen[path] = true
                        all = append(all, path)
 }
 
 func (p *Package) copyBuild(pp *build.Package) {
-       p.build = pp
+       p.Internal.Build = pp
 
        if pp.PkgTargetRoot != "" && cfg.BuildPkgdir != "" {
                old := pp.PkgTargetRoot
        p.TestImports = pp.TestImports
        p.XTestGoFiles = pp.XTestGoFiles
        p.XTestImports = pp.XTestImports
-       if ignoreImports {
+       if IgnoreImports {
                p.Imports = nil
                p.TestImports = nil
                p.XTestImports = nil
        ImportStack   []string // shortest path from package named on command line to this one
        Pos           string   // position of error
        Err           string   // the error itself
-       isImportCycle bool     // the error is an import cycle
-       hard          bool     // whether the error is soft or hard; soft errors are ignored in some places
+       IsImportCycle bool     `json:"-"` // the error is an import cycle
+       Hard          bool     `json:"-"` // whether the error is soft or hard; soft errors are ignored in some places
 }
 
 func (p *PackageError) Error() string {
        // Import cycles deserve special treatment.
-       if p.isImportCycle {
+       if p.IsImportCycle {
                return fmt.Sprintf("%s\npackage %s\n", p.Err, strings.Join(p.ImportStack, "\n\timports "))
        }
        if p.Pos != "" {
        return "package " + strings.Join(p.ImportStack, "\n\timports ") + ": " + p.Err
 }
 
-// An importStack is a stack of import paths.
-type importStack []string
+// An ImportStack is a stack of import paths.
+type ImportStack []string
 
-func (s *importStack) push(p string) {
+func (s *ImportStack) Push(p string) {
        *s = append(*s, p)
 }
 
-func (s *importStack) pop() {
+func (s *ImportStack) Pop() {
        *s = (*s)[0 : len(*s)-1]
 }
 
-func (s *importStack) copy() []string {
+func (s *ImportStack) Copy() []string {
        return append([]string{}, *s...)
 }
 
 // shorterThan reports whether sp is shorter than t.
 // We use this to record the shortest import sequence
 // that leads to a particular package.
-func (sp *importStack) shorterThan(t []string) bool {
+func (sp *ImportStack) shorterThan(t []string) bool {
        s := *sp
        if len(s) != len(t) {
                return len(s) < len(t)
 // we return the same pointer each time.
 var packageCache = map[string]*Package{}
 
+func ClearPackageCache() {
+       for name := range packageCache {
+               delete(packageCache, name)
+       }
+}
+
+func ClearPackageCachePartial(args []string) {
+       for _, arg := range args {
+               p := packageCache[arg]
+               if p != nil {
+                       delete(packageCache, p.Dir)
+                       delete(packageCache, p.ImportPath)
+               }
+       }
+}
+
 // reloadPackage is like loadPackage but makes sure
 // not to use the package cache.
-func reloadPackage(arg string, stk *importStack) *Package {
+func ReloadPackage(arg string, stk *ImportStack) *Package {
        p := packageCache[arg]
        if p != nil {
                delete(packageCache, p.Dir)
                delete(packageCache, p.ImportPath)
        }
-       return loadPackage(arg, stk)
+       return LoadPackage(arg, stk)
 }
 
 // dirToImportPath returns the pseudo-import path we use for a package
        // recorded as the canonical import path. At that point, future loads
        // of that package must not pass useVendor, because
        // disallowVendor will reject direct use of paths containing /vendor/.
-       useVendor = 1 << iota
+       UseVendor = 1 << iota
 
        // getTestDeps is for download (part of "go get") and indicates
        // that test dependencies should be fetched too.
-       getTestDeps
+       GetTestDeps
 )
 
 // loadImport scans the directory named by path, which must be an import path,
 // but possibly a local import path (an absolute file system path or one beginning
 // with ./ or ../).  A local relative path is interpreted relative to srcDir.
 // It returns a *Package describing the package found in that directory.
-func loadImport(path, srcDir string, parent *Package, stk *importStack, importPos []token.Position, mode int) *Package {
-       stk.push(path)
-       defer stk.pop()
+func LoadImport(path, srcDir string, parent *Package, stk *ImportStack, importPos []token.Position, mode int) *Package {
+       stk.Push(path)
+       defer stk.Pop()
 
        // Determine canonical identifier for this package.
        // For a local import the identifier is the pseudo-import path
        isLocal := build.IsLocalImport(path)
        if isLocal {
                importPath = dirToImportPath(filepath.Join(srcDir, path))
-       } else if mode&useVendor != 0 {
+       } else if mode&UseVendor != 0 {
                // We do our own vendor resolution, because we want to
                // find out the key to use in packageCache without the
                // overhead of repeated calls to buildContext.Import.
                // The code is also needed in a few other places anyway.
-               path = vendoredImportPath(parent, path)
+               path = VendoredImportPath(parent, path)
                importPath = path
        }
 
                p = reusePackage(p, stk)
        } else {
                p = new(Package)
-               p.local = isLocal
+               p.Internal.Local = isLocal
                p.ImportPath = importPath
                packageCache[importPath] = p
 
                // TODO: After Go 1, decide when to pass build.AllowBinary here.
                // See issue 3268 for mistakes to avoid.
                buildMode := build.ImportComment
-               if mode&useVendor == 0 || path != origPath {
+               if mode&UseVendor == 0 || path != origPath {
                        // Not vendoring, or we already found the vendored path.
                        buildMode |= build.IgnoreVendor
                }
                bp, err := cfg.BuildContext.Import(path, srcDir, buildMode)
                bp.ImportPath = importPath
-               if gobin != "" {
-                       bp.BinDir = gobin
+               if cfg.GOBIN != "" {
+                       bp.BinDir = cfg.GOBIN
                }
                if err == nil && !isLocal && bp.ImportComment != "" && bp.ImportComment != path &&
                        !strings.Contains(path, "/vendor/") && !strings.HasPrefix(path, "vendor/") {
 
                if origPath != cleanImport(origPath) {
                        p.Error = &PackageError{
-                               ImportStack: stk.copy(),
+                               ImportStack: stk.Copy(),
                                Err:         fmt.Sprintf("non-canonical import path: %q should be %q", origPath, pathpkg.Clean(origPath)),
                        }
                        p.Incomplete = true
        if perr := disallowInternal(srcDir, p, stk); perr != p {
                return setErrorPos(perr, importPos)
        }
-       if mode&useVendor != 0 {
+       if mode&UseVendor != 0 {
                if perr := disallowVendor(srcDir, origPath, p, stk); perr != p {
                        return setErrorPos(perr, importPos)
                }
        if p.Name == "main" && parent != nil && parent.Dir != p.Dir {
                perr := *p
                perr.Error = &PackageError{
-                       ImportStack: stk.copy(),
+                       ImportStack: stk.Copy(),
                        Err:         fmt.Sprintf("import %q is a program, not an importable package", path),
                }
                return setErrorPos(&perr, importPos)
        }
 
-       if p.local && parent != nil && !parent.local {
+       if p.Internal.Local && parent != nil && !parent.Internal.Local {
                perr := *p
                perr.Error = &PackageError{
-                       ImportStack: stk.copy(),
+                       ImportStack: stk.Copy(),
                        Err:         fmt.Sprintf("local import %q in non-local package", path),
                }
                return setErrorPos(&perr, importPos)
        return result
 }
 
-// vendoredImportPath returns the expansion of path when it appears in parent.
+// VendoredImportPath returns the expansion of path when it appears in parent.
 // If parent is x/y/z, then path might expand to x/y/z/vendor/path, x/y/vendor/path,
 // x/vendor/path, vendor/path, or else stay path if none of those exist.
-// vendoredImportPath returns the expanded path or, if no expansion is found, the original.
-func vendoredImportPath(parent *Package, path string) (found string) {
+// VendoredImportPath returns the expanded path or, if no expansion is found, the original.
+func VendoredImportPath(parent *Package, path string) (found string) {
        if parent == nil || parent.Root == "" {
                return path
        }
                root = expandPath(root)
        }
 
-       if !hasFilePathPrefix(dir, root) || len(dir) <= len(root) || dir[len(root)] != filepath.Separator || parent.ImportPath != "command-line-arguments" && !parent.local && filepath.Join(root, parent.ImportPath) != dir {
+       if !hasFilePathPrefix(dir, root) || len(dir) <= len(root) || dir[len(root)] != filepath.Separator || parent.ImportPath != "command-line-arguments" && !parent.Internal.Local && filepath.Join(root, parent.ImportPath) != dir {
                base.Fatalf("unexpected directory layout:\n"+
                        "       import path: %s\n"+
                        "       root: %s\n"+
 // reusePackage reuses package p to satisfy the import at the top
 // of the import stack stk. If this use causes an import loop,
 // reusePackage updates p's error information to record the loop.
-func reusePackage(p *Package, stk *importStack) *Package {
-       // We use p.imports==nil to detect a package that
+func reusePackage(p *Package, stk *ImportStack) *Package {
+       // We use p.Internal.Imports==nil to detect a package that
        // is in the midst of its own loadPackage call
-       // (all the recursion below happens before p.imports gets set).
-       if p.imports == nil {
+       // (all the recursion below happens before p.Internal.Imports gets set).
+       if p.Internal.Imports == nil {
                if p.Error == nil {
                        p.Error = &PackageError{
-                               ImportStack:   stk.copy(),
+                               ImportStack:   stk.Copy(),
                                Err:           "import cycle not allowed",
-                               isImportCycle: true,
+                               IsImportCycle: true,
                        }
                }
                p.Incomplete = true
        }
        // Don't rewrite the import stack in the error if we have an import cycle.
        // If we do, we'll lose the path that describes the cycle.
-       if p.Error != nil && !p.Error.isImportCycle && stk.shorterThan(p.Error.ImportStack) {
-               p.Error.ImportStack = stk.copy()
+       if p.Error != nil && !p.Error.IsImportCycle && stk.shorterThan(p.Error.ImportStack) {
+               p.Error.ImportStack = stk.Copy()
        }
        return p
 }
 // disallowInternal checks that srcDir is allowed to import p.
 // If the import is allowed, disallowInternal returns the original package p.
 // If not, it returns a new package containing just an appropriate error.
-func disallowInternal(srcDir string, p *Package, stk *importStack) *Package {
+func disallowInternal(srcDir string, p *Package, stk *ImportStack) *Package {
        // golang.org/s/go14internal:
        // An import of a path containing the element “internal”
        // is disallowed if the importing code is outside the tree
        // Internal is present, and srcDir is outside parent's tree. Not allowed.
        perr := *p
        perr.Error = &PackageError{
-               ImportStack: stk.copy(),
+               ImportStack: stk.Copy(),
                Err:         "use of internal package not allowed",
        }
        perr.Incomplete = true
 // disallowVendor checks that srcDir is allowed to import p as path.
 // If the import is allowed, disallowVendor returns the original package p.
 // If not, it returns a new package containing just an appropriate error.
-func disallowVendor(srcDir, path string, p *Package, stk *importStack) *Package {
+func disallowVendor(srcDir, path string, p *Package, stk *ImportStack) *Package {
        // The stack includes p.ImportPath.
        // If that's the only thing on the stack, we started
        // with a name given on the command line, not an
        }
 
        // Paths like x/vendor/y must be imported as y, never as x/vendor/y.
-       if i, ok := findVendor(path); ok {
+       if i, ok := FindVendor(path); ok {
                perr := *p
                perr.Error = &PackageError{
-                       ImportStack: stk.copy(),
+                       ImportStack: stk.Copy(),
                        Err:         "must be imported as " + path[i+len("vendor/"):],
                }
                perr.Incomplete = true
 // is not subject to the rules, only subdirectories of vendor.
 // This allows people to have packages and commands named vendor,
 // for maximal compatibility with existing source trees.
-func disallowVendorVisibility(srcDir string, p *Package, stk *importStack) *Package {
+func disallowVendorVisibility(srcDir string, p *Package, stk *ImportStack) *Package {
        // The stack includes p.ImportPath.
        // If that's the only thing on the stack, we started
        // with a name given on the command line, not an
        }
 
        // Check for "vendor" element.
-       i, ok := findVendor(p.ImportPath)
+       i, ok := FindVendor(p.ImportPath)
        if !ok {
                return p
        }
        // Vendor is present, and srcDir is outside parent's tree. Not allowed.
        perr := *p
        perr.Error = &PackageError{
-               ImportStack: stk.copy(),
+               ImportStack: stk.Copy(),
                Err:         "use of vendored package not allowed",
        }
        perr.Incomplete = true
        return &perr
 }
 
-// findVendor looks for the last non-terminating "vendor" path element in the given import path.
-// If there isn't one, findVendor returns ok=false.
-// Otherwise, findVendor returns ok=true and the index of the "vendor".
+// FindVendor looks for the last non-terminating "vendor" path element in the given import path.
+// If there isn't one, FindVendor returns ok=false.
+// Otherwise, FindVendor returns ok=true and the index of the "vendor".
 //
 // Note that terminating "vendor" elements don't count: "x/vendor" is its own package,
 // not the vendored copy of an import "" (the empty import path).
 // This will allow people to have packages or commands named vendor.
 // This may help reduce breakage, or it may just be confusing. We'll see.
-func findVendor(path string) (index int, ok bool) {
+func FindVendor(path string) (index int, ok bool) {
        // Two cases, depending on internal at start of string or not.
        // The order matters: we must return the index of the final element,
        // because the final one is where the effective import path starts.
 type targetDir int
 
 const (
-       toRoot    targetDir = iota // to bin dir inside package root (default)
-       toTool                     // GOROOT/pkg/tool
-       stalePath                  // the old import path; fail to build
+       ToRoot    targetDir = iota // to bin dir inside package root (default)
+       ToTool                     // GOROOT/pkg/tool
+       StalePath                  // the old import path; fail to build
 )
 
 // goTools is a map of Go program import path to install target directory.
-var goTools = map[string]targetDir{
-       "cmd/addr2line": toTool,
-       "cmd/api":       toTool,
-       "cmd/asm":       toTool,
-       "cmd/compile":   toTool,
-       "cmd/cgo":       toTool,
-       "cmd/cover":     toTool,
-       "cmd/dist":      toTool,
-       "cmd/doc":       toTool,
-       "cmd/fix":       toTool,
-       "cmd/link":      toTool,
-       "cmd/newlink":   toTool,
-       "cmd/nm":        toTool,
-       "cmd/objdump":   toTool,
-       "cmd/pack":      toTool,
-       "cmd/pprof":     toTool,
-       "cmd/trace":     toTool,
-       "cmd/vet":       toTool,
-       "code.google.com/p/go.tools/cmd/cover": stalePath,
-       "code.google.com/p/go.tools/cmd/godoc": stalePath,
-       "code.google.com/p/go.tools/cmd/vet":   stalePath,
-}
-
-// expandScanner expands a scanner.List error into all the errors in the list.
-// The default Error method only shows the first error.
-func expandScanner(err error) error {
-       // Look for parser errors.
-       if err, ok := err.(scanner.ErrorList); ok {
-               // Prepare error with \n before each message.
-               // When printed in something like context: %v
-               // this will put the leading file positions each on
-               // its own line. It will also show all the errors
-               // instead of just the first, as err.Error does.
-               var buf bytes.Buffer
-               for _, e := range err {
-                       e.Pos.Filename = base.ShortPath(e.Pos.Filename)
-                       buf.WriteString("\n")
-                       buf.WriteString(e.Error())
-               }
-               return errors.New(buf.String())
-       }
-       return err
+var GoTools = map[string]targetDir{
+       "cmd/addr2line": ToTool,
+       "cmd/api":       ToTool,
+       "cmd/asm":       ToTool,
+       "cmd/compile":   ToTool,
+       "cmd/cgo":       ToTool,
+       "cmd/cover":     ToTool,
+       "cmd/dist":      ToTool,
+       "cmd/doc":       ToTool,
+       "cmd/fix":       ToTool,
+       "cmd/link":      ToTool,
+       "cmd/newlink":   ToTool,
+       "cmd/nm":        ToTool,
+       "cmd/objdump":   ToTool,
+       "cmd/pack":      ToTool,
+       "cmd/pprof":     ToTool,
+       "cmd/trace":     ToTool,
+       "cmd/vet":       ToTool,
+       "code.google.com/p/go.tools/cmd/cover": StalePath,
+       "code.google.com/p/go.tools/cmd/godoc": StalePath,
+       "code.google.com/p/go.tools/cmd/vet":   StalePath,
 }
 
 var raceExclude = map[string]bool{
 
 // load populates p using information from bp, err, which should
 // be the result of calling build.Context.Import.
-func (p *Package) load(stk *importStack, bp *build.Package, err error) *Package {
+func (p *Package) load(stk *ImportStack, bp *build.Package, err error) *Package {
        p.copyBuild(bp)
 
        // The localPrefix is the path we interpret ./ imports relative to.
        // Synthesized main packages sometimes override this.
-       p.localPrefix = dirToImportPath(p.Dir)
+       p.Internal.LocalPrefix = dirToImportPath(p.Dir)
 
        if err != nil {
                p.Incomplete = true
-               err = expandScanner(err)
+               err = base.ExpandScanner(err)
                p.Error = &PackageError{
-                       ImportStack: stk.copy(),
+                       ImportStack: stk.Copy(),
                        Err:         err.Error(),
                }
                return p
 
        if useBindir {
                // Report an error when the old code.google.com/p/go.tools paths are used.
-               if goTools[p.ImportPath] == stalePath {
+               if GoTools[p.ImportPath] == StalePath {
                        newPath := strings.Replace(p.ImportPath, "code.google.com/p/go.", "golang.org/x/", 1)
                        e := fmt.Sprintf("the %v command has moved; use %v instead.", p.ImportPath, newPath)
                        p.Error = &PackageError{Err: e}
                        // Install cross-compiled binaries to subdirectories of bin.
                        elem = full
                }
-               if p.build.BinDir != "" {
+               if p.Internal.Build.BinDir != "" {
                        // Install to GOBIN or bin of GOPATH entry.
-                       p.target = filepath.Join(p.build.BinDir, elem)
-                       if !p.Goroot && strings.Contains(elem, "/") && gobin != "" {
+                       p.Internal.Target = filepath.Join(p.Internal.Build.BinDir, elem)
+                       if !p.Goroot && strings.Contains(elem, "/") && cfg.GOBIN != "" {
                                // Do not create $GOBIN/goos_goarch/elem.
-                               p.target = ""
-                               p.gobinSubdir = true
+                               p.Internal.Target = ""
+                               p.Internal.GobinSubdir = true
                        }
                }
-               if goTools[p.ImportPath] == toTool {
+               if GoTools[p.ImportPath] == ToTool {
                        // This is for 'go tool'.
                        // Override all the usual logic and force it into the tool directory.
-                       p.target = filepath.Join(gorootPkg, "tool", full)
+                       p.Internal.Target = filepath.Join(cfg.GOROOTpkg, "tool", full)
                }
-               if p.target != "" && cfg.BuildContext.GOOS == "windows" {
-                       p.target += ".exe"
+               if p.Internal.Target != "" && cfg.BuildContext.GOOS == "windows" {
+                       p.Internal.Target += ".Internal.Exe"
                }
-       } else if p.local {
+       } else if p.Internal.Local {
                // Local import turned into absolute path.
                // No permanent install target.
-               p.target = ""
+               p.Internal.Target = ""
        } else {
-               p.target = p.build.PkgObj
+               p.Internal.Target = p.Internal.Build.PkgObj
                if cfg.BuildLinkshared {
-                       shlibnamefile := p.target[:len(p.target)-2] + ".shlibname"
+                       shlibnamefile := p.Internal.Target[:len(p.Internal.Target)-2] + ".shlibname"
                        shlib, err := ioutil.ReadFile(shlibnamefile)
                        if err == nil {
                                libname := strings.TrimSpace(string(shlib))
                                if cfg.BuildContext.Compiler == "gccgo" {
-                                       p.Shlib = filepath.Join(p.build.PkgTargetRoot, "shlibs", libname)
+                                       p.Shlib = filepath.Join(p.Internal.Build.PkgTargetRoot, "shlibs", libname)
                                } else {
-                                       p.Shlib = filepath.Join(p.build.PkgTargetRoot, libname)
+                                       p.Shlib = filepath.Join(p.Internal.Build.PkgTargetRoot, libname)
 
                                }
                        } else if !os.IsNotExist(err) {
                }
        }
 
-       importPaths := p.Imports
+       ImportPaths := p.Imports
        // Packages that use cgo import runtime/cgo implicitly.
        // Packages that use cgo also import syscall implicitly,
        // to wrap errno.
        // Exclude certain packages to avoid circular dependencies.
        if len(p.CgoFiles) > 0 && (!p.Standard || !cgoExclude[p.ImportPath]) {
-               importPaths = append(importPaths, "runtime/cgo")
+               ImportPaths = append(ImportPaths, "runtime/cgo")
        }
        if len(p.CgoFiles) > 0 && (!p.Standard || !cgoSyscallExclude[p.ImportPath]) {
-               importPaths = append(importPaths, "syscall")
+               ImportPaths = append(ImportPaths, "syscall")
        }
 
        if cfg.BuildContext.CgoEnabled && p.Name == "main" && !p.Goroot {
                        }
                }
                if cfg.BuildBuildmode == "c-shared" || cfg.BuildBuildmode == "plugin" || pieCgo || cfg.BuildLinkshared || linkmodeExternal {
-                       importPaths = append(importPaths, "runtime/cgo")
+                       ImportPaths = append(ImportPaths, "runtime/cgo")
                }
        }
 
        // Everything depends on runtime, except runtime, its internal
        // subpackages, and unsafe.
        if !p.Standard || (p.ImportPath != "runtime" && !strings.HasPrefix(p.ImportPath, "runtime/internal/") && p.ImportPath != "unsafe") {
-               importPaths = append(importPaths, "runtime")
+               ImportPaths = append(ImportPaths, "runtime")
                // When race detection enabled everything depends on runtime/race.
                // Exclude certain packages to avoid circular dependencies.
                if cfg.BuildRace && (!p.Standard || !raceExclude[p.ImportPath]) {
-                       importPaths = append(importPaths, "runtime/race")
+                       ImportPaths = append(ImportPaths, "runtime/race")
                }
                // MSan uses runtime/msan.
                if cfg.BuildMSan && (!p.Standard || !raceExclude[p.ImportPath]) {
-                       importPaths = append(importPaths, "runtime/msan")
+                       ImportPaths = append(ImportPaths, "runtime/msan")
                }
                // On ARM with GOARM=5, everything depends on math for the link.
                if p.Name == "main" && cfg.Goarch == "arm" {
-                       importPaths = append(importPaths, "math")
+                       ImportPaths = append(ImportPaths, "math")
                }
                // In coverage atomic mode everything depends on sync/atomic.
                if cfg.TestCoverMode == "atomic" && (!p.Standard || (p.ImportPath != "runtime/cgo" && p.ImportPath != "runtime/race" && p.ImportPath != "sync/atomic")) {
-                       importPaths = append(importPaths, "sync/atomic")
+                       ImportPaths = append(ImportPaths, "sync/atomic")
                }
        }
 
        // This can be an issue particularly for runtime/internal/atomic;
        // see issue 13655.
        if p.Standard && (p.ImportPath == "runtime" || strings.HasPrefix(p.ImportPath, "runtime/internal/")) && p.ImportPath != "runtime/internal/sys" {
-               importPaths = append(importPaths, "runtime/internal/sys")
+               ImportPaths = append(ImportPaths, "runtime/internal/sys")
        }
 
        // Build list of full paths to all Go files in the package,
        // for use by commands like go fmt.
-       p.gofiles = str.StringList(p.GoFiles, p.CgoFiles, p.TestGoFiles, p.XTestGoFiles)
-       for i := range p.gofiles {
-               p.gofiles[i] = filepath.Join(p.Dir, p.gofiles[i])
+       p.Internal.GoFiles = str.StringList(p.GoFiles, p.CgoFiles, p.TestGoFiles, p.XTestGoFiles)
+       for i := range p.Internal.GoFiles {
+               p.Internal.GoFiles[i] = filepath.Join(p.Dir, p.Internal.GoFiles[i])
        }
-       sort.Strings(p.gofiles)
+       sort.Strings(p.Internal.GoFiles)
 
-       p.sfiles = str.StringList(p.SFiles)
-       for i := range p.sfiles {
-               p.sfiles[i] = filepath.Join(p.Dir, p.sfiles[i])
+       p.Internal.SFiles = str.StringList(p.SFiles)
+       for i := range p.Internal.SFiles {
+               p.Internal.SFiles[i] = filepath.Join(p.Dir, p.Internal.SFiles[i])
        }
-       sort.Strings(p.sfiles)
+       sort.Strings(p.Internal.SFiles)
 
-       p.allgofiles = str.StringList(p.IgnoredGoFiles)
-       for i := range p.allgofiles {
-               p.allgofiles[i] = filepath.Join(p.Dir, p.allgofiles[i])
+       p.Internal.AllGoFiles = str.StringList(p.IgnoredGoFiles)
+       for i := range p.Internal.AllGoFiles {
+               p.Internal.AllGoFiles[i] = filepath.Join(p.Dir, p.Internal.AllGoFiles[i])
        }
-       p.allgofiles = append(p.allgofiles, p.gofiles...)
-       sort.Strings(p.allgofiles)
+       p.Internal.AllGoFiles = append(p.Internal.AllGoFiles, p.Internal.GoFiles...)
+       sort.Strings(p.Internal.AllGoFiles)
 
        // Check for case-insensitive collision of input files.
        // To avoid problems on case-insensitive files, we reject any package
        ))
        if f1 != "" {
                p.Error = &PackageError{
-                       ImportStack: stk.copy(),
+                       ImportStack: stk.Copy(),
                        Err:         fmt.Sprintf("case-insensitive file name collision: %q and %q", f1, f2),
                }
                return p
                }
        }
 
-       for i, path := range importPaths {
+       for i, path := range ImportPaths {
                if path == "C" {
                        continue
                }
-               p1 := loadImport(path, p.Dir, p, stk, p.build.ImportPos[path], useVendor)
+               p1 := LoadImport(path, p.Dir, p, stk, p.Internal.Build.ImportPos[path], UseVendor)
                if p.Standard && p.Error == nil && !p1.Standard && p1.Error == nil {
                        p.Error = &PackageError{
-                               ImportStack: stk.copy(),
+                               ImportStack: stk.Copy(),
                                Err:         fmt.Sprintf("non-standard import %q in standard package %q", path, p.ImportPath),
                        }
-                       pos := p.build.ImportPos[path]
+                       pos := p.Internal.Build.ImportPos[path]
                        if len(pos) > 0 {
                                p.Error.Pos = pos[0].String()
                        }
                }
 
                path = p1.ImportPath
-               importPaths[i] = path
+               ImportPaths[i] = path
                if i < len(p.Imports) {
                        p.Imports[i] = path
                }
 
                save(path, p1)
                imports = append(imports, p1)
-               for _, dep := range p1.deps {
+               for _, dep := range p1.Internal.Deps {
                        save(dep.ImportPath, dep)
                }
                if p1.Incomplete {
                        p.Incomplete = true
                }
        }
-       p.imports = imports
+       p.Internal.Imports = imports
 
        p.Deps = make([]string, 0, len(deps))
        for dep := range deps {
                if p1 == nil {
                        panic("impossible: missing entry in package cache for " + dep + " imported by " + p.ImportPath)
                }
-               p.deps = append(p.deps, p1)
+               p.Internal.Deps = append(p.Internal.Deps, p1)
                if p1.Error != nil {
                        p.DepsErrors = append(p.DepsErrors, p1.Error)
                }
 
        // unsafe is a fake package.
        if p.Standard && (p.ImportPath == "unsafe" || cfg.BuildContext.Compiler == "gccgo") {
-               p.target = ""
+               p.Internal.Target = ""
        }
-       p.Target = p.target
+       p.Target = p.Internal.Target
 
        // If cgo is not enabled, ignore cgo supporting sources
        // just as we ignore go files containing import "C".
        }
 
        // The gc toolchain only permits C source files with cgo.
-       if len(p.CFiles) > 0 && !p.usesCgo() && !p.usesSwig() && cfg.BuildContext.Compiler == "gc" {
+       if len(p.CFiles) > 0 && !p.UsesCgo() && !p.UsesSwig() && cfg.BuildContext.Compiler == "gc" {
                p.Error = &PackageError{
-                       ImportStack: stk.copy(),
+                       ImportStack: stk.Copy(),
                        Err:         fmt.Sprintf("C source files not allowed when not using cgo or SWIG: %s", strings.Join(p.CFiles, " ")),
                }
                return p
                dep1, dep2 := str.FoldDup(p.Deps)
                if dep1 != "" {
                        p.Error = &PackageError{
-                               ImportStack: stk.copy(),
+                               ImportStack: stk.Copy(),
                                Err:         fmt.Sprintf("case-insensitive import collision: %q and %q", dep1, dep2),
                        }
                        return p
                // For binary-only package, use build ID from supplied package binary.
                buildID, err := buildid.ReadBuildID(p.Name, p.Target)
                if err == nil {
-                       p.buildID = buildID
+                       p.Internal.BuildID = buildID
                }
        } else {
                computeBuildID(p)
 }
 
 // usesSwig reports whether the package needs to run SWIG.
-func (p *Package) usesSwig() bool {
+func (p *Package) UsesSwig() bool {
        return len(p.SwigFiles) > 0 || len(p.SwigCXXFiles) > 0
 }
 
 // usesCgo reports whether the package needs to run cgo
-func (p *Package) usesCgo() bool {
+func (p *Package) UsesCgo() bool {
        return len(p.CgoFiles) > 0
 }
 
 // packageList returns the list of packages in the dag rooted at roots
 // as visited in a depth-first post-order traversal.
-func packageList(roots []*Package) []*Package {
+func PackageList(roots []*Package) []*Package {
        seen := map[*Package]bool{}
        all := []*Package{}
        var walk func(*Package)
                        return
                }
                seen[p] = true
-               for _, p1 := range p.imports {
+               for _, p1 := range p.Internal.Imports {
                        walk(p1)
                }
                all = append(all, p)
 
 // computeStale computes the Stale flag in the package dag that starts
 // at the named pkgs (command-line arguments).
-func computeStale(pkgs ...*Package) {
-       for _, p := range packageList(pkgs) {
+func ComputeStale(pkgs ...*Package) {
+       for _, p := range PackageList(pkgs) {
                p.Stale, p.StaleReason = isStale(p)
        }
 }
        // if a rebuild is needed, that rebuild attempt will produce a useful error.
        // (Some commands, such as 'go list', do not attempt to rebuild.)
        if p.BinaryOnly {
-               if p.target == "" {
+               if p.Internal.Target == "" {
                        // Fail if a build is attempted.
                        return true, "no source code for package, but no install target"
                }
-               if _, err := os.Stat(p.target); err != nil {
+               if _, err := os.Stat(p.Internal.Target); err != nil {
                        // Fail if a build is attempted.
                        return true, "no source code for package, but cannot access install target: " + err.Error()
                }
        }
 
        // If there's no install target, we have to rebuild.
-       if p.target == "" {
+       if p.Internal.Target == "" {
                return true, "no install target"
        }
 
        // Package is stale if completely unbuilt.
-       fi, err := os.Stat(p.target)
+       fi, err := os.Stat(p.Internal.Target)
        if err != nil {
                return true, "cannot stat install target"
        }
        // two versions of Go compiling a single GOPATH.
        // See issue 8290 and issue 10702.
        targetBuildID, err := buildid.ReadBuildID(p.Name, p.Target)
-       if err == nil && targetBuildID != p.buildID {
+       if err == nil && targetBuildID != p.Internal.BuildID {
                return true, "build ID mismatch"
        }
 
        // Package is stale if a dependency is.
-       for _, p1 := range p.deps {
+       for _, p1 := range p.Internal.Deps {
                if p1.Stale {
                        return true, "stale dependency"
                }
        }
 
        // Package is stale if a dependency is, or if a dependency is newer.
-       for _, p1 := range p.deps {
-               if p1.target != "" && olderThan(p1.target) {
+       for _, p1 := range p.Internal.Deps {
+               if p1.Internal.Target != "" && olderThan(p1.Internal.Target) {
                        return true, "newer dependency"
                }
        }
        // and get a full rebuild anyway.
        // Excluding $GOROOT used to also fix issue 4106, but that's now
        // taken care of above (at least when the installed Go is a released version).
-       if p.Root != goroot {
+       if p.Root != cfg.GOROOT {
                if olderThan(cfg.BuildToolchainCompiler) {
                        return true, "newer compiler"
                }
-               if p.build.IsCommand() && olderThan(cfg.BuildToolchainLinker) {
+               if p.Internal.Build.IsCommand() && olderThan(cfg.BuildToolchainLinker) {
                        return true, "newer linker"
                }
        }
        return false, ""
 }
 
-// computeBuildID computes the build ID for p, leaving it in p.buildID.
+// computeBuildID computes the build ID for p, leaving it in p.Internal.BuildID.
 // Build ID is a hash of the information we want to detect changes in.
 // See the long comment in isStale for details.
 func computeBuildID(p *Package) {
        // people use the same GOPATH but switch between
        // different Go releases. See issue 10702.
        // This is also a better fix for issue 8290.
-       for _, p1 := range p.deps {
-               fmt.Fprintf(h, "dep %s %s\n", p1.ImportPath, p1.buildID)
+       for _, p1 := range p.Internal.Deps {
+               fmt.Fprintf(h, "dep %s %s\n", p1.ImportPath, p1.Internal.BuildID)
        }
 
-       p.buildID = fmt.Sprintf("%x", h.Sum(nil))
+       p.Internal.BuildID = fmt.Sprintf("%x", h.Sum(nil))
 }
 
 var cmdCache = map[string]*Package{}
 
+func ClearCmdCache() {
+       for name := range cmdCache {
+               delete(cmdCache, name)
+       }
+}
+
 // loadPackage is like loadImport but is used for command-line arguments,
 // not for paths found in import statements. In addition to ordinary import paths,
 // loadPackage accepts pseudo-paths beginning with cmd/ to denote commands
 // in the Go command directory, as well as paths to those directories.
-func loadPackage(arg string, stk *importStack) *Package {
+func LoadPackage(arg string, stk *ImportStack) *Package {
        if build.IsLocalImport(arg) {
                dir := arg
                if !filepath.IsAbs(dir) {
                                dir = abs
                        }
                }
-               if sub, ok := hasSubdir(gorootSrc, dir); ok && strings.HasPrefix(sub, "cmd/") && !strings.Contains(sub[4:], "/") {
+               if sub, ok := hasSubdir(cfg.GOROOTsrc, dir); ok && strings.HasPrefix(sub, "cmd/") && !strings.Contains(sub[4:], "/") {
                        arg = sub
                }
        }
                if p := cmdCache[arg]; p != nil {
                        return p
                }
-               stk.push(arg)
-               defer stk.pop()
+               stk.Push(arg)
+               defer stk.Pop()
 
-               bp, err := cfg.BuildContext.ImportDir(filepath.Join(gorootSrc, arg), 0)
+               bp, err := cfg.BuildContext.ImportDir(filepath.Join(cfg.GOROOTsrc, arg), 0)
                bp.ImportPath = arg
                bp.Goroot = true
-               bp.BinDir = gorootBin
-               if gobin != "" {
-                       bp.BinDir = gobin
+               bp.BinDir = cfg.GOROOTbin
+               if cfg.GOROOTbin != "" {
+                       bp.BinDir = cfg.GOROOTbin
                }
-               bp.Root = goroot
-               bp.SrcRoot = gorootSrc
+               bp.Root = cfg.GOROOT
+               bp.SrcRoot = cfg.GOROOTsrc
                p := new(Package)
                cmdCache[arg] = p
                p.load(stk, bp, err)
                if p.Error == nil && p.Name != "main" {
                        p.Error = &PackageError{
-                               ImportStack: stk.copy(),
+                               ImportStack: stk.Copy(),
                                Err:         fmt.Sprintf("expected package main but found package %s in %s", p.Name, p.Dir),
                        }
                }
                }
        }
 
-       return loadImport(arg, base.Cwd, nil, stk, nil, 0)
+       return LoadImport(arg, base.Cwd, nil, stk, nil, 0)
 }
 
 // packages returns the packages named by the
 // to load dependencies of a named package, the named
 // package is still returned, with p.Incomplete = true
 // and details in p.DepsErrors.
-func packages(args []string) []*Package {
+func Packages(args []string) []*Package {
        var pkgs []*Package
-       for _, pkg := range packagesAndErrors(args) {
+       for _, pkg := range PackagesAndErrors(args) {
                if pkg.Error != nil {
                        base.Errorf("can't load package: %s", pkg.Error)
                        continue
 // *Package for every argument, even the ones that
 // cannot be loaded at all.
 // The packages that fail to load will have p.Error != nil.
-func packagesAndErrors(args []string) []*Package {
+func PackagesAndErrors(args []string) []*Package {
        if len(args) > 0 && strings.HasSuffix(args[0], ".go") {
-               return []*Package{goFilesPackage(args)}
+               return []*Package{GoFilesPackage(args)}
        }
 
-       args = importPaths(args)
+       args = ImportPaths(args)
        var (
                pkgs    []*Package
-               stk     importStack
+               stk     ImportStack
                seenArg = make(map[string]bool)
                seenPkg = make(map[*Package]bool)
        )
                        continue
                }
                seenArg[arg] = true
-               pkg := loadPackage(arg, &stk)
+               pkg := LoadPackage(arg, &stk)
                if seenPkg[pkg] {
                        continue
                }
                seenPkg[pkg] = true
                pkgs = append(pkgs, pkg)
        }
-       computeStale(pkgs...)
+       ComputeStale(pkgs...)
 
        return pkgs
 }
 // packagesForBuild is like 'packages' but fails if any of
 // the packages or their dependencies have errors
 // (cannot be built).
-func packagesForBuild(args []string) []*Package {
-       pkgs := packagesAndErrors(args)
+func PackagesForBuild(args []string) []*Package {
+       pkgs := PackagesAndErrors(args)
        printed := map[*PackageError]bool{}
        for _, pkg := range pkgs {
                if pkg.Error != nil {
        // which doesn't work very well.
        seen := map[string]bool{}
        reported := map[string]bool{}
-       for _, pkg := range packageList(pkgs) {
+       for _, pkg := range PackageList(pkgs) {
                if seen[pkg.ImportPath] && !reported[pkg.ImportPath] {
                        reported[pkg.ImportPath] = true
                        base.Errorf("internal error: duplicate loads of %s", pkg.ImportPath)
        return pkgs
 }
 
-// hasSubdir reports whether dir is a subdirectory of
-// (possibly multiple levels below) root.
-// If so, it sets rel to the path fragment that must be
-// appended to root to reach dir.
-func hasSubdir(root, dir string) (rel string, ok bool) {
-       if p, err := filepath.EvalSymlinks(root); err == nil {
-               root = p
+// GoFilesPackage creates a package for building a collection of Go files
+// (typically named on the command line).  The target is named p.a for
+// package p or named after the first Go file for package main.
+func GoFilesPackage(gofiles []string) *Package {
+       // TODO: Remove this restriction.
+       for _, f := range gofiles {
+               if !strings.HasSuffix(f, ".go") {
+                       base.Fatalf("named files must be .go files")
+               }
+       }
+
+       var stk ImportStack
+       ctxt := cfg.BuildContext
+       ctxt.UseAllFiles = true
+
+       // Synthesize fake "directory" that only shows the named files,
+       // to make it look like this is a standard package or
+       // command directory. So that local imports resolve
+       // consistently, the files must all be in the same directory.
+       var dirent []os.FileInfo
+       var dir string
+       for _, file := range gofiles {
+               fi, err := os.Stat(file)
+               if err != nil {
+                       base.Fatalf("%s", err)
+               }
+               if fi.IsDir() {
+                       base.Fatalf("%s is a directory, should be a Go file", file)
+               }
+               dir1, _ := filepath.Split(file)
+               if dir1 == "" {
+                       dir1 = "./"
+               }
+               if dir == "" {
+                       dir = dir1
+               } else if dir != dir1 {
+                       base.Fatalf("named files must all be in one directory; have %s and %s", dir, dir1)
+               }
+               dirent = append(dirent, fi)
        }
-       if p, err := filepath.EvalSymlinks(dir); err == nil {
-               dir = p
+       ctxt.ReadDir = func(string) ([]os.FileInfo, error) { return dirent, nil }
+
+       var err error
+       if dir == "" {
+               dir = base.Cwd
        }
-       const sep = string(filepath.Separator)
-       root = filepath.Clean(root)
-       if !strings.HasSuffix(root, sep) {
-               root += sep
+       dir, err = filepath.Abs(dir)
+       if err != nil {
+               base.Fatalf("%s", err)
        }
-       dir = filepath.Clean(dir)
-       if !strings.HasPrefix(dir, root) {
-               return "", false
+
+       bp, err := ctxt.ImportDir(dir, 0)
+       pkg := new(Package)
+       pkg.Internal.Local = true
+       pkg.Internal.Cmdline = true
+       stk.Push("main")
+       pkg.load(&stk, bp, err)
+       stk.Pop()
+       pkg.Internal.LocalPrefix = dirToImportPath(dir)
+       pkg.ImportPath = "command-line-arguments"
+       pkg.Internal.Target = ""
+
+       if pkg.Name == "main" {
+               _, elem := filepath.Split(gofiles[0])
+               exe := elem[:len(elem)-len(".go")] + cfg.ExeSuffix
+               if cfg.BuildO == "" {
+                       cfg.BuildO = exe
+               }
+               if cfg.GOBIN != "" {
+                       pkg.Internal.Target = filepath.Join(cfg.GOBIN, exe)
+               }
        }
-       return filepath.ToSlash(dir[len(root):]), true
+
+       pkg.Target = pkg.Internal.Target
+       pkg.Stale = true
+       pkg.StaleReason = "files named on command line"
+
+       ComputeStale(pkg)
+       return pkg
 }
 
--- /dev/null
+// Copyright 2017 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 load
+
+import (
+       "cmd/go/internal/cfg"
+       "fmt"
+       "go/build"
+       "log"
+       "os"
+       "path"
+       "path/filepath"
+       "regexp"
+       "strings"
+)
+
+// allPackages returns all the packages that can be found
+// under the $GOPATH directories and $GOROOT matching pattern.
+// The pattern is either "all" (all packages), "std" (standard packages),
+// "cmd" (standard commands), or a path including "...".
+func allPackages(pattern string) []string {
+       pkgs := MatchPackages(pattern)
+       if len(pkgs) == 0 {
+               fmt.Fprintf(os.Stderr, "warning: %q matched no packages\n", pattern)
+       }
+       return pkgs
+}
+
+// allPackagesInFS is like allPackages but is passed a pattern
+// beginning ./ or ../, meaning it should scan the tree rooted
+// at the given directory. There are ... in the pattern too.
+func allPackagesInFS(pattern string) []string {
+       pkgs := MatchPackagesInFS(pattern)
+       if len(pkgs) == 0 {
+               fmt.Fprintf(os.Stderr, "warning: %q matched no packages\n", pattern)
+       }
+       return pkgs
+}
+
+// MatchPackages returns a list of package paths matching pattern
+// (see go help packages for pattern syntax).
+func MatchPackages(pattern string) []string {
+       match := func(string) bool { return true }
+       treeCanMatch := func(string) bool { return true }
+       if !IsMetaPackage(pattern) {
+               match = matchPattern(pattern)
+               treeCanMatch = treeCanMatchPattern(pattern)
+       }
+
+       have := map[string]bool{
+               "builtin": true, // ignore pseudo-package that exists only for documentation
+       }
+       if !cfg.BuildContext.CgoEnabled {
+               have["runtime/cgo"] = true // ignore during walk
+       }
+       var pkgs []string
+
+       for _, src := range cfg.BuildContext.SrcDirs() {
+               if (pattern == "std" || pattern == "cmd") && src != cfg.GOROOTsrc {
+                       continue
+               }
+               src = filepath.Clean(src) + string(filepath.Separator)
+               root := src
+               if pattern == "cmd" {
+                       root += "cmd" + string(filepath.Separator)
+               }
+               filepath.Walk(root, func(path string, fi os.FileInfo, err error) error {
+                       if err != nil || !fi.IsDir() || path == src {
+                               return nil
+                       }
+
+                       // Avoid .foo, _foo, and testdata directory trees.
+                       _, elem := filepath.Split(path)
+                       if strings.HasPrefix(elem, ".") || strings.HasPrefix(elem, "_") || elem == "testdata" {
+                               return filepath.SkipDir
+                       }
+
+                       name := filepath.ToSlash(path[len(src):])
+                       if pattern == "std" && (!isStandardImportPath(name) || name == "cmd") {
+                               // The name "std" is only the standard library.
+                               // If the name is cmd, it's the root of the command tree.
+                               return filepath.SkipDir
+                       }
+                       if !treeCanMatch(name) {
+                               return filepath.SkipDir
+                       }
+                       if have[name] {
+                               return nil
+                       }
+                       have[name] = true
+                       if !match(name) {
+                               return nil
+                       }
+                       _, err = cfg.BuildContext.ImportDir(path, 0)
+                       if err != nil {
+                               if _, noGo := err.(*build.NoGoError); noGo {
+                                       return nil
+                               }
+                       }
+                       pkgs = append(pkgs, name)
+                       return nil
+               })
+       }
+       return pkgs
+}
+
+// MatchPackagesInFS returns a list of package paths matching pattern,
+// which must begin with ./ or ../
+// (see go help packages for pattern syntax).
+func MatchPackagesInFS(pattern string) []string {
+       // Find directory to begin the scan.
+       // Could be smarter but this one optimization
+       // is enough for now, since ... is usually at the
+       // end of a path.
+       i := strings.Index(pattern, "...")
+       dir, _ := path.Split(pattern[:i])
+
+       // pattern begins with ./ or ../.
+       // path.Clean will discard the ./ but not the ../.
+       // We need to preserve the ./ for pattern matching
+       // and in the returned import paths.
+       prefix := ""
+       if strings.HasPrefix(pattern, "./") {
+               prefix = "./"
+       }
+       match := matchPattern(pattern)
+
+       var pkgs []string
+       filepath.Walk(dir, func(path string, fi os.FileInfo, err error) error {
+               if err != nil || !fi.IsDir() {
+                       return nil
+               }
+               if path == dir {
+                       // filepath.Walk starts at dir and recurses. For the recursive case,
+                       // the path is the result of filepath.Join, which calls filepath.Clean.
+                       // The initial case is not Cleaned, though, so we do this explicitly.
+                       //
+                       // This converts a path like "./io/" to "io". Without this step, running
+                       // "cd $GOROOT/src; go list ./io/..." would incorrectly skip the io
+                       // package, because prepending the prefix "./" to the unclean path would
+                       // result in "././io", and match("././io") returns false.
+                       path = filepath.Clean(path)
+               }
+
+               // Avoid .foo, _foo, and testdata directory trees, but do not avoid "." or "..".
+               _, elem := filepath.Split(path)
+               dot := strings.HasPrefix(elem, ".") && elem != "." && elem != ".."
+               if dot || strings.HasPrefix(elem, "_") || elem == "testdata" {
+                       return filepath.SkipDir
+               }
+
+               name := prefix + filepath.ToSlash(path)
+               if !match(name) {
+                       return nil
+               }
+
+               // We keep the directory if we can import it, or if we can't import it
+               // due to invalid Go source files. This means that directories containing
+               // parse errors will be built (and fail) instead of being silently skipped
+               // as not matching the pattern. Go 1.5 and earlier skipped, but that
+               // behavior means people miss serious mistakes.
+               // See golang.org/issue/11407.
+               if p, err := cfg.BuildContext.ImportDir(path, 0); err != nil && (p == nil || len(p.InvalidGoFiles) == 0) {
+                       if _, noGo := err.(*build.NoGoError); !noGo {
+                               log.Print(err)
+                       }
+                       return nil
+               }
+               pkgs = append(pkgs, name)
+               return nil
+       })
+       return pkgs
+}
+
+// treeCanMatchPattern(pattern)(name) reports whether
+// name or children of name can possibly match pattern.
+// Pattern is the same limited glob accepted by matchPattern.
+func treeCanMatchPattern(pattern string) func(name string) bool {
+       wildCard := false
+       if i := strings.Index(pattern, "..."); i >= 0 {
+               wildCard = true
+               pattern = pattern[:i]
+       }
+       return func(name string) bool {
+               return len(name) <= len(pattern) && hasPathPrefix(pattern, name) ||
+                       wildCard && strings.HasPrefix(name, pattern)
+       }
+}
+
+// matchPattern(pattern)(name) reports whether
+// name matches pattern. Pattern is a limited glob
+// pattern in which '...' means 'any string' and there
+// is no other special syntax.
+func matchPattern(pattern string) func(name string) bool {
+       re := regexp.QuoteMeta(pattern)
+       re = strings.Replace(re, `\.\.\.`, `.*`, -1)
+       // Special case: foo/... matches foo too.
+       if strings.HasSuffix(re, `/.*`) {
+               re = re[:len(re)-len(`/.*`)] + `(/.*)?`
+       }
+       reg := regexp.MustCompile(`^` + re + `$`)
+       return func(name string) bool {
+               return reg.MatchString(name)
+       }
+}
+
+// ImportPaths returns the import paths to use for the given command line.
+func ImportPaths(args []string) []string {
+       args = ImportPathsNoDotExpansion(args)
+       var out []string
+       for _, a := range args {
+               if strings.Contains(a, "...") {
+                       if build.IsLocalImport(a) {
+                               out = append(out, allPackagesInFS(a)...)
+                       } else {
+                               out = append(out, allPackages(a)...)
+                       }
+                       continue
+               }
+               out = append(out, a)
+       }
+       return out
+}
+
+// ImportPathsNoDotExpansion returns the import paths to use for the given
+// command line, but it does no ... expansion.
+func ImportPathsNoDotExpansion(args []string) []string {
+       if len(args) == 0 {
+               return []string{"."}
+       }
+       var out []string
+       for _, a := range args {
+               // Arguments are supposed to be import paths, but
+               // as a courtesy to Windows developers, rewrite \ to /
+               // in command-line arguments. Handles .\... and so on.
+               if filepath.Separator == '\\' {
+                       a = strings.Replace(a, `\`, `/`, -1)
+               }
+
+               // Put argument in canonical form, but preserve leading ./.
+               if strings.HasPrefix(a, "./") {
+                       a = "./" + path.Clean(a)
+                       if a == "./." {
+                               a = "."
+                       }
+               } else {
+                       a = path.Clean(a)
+               }
+               if IsMetaPackage(a) {
+                       out = append(out, allPackages(a)...)
+                       continue
+               }
+               out = append(out, a)
+       }
+       return out
+}
+
+// isMetaPackage checks if name is a reserved package name that expands to multiple packages.
+func IsMetaPackage(name string) bool {
+       return name == "std" || name == "cmd" || name == "all"
+}
 
 
 // +build testgo
 
-package main
+package load
 
 import "os"
 
 
 
 import (
        "bufio"
-       "cmd/go/internal/cfg"
        "cmd/go/internal/base"
+       "cmd/go/internal/cfg"
+       "cmd/go/internal/load"
        "encoding/json"
        "io"
        "os"
        out := newTrackingWriter(os.Stdout)
        defer out.w.Flush()
 
-       var do func(*Package)
+       var do func(*load.PackagePublic)
        if *listJson {
-               do = func(p *Package) {
+               do = func(p *load.PackagePublic) {
                        b, err := json.MarshalIndent(p, "", "\t")
                        if err != nil {
                                out.Flush()
                if err != nil {
                        base.Fatalf("%s", err)
                }
-               do = func(p *Package) {
+               do = func(p *load.PackagePublic) {
                        if err := tmpl.Execute(out, p); err != nil {
                                out.Flush()
                                base.Fatalf("%s", err)
                }
        }
 
-       load := packages
+       loadpkgs := load.Packages
        if *listE {
-               load = packagesAndErrors
+               loadpkgs = load.PackagesAndErrors
        }
 
-       for _, pkg := range load(args) {
+       for _, pkg := range loadpkgs(args) {
                // Show vendor-expanded paths in listing
-               pkg.TestImports = pkg.vendored(pkg.TestImports)
-               pkg.XTestImports = pkg.vendored(pkg.XTestImports)
+               pkg.TestImports = pkg.Vendored(pkg.TestImports)
+               pkg.XTestImports = pkg.Vendored(pkg.XTestImports)
 
-               do(pkg)
+               do(&pkg.PackagePublic)
        }
 }
 
 
 import (
        "flag"
        "fmt"
-       "go/build"
        "log"
        "os"
-       "path"
        "path/filepath"
-       "regexp"
        "runtime"
        "strings"
 
                }
        }
 
-       if fi, err := os.Stat(goroot); err != nil || !fi.IsDir() {
-               fmt.Fprintf(os.Stderr, "go: cannot find GOROOT directory: %v\n", goroot)
+       if fi, err := os.Stat(cfg.GOROOT); err != nil || !fi.IsDir() {
+               fmt.Fprintf(os.Stderr, "go: cannot find GOROOT directory: %v\n", cfg.GOROOT)
                os.Exit(2)
        }
 
        os.Exit(2)
 }
 
-// importPathsNoDotExpansion returns the import paths to use for the given
-// command line, but it does no ... expansion.
-func importPathsNoDotExpansion(args []string) []string {
-       if len(args) == 0 {
-               return []string{"."}
-       }
-       var out []string
-       for _, a := range args {
-               // Arguments are supposed to be import paths, but
-               // as a courtesy to Windows developers, rewrite \ to /
-               // in command-line arguments. Handles .\... and so on.
-               if filepath.Separator == '\\' {
-                       a = strings.Replace(a, `\`, `/`, -1)
-               }
-
-               // Put argument in canonical form, but preserve leading ./.
-               if strings.HasPrefix(a, "./") {
-                       a = "./" + path.Clean(a)
-                       if a == "./." {
-                               a = "."
-                       }
-               } else {
-                       a = path.Clean(a)
-               }
-               if isMetaPackage(a) {
-                       out = append(out, allPackages(a)...)
-                       continue
-               }
-               out = append(out, a)
-       }
-       return out
-}
-
-// importPaths returns the import paths to use for the given command line.
-func importPaths(args []string) []string {
-       args = importPathsNoDotExpansion(args)
-       var out []string
-       for _, a := range args {
-               if strings.Contains(a, "...") {
-                       if build.IsLocalImport(a) {
-                               out = append(out, allPackagesInFS(a)...)
-                       } else {
-                               out = append(out, allPackages(a)...)
-                       }
-                       continue
-               }
-               out = append(out, a)
-       }
-       return out
-}
-
 // envForDir returns a copy of the environment
 // suitable for running in the given directory.
 // The environment is the current process's environment
        }
        return out
 }
-
-// matchPattern(pattern)(name) reports whether
-// name matches pattern. Pattern is a limited glob
-// pattern in which '...' means 'any string' and there
-// is no other special syntax.
-func matchPattern(pattern string) func(name string) bool {
-       re := regexp.QuoteMeta(pattern)
-       re = strings.Replace(re, `\.\.\.`, `.*`, -1)
-       // Special case: foo/... matches foo too.
-       if strings.HasSuffix(re, `/.*`) {
-               re = re[:len(re)-len(`/.*`)] + `(/.*)?`
-       }
-       reg := regexp.MustCompile(`^` + re + `$`)
-       return func(name string) bool {
-               return reg.MatchString(name)
-       }
-}
-
-// hasPathPrefix reports whether the path s begins with the
-// elements in prefix.
-func hasPathPrefix(s, prefix string) bool {
-       switch {
-       default:
-               return false
-       case len(s) == len(prefix):
-               return s == prefix
-       case len(s) > len(prefix):
-               if prefix != "" && prefix[len(prefix)-1] == '/' {
-                       return strings.HasPrefix(s, prefix)
-               }
-               return s[len(prefix)] == '/' && s[:len(prefix)] == prefix
-       }
-}
-
-// hasFilePathPrefix reports whether the filesystem path s begins with the
-// elements in prefix.
-func hasFilePathPrefix(s, prefix string) bool {
-       sv := strings.ToUpper(filepath.VolumeName(s))
-       pv := strings.ToUpper(filepath.VolumeName(prefix))
-       s = s[len(sv):]
-       prefix = prefix[len(pv):]
-       switch {
-       default:
-               return false
-       case sv != pv:
-               return false
-       case len(s) == len(prefix):
-               return s == prefix
-       case len(s) > len(prefix):
-               if prefix != "" && prefix[len(prefix)-1] == filepath.Separator {
-                       return strings.HasPrefix(s, prefix)
-               }
-               return s[len(prefix)] == filepath.Separator && s[:len(prefix)] == prefix
-       }
-}
-
-// expandPath returns the symlink-expanded form of path.
-func expandPath(p string) string {
-       x, err := filepath.EvalSymlinks(p)
-       if err == nil {
-               return x
-       }
-       return p
-}
-
-// treeCanMatchPattern(pattern)(name) reports whether
-// name or children of name can possibly match pattern.
-// Pattern is the same limited glob accepted by matchPattern.
-func treeCanMatchPattern(pattern string) func(name string) bool {
-       wildCard := false
-       if i := strings.Index(pattern, "..."); i >= 0 {
-               wildCard = true
-               pattern = pattern[:i]
-       }
-       return func(name string) bool {
-               return len(name) <= len(pattern) && hasPathPrefix(pattern, name) ||
-                       wildCard && strings.HasPrefix(name, pattern)
-       }
-}
-
-// allPackages returns all the packages that can be found
-// under the $GOPATH directories and $GOROOT matching pattern.
-// The pattern is either "all" (all packages), "std" (standard packages),
-// "cmd" (standard commands), or a path including "...".
-func allPackages(pattern string) []string {
-       pkgs := matchPackages(pattern)
-       if len(pkgs) == 0 {
-               fmt.Fprintf(os.Stderr, "warning: %q matched no packages\n", pattern)
-       }
-       return pkgs
-}
-
-func matchPackages(pattern string) []string {
-       match := func(string) bool { return true }
-       treeCanMatch := func(string) bool { return true }
-       if !isMetaPackage(pattern) {
-               match = matchPattern(pattern)
-               treeCanMatch = treeCanMatchPattern(pattern)
-       }
-
-       have := map[string]bool{
-               "builtin": true, // ignore pseudo-package that exists only for documentation
-       }
-       if !cfg.BuildContext.CgoEnabled {
-               have["runtime/cgo"] = true // ignore during walk
-       }
-       var pkgs []string
-
-       for _, src := range cfg.BuildContext.SrcDirs() {
-               if (pattern == "std" || pattern == "cmd") && src != gorootSrc {
-                       continue
-               }
-               src = filepath.Clean(src) + string(filepath.Separator)
-               root := src
-               if pattern == "cmd" {
-                       root += "cmd" + string(filepath.Separator)
-               }
-               filepath.Walk(root, func(path string, fi os.FileInfo, err error) error {
-                       if err != nil || !fi.IsDir() || path == src {
-                               return nil
-                       }
-
-                       // Avoid .foo, _foo, and testdata directory trees.
-                       _, elem := filepath.Split(path)
-                       if strings.HasPrefix(elem, ".") || strings.HasPrefix(elem, "_") || elem == "testdata" {
-                               return filepath.SkipDir
-                       }
-
-                       name := filepath.ToSlash(path[len(src):])
-                       if pattern == "std" && (!isStandardImportPath(name) || name == "cmd") {
-                               // The name "std" is only the standard library.
-                               // If the name is cmd, it's the root of the command tree.
-                               return filepath.SkipDir
-                       }
-                       if !treeCanMatch(name) {
-                               return filepath.SkipDir
-                       }
-                       if have[name] {
-                               return nil
-                       }
-                       have[name] = true
-                       if !match(name) {
-                               return nil
-                       }
-                       _, err = cfg.BuildContext.ImportDir(path, 0)
-                       if err != nil {
-                               if _, noGo := err.(*build.NoGoError); noGo {
-                                       return nil
-                               }
-                       }
-                       pkgs = append(pkgs, name)
-                       return nil
-               })
-       }
-       return pkgs
-}
-
-// allPackagesInFS is like allPackages but is passed a pattern
-// beginning ./ or ../, meaning it should scan the tree rooted
-// at the given directory. There are ... in the pattern too.
-func allPackagesInFS(pattern string) []string {
-       pkgs := matchPackagesInFS(pattern)
-       if len(pkgs) == 0 {
-               fmt.Fprintf(os.Stderr, "warning: %q matched no packages\n", pattern)
-       }
-       return pkgs
-}
-
-func matchPackagesInFS(pattern string) []string {
-       // Find directory to begin the scan.
-       // Could be smarter but this one optimization
-       // is enough for now, since ... is usually at the
-       // end of a path.
-       i := strings.Index(pattern, "...")
-       dir, _ := path.Split(pattern[:i])
-
-       // pattern begins with ./ or ../.
-       // path.Clean will discard the ./ but not the ../.
-       // We need to preserve the ./ for pattern matching
-       // and in the returned import paths.
-       prefix := ""
-       if strings.HasPrefix(pattern, "./") {
-               prefix = "./"
-       }
-       match := matchPattern(pattern)
-
-       var pkgs []string
-       filepath.Walk(dir, func(path string, fi os.FileInfo, err error) error {
-               if err != nil || !fi.IsDir() {
-                       return nil
-               }
-               if path == dir {
-                       // filepath.Walk starts at dir and recurses. For the recursive case,
-                       // the path is the result of filepath.Join, which calls filepath.Clean.
-                       // The initial case is not Cleaned, though, so we do this explicitly.
-                       //
-                       // This converts a path like "./io/" to "io". Without this step, running
-                       // "cd $GOROOT/src; go list ./io/..." would incorrectly skip the io
-                       // package, because prepending the prefix "./" to the unclean path would
-                       // result in "././io", and match("././io") returns false.
-                       path = filepath.Clean(path)
-               }
-
-               // Avoid .foo, _foo, and testdata directory trees, but do not avoid "." or "..".
-               _, elem := filepath.Split(path)
-               dot := strings.HasPrefix(elem, ".") && elem != "." && elem != ".."
-               if dot || strings.HasPrefix(elem, "_") || elem == "testdata" {
-                       return filepath.SkipDir
-               }
-
-               name := prefix + filepath.ToSlash(path)
-               if !match(name) {
-                       return nil
-               }
-
-               // We keep the directory if we can import it, or if we can't import it
-               // due to invalid Go source files. This means that directories containing
-               // parse errors will be built (and fail) instead of being silently skipped
-               // as not matching the pattern. Go 1.5 and earlier skipped, but that
-               // behavior means people miss serious mistakes.
-               // See golang.org/issue/11407.
-               if p, err := cfg.BuildContext.ImportDir(path, 0); err != nil && (p == nil || len(p.InvalidGoFiles) == 0) {
-                       if _, noGo := err.(*build.NoGoError); !noGo {
-                               log.Print(err)
-                       }
-                       return nil
-               }
-               pkgs = append(pkgs, name)
-               return nil
-       })
-       return pkgs
-}
 
 package main
 
 import (
-       "cmd/go/internal/cfg"
        "cmd/go/internal/base"
+       "cmd/go/internal/cfg"
+       "cmd/go/internal/load"
        "cmd/go/internal/str"
        "io/ioutil"
        "os"
        }
 }
 
+func pkgImportPath(path string) *load.Package {
+       return &load.Package{
+               PackagePublic: load.PackagePublic{
+                       ImportPath: path,
+               },
+       }
+}
+
 func TestSharedLibName(t *testing.T) {
        // TODO(avdva) - make these values platform-specific
        prefix := "lib"
        suffix := ".so"
        testData := []struct {
                args      []string
-               pkgs      []*Package
+               pkgs      []*load.Package
                expected  string
                expectErr bool
                rootedAt  string
        }{
                {
                        args:     []string{"std"},
-                       pkgs:     []*Package{},
+                       pkgs:     []*load.Package{},
                        expected: "std",
                },
                {
                        args:     []string{"std", "cmd"},
-                       pkgs:     []*Package{},
+                       pkgs:     []*load.Package{},
                        expected: "std,cmd",
                },
                {
                        args:     []string{},
-                       pkgs:     []*Package{&Package{ImportPath: "gopkg.in/somelib"}},
+                       pkgs:     []*load.Package{pkgImportPath("gopkg.in/somelib")},
                        expected: "gopkg.in-somelib",
                },
                {
                        args:     []string{"./..."},
-                       pkgs:     []*Package{&Package{ImportPath: "somelib"}},
+                       pkgs:     []*load.Package{pkgImportPath("somelib")},
                        expected: "somelib",
                        rootedAt: "somelib",
                },
                {
                        args:     []string{"../somelib", "../somelib"},
-                       pkgs:     []*Package{&Package{ImportPath: "somelib"}},
+                       pkgs:     []*load.Package{pkgImportPath("somelib")},
                        expected: "somelib",
                },
                {
                        args:     []string{"../lib1", "../lib2"},
-                       pkgs:     []*Package{&Package{ImportPath: "gopkg.in/lib1"}, &Package{ImportPath: "gopkg.in/lib2"}},
+                       pkgs:     []*load.Package{pkgImportPath("gopkg.in/lib1"), pkgImportPath("gopkg.in/lib2")},
                        expected: "gopkg.in-lib1,gopkg.in-lib2",
                },
                {
                        args: []string{"./..."},
-                       pkgs: []*Package{
-                               &Package{ImportPath: "gopkg.in/dir/lib1"},
-                               &Package{ImportPath: "gopkg.in/lib2"},
-                               &Package{ImportPath: "gopkg.in/lib3"},
+                       pkgs: []*load.Package{
+                               pkgImportPath("gopkg.in/dir/lib1"),
+                               pkgImportPath("gopkg.in/lib2"),
+                               pkgImportPath("gopkg.in/lib3"),
                        },
                        expected: "gopkg.in",
                        rootedAt: "gopkg.in",
                },
                {
                        args:      []string{"std", "../lib2"},
-                       pkgs:      []*Package{},
+                       pkgs:      []*load.Package{},
                        expectErr: true,
                },
                {
                        args:      []string{"all", "./"},
-                       pkgs:      []*Package{},
+                       pkgs:      []*load.Package{},
                        expectErr: true,
                },
                {
                        args:      []string{"cmd", "fmt"},
-                       pkgs:      []*Package{},
+                       pkgs:      []*load.Package{},
                        expectErr: true,
                },
        }
 
 package main
 
 import (
-       "cmd/go/internal/cfg"
        "cmd/go/internal/base"
+       "cmd/go/internal/cfg"
+       "cmd/go/internal/load"
        "cmd/go/internal/str"
        "fmt"
        "os"
                        base.Fatalf("go run: cannot run *_test.go files (%s)", file)
                }
        }
-       p := goFilesPackage(files)
+       p := load.GoFilesPackage(files)
        if p.Error != nil {
                base.Fatalf("%s", p.Error)
        }
-       p.omitDWARF = true
+       p.Internal.OmitDWARF = true
        if len(p.DepsErrors) > 0 {
                // Since these are errors in dependencies,
                // the same error might show up multiple times,
                // once in each package that depends on it.
                // Only print each once.
-               printed := map[*PackageError]bool{}
+               printed := map[*load.PackageError]bool{}
                for _, err := range p.DepsErrors {
                        if !printed[err] {
                                printed[err] = true
        if p.Name != "main" {
                base.Fatalf("go run: cannot run non-main package")
        }
-       p.target = "" // must build - not up to date
+       p.Internal.Target = "" // must build - not up to date
        var src string
        if len(p.GoFiles) > 0 {
                src = p.GoFiles[0]
                }
                base.Fatalf("go run: no suitable source files%s", hint)
        }
-       p.exeName = src[:len(src)-len(".go")] // name temporary executable for first go file
+       p.Internal.ExeName = src[:len(src)-len(".go")] // name temporary executable for first go file
        a1 := b.action(modeBuild, modeBuild, p)
        a := &action{f: (*builder).runProgram, args: cmdArgs, deps: []*action{a1}}
        b.do(a)
 
 
 import (
        "bytes"
-       "cmd/go/internal/cfg"
        "cmd/go/internal/base"
+       "cmd/go/internal/cfg"
+       "cmd/go/internal/load"
        "cmd/go/internal/str"
        "errors"
        "fmt"
        testC     bool // -c flag
        testCover bool // -cover flag
        // Note: testCoverMode is cfg.TestCoverMode (-covermode)
-       testCoverPaths   []string   // -coverpkg flag
-       testCoverPkgs    []*Package // -coverpkg flag
-       testO            string     // -o flag
-       testProfile      bool       // some profiling flag
-       testNeedBinary   bool       // profile needs to keep binary around
-       testV            bool       // -v flag
-       testTimeout      string     // -timeout flag
+       testCoverPaths   []string        // -coverpkg flag
+       testCoverPkgs    []*load.Package // -coverpkg flag
+       testO            string          // -o flag
+       testProfile      bool            // some profiling flag
+       testNeedBinary   bool            // profile needs to keep binary around
+       testV            bool            // -v flag
+       testTimeout      string          // -timeout flag
        testArgs         []string
        testBench        bool
        testStreamOutput bool // show output as it is generated
 
        instrumentInit()
        buildModeInit()
-       pkgs := packagesForBuild(pkgArgs)
+       pkgs := load.PackagesForBuild(pkgArgs)
        if len(pkgs) == 0 {
                base.Fatalf("no packages to test")
        }
                        for _, path := range p.Imports {
                                deps[path] = true
                        }
-                       for _, path := range p.vendored(p.TestImports) {
+                       for _, path := range p.Vendored(p.TestImports) {
                                deps[path] = true
                        }
-                       for _, path := range p.vendored(p.XTestImports) {
+                       for _, path := range p.Vendored(p.XTestImports) {
                                deps[path] = true
                        }
                }
                sort.Strings(all)
 
                a := &action{}
-               for _, p := range packagesForBuild(all) {
+               for _, p := range load.PackagesForBuild(all) {
                        a.deps = append(a.deps, b.action(modeInstall, modeInstall, p))
                }
                b.do(a)
        if testCoverPaths != nil {
                // Load packages that were asked about for coverage.
                // packagesForBuild exits if the packages cannot be loaded.
-               testCoverPkgs = packagesForBuild(testCoverPaths)
+               testCoverPkgs = load.PackagesForBuild(testCoverPaths)
 
                // Warn about -coverpkg arguments that are not actually used.
                used := make(map[string]bool)
                        }
                        p.Stale = true // rebuild
                        p.StaleReason = "rebuild for coverage"
-                       p.fake = true // do not warn about rebuild
-                       p.coverMode = cfg.TestCoverMode
+                       p.Internal.Fake = true // do not warn about rebuild
+                       p.Internal.CoverMode = cfg.TestCoverMode
                        var coverFiles []string
                        coverFiles = append(coverFiles, p.GoFiles...)
                        coverFiles = append(coverFiles, p.CgoFiles...)
                        coverFiles = append(coverFiles, p.TestGoFiles...)
-                       p.coverVars = declareCoverVars(p.ImportPath, coverFiles...)
+                       p.Internal.CoverVars = declareCoverVars(p.ImportPath, coverFiles...)
                }
        }
 
 
        // If we are building any out-of-date packages other
        // than those under test, warn.
-       okBuild := map[*Package]bool{}
+       okBuild := map[*load.Package]bool{}
        for _, p := range pkgs {
                okBuild[p] = true
        }
 
                // Don't warn about packages being rebuilt because of
                // things like coverage analysis.
-               for _, p1 := range a.p.imports {
-                       if p1.fake {
-                               a.p.fake = true
+               for _, p1 := range a.p.Internal.Imports {
+                       if p1.Internal.Fake {
+                               a.p.Internal.Fake = true
                        }
                }
 
-               if a.f != nil && !okBuild[a.p] && !a.p.fake && !a.p.local {
+               if a.f != nil && !okBuild[a.p] && !a.p.Internal.Fake && !a.p.Internal.Local {
                        if !warned {
                                fmt.Fprintf(os.Stderr, "warning: building out-of-date packages:\n")
                                warned = true
        "update",
 }
 
-func builderTest(b *builder, p *Package) (buildAction, runAction, printAction *action, err error) {
+func builderTest(b *builder, p *load.Package) (buildAction, runAction, printAction *action, err error) {
        if len(p.TestGoFiles)+len(p.XTestGoFiles) == 0 {
                build := b.action(modeBuild, modeBuild, p)
                run := &action{p: p, deps: []*action{build}}
        //      ptest - package + test files
        //      pxtest - package of external test files
        //      pmain - pkg.test binary
-       var ptest, pxtest, pmain *Package
+       var ptest, pxtest, pmain *load.Package
 
-       var imports, ximports []*Package
-       var stk importStack
-       stk.push(p.ImportPath + " (test)")
+       var imports, ximports []*load.Package
+       var stk load.ImportStack
+       stk.Push(p.ImportPath + " (test)")
        for i, path := range p.TestImports {
-               p1 := loadImport(path, p.Dir, p, &stk, p.build.TestImportPos[path], useVendor)
+               p1 := load.LoadImport(path, p.Dir, p, &stk, p.Internal.Build.TestImportPos[path], load.UseVendor)
                if p1.Error != nil {
                        return nil, nil, nil, p1.Error
                }
                        // Same error that loadPackage returns (via reusePackage) in pkg.go.
                        // Can't change that code, because that code is only for loading the
                        // non-test copy of a package.
-                       err := &PackageError{
+                       err := &load.PackageError{
                                ImportStack:   testImportStack(stk[0], p1, p.ImportPath),
                                Err:           "import cycle not allowed in test",
-                               isImportCycle: true,
+                               IsImportCycle: true,
                        }
                        return nil, nil, nil, err
                }
                p.TestImports[i] = p1.ImportPath
                imports = append(imports, p1)
        }
-       stk.pop()
-       stk.push(p.ImportPath + "_test")
+       stk.Pop()
+       stk.Push(p.ImportPath + "_test")
        pxtestNeedsPtest := false
        for i, path := range p.XTestImports {
-               p1 := loadImport(path, p.Dir, p, &stk, p.build.XTestImportPos[path], useVendor)
+               p1 := load.LoadImport(path, p.Dir, p, &stk, p.Internal.Build.XTestImportPos[path], load.UseVendor)
                if p1.Error != nil {
                        return nil, nil, nil, p1.Error
                }
                }
                p.XTestImports[i] = p1.ImportPath
        }
-       stk.pop()
+       stk.Pop()
 
        // Use last element of import path, not package name.
        // They differ when package name is "main".
 
        // Test package.
        if len(p.TestGoFiles) > 0 || localCover || p.Name == "main" {
-               ptest = new(Package)
+               ptest = new(load.Package)
                *ptest = *p
                ptest.GoFiles = nil
                ptest.GoFiles = append(ptest.GoFiles, p.GoFiles...)
                ptest.GoFiles = append(ptest.GoFiles, p.TestGoFiles...)
-               ptest.target = ""
+               ptest.Internal.Target = ""
                ptest.Imports = str.StringList(p.Imports, p.TestImports)
-               ptest.imports = append(append([]*Package{}, p.imports...), imports...)
-               ptest.pkgdir = testDir
-               ptest.fake = true
-               ptest.forceLibrary = true
+               ptest.Internal.Imports = append(append([]*load.Package{}, p.Internal.Imports...), imports...)
+               ptest.Internal.Pkgdir = testDir
+               ptest.Internal.Fake = true
+               ptest.Internal.ForceLibrary = true
                ptest.Stale = true
                ptest.StaleReason = "rebuild for test"
-               ptest.build = new(build.Package)
-               *ptest.build = *p.build
+               ptest.Internal.Build = new(build.Package)
+               *ptest.Internal.Build = *p.Internal.Build
                m := map[string][]token.Position{}
-               for k, v := range p.build.ImportPos {
+               for k, v := range p.Internal.Build.ImportPos {
                        m[k] = append(m[k], v...)
                }
-               for k, v := range p.build.TestImportPos {
+               for k, v := range p.Internal.Build.TestImportPos {
                        m[k] = append(m[k], v...)
                }
-               ptest.build.ImportPos = m
+               ptest.Internal.Build.ImportPos = m
 
                if localCover {
-                       ptest.coverMode = cfg.TestCoverMode
+                       ptest.Internal.CoverMode = cfg.TestCoverMode
                        var coverFiles []string
                        coverFiles = append(coverFiles, ptest.GoFiles...)
                        coverFiles = append(coverFiles, ptest.CgoFiles...)
-                       ptest.coverVars = declareCoverVars(ptest.ImportPath, coverFiles...)
+                       ptest.Internal.CoverVars = declareCoverVars(ptest.ImportPath, coverFiles...)
                }
        } else {
                ptest = p
 
        // External test package.
        if len(p.XTestGoFiles) > 0 {
-               pxtest = &Package{
-                       Name:        p.Name + "_test",
-                       ImportPath:  p.ImportPath + "_test",
-                       localPrefix: p.localPrefix,
-                       Root:        p.Root,
-                       Dir:         p.Dir,
-                       GoFiles:     p.XTestGoFiles,
-                       Imports:     p.XTestImports,
-                       build: &build.Package{
-                               ImportPos: p.build.XTestImportPos,
+               pxtest = &load.Package{
+                       PackagePublic: load.PackagePublic{
+                               Name:       p.Name + "_test",
+                               ImportPath: p.ImportPath + "_test",
+                               Root:       p.Root,
+                               Dir:        p.Dir,
+                               GoFiles:    p.XTestGoFiles,
+                               Imports:    p.XTestImports,
+                               Stale:      true,
+                       },
+                       Internal: load.PackageInternal{
+                               LocalPrefix: p.Internal.LocalPrefix,
+                               Build: &build.Package{
+                                       ImportPos: p.Internal.Build.XTestImportPos,
+                               },
+                               Imports:  ximports,
+                               Pkgdir:   testDir,
+                               Fake:     true,
+                               External: true,
                        },
-                       imports:  ximports,
-                       pkgdir:   testDir,
-                       fake:     true,
-                       external: true,
-                       Stale:    true,
                }
                if pxtestNeedsPtest {
-                       pxtest.imports = append(pxtest.imports, ptest)
+                       pxtest.Internal.Imports = append(pxtest.Internal.Imports, ptest)
                }
        }
 
        // Action for building pkg.test.
-       pmain = &Package{
-               Name:       "main",
-               Dir:        testDir,
-               GoFiles:    []string{"_testmain.go"},
-               ImportPath: "testmain",
-               Root:       p.Root,
-               build:      &build.Package{Name: "main"},
-               pkgdir:     testDir,
-               fake:       true,
-               Stale:      true,
-               omitDWARF:  !testC && !testNeedBinary,
+       pmain = &load.Package{
+               PackagePublic: load.PackagePublic{
+                       Name:       "main",
+                       Dir:        testDir,
+                       GoFiles:    []string{"_testmain.go"},
+                       ImportPath: "testmain",
+                       Root:       p.Root,
+                       Stale:      true,
+               },
+               Internal: load.PackageInternal{
+                       Build:     &build.Package{Name: "main"},
+                       Pkgdir:    testDir,
+                       Fake:      true,
+                       OmitDWARF: !testC && !testNeedBinary,
+               },
        }
 
        // The generated main also imports testing, regexp, and os.
-       stk.push("testmain")
+       stk.Push("testmain")
        for dep := range testMainDeps {
                if dep == ptest.ImportPath {
-                       pmain.imports = append(pmain.imports, ptest)
+                       pmain.Internal.Imports = append(pmain.Internal.Imports, ptest)
                } else {
-                       p1 := loadImport(dep, "", nil, &stk, nil, 0)
+                       p1 := load.LoadImport(dep, "", nil, &stk, nil, 0)
                        if p1.Error != nil {
                                return nil, nil, nil, p1.Error
                        }
-                       pmain.imports = append(pmain.imports, p1)
+                       pmain.Internal.Imports = append(pmain.Internal.Imports, p1)
                }
        }
 
        if testCoverPkgs != nil {
                // Add imports, but avoid duplicates.
-               seen := map[*Package]bool{p: true, ptest: true}
-               for _, p1 := range pmain.imports {
+               seen := map[*load.Package]bool{p: true, ptest: true}
+               for _, p1 := range pmain.Internal.Imports {
                        seen[p1] = true
                }
                for _, p1 := range testCoverPkgs {
                        if !seen[p1] {
                                seen[p1] = true
-                               pmain.imports = append(pmain.imports, p1)
+                               pmain.Internal.Imports = append(pmain.Internal.Imports, p1)
                        }
                }
        }
                return nil, nil, nil, err
        }
        if len(ptest.GoFiles)+len(ptest.CgoFiles) > 0 {
-               pmain.imports = append(pmain.imports, ptest)
+               pmain.Internal.Imports = append(pmain.Internal.Imports, ptest)
                t.ImportTest = true
        }
        if pxtest != nil {
-               pmain.imports = append(pmain.imports, pxtest)
+               pmain.Internal.Imports = append(pmain.Internal.Imports, pxtest)
                t.ImportXtest = true
        }
 
                t.NeedOS = true
        }
 
-       for _, cp := range pmain.imports {
-               if len(cp.coverVars) > 0 {
-                       t.Cover = append(t.Cover, coverInfo{cp, cp.coverVars})
+       for _, cp := range pmain.Internal.Imports {
+               if len(cp.Internal.CoverVars) > 0 {
+                       t.Cover = append(t.Cover, coverInfo{cp, cp.Internal.CoverVars})
                }
        }
 
                }
        }
 
-       computeStale(pmain)
+       load.ComputeStale(pmain)
 
        if ptest != p {
                a := b.action(modeBuild, modeBuild, ptest)
        return buildAction, runAction, printAction, nil
 }
 
-func testImportStack(top string, p *Package, target string) []string {
+func testImportStack(top string, p *load.Package, target string) []string {
        stk := []string{top, p.ImportPath}
 Search:
        for p.ImportPath != target {
-               for _, p1 := range p.imports {
+               for _, p1 := range p.Internal.Imports {
                        if p1.ImportPath == target || str.Contains(p1.Deps, target) {
                                stk = append(stk, p1.ImportPath)
                                p = p1
        return stk
 }
 
-func recompileForTest(pmain, preal, ptest *Package, testDir string) {
+func recompileForTest(pmain, preal, ptest *load.Package, testDir string) {
        // The "test copy" of preal is ptest.
        // For each package that depends on preal, make a "test copy"
        // that depends on ptest. And so on, up the dependency tree.
-       testCopy := map[*Package]*Package{preal: ptest}
-       for _, p := range packageList([]*Package{pmain}) {
+       testCopy := map[*load.Package]*load.Package{preal: ptest}
+       for _, p := range load.PackageList([]*load.Package{pmain}) {
                // Copy on write.
                didSplit := false
                split := func() {
                                return
                        }
                        didSplit = true
-                       if p.pkgdir != testDir {
-                               p1 := new(Package)
+                       if p.Internal.Pkgdir != testDir {
+                               p1 := new(load.Package)
                                testCopy[p] = p1
                                *p1 = *p
-                               p1.imports = make([]*Package, len(p.imports))
-                               copy(p1.imports, p.imports)
+                               p1.Internal.Imports = make([]*load.Package, len(p.Internal.Imports))
+                               copy(p1.Internal.Imports, p.Internal.Imports)
                                p = p1
-                               p.pkgdir = testDir
-                               p.target = ""
-                               p.fake = true
+                               p.Internal.Pkgdir = testDir
+                               p.Internal.Target = ""
+                               p.Internal.Fake = true
                                p.Stale = true
                                p.StaleReason = "depends on package being tested"
                        }
                }
 
-               // Update p.deps and p.imports to use at test copies.
-               for i, dep := range p.deps {
+               // Update p.deps and p.Internal.Imports to use at test copies.
+               for i, dep := range p.Internal.Deps {
                        if p1 := testCopy[dep]; p1 != nil && p1 != dep {
                                split()
-                               p.deps[i] = p1
+                               p.Internal.Deps[i] = p1
                        }
                }
-               for i, imp := range p.imports {
+               for i, imp := range p.Internal.Imports {
                        if p1 := testCopy[imp]; p1 != nil && p1 != imp {
                                split()
-                               p.imports[i] = p1
+                               p.Internal.Imports[i] = p1
                        }
                }
        }
 
 // declareCoverVars attaches the required cover variables names
 // to the files, to be used when annotating the files.
-func declareCoverVars(importPath string, files ...string) map[string]*CoverVar {
-       coverVars := make(map[string]*CoverVar)
+func declareCoverVars(importPath string, files ...string) map[string]*load.CoverVar {
+       coverVars := make(map[string]*load.CoverVar)
        for _, file := range files {
                if isTestFile(file) {
                        continue
                }
-               coverVars[file] = &CoverVar{
+               coverVars[file] = &load.CoverVar{
                        File: filepath.Join(importPath, file),
                        Var:  fmt.Sprintf("GoCover_%d", coverIndex),
                }
 
        // If there are any local SWIG dependencies, we want to load
        // the shared library from the build directory.
-       if a.p.usesSwig() {
+       if a.p.UsesSwig() {
                env := cmd.Env
                found := false
                prefix := "LD_LIBRARY_PATH="
 }
 
 type coverInfo struct {
-       Package *Package
-       Vars    map[string]*CoverVar
+       Package *load.Package
+       Vars    map[string]*load.CoverVar
 }
 
 // loadTestFuncs returns the testFuncs describing the tests that will be run.
-func loadTestFuncs(ptest *Package) (*testFuncs, error) {
+func loadTestFuncs(ptest *load.Package) (*testFuncs, error) {
        t := &testFuncs{
                Package: ptest,
        }
        Benchmarks  []testFunc
        Examples    []testFunc
        TestMain    *testFunc
-       Package     *Package
+       Package     *load.Package
        ImportTest  bool
        NeedTest    bool
        ImportXtest bool
 func (t *testFuncs) load(filename, pkg string, doImport, seen *bool) error {
        f, err := parser.ParseFile(testFileSet, filename, nil, parser.ParseComments)
        if err != nil {
-               return expandScanner(err)
+               return base.ExpandScanner(err)
        }
        for _, d := range f.Decls {
                n, ok := d.(*ast.FuncDecl)
 
 package main
 
 import (
-       "cmd/go/internal/cfg"
        "cmd/go/internal/base"
+       "cmd/go/internal/cfg"
        "flag"
        "fmt"
        "os"
 
        "sort"
        "strings"
 
-       "cmd/go/internal/cfg"
        "cmd/go/internal/base"
+       "cmd/go/internal/cfg"
 )
 
 var cmdTool = &base.Command{
                Stdout: os.Stdout,
                Stderr: os.Stderr,
                // Set $GOROOT, mainly for go tool dist.
-               Env: mergeEnvLists([]string{"GOROOT=" + goroot}, os.Environ()),
+               Env: mergeEnvLists([]string{"GOROOT=" + cfg.GOROOT}, os.Environ()),
        }
        err := toolCmd.Run()
        if err != nil {
 
 import (
        "path/filepath"
 
-       "cmd/go/internal/cfg"
        "cmd/go/internal/base"
+       "cmd/go/internal/cfg"
+       "cmd/go/internal/load"
        "cmd/go/internal/str"
 )
 
 }
 
 func runVet(cmd *base.Command, args []string) {
-       for _, p := range packages(args) {
+       for _, p := range load.Packages(args) {
                // Vet expects to be given a set of files all from the same package.
                // Run once for package p and once for package p_test.
                if len(p.GoFiles)+len(p.CgoFiles)+len(p.TestGoFiles) > 0 {
        }
 }
 
-func runVetFiles(p *Package, files []string) {
+func runVetFiles(p *load.Package, files []string) {
        for i := range files {
                files[i] = filepath.Join(p.Dir, files[i])
        }