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