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