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