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