...
Run Format

Source file src/go/build/build.go

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

View as plain text