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

View as plain text