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