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 5package build 6 7import ( 8 "bytes" 9 "errors" 10 "fmt" 11 "go/ast" 12 "go/doc" 13 "go/parser" 14 "go/token" 15 "internal/goroot" 16 "internal/goversion" 17 "io" 18 "io/ioutil" 19 "log" 20 "os" 21 "os/exec" 22 pathpkg "path" 23 "path/filepath" 24 "runtime" 25 "sort" 26 "strconv" 27 "strings" 28 "unicode" 29 "unicode/utf8" 30) 31 32// A Context specifies the supporting context for a build. 33type Context struct { 34 GOARCH string // target architecture 35 GOOS string // target operating system 36 GOROOT string // Go root 37 GOPATH string // Go path 38 39 // Dir is the caller's working directory, or the empty string to use 40 // the current directory of the running process. In module mode, this is used 41 // to locate the main module. 42 // 43 // If Dir is non-empty, directories passed to Import and ImportDir must 44 // be absolute. 45 Dir string 46 47 CgoEnabled bool // whether cgo files are included 48 UseAllFiles bool // use files regardless of +build lines, file names 49 Compiler string // compiler to assume when computing target paths 50 51 // The build and release tags specify build constraints 52 // that should be considered satisfied when processing +build lines. 53 // Clients creating a new context may customize BuildTags, which 54 // defaults to empty, but it is usually an error to customize ReleaseTags, 55 // which defaults to the list of Go releases the current release is compatible with. 56 // BuildTags is not set for the Default build Context. 57 // In addition to the BuildTags and ReleaseTags, build constraints 58 // consider the values of GOARCH and GOOS as satisfied tags. 59 // The last element in ReleaseTags is assumed to be the current release. 60 BuildTags []string 61 ReleaseTags []string 62 63 // The install suffix specifies a suffix to use in the name of the installation 64 // directory. By default it is empty, but custom builds that need to keep 65 // their outputs separate can set InstallSuffix to do so. For example, when 66 // using the race detector, the go command uses InstallSuffix = "race", so 67 // that on a Linux/386 system, packages are written to a directory named 68 // "linux_386_race" instead of the usual "linux_386". 69 InstallSuffix string 70 71 // By default, Import uses the operating system's file system calls 72 // to read directories and files. To read from other sources, 73 // callers can set the following functions. They all have default 74 // behaviors that use the local file system, so clients need only set 75 // the functions whose behaviors they wish to change. 76 77 // JoinPath joins the sequence of path fragments into a single path. 78 // If JoinPath is nil, Import uses filepath.Join. 79 JoinPath func(elem ...string) string 80 81 // SplitPathList splits the path list into a slice of individual paths. 82 // If SplitPathList is nil, Import uses filepath.SplitList. 83 SplitPathList func(list string) []string 84 85 // IsAbsPath reports whether path is an absolute path. 86 // If IsAbsPath is nil, Import uses filepath.IsAbs. 87 IsAbsPath func(path string) bool 88 89 // IsDir reports whether the path names a directory. 90 // If IsDir is nil, Import calls os.Stat and uses the result's IsDir method. 91 IsDir func(path string) bool 92 93 // HasSubdir reports whether dir is lexically a subdirectory of 94 // root, perhaps multiple levels below. It does not try to check 95 // whether dir exists. 96 // If so, HasSubdir sets rel to a slash-separated path that 97 // can be joined to root to produce a path equivalent to dir. 98 // If HasSubdir is nil, Import uses an implementation built on 99 // filepath.EvalSymlinks. 100 HasSubdir func(root, dir string) (rel string, ok bool) 101 102 // ReadDir returns a slice of os.FileInfo, sorted by Name, 103 // describing the content of the named directory. 104 // If ReadDir is nil, Import uses ioutil.ReadDir. 105 ReadDir func(dir string) ([]os.FileInfo, error) 106 107 // OpenFile opens a file (not a directory) for reading. 108 // If OpenFile is nil, Import uses os.Open. 109 OpenFile func(path string) (io.ReadCloser, error) 110} 111 112// joinPath calls ctxt.JoinPath (if not nil) or else filepath.Join. 113func (ctxt *Context) joinPath(elem ...string) string { 114 if f := ctxt.JoinPath; f != nil { 115 return f(elem...) 116 } 117 return filepath.Join(elem...) 118} 119 120// splitPathList calls ctxt.SplitPathList (if not nil) or else filepath.SplitList. 121func (ctxt *Context) splitPathList(s string) []string { 122 if f := ctxt.SplitPathList; f != nil { 123 return f(s) 124 } 125 return filepath.SplitList(s) 126} 127 128// isAbsPath calls ctxt.IsAbsPath (if not nil) or else filepath.IsAbs. 129func (ctxt *Context) isAbsPath(path string) bool { 130 if f := ctxt.IsAbsPath; f != nil { 131 return f(path) 132 } 133 return filepath.IsAbs(path) 134} 135 136// isDir calls ctxt.IsDir (if not nil) or else uses os.Stat. 137func (ctxt *Context) isDir(path string) bool { 138 if f := ctxt.IsDir; f != nil { 139 return f(path) 140 } 141 fi, err := os.Stat(path) 142 return err == nil && fi.IsDir() 143} 144 145// hasSubdir calls ctxt.HasSubdir (if not nil) or else uses 146// the local file system to answer the question. 147func (ctxt *Context) hasSubdir(root, dir string) (rel string, ok bool) { 148 if f := ctxt.HasSubdir; f != nil { 149 return f(root, dir) 150 } 151 152 // Try using paths we received. 153 if rel, ok = hasSubdir(root, dir); ok { 154 return 155 } 156 157 // Try expanding symlinks and comparing 158 // expanded against unexpanded and 159 // expanded against expanded. 160 rootSym, _ := filepath.EvalSymlinks(root) 161 dirSym, _ := filepath.EvalSymlinks(dir) 162 163 if rel, ok = hasSubdir(rootSym, dir); ok { 164 return 165 } 166 if rel, ok = hasSubdir(root, dirSym); ok { 167 return 168 } 169 return hasSubdir(rootSym, dirSym) 170} 171 172// hasSubdir reports if dir is within root by performing lexical analysis only. 173func hasSubdir(root, dir string) (rel string, ok bool) { 174 const sep = string(filepath.Separator) 175 root = filepath.Clean(root) 176 if !strings.HasSuffix(root, sep) { 177 root += sep 178 } 179 dir = filepath.Clean(dir) 180 if !strings.HasPrefix(dir, root) { 181 return "", false 182 } 183 return filepath.ToSlash(dir[len(root):]), true 184} 185 186// readDir calls ctxt.ReadDir (if not nil) or else ioutil.ReadDir. 187func (ctxt *Context) readDir(path string) ([]os.FileInfo, error) { 188 if f := ctxt.ReadDir; f != nil { 189 return f(path) 190 } 191 return ioutil.ReadDir(path) 192} 193 194// openFile calls ctxt.OpenFile (if not nil) or else os.Open. 195func (ctxt *Context) openFile(path string) (io.ReadCloser, error) { 196 if fn := ctxt.OpenFile; fn != nil { 197 return fn(path) 198 } 199 200 f, err := os.Open(path) 201 if err != nil { 202 return nil, err // nil interface 203 } 204 return f, nil 205} 206 207// isFile determines whether path is a file by trying to open it. 208// It reuses openFile instead of adding another function to the 209// list in Context. 210func (ctxt *Context) isFile(path string) bool { 211 f, err := ctxt.openFile(path) 212 if err != nil { 213 return false 214 } 215 f.Close() 216 return true 217} 218 219// gopath returns the list of Go path directories. 220func (ctxt *Context) gopath() []string { 221 var all []string 222 for _, p := range ctxt.splitPathList(ctxt.GOPATH) { 223 if p == "" || p == ctxt.GOROOT { 224 // Empty paths are uninteresting. 225 // If the path is the GOROOT, ignore it. 226 // People sometimes set GOPATH=$GOROOT. 227 // Do not get confused by this common mistake. 228 continue 229 } 230 if strings.HasPrefix(p, "~") { 231 // Path segments starting with ~ on Unix are almost always 232 // users who have incorrectly quoted ~ while setting GOPATH, 233 // preventing it from expanding to $HOME. 234 // The situation is made more confusing by the fact that 235 // bash allows quoted ~ in $PATH (most shells do not). 236 // Do not get confused by this, and do not try to use the path. 237 // It does not exist, and printing errors about it confuses 238 // those users even more, because they think "sure ~ exists!". 239 // The go command diagnoses this situation and prints a 240 // useful error. 241 // On Windows, ~ is used in short names, such as c:\progra~1 242 // for c:\program files. 243 continue 244 } 245 all = append(all, p) 246 } 247 return all 248} 249 250// SrcDirs returns a list of package source root directories. 251// It draws from the current Go root and Go path but omits directories 252// that do not exist. 253func (ctxt *Context) SrcDirs() []string { 254 var all []string 255 if ctxt.GOROOT != "" && ctxt.Compiler != "gccgo" { 256 dir := ctxt.joinPath(ctxt.GOROOT, "src") 257 if ctxt.isDir(dir) { 258 all = append(all, dir) 259 } 260 } 261 for _, p := range ctxt.gopath() { 262 dir := ctxt.joinPath(p, "src") 263 if ctxt.isDir(dir) { 264 all = append(all, dir) 265 } 266 } 267 return all 268} 269 270// Default is the default Context for builds. 271// It uses the GOARCH, GOOS, GOROOT, and GOPATH environment variables 272// if set, or else the compiled code's GOARCH, GOOS, and GOROOT. 273var Default Context = defaultContext() 274 275func defaultGOPATH() string { 276 env := "HOME" 277 if runtime.GOOS == "windows" { 278 env = "USERPROFILE" 279 } else if runtime.GOOS == "plan9" { 280 env = "home" 281 } 282 if home := os.Getenv(env); home != "" { 283 def := filepath.Join(home, "go") 284 if filepath.Clean(def) == filepath.Clean(runtime.GOROOT()) { 285 // Don't set the default GOPATH to GOROOT, 286 // as that will trigger warnings from the go tool. 287 return "" 288 } 289 return def 290 } 291 return "" 292} 293 294var defaultReleaseTags []string 295 296func defaultContext() Context { 297 var c Context 298 299 c.GOARCH = envOr("GOARCH", runtime.GOARCH) 300 c.GOOS = envOr("GOOS", runtime.GOOS) 301 c.GOROOT = pathpkg.Clean(runtime.GOROOT()) 302 c.GOPATH = envOr("GOPATH", defaultGOPATH()) 303 c.Compiler = runtime.Compiler 304 305 // Each major Go release in the Go 1.x series adds a new 306 // "go1.x" release tag. That is, the go1.x tag is present in 307 // all releases >= Go 1.x. Code that requires Go 1.x or later 308 // should say "+build go1.x", and code that should only be 309 // built before Go 1.x (perhaps it is the stub to use in that 310 // case) should say "+build !go1.x". 311 // The last element in ReleaseTags is the current release. 312 for i := 1; i <= goversion.Version; i++ { 313 c.ReleaseTags = append(c.ReleaseTags, "go1."+strconv.Itoa(i)) 314 } 315 316 defaultReleaseTags = append([]string{}, c.ReleaseTags...) // our own private copy 317 318 env := os.Getenv("CGO_ENABLED") 319 // No defaultCGO_ENABLED in gccgo. 320 // if env == "" { 321 // env = defaultCGO_ENABLED 322 // } 323 switch env { 324 case "1": 325 c.CgoEnabled = true 326 case "0": 327 c.CgoEnabled = false 328 default: 329 // cgo must be explicitly enabled for cross compilation builds 330 if runtime.GOARCH == c.GOARCH && runtime.GOOS == c.GOOS { 331 // Always enabled for gccgo. 332 c.CgoEnabled = true 333 break 334 } 335 c.CgoEnabled = false 336 } 337 338 return c 339} 340 341func envOr(name, def string) string { 342 s := os.Getenv(name) 343 if s == "" { 344 return def 345 } 346 return s 347} 348 349// An ImportMode controls the behavior of the Import method. 350type ImportMode uint 351 352const ( 353 // If FindOnly is set, Import stops after locating the directory 354 // that should contain the sources for a package. It does not 355 // read any files in the directory. 356 FindOnly ImportMode = 1 << iota 357 358 // If AllowBinary is set, Import can be satisfied by a compiled 359 // package object without corresponding sources. 360 // 361 // Deprecated: 362 // The supported way to create a compiled-only package is to 363 // write source code containing a //go:binary-only-package comment at 364 // the top of the file. Such a package will be recognized 365 // regardless of this flag setting (because it has source code) 366 // and will have BinaryOnly set to true in the returned Package. 367 AllowBinary 368 369 // If ImportComment is set, parse import comments on package statements. 370 // Import returns an error if it finds a comment it cannot understand 371 // or finds conflicting comments in multiple source files. 372 // See golang.org/s/go14customimport for more information. 373 ImportComment 374 375 // By default, Import searches vendor directories 376 // that apply in the given source directory before searching 377 // the GOROOT and GOPATH roots. 378 // If an Import finds and returns a package using a vendor 379 // directory, the resulting ImportPath is the complete path 380 // to the package, including the path elements leading up 381 // to and including "vendor". 382 // For example, if Import("y", "x/subdir", 0) finds 383 // "x/vendor/y", the returned package's ImportPath is "x/vendor/y", 384 // not plain "y". 385 // See golang.org/s/go15vendor for more information. 386 // 387 // Setting IgnoreVendor ignores vendor directories. 388 // 389 // In contrast to the package's ImportPath, 390 // the returned package's Imports, TestImports, and XTestImports 391 // are always the exact import paths from the source files: 392 // Import makes no attempt to resolve or check those paths. 393 IgnoreVendor 394) 395 396// A Package describes the Go package found in a directory. 397type Package struct { 398 Dir string // directory containing package sources 399 Name string // package name 400 ImportComment string // path in import comment on package statement 401 Doc string // documentation synopsis 402 ImportPath string // import path of package ("" if unknown) 403 Root string // root of Go tree where this package lives 404 SrcRoot string // package source root directory ("" if unknown) 405 PkgRoot string // package install root directory ("" if unknown) 406 PkgTargetRoot string // architecture dependent install root directory ("" if unknown) 407 BinDir string // command install directory ("" if unknown) 408 Goroot bool // package found in Go root 409 PkgObj string // installed .a file 410 AllTags []string // tags that can influence file selection in this directory 411 ConflictDir string // this directory shadows Dir in $GOPATH 412 BinaryOnly bool // cannot be rebuilt from source (has //go:binary-only-package comment) 413 414 // Source files 415 GoFiles []string // .go source files (excluding CgoFiles, TestGoFiles, XTestGoFiles) 416 CgoFiles []string // .go source files that import "C" 417 IgnoredGoFiles []string // .go source files ignored for this build 418 InvalidGoFiles []string // .go source files with detected problems (parse error, wrong package name, and so on) 419 CFiles []string // .c source files 420 CXXFiles []string // .cc, .cpp and .cxx source files 421 MFiles []string // .m (Objective-C) source files 422 HFiles []string // .h, .hh, .hpp and .hxx source files 423 FFiles []string // .f, .F, .for and .f90 Fortran source files 424 SFiles []string // .s source files 425 SwigFiles []string // .swig files 426 SwigCXXFiles []string // .swigcxx files 427 SysoFiles []string // .syso system object files to add to archive 428 429 // Cgo directives 430 CgoCFLAGS []string // Cgo CFLAGS directives 431 CgoCPPFLAGS []string // Cgo CPPFLAGS directives 432 CgoCXXFLAGS []string // Cgo CXXFLAGS directives 433 CgoFFLAGS []string // Cgo FFLAGS directives 434 CgoLDFLAGS []string // Cgo LDFLAGS directives 435 CgoPkgConfig []string // Cgo pkg-config directives 436 437 // Dependency information 438 Imports []string // import paths from GoFiles, CgoFiles 439 ImportPos map[string][]token.Position // line information for Imports 440 441 // Test information 442 TestGoFiles []string // _test.go files in package 443 TestImports []string // import paths from TestGoFiles 444 TestImportPos map[string][]token.Position // line information for TestImports 445 XTestGoFiles []string // _test.go files outside package 446 XTestImports []string // import paths from XTestGoFiles 447 XTestImportPos map[string][]token.Position // line information for XTestImports 448} 449 450// IsCommand reports whether the package is considered a 451// command to be installed (not just a library). 452// Packages named "main" are treated as commands. 453func (p *Package) IsCommand() bool { 454 return p.Name == "main" 455} 456 457// ImportDir is like Import but processes the Go package found in 458// the named directory. 459func (ctxt *Context) ImportDir(dir string, mode ImportMode) (*Package, error) { 460 return ctxt.Import(".", dir, mode) 461} 462 463// NoGoError is the error used by Import to describe a directory 464// containing no buildable Go source files. (It may still contain 465// test files, files hidden by build tags, and so on.) 466type NoGoError struct { 467 Dir string 468} 469 470func (e *NoGoError) Error() string { 471 return "no buildable Go source files in " + e.Dir 472} 473 474// MultiplePackageError describes a directory containing 475// multiple buildable Go source files for multiple packages. 476type MultiplePackageError struct { 477 Dir string // directory containing files 478 Packages []string // package names found 479 Files []string // corresponding files: Files[i] declares package Packages[i] 480} 481 482func (e *MultiplePackageError) Error() string { 483 // Error string limited to two entries for compatibility. 484 return fmt.Sprintf("found packages %s (%s) and %s (%s) in %s", e.Packages[0], e.Files[0], e.Packages[1], e.Files[1], e.Dir) 485} 486 487func nameExt(name string) string { 488 i := strings.LastIndex(name, ".") 489 if i < 0 { 490 return "" 491 } 492 return name[i:] 493} 494 495// Import returns details about the Go package named by the import path, 496// interpreting local import paths relative to the srcDir directory. 497// If the path is a local import path naming a package that can be imported 498// using a standard import path, the returned package will set p.ImportPath 499// to that path. 500// 501// In the directory containing the package, .go, .c, .h, and .s files are 502// considered part of the package except for: 503// 504// - .go files in package documentation 505// - files starting with _ or . (likely editor temporary files) 506// - files with build constraints not satisfied by the context 507// 508// If an error occurs, Import returns a non-nil error and a non-nil 509// *Package containing partial information. 510// 511func (ctxt *Context) Import(path string, srcDir string, mode ImportMode) (*Package, error) { 512 p := &Package{ 513 ImportPath: path, 514 } 515 if path == "" { 516 return p, fmt.Errorf("import %q: invalid import path", path) 517 } 518 519 var pkgtargetroot string 520 var pkga string 521 var pkgerr error 522 suffix := "" 523 if ctxt.InstallSuffix != "" { 524 suffix = "_" + ctxt.InstallSuffix 525 } 526 switch ctxt.Compiler { 527 case "gccgo": 528 pkgtargetroot = "pkg/gccgo_" + ctxt.GOOS + "_" + ctxt.GOARCH + suffix 529 case "gc": 530 pkgtargetroot = "pkg/" + ctxt.GOOS + "_" + ctxt.GOARCH + suffix 531 default: 532 // Save error for end of function. 533 pkgerr = fmt.Errorf("import %q: unknown compiler %q", path, ctxt.Compiler) 534 } 535 setPkga := func() { 536 switch ctxt.Compiler { 537 case "gccgo": 538 dir, elem := pathpkg.Split(p.ImportPath) 539 pkga = pkgtargetroot + "/" + dir + "lib" + elem + ".a" 540 case "gc": 541 pkga = pkgtargetroot + "/" + p.ImportPath + ".a" 542 } 543 } 544 setPkga() 545 546 binaryOnly := false 547 if IsLocalImport(path) { 548 pkga = "" // local imports have no installed path 549 if srcDir == "" { 550 return p, fmt.Errorf("import %q: import relative to unknown directory", path) 551 } 552 if !ctxt.isAbsPath(path) { 553 p.Dir = ctxt.joinPath(srcDir, path) 554 } 555 // p.Dir directory may or may not exist. Gather partial information first, check if it exists later. 556 // Determine canonical import path, if any. 557 // Exclude results where the import path would include /testdata/. 558 inTestdata := func(sub string) bool { 559 return strings.Contains(sub, "/testdata/") || strings.HasSuffix(sub, "/testdata") || strings.HasPrefix(sub, "testdata/") || sub == "testdata" 560 } 561 if ctxt.GOROOT != "" { 562 root := ctxt.joinPath(ctxt.GOROOT, "src") 563 if sub, ok := ctxt.hasSubdir(root, p.Dir); ok && !inTestdata(sub) { 564 p.Goroot = true 565 p.ImportPath = sub 566 p.Root = ctxt.GOROOT 567 setPkga() // p.ImportPath changed 568 goto Found 569 } 570 } 571 all := ctxt.gopath() 572 for i, root := range all { 573 rootsrc := ctxt.joinPath(root, "src") 574 if sub, ok := ctxt.hasSubdir(rootsrc, p.Dir); ok && !inTestdata(sub) { 575 // We found a potential import path for dir, 576 // but check that using it wouldn't find something 577 // else first. 578 if ctxt.GOROOT != "" && ctxt.Compiler != "gccgo" { 579 if dir := ctxt.joinPath(ctxt.GOROOT, "src", sub); ctxt.isDir(dir) { 580 p.ConflictDir = dir 581 goto Found 582 } 583 } 584 for _, earlyRoot := range all[:i] { 585 if dir := ctxt.joinPath(earlyRoot, "src", sub); ctxt.isDir(dir) { 586 p.ConflictDir = dir 587 goto Found 588 } 589 } 590 591 // sub would not name some other directory instead of this one. 592 // Record it. 593 p.ImportPath = sub 594 p.Root = root 595 setPkga() // p.ImportPath changed 596 goto Found 597 } 598 } 599 // It's okay that we didn't find a root containing dir. 600 // Keep going with the information we have. 601 } else { 602 if strings.HasPrefix(path, "/") { 603 return p, fmt.Errorf("import %q: cannot import absolute path", path) 604 } 605 606 if err := ctxt.importGo(p, path, srcDir, mode); err == nil { 607 goto Found 608 } else if err != errNoModules { 609 return p, err 610 } 611 612 gopath := ctxt.gopath() // needed twice below; avoid computing many times 613 614 // tried records the location of unsuccessful package lookups 615 var tried struct { 616 vendor []string 617 goroot string 618 gopath []string 619 } 620 621 // Vendor directories get first chance to satisfy import. 622 if mode&IgnoreVendor == 0 && srcDir != "" { 623 searchVendor := func(root string, isGoroot bool) bool { 624 sub, ok := ctxt.hasSubdir(root, srcDir) 625 if !ok || !strings.HasPrefix(sub, "src/") || strings.Contains(sub, "/testdata/") { 626 return false 627 } 628 for { 629 vendor := ctxt.joinPath(root, sub, "vendor") 630 if ctxt.isDir(vendor) { 631 dir := ctxt.joinPath(vendor, path) 632 if ctxt.isDir(dir) && hasGoFiles(ctxt, dir) { 633 p.Dir = dir 634 p.ImportPath = strings.TrimPrefix(pathpkg.Join(sub, "vendor", path), "src/") 635 p.Goroot = isGoroot 636 p.Root = root 637 setPkga() // p.ImportPath changed 638 return true 639 } 640 tried.vendor = append(tried.vendor, dir) 641 } 642 i := strings.LastIndex(sub, "/") 643 if i < 0 { 644 break 645 } 646 sub = sub[:i] 647 } 648 return false 649 } 650 if ctxt.Compiler != "gccgo" && searchVendor(ctxt.GOROOT, true) { 651 goto Found 652 } 653 for _, root := range gopath { 654 if searchVendor(root, false) { 655 goto Found 656 } 657 } 658 } 659 660 // Determine directory from import path. 661 if ctxt.GOROOT != "" { 662 // If the package path starts with "vendor/", only search GOROOT before 663 // GOPATH if the importer is also within GOROOT. That way, if the user has 664 // vendored in a package that is subsequently included in the standard 665 // distribution, they'll continue to pick up their own vendored copy. 666 gorootFirst := srcDir == "" || !strings.HasPrefix(path, "vendor/") 667 if !gorootFirst { 668 _, gorootFirst = ctxt.hasSubdir(ctxt.GOROOT, srcDir) 669 } 670 if gorootFirst { 671 dir := ctxt.joinPath(ctxt.GOROOT, "src", path) 672 if ctxt.Compiler != "gccgo" { 673 isDir := ctxt.isDir(dir) 674 binaryOnly = !isDir && mode&AllowBinary != 0 && pkga != "" && ctxt.isFile(ctxt.joinPath(ctxt.GOROOT, pkga)) 675 if isDir || binaryOnly { 676 p.Dir = dir 677 p.Goroot = true 678 p.Root = ctxt.GOROOT 679 goto Found 680 } 681 } 682 tried.goroot = dir 683 } 684 } 685 if ctxt.Compiler == "gccgo" && goroot.IsStandardPackage(ctxt.GOROOT, ctxt.Compiler, path) { 686 p.Dir = ctxt.joinPath(ctxt.GOROOT, "src", path) 687 p.Goroot = true 688 p.Root = ctxt.GOROOT 689 goto Found 690 } 691 for _, root := range gopath { 692 dir := ctxt.joinPath(root, "src", path) 693 isDir := ctxt.isDir(dir) 694 binaryOnly = !isDir && mode&AllowBinary != 0 && pkga != "" && ctxt.isFile(ctxt.joinPath(root, pkga)) 695 if isDir || binaryOnly { 696 p.Dir = dir 697 p.Root = root 698 goto Found 699 } 700 tried.gopath = append(tried.gopath, dir) 701 } 702 703 // If we tried GOPATH first due to a "vendor/" prefix, fall back to GOPATH. 704 // That way, the user can still get useful results from 'go list' for 705 // standard-vendored paths passed on the command line. 706 if ctxt.GOROOT != "" && tried.goroot == "" { 707 dir := ctxt.joinPath(ctxt.GOROOT, "src", path) 708 if ctxt.Compiler != "gccgo" { 709 isDir := ctxt.isDir(dir) 710 binaryOnly = !isDir && mode&AllowBinary != 0 && pkga != "" && ctxt.isFile(ctxt.joinPath(ctxt.GOROOT, pkga)) 711 if isDir || binaryOnly { 712 p.Dir = dir 713 p.Goroot = true 714 p.Root = ctxt.GOROOT 715 goto Found 716 } 717 } 718 tried.goroot = dir 719 } 720 721 // package was not found 722 var paths []string 723 format := "\t%s (vendor tree)" 724 for _, dir := range tried.vendor { 725 paths = append(paths, fmt.Sprintf(format, dir)) 726 format = "\t%s" 727 } 728 if tried.goroot != "" { 729 paths = append(paths, fmt.Sprintf("\t%s (from $GOROOT)", tried.goroot)) 730 } else { 731 paths = append(paths, "\t($GOROOT not set)") 732 } 733 format = "\t%s (from $GOPATH)" 734 for _, dir := range tried.gopath { 735 paths = append(paths, fmt.Sprintf(format, dir)) 736 format = "\t%s" 737 } 738 if len(tried.gopath) == 0 { 739 paths = append(paths, "\t($GOPATH not set. For more details see: 'go help gopath')") 740 } 741 return p, fmt.Errorf("cannot find package %q in any of:\n%s", path, strings.Join(paths, "\n")) 742 } 743 744Found: 745 if p.Root != "" { 746 p.SrcRoot = ctxt.joinPath(p.Root, "src") 747 p.PkgRoot = ctxt.joinPath(p.Root, "pkg") 748 p.BinDir = ctxt.joinPath(p.Root, "bin") 749 if pkga != "" { 750 p.PkgTargetRoot = ctxt.joinPath(p.Root, pkgtargetroot) 751 p.PkgObj = ctxt.joinPath(p.Root, pkga) 752 } 753 } 754 755 // If it's a local import path, by the time we get here, we still haven't checked 756 // that p.Dir directory exists. This is the right time to do that check. 757 // We can't do it earlier, because we want to gather partial information for the 758 // non-nil *Package returned when an error occurs. 759 // We need to do this before we return early on FindOnly flag. 760 if IsLocalImport(path) && !ctxt.isDir(p.Dir) { 761 if ctxt.Compiler == "gccgo" && p.Goroot { 762 // gccgo has no sources for GOROOT packages. 763 return p, nil 764 } 765 766 // package was not found 767 return p, fmt.Errorf("cannot find package %q in:\n\t%s", path, p.Dir) 768 } 769 770 if mode&FindOnly != 0 { 771 return p, pkgerr 772 } 773 if binaryOnly && (mode&AllowBinary) != 0 { 774 return p, pkgerr 775 } 776 777 if ctxt.Compiler == "gccgo" && p.Goroot { 778 // gccgo has no sources for GOROOT packages. 779 return p, nil 780 } 781 782 dirs, err := ctxt.readDir(p.Dir) 783 if err != nil { 784 return p, err 785 } 786 787 var badGoError error 788 var Sfiles []string // files with ".S"(capital S)/.sx(capital s equivalent for case insensitive filesystems) 789 var firstFile, firstCommentFile string 790 imported := make(map[string][]token.Position) 791 testImported := make(map[string][]token.Position) 792 xTestImported := make(map[string][]token.Position) 793 allTags := make(map[string]bool) 794 fset := token.NewFileSet() 795 for _, d := range dirs { 796 if d.IsDir() { 797 continue 798 } 799 800 name := d.Name() 801 ext := nameExt(name) 802 803 badFile := func(err error) { 804 if badGoError == nil { 805 badGoError = err 806 } 807 p.InvalidGoFiles = append(p.InvalidGoFiles, name) 808 } 809 810 match, data, filename, err := ctxt.matchFile(p.Dir, name, allTags, &p.BinaryOnly) 811 if err != nil { 812 badFile(err) 813 continue 814 } 815 if !match { 816 if ext == ".go" { 817 p.IgnoredGoFiles = append(p.IgnoredGoFiles, name) 818 } 819 continue 820 } 821 822 // Going to save the file. For non-Go files, can stop here. 823 switch ext { 824 case ".c": 825 p.CFiles = append(p.CFiles, name) 826 continue 827 case ".cc", ".cpp", ".cxx": 828 p.CXXFiles = append(p.CXXFiles, name) 829 continue 830 case ".m": 831 p.MFiles = append(p.MFiles, name) 832 continue 833 case ".h", ".hh", ".hpp", ".hxx": 834 p.HFiles = append(p.HFiles, name) 835 continue 836 case ".f", ".F", ".for", ".f90": 837 p.FFiles = append(p.FFiles, name) 838 continue 839 case ".s": 840 p.SFiles = append(p.SFiles, name) 841 continue 842 case ".S", ".sx": 843 Sfiles = append(Sfiles, name) 844 continue 845 case ".swig": 846 p.SwigFiles = append(p.SwigFiles, name) 847 continue 848 case ".swigcxx": 849 p.SwigCXXFiles = append(p.SwigCXXFiles, name) 850 continue 851 case ".syso": 852 // binary objects to add to package archive 853 // Likely of the form foo_windows.syso, but 854 // the name was vetted above with goodOSArchFile. 855 p.SysoFiles = append(p.SysoFiles, name) 856 continue 857 } 858 859 pf, err := parser.ParseFile(fset, filename, data, parser.ImportsOnly|parser.ParseComments) 860 if err != nil { 861 badFile(err) 862 continue 863 } 864 865 pkg := pf.Name.Name 866 if pkg == "documentation" { 867 p.IgnoredGoFiles = append(p.IgnoredGoFiles, name) 868 continue 869 } 870 871 isTest := strings.HasSuffix(name, "_test.go") 872 isXTest := false 873 if isTest && strings.HasSuffix(pkg, "_test") { 874 isXTest = true 875 pkg = pkg[:len(pkg)-len("_test")] 876 } 877 878 if p.Name == "" { 879 p.Name = pkg 880 firstFile = name 881 } else if pkg != p.Name { 882 badFile(&MultiplePackageError{ 883 Dir: p.Dir, 884 Packages: []string{p.Name, pkg}, 885 Files: []string{firstFile, name}, 886 }) 887 p.InvalidGoFiles = append(p.InvalidGoFiles, name) 888 } 889 // Grab the first package comment as docs, provided it is not from a test file. 890 if pf.Doc != nil && p.Doc == "" && !isTest && !isXTest { 891 p.Doc = doc.Synopsis(pf.Doc.Text()) 892 } 893 894 if mode&ImportComment != 0 { 895 qcom, line := findImportComment(data) 896 if line != 0 { 897 com, err := strconv.Unquote(qcom) 898 if err != nil { 899 badFile(fmt.Errorf("%s:%d: cannot parse import comment", filename, line)) 900 } else if p.ImportComment == "" { 901 p.ImportComment = com 902 firstCommentFile = name 903 } else if p.ImportComment != com { 904 badFile(fmt.Errorf("found import comments %q (%s) and %q (%s) in %s", p.ImportComment, firstCommentFile, com, name, p.Dir)) 905 } 906 } 907 } 908 909 // Record imports and information about cgo. 910 type importPos struct { 911 path string 912 pos token.Pos 913 } 914 var fileImports []importPos 915 isCgo := false 916 for _, decl := range pf.Decls { 917 d, ok := decl.(*ast.GenDecl) 918 if !ok { 919 continue 920 } 921 for _, dspec := range d.Specs { 922 spec, ok := dspec.(*ast.ImportSpec) 923 if !ok { 924 continue 925 } 926 quoted := spec.Path.Value 927 path, err := strconv.Unquote(quoted) 928 if err != nil { 929 log.Panicf("%s: parser returned invalid quoted string: <%s>", filename, quoted) 930 } 931 fileImports = append(fileImports, importPos{path, spec.Pos()}) 932 if path == "C" { 933 if isTest { 934 badFile(fmt.Errorf("use of cgo in test %s not supported", filename)) 935 } else { 936 cg := spec.Doc 937 if cg == nil && len(d.Specs) == 1 { 938 cg = d.Doc 939 } 940 if cg != nil { 941 if err := ctxt.saveCgo(filename, p, cg); err != nil { 942 badFile(err) 943 } 944 } 945 isCgo = true 946 } 947 } 948 } 949 } 950 951 var fileList *[]string 952 var importMap map[string][]token.Position 953 switch { 954 case isCgo: 955 allTags["cgo"] = true 956 if ctxt.CgoEnabled { 957 fileList = &p.CgoFiles 958 importMap = imported 959 } else { 960 // Ignore imports from cgo files if cgo is disabled. 961 fileList = &p.IgnoredGoFiles 962 } 963 case isXTest: 964 fileList = &p.XTestGoFiles 965 importMap = xTestImported 966 case isTest: 967 fileList = &p.TestGoFiles 968 importMap = testImported 969 default: 970 fileList = &p.GoFiles 971 importMap = imported 972 } 973 *fileList = append(*fileList, name) 974 if importMap != nil { 975 for _, imp := range fileImports { 976 importMap[imp.path] = append(importMap[imp.path], fset.Position(imp.pos)) 977 } 978 } 979 } 980 981 for tag := range allTags { 982 p.AllTags = append(p.AllTags, tag) 983 } 984 sort.Strings(p.AllTags) 985 986 p.Imports, p.ImportPos = cleanImports(imported) 987 p.TestImports, p.TestImportPos = cleanImports(testImported) 988 p.XTestImports, p.XTestImportPos = cleanImports(xTestImported) 989 990 // add the .S/.sx files only if we are using cgo 991 // (which means gcc will compile them). 992 // The standard assemblers expect .s files. 993 if len(p.CgoFiles) > 0 { 994 p.SFiles = append(p.SFiles, Sfiles...) 995 sort.Strings(p.SFiles) 996 } 997 998 if badGoError != nil { 999 return p, badGoError 1000 } 1001 if len(p.GoFiles)+len(p.CgoFiles)+len(p.TestGoFiles)+len(p.XTestGoFiles) == 0 { 1002 return p, &NoGoError{p.Dir} 1003 } 1004 return p, pkgerr 1005} 1006 1007var errNoModules = errors.New("not using modules") 1008 1009// importGo checks whether it can use the go command to find the directory for path. 1010// If using the go command is not appropriate, importGo returns errNoModules. 1011// Otherwise, importGo tries using the go command and reports whether that succeeded. 1012// Using the go command lets build.Import and build.Context.Import find code 1013// in Go modules. In the long term we want tools to use go/packages (currently golang.org/x/tools/go/packages), 1014// which will also use the go command. 1015// Invoking the go command here is not very efficient in that it computes information 1016// about the requested package and all dependencies and then only reports about the requested package. 1017// Then we reinvoke it for every dependency. But this is still better than not working at all. 1018// See golang.org/issue/26504. 1019func (ctxt *Context) importGo(p *Package, path, srcDir string, mode ImportMode) error { 1020 // To invoke the go command, 1021 // we must not being doing special things like AllowBinary or IgnoreVendor, 1022 // and all the file system callbacks must be nil (we're meant to use the local file system). 1023 if mode&AllowBinary != 0 || mode&IgnoreVendor != 0 || 1024 ctxt.JoinPath != nil || ctxt.SplitPathList != nil || ctxt.IsAbsPath != nil || ctxt.IsDir != nil || ctxt.HasSubdir != nil || ctxt.ReadDir != nil || ctxt.OpenFile != nil || !equal(ctxt.ReleaseTags, defaultReleaseTags) { 1025 return errNoModules 1026 } 1027 1028 // Predict whether module aware mode is enabled by checking the value of 1029 // GO111MODULE and looking for a go.mod file in the source directory or 1030 // one of its parents. Running 'go env GOMOD' in the source directory would 1031 // give a canonical answer, but we'd prefer not to execute another command. 1032 go111Module := os.Getenv("GO111MODULE") 1033 switch go111Module { 1034 case "off": 1035 return errNoModules 1036 default: // "", "on", "auto", anything else 1037 // Maybe use modules. 1038 } 1039 1040 if srcDir != "" { 1041 var absSrcDir string 1042 if filepath.IsAbs(srcDir) { 1043 absSrcDir = srcDir 1044 } else if ctxt.Dir != "" { 1045 return fmt.Errorf("go/build: Dir is non-empty, so relative srcDir is not allowed: %v", srcDir) 1046 } else { 1047 // Find the absolute source directory. hasSubdir does not handle 1048 // relative paths (and can't because the callbacks don't support this). 1049 var err error 1050 absSrcDir, err = filepath.Abs(srcDir) 1051 if err != nil { 1052 return errNoModules 1053 } 1054 } 1055 1056 // If the source directory is in GOROOT, then the in-process code works fine 1057 // and we should keep using it. Moreover, the 'go list' approach below doesn't 1058 // take standard-library vendoring into account and will fail. 1059 if _, ok := ctxt.hasSubdir(filepath.Join(ctxt.GOROOT, "src"), absSrcDir); ok { 1060 return errNoModules 1061 } 1062 } 1063 1064 // For efficiency, if path is a standard library package, let the usual lookup code handle it. 1065 if ctxt.GOROOT != "" { 1066 dir := ctxt.joinPath(ctxt.GOROOT, "src", path) 1067 if ctxt.isDir(dir) { 1068 return errNoModules 1069 } 1070 } 1071 1072 // Unless GO111MODULE=on, look to see if there is a go.mod. 1073 // Since go1.13, it doesn't matter if we're inside GOPATH. 1074 if go111Module != "on" { 1075 var ( 1076 parent string 1077 err error 1078 ) 1079 if ctxt.Dir == "" { 1080 parent, err = os.Getwd() 1081 if err != nil { 1082 // A nonexistent working directory can't be in a module. 1083 return errNoModules 1084 } 1085 } else { 1086 parent, err = filepath.Abs(ctxt.Dir) 1087 if err != nil { 1088 // If the caller passed a bogus Dir explicitly, that's materially 1089 // different from not having modules enabled. 1090 return err 1091 } 1092 } 1093 for { 1094 info, err := os.Stat(filepath.Join(parent, "go.mod")) 1095 if err == nil && !info.IsDir() { 1096 break 1097 } 1098 d := filepath.Dir(parent) 1099 if len(d) >= len(parent) { 1100 return errNoModules // reached top of file system, no go.mod 1101 } 1102 parent = d 1103 } 1104 } 1105 1106 cmd := exec.Command("go", "list", "-e", "-compiler="+ctxt.Compiler, "-tags="+strings.Join(ctxt.BuildTags, ","), "-installsuffix="+ctxt.InstallSuffix, "-f={{.Dir}}\n{{.ImportPath}}\n{{.Root}}\n{{.Goroot}}\n{{if .Error}}{{.Error}}{{end}}\n", "--", path) 1107 1108 if ctxt.Dir != "" { 1109 cmd.Dir = ctxt.Dir 1110 } 1111 1112 var stdout, stderr strings.Builder 1113 cmd.Stdout = &stdout 1114 cmd.Stderr = &stderr 1115 1116 cgo := "0" 1117 if ctxt.CgoEnabled { 1118 cgo = "1" 1119 } 1120 cmd.Env = append(os.Environ(), 1121 "GOOS="+ctxt.GOOS, 1122 "GOARCH="+ctxt.GOARCH, 1123 "GOROOT="+ctxt.GOROOT, 1124 "GOPATH="+ctxt.GOPATH, 1125 "CGO_ENABLED="+cgo, 1126 ) 1127 1128 if err := cmd.Run(); err != nil { 1129 return fmt.Errorf("go/build: go list %s: %v\n%s\n", path, err, stderr.String()) 1130 } 1131 1132 f := strings.SplitN(stdout.String(), "\n", 5) 1133 if len(f) != 5 { 1134 return fmt.Errorf("go/build: importGo %s: unexpected output:\n%s\n", path, stdout.String()) 1135 } 1136 dir := f[0] 1137 errStr := strings.TrimSpace(f[4]) 1138 if errStr != "" && dir == "" { 1139 // If 'go list' could not locate the package (dir is empty), 1140 // return the same error that 'go list' reported. 1141 return errors.New(errStr) 1142 } 1143 1144 // If 'go list' did locate the package, ignore the error. 1145 // It was probably related to loading source files, and we'll 1146 // encounter it ourselves shortly if the FindOnly flag isn't set. 1147 p.Dir = dir 1148 p.ImportPath = f[1] 1149 p.Root = f[2] 1150 p.Goroot = f[3] == "true" 1151 return nil 1152} 1153 1154func equal(x, y []string) bool { 1155 if len(x) != len(y) { 1156 return false 1157 } 1158 for i, xi := range x { 1159 if xi != y[i] { 1160 return false 1161 } 1162 } 1163 return true 1164} 1165 1166// hasGoFiles reports whether dir contains any files with names ending in .go. 1167// For a vendor check we must exclude directories that contain no .go files. 1168// Otherwise it is not possible to vendor just a/b/c and still import the 1169// non-vendored a/b. See golang.org/issue/13832. 1170func hasGoFiles(ctxt *Context, dir string) bool { 1171 ents, _ := ctxt.readDir(dir) 1172 for _, ent := range ents { 1173 if !ent.IsDir() && strings.HasSuffix(ent.Name(), ".go") { 1174 return true 1175 } 1176 } 1177 return false 1178} 1179 1180func findImportComment(data []byte) (s string, line int) { 1181 // expect keyword package 1182 word, data := parseWord(data) 1183 if string(word) != "package" { 1184 return "", 0 1185 } 1186 1187 // expect package name 1188 _, data = parseWord(data) 1189 1190 // now ready for import comment, a // or /* */ comment 1191 // beginning and ending on the current line. 1192 for len(data) > 0 && (data[0] == ' ' || data[0] == '\t' || data[0] == '\r') { 1193 data = data[1:] 1194 } 1195 1196 var comment []byte 1197 switch { 1198 case bytes.HasPrefix(data, slashSlash): 1199 i := bytes.Index(data, newline) 1200 if i < 0 { 1201 i = len(data) 1202 } 1203 comment = data[2:i] 1204 case bytes.HasPrefix(data, slashStar): 1205 data = data[2:] 1206 i := bytes.Index(data, starSlash) 1207 if i < 0 { 1208 // malformed comment 1209 return "", 0 1210 } 1211 comment = data[:i] 1212 if bytes.Contains(comment, newline) { 1213 return "", 0 1214 } 1215 } 1216 comment = bytes.TrimSpace(comment) 1217 1218 // split comment into `import`, `"pkg"` 1219 word, arg := parseWord(comment) 1220 if string(word) != "import" { 1221 return "", 0 1222 } 1223 1224 line = 1 + bytes.Count(data[:cap(data)-cap(arg)], newline) 1225 return strings.TrimSpace(string(arg)), line 1226} 1227 1228var ( 1229 slashSlash = []byte("//") 1230 slashStar = []byte("/*") 1231 starSlash = []byte("*/") 1232 newline = []byte("\n") 1233) 1234 1235// skipSpaceOrComment returns data with any leading spaces or comments removed. 1236func skipSpaceOrComment(data []byte) []byte { 1237 for len(data) > 0 { 1238 switch data[0] { 1239 case ' ', '\t', '\r', '\n': 1240 data = data[1:] 1241 continue 1242 case '/': 1243 if bytes.HasPrefix(data, slashSlash) { 1244 i := bytes.Index(data, newline) 1245 if i < 0 { 1246 return nil 1247 } 1248 data = data[i+1:] 1249 continue 1250 } 1251 if bytes.HasPrefix(data, slashStar) { 1252 data = data[2:] 1253 i := bytes.Index(data, starSlash) 1254 if i < 0 { 1255 return nil 1256 } 1257 data = data[i+2:] 1258 continue 1259 } 1260 } 1261 break 1262 } 1263 return data 1264} 1265 1266// parseWord skips any leading spaces or comments in data 1267// and then parses the beginning of data as an identifier or keyword, 1268// returning that word and what remains after the word. 1269func parseWord(data []byte) (word, rest []byte) { 1270 data = skipSpaceOrComment(data) 1271 1272 // Parse past leading word characters. 1273 rest = data 1274 for { 1275 r, size := utf8.DecodeRune(rest) 1276 if unicode.IsLetter(r) || '0' <= r && r <= '9' || r == '_' { 1277 rest = rest[size:] 1278 continue 1279 } 1280 break 1281 } 1282 1283 word = data[:len(data)-len(rest)] 1284 if len(word) == 0 { 1285 return nil, nil 1286 } 1287 1288 return word, rest 1289} 1290 1291// MatchFile reports whether the file with the given name in the given directory 1292// matches the context and would be included in a Package created by ImportDir 1293// of that directory. 1294// 1295// MatchFile considers the name of the file and may use ctxt.OpenFile to 1296// read some or all of the file's content. 1297func (ctxt *Context) MatchFile(dir, name string) (match bool, err error) { 1298 match, _, _, err = ctxt.matchFile(dir, name, nil, nil) 1299 return 1300} 1301 1302// matchFile determines whether the file with the given name in the given directory 1303// should be included in the package being constructed. 1304// It returns the data read from the file. 1305// If name denotes a Go program, matchFile reads until the end of the 1306// imports (and returns that data) even though it only considers text 1307// until the first non-comment. 1308// If allTags is non-nil, matchFile records any encountered build tag 1309// by setting allTags[tag] = true. 1310func (ctxt *Context) matchFile(dir, name string, allTags map[string]bool, binaryOnly *bool) (match bool, data []byte, filename string, err error) { 1311 if strings.HasPrefix(name, "_") || 1312 strings.HasPrefix(name, ".") { 1313 return 1314 } 1315 1316 i := strings.LastIndex(name, ".") 1317 if i < 0 { 1318 i = len(name) 1319 } 1320 ext := name[i:] 1321 1322 if !ctxt.goodOSArchFile(name, allTags) && !ctxt.UseAllFiles { 1323 return 1324 } 1325 1326 switch ext { 1327 case ".go", ".c", ".cc", ".cxx", ".cpp", ".m", ".s", ".h", ".hh", ".hpp", ".hxx", ".f", ".F", ".f90", ".S", ".sx", ".swig", ".swigcxx": 1328 // tentatively okay - read to make sure 1329 case ".syso": 1330 // binary, no reading 1331 match = true 1332 return 1333 default: 1334 // skip 1335 return 1336 } 1337 1338 filename = ctxt.joinPath(dir, name) 1339 f, err := ctxt.openFile(filename) 1340 if err != nil { 1341 return 1342 } 1343 1344 if strings.HasSuffix(filename, ".go") { 1345 data, err = readImports(f, false, nil) 1346 if strings.HasSuffix(filename, "_test.go") { 1347 binaryOnly = nil // ignore //go:binary-only-package comments in _test.go files 1348 } 1349 } else { 1350 binaryOnly = nil // ignore //go:binary-only-package comments in non-Go sources 1351 data, err = readComments(f) 1352 } 1353 f.Close() 1354 if err != nil { 1355 err = fmt.Errorf("read %s: %v", filename, err) 1356 return 1357 } 1358 1359 // Look for +build comments to accept or reject the file. 1360 var sawBinaryOnly bool 1361 if !ctxt.shouldBuild(data, allTags, &sawBinaryOnly) && !ctxt.UseAllFiles { 1362 return 1363 } 1364 1365 if binaryOnly != nil && sawBinaryOnly { 1366 *binaryOnly = true 1367 } 1368 match = true 1369 return 1370} 1371 1372func cleanImports(m map[string][]token.Position) ([]string, map[string][]token.Position) { 1373 all := make([]string, 0, len(m)) 1374 for path := range m { 1375 all = append(all, path) 1376 } 1377 sort.Strings(all) 1378 return all, m 1379} 1380 1381// Import is shorthand for Default.Import. 1382func Import(path, srcDir string, mode ImportMode) (*Package, error) { 1383 return Default.Import(path, srcDir, mode) 1384} 1385 1386// ImportDir is shorthand for Default.ImportDir. 1387func ImportDir(dir string, mode ImportMode) (*Package, error) { 1388 return Default.ImportDir(dir, mode) 1389} 1390 1391var slashslash = []byte("//") 1392 1393// Special comment denoting a binary-only package. 1394// See https://golang.org/design/2775-binary-only-packages 1395// for more about the design of binary-only packages. 1396var binaryOnlyComment = []byte("//go:binary-only-package") 1397 1398// shouldBuild reports whether it is okay to use this file, 1399// The rule is that in the file's leading run of // comments 1400// and blank lines, which must be followed by a blank line 1401// (to avoid including a Go package clause doc comment), 1402// lines beginning with '// +build' are taken as build directives. 1403// 1404// The file is accepted only if each such line lists something 1405// matching the file. For example: 1406// 1407// // +build windows linux 1408// 1409// marks the file as applicable only on Windows and Linux. 1410// 1411// If shouldBuild finds a //go:binary-only-package comment in the file, 1412// it sets *binaryOnly to true. Otherwise it does not change *binaryOnly. 1413// 1414func (ctxt *Context) shouldBuild(content []byte, allTags map[string]bool, binaryOnly *bool) bool { 1415 sawBinaryOnly := false 1416 1417 // Pass 1. Identify leading run of // comments and blank lines, 1418 // which must be followed by a blank line. 1419 end := 0 1420 p := content 1421 for len(p) > 0 { 1422 line := p 1423 if i := bytes.IndexByte(line, '\n'); i >= 0 { 1424 line, p = line[:i], p[i+1:] 1425 } else { 1426 p = p[len(p):] 1427 } 1428 line = bytes.TrimSpace(line) 1429 if len(line) == 0 { // Blank line 1430 end = len(content) - len(p) 1431 continue 1432 } 1433 if !bytes.HasPrefix(line, slashslash) { // Not comment line 1434 break 1435 } 1436 } 1437 content = content[:end] 1438 1439 // Pass 2. Process each line in the run. 1440 p = content 1441 allok := true 1442 for len(p) > 0 { 1443 line := p 1444 if i := bytes.IndexByte(line, '\n'); i >= 0 { 1445 line, p = line[:i], p[i+1:] 1446 } else { 1447 p = p[len(p):] 1448 } 1449 line = bytes.TrimSpace(line) 1450 if !bytes.HasPrefix(line, slashslash) { 1451 continue 1452 } 1453 if bytes.Equal(line, binaryOnlyComment) { 1454 sawBinaryOnly = true 1455 } 1456 line = bytes.TrimSpace(line[len(slashslash):]) 1457 if len(line) > 0 && line[0] == '+' { 1458 // Looks like a comment +line. 1459 f := strings.Fields(string(line)) 1460 if f[0] == "+build" { 1461 ok := false 1462 for _, tok := range f[1:] { 1463 if ctxt.match(tok, allTags) { 1464 ok = true 1465 } 1466 } 1467 if !ok { 1468 allok = false 1469 } 1470 } 1471 } 1472 } 1473 1474 if binaryOnly != nil && sawBinaryOnly { 1475 *binaryOnly = true 1476 } 1477 1478 return allok 1479} 1480 1481// saveCgo saves the information from the #cgo lines in the import "C" comment. 1482// These lines set CFLAGS, CPPFLAGS, CXXFLAGS and LDFLAGS and pkg-config directives 1483// that affect the way cgo's C code is built. 1484func (ctxt *Context) saveCgo(filename string, di *Package, cg *ast.CommentGroup) error { 1485 text := cg.Text() 1486 for _, line := range strings.Split(text, "\n") { 1487 orig := line 1488 1489 // Line is 1490 // #cgo [GOOS/GOARCH...] LDFLAGS: stuff 1491 // 1492 line = strings.TrimSpace(line) 1493 if len(line) < 5 || line[:4] != "#cgo" || (line[4] != ' ' && line[4] != '\t') { 1494 continue 1495 } 1496 1497 // Split at colon. 1498 line = strings.TrimSpace(line[4:]) 1499 i := strings.Index(line, ":") 1500 if i < 0 { 1501 return fmt.Errorf("%s: invalid #cgo line: %s", filename, orig) 1502 } 1503 line, argstr := line[:i], line[i+1:] 1504 1505 // Parse GOOS/GOARCH stuff. 1506 f := strings.Fields(line) 1507 if len(f) < 1 { 1508 return fmt.Errorf("%s: invalid #cgo line: %s", filename, orig) 1509 } 1510 1511 cond, verb := f[:len(f)-1], f[len(f)-1] 1512 if len(cond) > 0 { 1513 ok := false 1514 for _, c := range cond { 1515 if ctxt.match(c, nil) { 1516 ok = true 1517 break 1518 } 1519 } 1520 if !ok { 1521 continue 1522 } 1523 } 1524 1525 args, err := splitQuoted(argstr) 1526 if err != nil { 1527 return fmt.Errorf("%s: invalid #cgo line: %s", filename, orig) 1528 } 1529 var ok bool 1530 for i, arg := range args { 1531 if arg, ok = expandSrcDir(arg, di.Dir); !ok { 1532 return fmt.Errorf("%s: malformed #cgo argument: %s", filename, arg) 1533 } 1534 args[i] = arg 1535 } 1536 1537 switch verb { 1538 case "CFLAGS", "CPPFLAGS", "CXXFLAGS", "FFLAGS", "LDFLAGS": 1539 // Change relative paths to absolute. 1540 ctxt.makePathsAbsolute(args, di.Dir) 1541 } 1542 1543 switch verb { 1544 case "CFLAGS": 1545 di.CgoCFLAGS = append(di.CgoCFLAGS, args...) 1546 case "CPPFLAGS": 1547 di.CgoCPPFLAGS = append(di.CgoCPPFLAGS, args...) 1548 case "CXXFLAGS": 1549 di.CgoCXXFLAGS = append(di.CgoCXXFLAGS, args...) 1550 case "FFLAGS": 1551 di.CgoFFLAGS = append(di.CgoFFLAGS, args...) 1552 case "LDFLAGS": 1553 di.CgoLDFLAGS = append(di.CgoLDFLAGS, args...) 1554 case "pkg-config": 1555 di.CgoPkgConfig = append(di.CgoPkgConfig, args...) 1556 default: 1557 return fmt.Errorf("%s: invalid #cgo verb: %s", filename, orig) 1558 } 1559 } 1560 return nil 1561} 1562 1563// expandSrcDir expands any occurrence of ${SRCDIR}, making sure 1564// the result is safe for the shell. 1565func expandSrcDir(str string, srcdir string) (string, bool) { 1566 // "\" delimited paths cause safeCgoName to fail 1567 // so convert native paths with a different delimiter 1568 // to "/" before starting (eg: on windows). 1569 srcdir = filepath.ToSlash(srcdir) 1570 1571 chunks := strings.Split(str, "${SRCDIR}") 1572 if len(chunks) < 2 { 1573 return str, safeCgoName(str) 1574 } 1575 ok := true 1576 for _, chunk := range chunks { 1577 ok = ok && (chunk == "" || safeCgoName(chunk)) 1578 } 1579 ok = ok && (srcdir == "" || safeCgoName(srcdir)) 1580 res := strings.Join(chunks, srcdir) 1581 return res, ok && res != "" 1582} 1583 1584// makePathsAbsolute looks for compiler options that take paths and 1585// makes them absolute. We do this because through the 1.8 release we 1586// ran the compiler in the package directory, so any relative -I or -L 1587// options would be relative to that directory. In 1.9 we changed to 1588// running the compiler in the build directory, to get consistent 1589// build results (issue #19964). To keep builds working, we change any 1590// relative -I or -L options to be absolute. 1591// 1592// Using filepath.IsAbs and filepath.Join here means the results will be 1593// different on different systems, but that's OK: -I and -L options are 1594// inherently system-dependent. 1595func (ctxt *Context) makePathsAbsolute(args []string, srcDir string) { 1596 nextPath := false 1597 for i, arg := range args { 1598 if nextPath { 1599 if !filepath.IsAbs(arg) { 1600 args[i] = filepath.Join(srcDir, arg) 1601 } 1602 nextPath = false 1603 } else if strings.HasPrefix(arg, "-I") || strings.HasPrefix(arg, "-L") { 1604 if len(arg) == 2 { 1605 nextPath = true 1606 } else { 1607 if !filepath.IsAbs(arg[2:]) { 1608 args[i] = arg[:2] + filepath.Join(srcDir, arg[2:]) 1609 } 1610 } 1611 } 1612 } 1613} 1614 1615// NOTE: $ is not safe for the shell, but it is allowed here because of linker options like -Wl,$ORIGIN. 1616// We never pass these arguments to a shell (just to programs we construct argv for), so this should be okay. 1617// See golang.org/issue/6038. 1618// The @ is for OS X. See golang.org/issue/13720. 1619// The % is for Jenkins. See golang.org/issue/16959. 1620// The ! is because module paths may use them. See golang.org/issue/26716. 1621// The ~ and ^ are for sr.ht. See golang.org/issue/32260. 1622const safeString = "+-.,/0123456789=ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz:$@%! ~^" 1623 1624func safeCgoName(s string) bool { 1625 if s == "" { 1626 return false 1627 } 1628 for i := 0; i < len(s); i++ { 1629 if c := s[i]; c < utf8.RuneSelf && strings.IndexByte(safeString, c) < 0 { 1630 return false 1631 } 1632 } 1633 return true 1634} 1635 1636// splitQuoted splits the string s around each instance of one or more consecutive 1637// white space characters while taking into account quotes and escaping, and 1638// returns an array of substrings of s or an empty list if s contains only white space. 1639// Single quotes and double quotes are recognized to prevent splitting within the 1640// quoted region, and are removed from the resulting substrings. If a quote in s 1641// isn't closed err will be set and r will have the unclosed argument as the 1642// last element. The backslash is used for escaping. 1643// 1644// For example, the following string: 1645// 1646// a b:"c d" 'e''f' "g\"" 1647// 1648// Would be parsed as: 1649// 1650// []string{"a", "b:c d", "ef", `g"`} 1651// 1652func splitQuoted(s string) (r []string, err error) { 1653 var args []string 1654 arg := make([]rune, len(s)) 1655 escaped := false 1656 quoted := false 1657 quote := '\x00' 1658 i := 0 1659 for _, rune := range s { 1660 switch { 1661 case escaped: 1662 escaped = false 1663 case rune == '\\': 1664 escaped = true 1665 continue 1666 case quote != '\x00': 1667 if rune == quote { 1668 quote = '\x00' 1669 continue 1670 } 1671 case rune == '"' || rune == '\'': 1672 quoted = true 1673 quote = rune 1674 continue 1675 case unicode.IsSpace(rune): 1676 if quoted || i > 0 { 1677 quoted = false 1678 args = append(args, string(arg[:i])) 1679 i = 0 1680 } 1681 continue 1682 } 1683 arg[i] = rune 1684 i++ 1685 } 1686 if quoted || i > 0 { 1687 args = append(args, string(arg[:i])) 1688 } 1689 if quote != 0 { 1690 err = errors.New("unclosed quote") 1691 } else if escaped { 1692 err = errors.New("unfinished escaping") 1693 } 1694 return args, err 1695} 1696 1697// match reports whether the name is one of: 1698// 1699// $GOOS 1700// $GOARCH 1701// cgo (if cgo is enabled) 1702// !cgo (if cgo is disabled) 1703// ctxt.Compiler 1704// !ctxt.Compiler 1705// tag (if tag is listed in ctxt.BuildTags or ctxt.ReleaseTags) 1706// !tag (if tag is not listed in ctxt.BuildTags or ctxt.ReleaseTags) 1707// a comma-separated list of any of these 1708// 1709func (ctxt *Context) match(name string, allTags map[string]bool) bool { 1710 if name == "" { 1711 if allTags != nil { 1712 allTags[name] = true 1713 } 1714 return false 1715 } 1716 if i := strings.Index(name, ","); i >= 0 { 1717 // comma-separated list 1718 ok1 := ctxt.match(name[:i], allTags) 1719 ok2 := ctxt.match(name[i+1:], allTags) 1720 return ok1 && ok2 1721 } 1722 if strings.HasPrefix(name, "!!") { // bad syntax, reject always 1723 return false 1724 } 1725 if strings.HasPrefix(name, "!") { // negation 1726 return len(name) > 1 && !ctxt.match(name[1:], allTags) 1727 } 1728 1729 if allTags != nil { 1730 allTags[name] = true 1731 } 1732 1733 // Tags must be letters, digits, underscores or dots. 1734 // Unlike in Go identifiers, all digits are fine (e.g., "386"). 1735 for _, c := range name { 1736 if !unicode.IsLetter(c) && !unicode.IsDigit(c) && c != '_' && c != '.' { 1737 return false 1738 } 1739 } 1740 1741 // special tags 1742 if ctxt.CgoEnabled && name == "cgo" { 1743 return true 1744 } 1745 if name == ctxt.GOOS || name == ctxt.GOARCH || name == ctxt.Compiler { 1746 return true 1747 } 1748 if ctxt.GOOS == "android" && name == "linux" { 1749 return true 1750 } 1751 if ctxt.GOOS == "illumos" && name == "solaris" { 1752 return true 1753 } 1754 1755 // other tags 1756 for _, tag := range ctxt.BuildTags { 1757 if tag == name { 1758 return true 1759 } 1760 } 1761 for _, tag := range ctxt.ReleaseTags { 1762 if tag == name { 1763 return true 1764 } 1765 } 1766 1767 return false 1768} 1769 1770// goodOSArchFile returns false if the name contains a $GOOS or $GOARCH 1771// suffix which does not match the current system. 1772// The recognized name formats are: 1773// 1774// name_$(GOOS).* 1775// name_$(GOARCH).* 1776// name_$(GOOS)_$(GOARCH).* 1777// name_$(GOOS)_test.* 1778// name_$(GOARCH)_test.* 1779// name_$(GOOS)_$(GOARCH)_test.* 1780// 1781// An exception: if GOOS=android, then files with GOOS=linux are also matched. 1782func (ctxt *Context) goodOSArchFile(name string, allTags map[string]bool) bool { 1783 if dot := strings.Index(name, "."); dot != -1 { 1784 name = name[:dot] 1785 } 1786 1787 // Before Go 1.4, a file called "linux.go" would be equivalent to having a 1788 // build tag "linux" in that file. For Go 1.4 and beyond, we require this 1789 // auto-tagging to apply only to files with a non-empty prefix, so 1790 // "foo_linux.go" is tagged but "linux.go" is not. This allows new operating 1791 // systems, such as android, to arrive without breaking existing code with 1792 // innocuous source code in "android.go". The easiest fix: cut everything 1793 // in the name before the initial _. 1794 i := strings.Index(name, "_") 1795 if i < 0 { 1796 return true 1797 } 1798 name = name[i:] // ignore everything before first _ 1799 1800 l := strings.Split(name, "_") 1801 if n := len(l); n > 0 && l[n-1] == "test" { 1802 l = l[:n-1] 1803 } 1804 n := len(l) 1805 if n >= 2 && knownOS[l[n-2]] && knownArch[l[n-1]] { 1806 return ctxt.match(l[n-1], allTags) && ctxt.match(l[n-2], allTags) 1807 } 1808 if n >= 1 && (knownOS[l[n-1]] || knownArch[l[n-1]]) { 1809 return ctxt.match(l[n-1], allTags) 1810 } 1811 return true 1812} 1813 1814var knownOS = make(map[string]bool) 1815var knownArch = make(map[string]bool) 1816 1817func init() { 1818 for _, v := range strings.Fields(goosList) { 1819 knownOS[v] = true 1820 } 1821 for _, v := range strings.Fields(goarchList) { 1822 knownArch[v] = true 1823 } 1824} 1825 1826// ToolDir is the directory containing build tools. 1827var ToolDir = getToolDir() 1828 1829// IsLocalImport reports whether the import path is 1830// a local import path, like ".", "..", "./foo", or "../foo". 1831func IsLocalImport(path string) bool { 1832 return path == "." || path == ".." || 1833 strings.HasPrefix(path, "./") || strings.HasPrefix(path, "../") 1834} 1835 1836// ArchChar returns "?" and an error. 1837// In earlier versions of Go, the returned string was used to derive 1838// the compiler and linker tool names, the default object file suffix, 1839// and the default linker output name. As of Go 1.5, those strings 1840// no longer vary by architecture; they are compile, link, .o, and a.out, respectively. 1841func ArchChar(goarch string) (string, error) { 1842 return "?", errors.New("architecture letter no longer used") 1843} 1844