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 }