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