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