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