github.com/rohankumardubey/syslog-redirector-golang@v0.0.0-20140320174030-4859f03d829a/src/cmd/go/pkg.go (about)

     1  // Copyright 2011 The Go Authors.  All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package main
     6  
     7  import (
     8  	"bytes"
     9  	"errors"
    10  	"fmt"
    11  	"go/build"
    12  	"go/scanner"
    13  	"go/token"
    14  	"os"
    15  	pathpkg "path"
    16  	"path/filepath"
    17  	"sort"
    18  	"strings"
    19  	"time"
    20  	"unicode"
    21  )
    22  
    23  // A Package describes a single package found in a directory.
    24  type Package struct {
    25  	// Note: These fields are part of the go command's public API.
    26  	// See list.go.  It is okay to add fields, but not to change or
    27  	// remove existing ones.  Keep in sync with list.go
    28  	Dir         string `json:",omitempty"` // directory containing package sources
    29  	ImportPath  string `json:",omitempty"` // import path of package in dir
    30  	Name        string `json:",omitempty"` // package name
    31  	Doc         string `json:",omitempty"` // package documentation string
    32  	Target      string `json:",omitempty"` // install path
    33  	Goroot      bool   `json:",omitempty"` // is this package found in the Go root?
    34  	Standard    bool   `json:",omitempty"` // is this package part of the standard Go library?
    35  	Stale       bool   `json:",omitempty"` // would 'go install' do anything for this package?
    36  	Root        string `json:",omitempty"` // Go root or Go path dir containing this package
    37  	ConflictDir string `json:",omitempty"` // Dir is hidden by this other directory
    38  
    39  	// Source files
    40  	GoFiles        []string `json:",omitempty"` // .go source files (excluding CgoFiles, TestGoFiles, XTestGoFiles)
    41  	CgoFiles       []string `json:",omitempty"` // .go sources files that import "C"
    42  	IgnoredGoFiles []string `json:",omitempty"` // .go sources ignored due to build constraints
    43  	CFiles         []string `json:",omitempty"` // .c source files
    44  	CXXFiles       []string `json:",omitempty"` // .cc, .cpp and .cxx source files
    45  	HFiles         []string `json:",omitempty"` // .h, .hh, .hpp and .hxx source files
    46  	SFiles         []string `json:",omitempty"` // .s source files
    47  	SwigFiles      []string `json:",omitempty"` // .swig files
    48  	SwigCXXFiles   []string `json:",omitempty"` // .swigcxx files
    49  	SysoFiles      []string `json:",omitempty"` // .syso system object files added to package
    50  
    51  	// Cgo directives
    52  	CgoCFLAGS    []string `json:",omitempty"` // cgo: flags for C compiler
    53  	CgoCPPFLAGS  []string `json:",omitempty"` // cgo: flags for C preprocessor
    54  	CgoCXXFLAGS  []string `json:",omitempty"` // cgo: flags for C++ compiler
    55  	CgoLDFLAGS   []string `json:",omitempty"` // cgo: flags for linker
    56  	CgoPkgConfig []string `json:",omitempty"` // cgo: pkg-config names
    57  
    58  	// Dependency information
    59  	Imports []string `json:",omitempty"` // import paths used by this package
    60  	Deps    []string `json:",omitempty"` // all (recursively) imported dependencies
    61  
    62  	// Error information
    63  	Incomplete bool            `json:",omitempty"` // was there an error loading this package or dependencies?
    64  	Error      *PackageError   `json:",omitempty"` // error loading this package (not dependencies)
    65  	DepsErrors []*PackageError `json:",omitempty"` // errors loading dependencies
    66  
    67  	// Test information
    68  	TestGoFiles  []string `json:",omitempty"` // _test.go files in package
    69  	TestImports  []string `json:",omitempty"` // imports from TestGoFiles
    70  	XTestGoFiles []string `json:",omitempty"` // _test.go files outside package
    71  	XTestImports []string `json:",omitempty"` // imports from XTestGoFiles
    72  
    73  	// Unexported fields are not part of the public API.
    74  	build        *build.Package
    75  	pkgdir       string // overrides build.PkgDir
    76  	imports      []*Package
    77  	deps         []*Package
    78  	gofiles      []string // GoFiles+CgoFiles+TestGoFiles+XTestGoFiles files, absolute paths
    79  	sfiles       []string
    80  	allgofiles   []string             // gofiles + IgnoredGoFiles, absolute paths
    81  	target       string               // installed file for this package (may be executable)
    82  	fake         bool                 // synthesized package
    83  	forceBuild   bool                 // this package must be rebuilt
    84  	forceLibrary bool                 // this package is a library (even if named "main")
    85  	cmdline      bool                 // defined by files listed on command line
    86  	local        bool                 // imported via local path (./ or ../)
    87  	localPrefix  string               // interpret ./ and ../ imports relative to this prefix
    88  	exeName      string               // desired name for temporary executable
    89  	coverMode    string               // preprocess Go source files with the coverage tool in this mode
    90  	coverVars    map[string]*CoverVar // variables created by coverage analysis
    91  }
    92  
    93  // CoverVar holds the name of the generated coverage variables targeting the named file.
    94  type CoverVar struct {
    95  	File string // local file name
    96  	Var  string // name of count struct
    97  }
    98  
    99  func (p *Package) copyBuild(pp *build.Package) {
   100  	p.build = pp
   101  
   102  	p.Dir = pp.Dir
   103  	p.ImportPath = pp.ImportPath
   104  	p.Name = pp.Name
   105  	p.Doc = pp.Doc
   106  	p.Root = pp.Root
   107  	p.ConflictDir = pp.ConflictDir
   108  	// TODO? Target
   109  	p.Goroot = pp.Goroot
   110  	p.Standard = p.Goroot && p.ImportPath != "" && !strings.Contains(p.ImportPath, ".")
   111  	p.GoFiles = pp.GoFiles
   112  	p.CgoFiles = pp.CgoFiles
   113  	p.IgnoredGoFiles = pp.IgnoredGoFiles
   114  	p.CFiles = pp.CFiles
   115  	p.CXXFiles = pp.CXXFiles
   116  	p.HFiles = pp.HFiles
   117  	p.SFiles = pp.SFiles
   118  	p.SwigFiles = pp.SwigFiles
   119  	p.SwigCXXFiles = pp.SwigCXXFiles
   120  	p.SysoFiles = pp.SysoFiles
   121  	p.CgoCFLAGS = pp.CgoCFLAGS
   122  	p.CgoCPPFLAGS = pp.CgoCPPFLAGS
   123  	p.CgoCXXFLAGS = pp.CgoCXXFLAGS
   124  	p.CgoLDFLAGS = pp.CgoLDFLAGS
   125  	p.CgoPkgConfig = pp.CgoPkgConfig
   126  	p.Imports = pp.Imports
   127  	p.TestGoFiles = pp.TestGoFiles
   128  	p.TestImports = pp.TestImports
   129  	p.XTestGoFiles = pp.XTestGoFiles
   130  	p.XTestImports = pp.XTestImports
   131  }
   132  
   133  // A PackageError describes an error loading information about a package.
   134  type PackageError struct {
   135  	ImportStack   []string // shortest path from package named on command line to this one
   136  	Pos           string   // position of error
   137  	Err           string   // the error itself
   138  	isImportCycle bool     // the error is an import cycle
   139  }
   140  
   141  func (p *PackageError) Error() string {
   142  	// Import cycles deserve special treatment.
   143  	if p.isImportCycle {
   144  		return fmt.Sprintf("%s: %s\npackage %s\n", p.Pos, p.Err, strings.Join(p.ImportStack, "\n\timports "))
   145  	}
   146  	if p.Pos != "" {
   147  		// Omit import stack.  The full path to the file where the error
   148  		// is the most important thing.
   149  		return p.Pos + ": " + p.Err
   150  	}
   151  	if len(p.ImportStack) == 0 {
   152  		return p.Err
   153  	}
   154  	return "package " + strings.Join(p.ImportStack, "\n\timports ") + ": " + p.Err
   155  }
   156  
   157  // An importStack is a stack of import paths.
   158  type importStack []string
   159  
   160  func (s *importStack) push(p string) {
   161  	*s = append(*s, p)
   162  }
   163  
   164  func (s *importStack) pop() {
   165  	*s = (*s)[0 : len(*s)-1]
   166  }
   167  
   168  func (s *importStack) copy() []string {
   169  	return append([]string{}, *s...)
   170  }
   171  
   172  // shorterThan returns true if sp is shorter than t.
   173  // We use this to record the shortest import sequence
   174  // that leads to a particular package.
   175  func (sp *importStack) shorterThan(t []string) bool {
   176  	s := *sp
   177  	if len(s) != len(t) {
   178  		return len(s) < len(t)
   179  	}
   180  	// If they are the same length, settle ties using string ordering.
   181  	for i := range s {
   182  		if s[i] != t[i] {
   183  			return s[i] < t[i]
   184  		}
   185  	}
   186  	return false // they are equal
   187  }
   188  
   189  // packageCache is a lookup cache for loadPackage,
   190  // so that if we look up a package multiple times
   191  // we return the same pointer each time.
   192  var packageCache = map[string]*Package{}
   193  
   194  // reloadPackage is like loadPackage but makes sure
   195  // not to use the package cache.
   196  func reloadPackage(arg string, stk *importStack) *Package {
   197  	p := packageCache[arg]
   198  	if p != nil {
   199  		delete(packageCache, p.Dir)
   200  		delete(packageCache, p.ImportPath)
   201  	}
   202  	return loadPackage(arg, stk)
   203  }
   204  
   205  // dirToImportPath returns the pseudo-import path we use for a package
   206  // outside the Go path.  It begins with _/ and then contains the full path
   207  // to the directory.  If the package lives in c:\home\gopher\my\pkg then
   208  // the pseudo-import path is _/c_/home/gopher/my/pkg.
   209  // Using a pseudo-import path like this makes the ./ imports no longer
   210  // a special case, so that all the code to deal with ordinary imports works
   211  // automatically.
   212  func dirToImportPath(dir string) string {
   213  	return pathpkg.Join("_", strings.Map(makeImportValid, filepath.ToSlash(dir)))
   214  }
   215  
   216  func makeImportValid(r rune) rune {
   217  	// Should match Go spec, compilers, and ../../pkg/go/parser/parser.go:/isValidImport.
   218  	const illegalChars = `!"#$%&'()*,:;<=>?[\]^{|}` + "`\uFFFD"
   219  	if !unicode.IsGraphic(r) || unicode.IsSpace(r) || strings.ContainsRune(illegalChars, r) {
   220  		return '_'
   221  	}
   222  	return r
   223  }
   224  
   225  // loadImport scans the directory named by path, which must be an import path,
   226  // but possibly a local import path (an absolute file system path or one beginning
   227  // with ./ or ../).  A local relative path is interpreted relative to srcDir.
   228  // It returns a *Package describing the package found in that directory.
   229  func loadImport(path string, srcDir string, stk *importStack, importPos []token.Position) *Package {
   230  	stk.push(path)
   231  	defer stk.pop()
   232  
   233  	// Determine canonical identifier for this package.
   234  	// For a local import the identifier is the pseudo-import path
   235  	// we create from the full directory to the package.
   236  	// Otherwise it is the usual import path.
   237  	importPath := path
   238  	isLocal := build.IsLocalImport(path)
   239  	if isLocal {
   240  		importPath = dirToImportPath(filepath.Join(srcDir, path))
   241  	}
   242  	if p := packageCache[importPath]; p != nil {
   243  		return reusePackage(p, stk)
   244  	}
   245  
   246  	p := new(Package)
   247  	p.local = isLocal
   248  	p.ImportPath = importPath
   249  	packageCache[importPath] = p
   250  
   251  	// Load package.
   252  	// Import always returns bp != nil, even if an error occurs,
   253  	// in order to return partial information.
   254  	//
   255  	// TODO: After Go 1, decide when to pass build.AllowBinary here.
   256  	// See issue 3268 for mistakes to avoid.
   257  	bp, err := buildContext.Import(path, srcDir, 0)
   258  	bp.ImportPath = importPath
   259  	if gobin != "" {
   260  		bp.BinDir = gobin
   261  	}
   262  	p.load(stk, bp, err)
   263  	if p.Error != nil && len(importPos) > 0 {
   264  		pos := importPos[0]
   265  		pos.Filename = shortPath(pos.Filename)
   266  		p.Error.Pos = pos.String()
   267  	}
   268  
   269  	return p
   270  }
   271  
   272  // reusePackage reuses package p to satisfy the import at the top
   273  // of the import stack stk.  If this use causes an import loop,
   274  // reusePackage updates p's error information to record the loop.
   275  func reusePackage(p *Package, stk *importStack) *Package {
   276  	// We use p.imports==nil to detect a package that
   277  	// is in the midst of its own loadPackage call
   278  	// (all the recursion below happens before p.imports gets set).
   279  	if p.imports == nil {
   280  		if p.Error == nil {
   281  			p.Error = &PackageError{
   282  				ImportStack:   stk.copy(),
   283  				Err:           "import cycle not allowed",
   284  				isImportCycle: true,
   285  			}
   286  		}
   287  		p.Incomplete = true
   288  	}
   289  	// Don't rewrite the import stack in the error if we have an import cycle.
   290  	// If we do, we'll lose the path that describes the cycle.
   291  	if p.Error != nil && !p.Error.isImportCycle && stk.shorterThan(p.Error.ImportStack) {
   292  		p.Error.ImportStack = stk.copy()
   293  	}
   294  	return p
   295  }
   296  
   297  type targetDir int
   298  
   299  const (
   300  	toRoot targetDir = iota // to bin dir inside package root (default)
   301  	toTool                  // GOROOT/pkg/tool
   302  	toBin                   // GOROOT/bin
   303  )
   304  
   305  // goTools is a map of Go program import path to install target directory.
   306  var goTools = map[string]targetDir{
   307  	"cmd/api":                              toTool,
   308  	"cmd/cgo":                              toTool,
   309  	"cmd/fix":                              toTool,
   310  	"cmd/yacc":                             toTool,
   311  	"code.google.com/p/go.tools/cmd/cover": toTool,
   312  	"code.google.com/p/go.tools/cmd/godoc": toBin,
   313  	"code.google.com/p/go.tools/cmd/vet":   toTool,
   314  }
   315  
   316  // expandScanner expands a scanner.List error into all the errors in the list.
   317  // The default Error method only shows the first error.
   318  func expandScanner(err error) error {
   319  	// Look for parser errors.
   320  	if err, ok := err.(scanner.ErrorList); ok {
   321  		// Prepare error with \n before each message.
   322  		// When printed in something like context: %v
   323  		// this will put the leading file positions each on
   324  		// its own line.  It will also show all the errors
   325  		// instead of just the first, as err.Error does.
   326  		var buf bytes.Buffer
   327  		for _, e := range err {
   328  			e.Pos.Filename = shortPath(e.Pos.Filename)
   329  			buf.WriteString("\n")
   330  			buf.WriteString(e.Error())
   331  		}
   332  		return errors.New(buf.String())
   333  	}
   334  	return err
   335  }
   336  
   337  var raceExclude = map[string]bool{
   338  	"runtime/race": true,
   339  	"runtime/cgo":  true,
   340  	"cmd/cgo":      true,
   341  	"syscall":      true,
   342  	"errors":       true,
   343  }
   344  
   345  var cgoExclude = map[string]bool{
   346  	"runtime/cgo": true,
   347  }
   348  
   349  var cgoSyscallExclude = map[string]bool{
   350  	"runtime/cgo":  true,
   351  	"runtime/race": true,
   352  }
   353  
   354  // load populates p using information from bp, err, which should
   355  // be the result of calling build.Context.Import.
   356  func (p *Package) load(stk *importStack, bp *build.Package, err error) *Package {
   357  	p.copyBuild(bp)
   358  
   359  	// The localPrefix is the path we interpret ./ imports relative to.
   360  	// Synthesized main packages sometimes override this.
   361  	p.localPrefix = dirToImportPath(p.Dir)
   362  
   363  	if err != nil {
   364  		p.Incomplete = true
   365  		err = expandScanner(err)
   366  		p.Error = &PackageError{
   367  			ImportStack: stk.copy(),
   368  			Err:         err.Error(),
   369  		}
   370  		return p
   371  	}
   372  
   373  	if p.Name == "main" {
   374  		_, elem := filepath.Split(p.Dir)
   375  		full := buildContext.GOOS + "_" + buildContext.GOARCH + "/" + elem
   376  		if buildContext.GOOS != toolGOOS || buildContext.GOARCH != toolGOARCH {
   377  			// Install cross-compiled binaries to subdirectories of bin.
   378  			elem = full
   379  		}
   380  		if p.build.BinDir != gobin && goTools[p.ImportPath] == toBin {
   381  			// Override BinDir.
   382  			// This is from a subrepo but installs to $GOROOT/bin
   383  			// by default anyway (like godoc).
   384  			p.target = filepath.Join(gorootBin, elem)
   385  		} else if p.build.BinDir != "" {
   386  			// Install to GOBIN or bin of GOPATH entry.
   387  			p.target = filepath.Join(p.build.BinDir, elem)
   388  		}
   389  		if goTools[p.ImportPath] == toTool {
   390  			// This is for 'go tool'.
   391  			// Override all the usual logic and force it into the tool directory.
   392  			p.target = filepath.Join(gorootPkg, "tool", full)
   393  		}
   394  		if p.target != "" && buildContext.GOOS == "windows" {
   395  			p.target += ".exe"
   396  		}
   397  	} else if p.local {
   398  		// Local import turned into absolute path.
   399  		// No permanent install target.
   400  		p.target = ""
   401  	} else {
   402  		p.target = p.build.PkgObj
   403  	}
   404  
   405  	importPaths := p.Imports
   406  	// Packages that use cgo import runtime/cgo implicitly.
   407  	// Packages that use cgo also import syscall implicitly,
   408  	// to wrap errno.
   409  	// Exclude certain packages to avoid circular dependencies.
   410  	if len(p.CgoFiles) > 0 && (!p.Standard || !cgoExclude[p.ImportPath]) {
   411  		importPaths = append(importPaths, "runtime/cgo")
   412  	}
   413  	if len(p.CgoFiles) > 0 && (!p.Standard || !cgoSyscallExclude[p.ImportPath]) {
   414  		importPaths = append(importPaths, "syscall")
   415  	}
   416  	// Everything depends on runtime, except runtime and unsafe.
   417  	if !p.Standard || (p.ImportPath != "runtime" && p.ImportPath != "unsafe") {
   418  		importPaths = append(importPaths, "runtime")
   419  		// When race detection enabled everything depends on runtime/race.
   420  		// Exclude certain packages to avoid circular dependencies.
   421  		if buildRace && (!p.Standard || !raceExclude[p.ImportPath]) {
   422  			importPaths = append(importPaths, "runtime/race")
   423  		}
   424  	}
   425  
   426  	// Build list of full paths to all Go files in the package,
   427  	// for use by commands like go fmt.
   428  	p.gofiles = stringList(p.GoFiles, p.CgoFiles, p.TestGoFiles, p.XTestGoFiles)
   429  	for i := range p.gofiles {
   430  		p.gofiles[i] = filepath.Join(p.Dir, p.gofiles[i])
   431  	}
   432  	sort.Strings(p.gofiles)
   433  
   434  	p.sfiles = stringList(p.SFiles)
   435  	for i := range p.sfiles {
   436  		p.sfiles[i] = filepath.Join(p.Dir, p.sfiles[i])
   437  	}
   438  	sort.Strings(p.sfiles)
   439  
   440  	p.allgofiles = stringList(p.IgnoredGoFiles)
   441  	for i := range p.allgofiles {
   442  		p.allgofiles[i] = filepath.Join(p.Dir, p.allgofiles[i])
   443  	}
   444  	p.allgofiles = append(p.allgofiles, p.gofiles...)
   445  	sort.Strings(p.allgofiles)
   446  
   447  	// Check for case-insensitive collision of input files.
   448  	// To avoid problems on case-insensitive files, we reject any package
   449  	// where two different input files have equal names under a case-insensitive
   450  	// comparison.
   451  	f1, f2 := foldDup(stringList(
   452  		p.GoFiles,
   453  		p.CgoFiles,
   454  		p.IgnoredGoFiles,
   455  		p.CFiles,
   456  		p.CXXFiles,
   457  		p.HFiles,
   458  		p.SFiles,
   459  		p.SysoFiles,
   460  		p.SwigFiles,
   461  		p.SwigCXXFiles,
   462  		p.TestGoFiles,
   463  		p.XTestGoFiles,
   464  	))
   465  	if f1 != "" {
   466  		p.Error = &PackageError{
   467  			ImportStack: stk.copy(),
   468  			Err:         fmt.Sprintf("case-insensitive file name collision: %q and %q", f1, f2),
   469  		}
   470  		return p
   471  	}
   472  
   473  	// Build list of imported packages and full dependency list.
   474  	imports := make([]*Package, 0, len(p.Imports))
   475  	deps := make(map[string]bool)
   476  	for i, path := range importPaths {
   477  		if path == "C" {
   478  			continue
   479  		}
   480  		p1 := loadImport(path, p.Dir, stk, p.build.ImportPos[path])
   481  		if p1.local {
   482  			if !p.local && p.Error == nil {
   483  				p.Error = &PackageError{
   484  					ImportStack: stk.copy(),
   485  					Err:         fmt.Sprintf("local import %q in non-local package", path),
   486  				}
   487  				pos := p.build.ImportPos[path]
   488  				if len(pos) > 0 {
   489  					p.Error.Pos = pos[0].String()
   490  				}
   491  			}
   492  			path = p1.ImportPath
   493  			importPaths[i] = path
   494  		}
   495  		deps[path] = true
   496  		imports = append(imports, p1)
   497  		for _, dep := range p1.Deps {
   498  			deps[dep] = true
   499  		}
   500  		if p1.Incomplete {
   501  			p.Incomplete = true
   502  		}
   503  	}
   504  	p.imports = imports
   505  
   506  	p.Deps = make([]string, 0, len(deps))
   507  	for dep := range deps {
   508  		p.Deps = append(p.Deps, dep)
   509  	}
   510  	sort.Strings(p.Deps)
   511  	for _, dep := range p.Deps {
   512  		p1 := packageCache[dep]
   513  		if p1 == nil {
   514  			panic("impossible: missing entry in package cache for " + dep + " imported by " + p.ImportPath)
   515  		}
   516  		p.deps = append(p.deps, p1)
   517  		if p1.Error != nil {
   518  			p.DepsErrors = append(p.DepsErrors, p1.Error)
   519  		}
   520  	}
   521  
   522  	// unsafe is a fake package.
   523  	if p.Standard && (p.ImportPath == "unsafe" || buildContext.Compiler == "gccgo") {
   524  		p.target = ""
   525  	}
   526  	p.Target = p.target
   527  
   528  	// In the absence of errors lower in the dependency tree,
   529  	// check for case-insensitive collisions of import paths.
   530  	if len(p.DepsErrors) == 0 {
   531  		dep1, dep2 := foldDup(p.Deps)
   532  		if dep1 != "" {
   533  			p.Error = &PackageError{
   534  				ImportStack: stk.copy(),
   535  				Err:         fmt.Sprintf("case-insensitive import collision: %q and %q", dep1, dep2),
   536  			}
   537  			return p
   538  		}
   539  	}
   540  
   541  	return p
   542  }
   543  
   544  // usesSwig reports whether the package needs to run SWIG.
   545  func (p *Package) usesSwig() bool {
   546  	return len(p.SwigFiles) > 0 || len(p.SwigCXXFiles) > 0
   547  }
   548  
   549  // usesCgo reports whether the package needs to run cgo
   550  func (p *Package) usesCgo() bool {
   551  	return len(p.CgoFiles) > 0
   552  }
   553  
   554  // swigSoname returns the name of the shared library we create for a
   555  // SWIG input file.
   556  func (p *Package) swigSoname(file string) string {
   557  	return strings.Replace(p.ImportPath, "/", "-", -1) + "-" + strings.Replace(file, ".", "-", -1) + ".so"
   558  }
   559  
   560  // swigDir returns the name of the shared SWIG directory for a
   561  // package.
   562  func (p *Package) swigDir(ctxt *build.Context) string {
   563  	dir := p.build.PkgRoot
   564  	if ctxt.Compiler == "gccgo" {
   565  		dir = filepath.Join(dir, "gccgo_"+ctxt.GOOS+"_"+ctxt.GOARCH)
   566  	} else {
   567  		dir = filepath.Join(dir, ctxt.GOOS+"_"+ctxt.GOARCH)
   568  	}
   569  	return filepath.Join(dir, "swig")
   570  }
   571  
   572  // packageList returns the list of packages in the dag rooted at roots
   573  // as visited in a depth-first post-order traversal.
   574  func packageList(roots []*Package) []*Package {
   575  	seen := map[*Package]bool{}
   576  	all := []*Package{}
   577  	var walk func(*Package)
   578  	walk = func(p *Package) {
   579  		if seen[p] {
   580  			return
   581  		}
   582  		seen[p] = true
   583  		for _, p1 := range p.imports {
   584  			walk(p1)
   585  		}
   586  		all = append(all, p)
   587  	}
   588  	for _, root := range roots {
   589  		walk(root)
   590  	}
   591  	return all
   592  }
   593  
   594  // computeStale computes the Stale flag in the package dag that starts
   595  // at the named pkgs (command-line arguments).
   596  func computeStale(pkgs ...*Package) {
   597  	topRoot := map[string]bool{}
   598  	for _, p := range pkgs {
   599  		topRoot[p.Root] = true
   600  	}
   601  
   602  	for _, p := range packageList(pkgs) {
   603  		p.Stale = isStale(p, topRoot)
   604  	}
   605  }
   606  
   607  // isStale reports whether package p needs to be rebuilt.
   608  func isStale(p *Package, topRoot map[string]bool) bool {
   609  	if p.Standard && (p.ImportPath == "unsafe" || buildContext.Compiler == "gccgo") {
   610  		// fake, builtin package
   611  		return false
   612  	}
   613  	if p.Error != nil {
   614  		return true
   615  	}
   616  
   617  	// A package without Go sources means we only found
   618  	// the installed .a file.  Since we don't know how to rebuild
   619  	// it, it can't be stale, even if -a is set.  This enables binary-only
   620  	// distributions of Go packages, although such binaries are
   621  	// only useful with the specific version of the toolchain that
   622  	// created them.
   623  	if len(p.gofiles) == 0 && !p.usesSwig() {
   624  		return false
   625  	}
   626  
   627  	if buildA || p.target == "" || p.Stale {
   628  		return true
   629  	}
   630  
   631  	// Package is stale if completely unbuilt.
   632  	var built time.Time
   633  	if fi, err := os.Stat(p.target); err == nil {
   634  		built = fi.ModTime()
   635  	}
   636  	if built.IsZero() {
   637  		return true
   638  	}
   639  
   640  	olderThan := func(file string) bool {
   641  		fi, err := os.Stat(file)
   642  		return err != nil || fi.ModTime().After(built)
   643  	}
   644  
   645  	// Package is stale if a dependency is, or if a dependency is newer.
   646  	for _, p1 := range p.deps {
   647  		if p1.Stale || p1.target != "" && olderThan(p1.target) {
   648  			return true
   649  		}
   650  	}
   651  
   652  	// As a courtesy to developers installing new versions of the compiler
   653  	// frequently, define that packages are stale if they are
   654  	// older than the compiler, and commands if they are older than
   655  	// the linker.  This heuristic will not work if the binaries are
   656  	// back-dated, as some binary distributions may do, but it does handle
   657  	// a very common case.
   658  	// See issue 3036.
   659  	// Assume code in $GOROOT is up to date, since it may not be writeable.
   660  	// See issue 4106.
   661  	if p.Root != goroot {
   662  		if olderThan(buildToolchain.compiler()) {
   663  			return true
   664  		}
   665  		if p.build.IsCommand() && olderThan(buildToolchain.linker()) {
   666  			return true
   667  		}
   668  	}
   669  
   670  	// Have installed copy, probably built using current compilers,
   671  	// and built after its imported packages.  The only reason now
   672  	// that we'd have to rebuild it is if the sources were newer than
   673  	// the package.   If a package p is not in the same tree as any
   674  	// package named on the command-line, assume it is up-to-date
   675  	// no matter what the modification times on the source files indicate.
   676  	// This avoids rebuilding $GOROOT packages when people are
   677  	// working outside the Go root, and it effectively makes each tree
   678  	// listed in $GOPATH a separate compilation world.
   679  	// See issue 3149.
   680  	if p.Root != "" && !topRoot[p.Root] {
   681  		return false
   682  	}
   683  
   684  	srcs := stringList(p.GoFiles, p.CFiles, p.CXXFiles, p.HFiles, p.SFiles, p.CgoFiles, p.SysoFiles, p.SwigFiles, p.SwigCXXFiles)
   685  	for _, src := range srcs {
   686  		if olderThan(filepath.Join(p.Dir, src)) {
   687  			return true
   688  		}
   689  	}
   690  
   691  	return false
   692  }
   693  
   694  var cwd, _ = os.Getwd()
   695  
   696  var cmdCache = map[string]*Package{}
   697  
   698  // loadPackage is like loadImport but is used for command-line arguments,
   699  // not for paths found in import statements.  In addition to ordinary import paths,
   700  // loadPackage accepts pseudo-paths beginning with cmd/ to denote commands
   701  // in the Go command directory, as well as paths to those directories.
   702  func loadPackage(arg string, stk *importStack) *Package {
   703  	if build.IsLocalImport(arg) {
   704  		dir := arg
   705  		if !filepath.IsAbs(dir) {
   706  			if abs, err := filepath.Abs(dir); err == nil {
   707  				// interpret relative to current directory
   708  				dir = abs
   709  			}
   710  		}
   711  		if sub, ok := hasSubdir(gorootSrc, dir); ok && strings.HasPrefix(sub, "cmd/") && !strings.Contains(sub[4:], "/") {
   712  			arg = sub
   713  		}
   714  	}
   715  	if strings.HasPrefix(arg, "cmd/") {
   716  		if p := cmdCache[arg]; p != nil {
   717  			return p
   718  		}
   719  		stk.push(arg)
   720  		defer stk.pop()
   721  
   722  		if strings.Contains(arg[4:], "/") {
   723  			p := &Package{
   724  				Error: &PackageError{
   725  					ImportStack: stk.copy(),
   726  					Err:         fmt.Sprintf("invalid import path: cmd/... is reserved for Go commands"),
   727  				},
   728  			}
   729  			return p
   730  		}
   731  
   732  		bp, err := buildContext.ImportDir(filepath.Join(gorootSrc, arg), 0)
   733  		bp.ImportPath = arg
   734  		bp.Goroot = true
   735  		bp.BinDir = gorootBin
   736  		if gobin != "" {
   737  			bp.BinDir = gobin
   738  		}
   739  		bp.Root = goroot
   740  		bp.SrcRoot = gorootSrc
   741  		p := new(Package)
   742  		cmdCache[arg] = p
   743  		p.load(stk, bp, err)
   744  		if p.Error == nil && p.Name != "main" {
   745  			p.Error = &PackageError{
   746  				ImportStack: stk.copy(),
   747  				Err:         fmt.Sprintf("expected package main but found package %s in %s", p.Name, p.Dir),
   748  			}
   749  		}
   750  		return p
   751  	}
   752  
   753  	// Wasn't a command; must be a package.
   754  	// If it is a local import path but names a standard package,
   755  	// we treat it as if the user specified the standard package.
   756  	// This lets you run go test ./ioutil in package io and be
   757  	// referring to io/ioutil rather than a hypothetical import of
   758  	// "./ioutil".
   759  	if build.IsLocalImport(arg) {
   760  		bp, _ := buildContext.ImportDir(filepath.Join(cwd, arg), build.FindOnly)
   761  		if bp.ImportPath != "" && bp.ImportPath != "." {
   762  			arg = bp.ImportPath
   763  		}
   764  	}
   765  
   766  	return loadImport(arg, cwd, stk, nil)
   767  }
   768  
   769  // packages returns the packages named by the
   770  // command line arguments 'args'.  If a named package
   771  // cannot be loaded at all (for example, if the directory does not exist),
   772  // then packages prints an error and does not include that
   773  // package in the results.  However, if errors occur trying
   774  // to load dependencies of a named package, the named
   775  // package is still returned, with p.Incomplete = true
   776  // and details in p.DepsErrors.
   777  func packages(args []string) []*Package {
   778  	var pkgs []*Package
   779  	for _, pkg := range packagesAndErrors(args) {
   780  		if pkg.Error != nil {
   781  			errorf("can't load package: %s", pkg.Error)
   782  			continue
   783  		}
   784  		pkgs = append(pkgs, pkg)
   785  	}
   786  	return pkgs
   787  }
   788  
   789  // packagesAndErrors is like 'packages' but returns a
   790  // *Package for every argument, even the ones that
   791  // cannot be loaded at all.
   792  // The packages that fail to load will have p.Error != nil.
   793  func packagesAndErrors(args []string) []*Package {
   794  	if len(args) > 0 && strings.HasSuffix(args[0], ".go") {
   795  		return []*Package{goFilesPackage(args)}
   796  	}
   797  
   798  	args = importPaths(args)
   799  	var pkgs []*Package
   800  	var stk importStack
   801  	var set = make(map[string]bool)
   802  
   803  	for _, arg := range args {
   804  		if !set[arg] {
   805  			pkgs = append(pkgs, loadPackage(arg, &stk))
   806  			set[arg] = true
   807  		}
   808  	}
   809  	computeStale(pkgs...)
   810  
   811  	return pkgs
   812  }
   813  
   814  // packagesForBuild is like 'packages' but fails if any of
   815  // the packages or their dependencies have errors
   816  // (cannot be built).
   817  func packagesForBuild(args []string) []*Package {
   818  	pkgs := packagesAndErrors(args)
   819  	printed := map[*PackageError]bool{}
   820  	for _, pkg := range pkgs {
   821  		if pkg.Error != nil {
   822  			errorf("can't load package: %s", pkg.Error)
   823  		}
   824  		for _, err := range pkg.DepsErrors {
   825  			// Since these are errors in dependencies,
   826  			// the same error might show up multiple times,
   827  			// once in each package that depends on it.
   828  			// Only print each once.
   829  			if !printed[err] {
   830  				printed[err] = true
   831  				errorf("%s", err)
   832  			}
   833  		}
   834  	}
   835  	exitIfErrors()
   836  	return pkgs
   837  }
   838  
   839  // hasSubdir reports whether dir is a subdirectory of
   840  // (possibly multiple levels below) root.
   841  // If so, it sets rel to the path fragment that must be
   842  // appended to root to reach dir.
   843  func hasSubdir(root, dir string) (rel string, ok bool) {
   844  	if p, err := filepath.EvalSymlinks(root); err == nil {
   845  		root = p
   846  	}
   847  	if p, err := filepath.EvalSymlinks(dir); err == nil {
   848  		dir = p
   849  	}
   850  	const sep = string(filepath.Separator)
   851  	root = filepath.Clean(root)
   852  	if !strings.HasSuffix(root, sep) {
   853  		root += sep
   854  	}
   855  	dir = filepath.Clean(dir)
   856  	if !strings.HasPrefix(dir, root) {
   857  		return "", false
   858  	}
   859  	return filepath.ToSlash(dir[len(root):]), true
   860  }