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

View as plain text