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