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.
16 exec
"internal/execabs"
33 // A Context specifies the supporting context for a build.
35 GOARCH
string // target architecture
36 GOOS
string // target operating system
37 GOROOT
string // Go root
38 GOPATH
string // Go path
40 // Dir is the caller's working directory, or the empty string to use
41 // the current directory of the running process. In module mode, this is used
42 // to locate the main module.
44 // If Dir is non-empty, directories passed to Import and ImportDir must
48 CgoEnabled
bool // whether cgo files are included
49 UseAllFiles
bool // use files regardless of +build lines, file names
50 Compiler
string // compiler to assume when computing target paths
52 // The build, tool, and release tags specify build constraints
53 // that should be considered satisfied when processing +build lines.
54 // Clients creating a new context may customize BuildTags, which
55 // defaults to empty, but it is usually an error to customize ToolTags or ReleaseTags.
56 // ToolTags defaults to build tags appropriate to the current Go toolchain configuration.
57 // ReleaseTags defaults to the list of Go releases the current release is compatible with.
58 // BuildTags is not set for the Default build Context.
59 // In addition to the BuildTags, ToolTags, and ReleaseTags, build constraints
60 // consider the values of GOARCH and GOOS as satisfied tags.
61 // The last element in ReleaseTags is assumed to be the current release.
66 // The install suffix specifies a suffix to use in the name of the installation
67 // directory. By default it is empty, but custom builds that need to keep
68 // their outputs separate can set InstallSuffix to do so. For example, when
69 // using the race detector, the go command uses InstallSuffix = "race", so
70 // that on a Linux/386 system, packages are written to a directory named
71 // "linux_386_race" instead of the usual "linux_386".
74 // By default, Import uses the operating system's file system calls
75 // to read directories and files. To read from other sources,
76 // callers can set the following functions. They all have default
77 // behaviors that use the local file system, so clients need only set
78 // the functions whose behaviors they wish to change.
80 // JoinPath joins the sequence of path fragments into a single path.
81 // If JoinPath is nil, Import uses filepath.Join.
82 JoinPath
func(elem
...string) string
84 // SplitPathList splits the path list into a slice of individual paths.
85 // If SplitPathList is nil, Import uses filepath.SplitList.
86 SplitPathList
func(list
string) []string
88 // IsAbsPath reports whether path is an absolute path.
89 // If IsAbsPath is nil, Import uses filepath.IsAbs.
90 IsAbsPath
func(path
string) bool
92 // IsDir reports whether the path names a directory.
93 // If IsDir is nil, Import calls os.Stat and uses the result's IsDir method.
94 IsDir
func(path
string) bool
96 // HasSubdir reports whether dir is lexically a subdirectory of
97 // root, perhaps multiple levels below. It does not try to check
98 // whether dir exists.
99 // If so, HasSubdir sets rel to a slash-separated path that
100 // can be joined to root to produce a path equivalent to dir.
101 // If HasSubdir is nil, Import uses an implementation built on
102 // filepath.EvalSymlinks.
103 HasSubdir
func(root
, dir
string) (rel
string, ok
bool)
105 // ReadDir returns a slice of fs.FileInfo, sorted by Name,
106 // describing the content of the named directory.
107 // If ReadDir is nil, Import uses ioutil.ReadDir.
108 ReadDir
func(dir
string) ([]fs
.FileInfo
, error
)
110 // OpenFile opens a file (not a directory) for reading.
111 // If OpenFile is nil, Import uses os.Open.
112 OpenFile
func(path
string) (io
.ReadCloser
, error
)
115 // joinPath calls ctxt.JoinPath (if not nil) or else filepath.Join.
116 func (ctxt
*Context
) joinPath(elem
...string) string {
117 if f
:= ctxt
.JoinPath
; f
!= nil {
120 return filepath
.Join(elem
...)
123 // splitPathList calls ctxt.SplitPathList (if not nil) or else filepath.SplitList.
124 func (ctxt
*Context
) splitPathList(s
string) []string {
125 if f
:= ctxt
.SplitPathList
; f
!= nil {
128 return filepath
.SplitList(s
)
131 // isAbsPath calls ctxt.IsAbsPath (if not nil) or else filepath.IsAbs.
132 func (ctxt
*Context
) isAbsPath(path
string) bool {
133 if f
:= ctxt
.IsAbsPath
; f
!= nil {
136 return filepath
.IsAbs(path
)
139 // isDir calls ctxt.IsDir (if not nil) or else uses os.Stat.
140 func (ctxt
*Context
) isDir(path
string) bool {
141 if f
:= ctxt
.IsDir
; f
!= nil {
144 fi
, err
:= os
.Stat(path
)
145 return err
== nil && fi
.IsDir()
148 // hasSubdir calls ctxt.HasSubdir (if not nil) or else uses
149 // the local file system to answer the question.
150 func (ctxt
*Context
) hasSubdir(root
, dir
string) (rel
string, ok
bool) {
151 if f
:= ctxt
.HasSubdir
; f
!= nil {
155 // Try using paths we received.
156 if rel
, ok
= hasSubdir(root
, dir
); ok
{
160 // Try expanding symlinks and comparing
161 // expanded against unexpanded and
162 // expanded against expanded.
163 rootSym
, _
:= filepath
.EvalSymlinks(root
)
164 dirSym
, _
:= filepath
.EvalSymlinks(dir
)
166 if rel
, ok
= hasSubdir(rootSym
, dir
); ok
{
169 if rel
, ok
= hasSubdir(root
, dirSym
); ok
{
172 return hasSubdir(rootSym
, dirSym
)
175 // hasSubdir reports if dir is within root by performing lexical analysis only.
176 func hasSubdir(root
, dir
string) (rel
string, ok
bool) {
177 const sep
= string(filepath
.Separator
)
178 root
= filepath
.Clean(root
)
179 if !strings
.HasSuffix(root
, sep
) {
182 dir
= filepath
.Clean(dir
)
183 if !strings
.HasPrefix(dir
, root
) {
186 return filepath
.ToSlash(dir
[len(root
):]), true
189 // readDir calls ctxt.ReadDir (if not nil) or else ioutil.ReadDir.
190 func (ctxt
*Context
) readDir(path
string) ([]fs
.FileInfo
, error
) {
191 if f
:= ctxt
.ReadDir
; f
!= nil {
194 // TODO: use os.ReadDir
195 return ioutil
.ReadDir(path
)
198 // openFile calls ctxt.OpenFile (if not nil) or else os.Open.
199 func (ctxt
*Context
) openFile(path
string) (io
.ReadCloser
, error
) {
200 if fn
:= ctxt
.OpenFile
; fn
!= nil {
204 f
, err
:= os
.Open(path
)
206 return nil, err
// nil interface
211 // isFile determines whether path is a file by trying to open it.
212 // It reuses openFile instead of adding another function to the
214 func (ctxt
*Context
) isFile(path
string) bool {
215 f
, err
:= ctxt
.openFile(path
)
223 // gopath returns the list of Go path directories.
224 func (ctxt
*Context
) gopath() []string {
226 for _
, p
:= range ctxt
.splitPathList(ctxt
.GOPATH
) {
227 if p
== "" || p
== ctxt
.GOROOT
{
228 // Empty paths are uninteresting.
229 // If the path is the GOROOT, ignore it.
230 // People sometimes set GOPATH=$GOROOT.
231 // Do not get confused by this common mistake.
234 if strings
.HasPrefix(p
, "~") {
235 // Path segments starting with ~ on Unix are almost always
236 // users who have incorrectly quoted ~ while setting GOPATH,
237 // preventing it from expanding to $HOME.
238 // The situation is made more confusing by the fact that
239 // bash allows quoted ~ in $PATH (most shells do not).
240 // Do not get confused by this, and do not try to use the path.
241 // It does not exist, and printing errors about it confuses
242 // those users even more, because they think "sure ~ exists!".
243 // The go command diagnoses this situation and prints a
245 // On Windows, ~ is used in short names, such as c:\progra~1
246 // for c:\program files.
254 // SrcDirs returns a list of package source root directories.
255 // It draws from the current Go root and Go path but omits directories
256 // that do not exist.
257 func (ctxt
*Context
) SrcDirs() []string {
259 if ctxt
.GOROOT
!= "" && ctxt
.Compiler
!= "gccgo" {
260 dir
:= ctxt
.joinPath(ctxt
.GOROOT
, "src")
262 all
= append(all
, dir
)
265 for _
, p
:= range ctxt
.gopath() {
266 dir
:= ctxt
.joinPath(p
, "src")
268 all
= append(all
, dir
)
274 // Default is the default Context for builds.
275 // It uses the GOARCH, GOOS, GOROOT, and GOPATH environment variables
276 // if set, or else the compiled code's GOARCH, GOOS, and GOROOT.
277 var Default Context
= defaultContext()
279 func defaultGOPATH() string {
281 if runtime
.GOOS
== "windows" {
283 } else if runtime
.GOOS
== "plan9" {
286 if home
:= os
.Getenv(env
); home
!= "" {
287 def
:= filepath
.Join(home
, "go")
288 if filepath
.Clean(def
) == filepath
.Clean(runtime
.GOROOT()) {
289 // Don't set the default GOPATH to GOROOT,
290 // as that will trigger warnings from the go tool.
298 var defaultToolTags
, defaultReleaseTags
[]string
300 func defaultContext() Context
{
303 c
.GOARCH
= buildcfg
.GOARCH
304 c
.GOOS
= buildcfg
.GOOS
305 c
.GOROOT
= pathpkg
.Clean(runtime
.GOROOT())
306 c
.GOPATH
= envOr("GOPATH", defaultGOPATH())
307 c
.Compiler
= runtime
.Compiler
309 // For each experiment that has been enabled in the toolchain, define a
310 // build tag with the same name but prefixed by "goexperiment." which can be
311 // used for compiling alternative files for the experiment. This allows
312 // changes for the experiment, like extra struct fields in the runtime,
313 // without affecting the base non-experiment code at all.
314 for _
, exp
:= range buildcfg
.EnabledExperiments() {
315 c
.ToolTags
= append(c
.ToolTags
, "goexperiment."+exp
)
317 defaultToolTags
= append([]string{}, c
.ToolTags
...) // our own private copy
319 // Each major Go release in the Go 1.x series adds a new
320 // "go1.x" release tag. That is, the go1.x tag is present in
321 // all releases >= Go 1.x. Code that requires Go 1.x or later
322 // should say "+build go1.x", and code that should only be
323 // built before Go 1.x (perhaps it is the stub to use in that
324 // case) should say "+build !go1.x".
325 // The last element in ReleaseTags is the current release.
326 for i
:= 1; i
<= goversion
.Version
; i
++ {
327 c
.ReleaseTags
= append(c
.ReleaseTags
, "go1."+strconv
.Itoa(i
))
330 defaultReleaseTags
= append([]string{}, c
.ReleaseTags
...) // our own private copy
332 env
:= os
.Getenv("CGO_ENABLED")
333 // No defaultCGO_ENABLED in gccgo.
335 // env = defaultCGO_ENABLED
343 // cgo must be explicitly enabled for cross compilation builds
344 if runtime
.GOARCH
== c
.GOARCH
&& runtime
.GOOS
== c
.GOOS
{
345 // Always enabled for gccgo.
355 func envOr(name
, def
string) string {
363 // An ImportMode controls the behavior of the Import method.
367 // If FindOnly is set, Import stops after locating the directory
368 // that should contain the sources for a package. It does not
369 // read any files in the directory.
370 FindOnly ImportMode
= 1 << iota
372 // If AllowBinary is set, Import can be satisfied by a compiled
373 // package object without corresponding sources.
376 // The supported way to create a compiled-only package is to
377 // write source code containing a //go:binary-only-package comment at
378 // the top of the file. Such a package will be recognized
379 // regardless of this flag setting (because it has source code)
380 // and will have BinaryOnly set to true in the returned Package.
383 // If ImportComment is set, parse import comments on package statements.
384 // Import returns an error if it finds a comment it cannot understand
385 // or finds conflicting comments in multiple source files.
386 // See golang.org/s/go14customimport for more information.
389 // By default, Import searches vendor directories
390 // that apply in the given source directory before searching
391 // the GOROOT and GOPATH roots.
392 // If an Import finds and returns a package using a vendor
393 // directory, the resulting ImportPath is the complete path
394 // to the package, including the path elements leading up
395 // to and including "vendor".
396 // For example, if Import("y", "x/subdir", 0) finds
397 // "x/vendor/y", the returned package's ImportPath is "x/vendor/y",
399 // See golang.org/s/go15vendor for more information.
401 // Setting IgnoreVendor ignores vendor directories.
403 // In contrast to the package's ImportPath,
404 // the returned package's Imports, TestImports, and XTestImports
405 // are always the exact import paths from the source files:
406 // Import makes no attempt to resolve or check those paths.
410 // A Package describes the Go package found in a directory.
411 type Package
struct {
412 Dir
string // directory containing package sources
413 Name
string // package name
414 ImportComment
string // path in import comment on package statement
415 Doc
string // documentation synopsis
416 ImportPath
string // import path of package ("" if unknown)
417 Root
string // root of Go tree where this package lives
418 SrcRoot
string // package source root directory ("" if unknown)
419 PkgRoot
string // package install root directory ("" if unknown)
420 PkgTargetRoot
string // architecture dependent install root directory ("" if unknown)
421 BinDir
string // command install directory ("" if unknown)
422 Goroot
bool // package found in Go root
423 PkgObj
string // installed .a file
424 AllTags
[]string // tags that can influence file selection in this directory
425 ConflictDir
string // this directory shadows Dir in $GOPATH
426 BinaryOnly
bool // cannot be rebuilt from source (has //go:binary-only-package comment)
429 GoFiles
[]string // .go source files (excluding CgoFiles, TestGoFiles, XTestGoFiles)
430 CgoFiles
[]string // .go source files that import "C"
431 IgnoredGoFiles
[]string // .go source files ignored for this build (including ignored _test.go files)
432 InvalidGoFiles
[]string // .go source files with detected problems (parse error, wrong package name, and so on)
433 IgnoredOtherFiles
[]string // non-.go source files ignored for this build
434 CFiles
[]string // .c source files
435 CXXFiles
[]string // .cc, .cpp and .cxx source files
436 MFiles
[]string // .m (Objective-C) source files
437 HFiles
[]string // .h, .hh, .hpp and .hxx source files
438 FFiles
[]string // .f, .F, .for and .f90 Fortran source files
439 SFiles
[]string // .s source files
440 SwigFiles
[]string // .swig files
441 SwigCXXFiles
[]string // .swigcxx files
442 SysoFiles
[]string // .syso system object files to add to archive
445 CgoCFLAGS
[]string // Cgo CFLAGS directives
446 CgoCPPFLAGS
[]string // Cgo CPPFLAGS directives
447 CgoCXXFLAGS
[]string // Cgo CXXFLAGS directives
448 CgoFFLAGS
[]string // Cgo FFLAGS directives
449 CgoLDFLAGS
[]string // Cgo LDFLAGS directives
450 CgoPkgConfig
[]string // Cgo pkg-config directives
453 TestGoFiles
[]string // _test.go files in package
454 XTestGoFiles
[]string // _test.go files outside package
456 // Dependency information
457 Imports
[]string // import paths from GoFiles, CgoFiles
458 ImportPos
map[string][]token
.Position
// line information for Imports
459 TestImports
[]string // import paths from TestGoFiles
460 TestImportPos
map[string][]token
.Position
// line information for TestImports
461 XTestImports
[]string // import paths from XTestGoFiles
462 XTestImportPos
map[string][]token
.Position
// line information for XTestImports
464 // //go:embed patterns found in Go source files
465 // For example, if a source file says
467 // then the list will contain those two strings as separate entries.
468 // (See package embed for more details about //go:embed.)
469 EmbedPatterns
[]string // patterns from GoFiles, CgoFiles
470 EmbedPatternPos
map[string][]token
.Position
// line information for EmbedPatterns
471 TestEmbedPatterns
[]string // patterns from TestGoFiles
472 TestEmbedPatternPos
map[string][]token
.Position
// line information for TestEmbedPatterns
473 XTestEmbedPatterns
[]string // patterns from XTestGoFiles
474 XTestEmbedPatternPos
map[string][]token
.Position
// line information for XTestEmbedPatternPos
477 // IsCommand reports whether the package is considered a
478 // command to be installed (not just a library).
479 // Packages named "main" are treated as commands.
480 func (p
*Package
) IsCommand() bool {
481 return p
.Name
== "main"
484 // ImportDir is like Import but processes the Go package found in
485 // the named directory.
486 func (ctxt
*Context
) ImportDir(dir
string, mode ImportMode
) (*Package
, error
) {
487 return ctxt
.Import(".", dir
, mode
)
490 // NoGoError is the error used by Import to describe a directory
491 // containing no buildable Go source files. (It may still contain
492 // test files, files hidden by build tags, and so on.)
493 type NoGoError
struct {
497 func (e
*NoGoError
) Error() string {
498 return "no buildable Go source files in " + e
.Dir
501 // MultiplePackageError describes a directory containing
502 // multiple buildable Go source files for multiple packages.
503 type MultiplePackageError
struct {
504 Dir
string // directory containing files
505 Packages
[]string // package names found
506 Files
[]string // corresponding files: Files[i] declares package Packages[i]
509 func (e
*MultiplePackageError
) Error() string {
510 // Error string limited to two entries for compatibility.
511 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
)
514 func nameExt(name
string) string {
515 i
:= strings
.LastIndex(name
, ".")
522 // Import returns details about the Go package named by the import path,
523 // interpreting local import paths relative to the srcDir directory.
524 // If the path is a local import path naming a package that can be imported
525 // using a standard import path, the returned package will set p.ImportPath
528 // In the directory containing the package, .go, .c, .h, and .s files are
529 // considered part of the package except for:
531 // - .go files in package documentation
532 // - files starting with _ or . (likely editor temporary files)
533 // - files with build constraints not satisfied by the context
535 // If an error occurs, Import returns a non-nil error and a non-nil
536 // *Package containing partial information.
538 func (ctxt
*Context
) Import(path
string, srcDir
string, mode ImportMode
) (*Package
, error
) {
543 return p
, fmt
.Errorf("import %q: invalid import path", path
)
546 var pkgtargetroot
string
550 if ctxt
.InstallSuffix
!= "" {
551 suffix
= "_" + ctxt
.InstallSuffix
553 switch ctxt
.Compiler
{
555 pkgtargetroot
= "pkg/gccgo_" + ctxt
.GOOS
+ "_" + ctxt
.GOARCH
+ suffix
557 pkgtargetroot
= "pkg/" + ctxt
.GOOS
+ "_" + ctxt
.GOARCH
+ suffix
559 // Save error for end of function.
560 pkgerr
= fmt
.Errorf("import %q: unknown compiler %q", path
, ctxt
.Compiler
)
563 switch ctxt
.Compiler
{
565 dir
, elem
:= pathpkg
.Split(p
.ImportPath
)
566 pkga
= pkgtargetroot
+ "/" + dir
+ "lib" + elem
+ ".a"
568 pkga
= pkgtargetroot
+ "/" + p
.ImportPath
+ ".a"
574 if IsLocalImport(path
) {
575 pkga
= "" // local imports have no installed path
577 return p
, fmt
.Errorf("import %q: import relative to unknown directory", path
)
579 if !ctxt
.isAbsPath(path
) {
580 p
.Dir
= ctxt
.joinPath(srcDir
, path
)
582 // p.Dir directory may or may not exist. Gather partial information first, check if it exists later.
583 // Determine canonical import path, if any.
584 // Exclude results where the import path would include /testdata/.
585 inTestdata
:= func(sub
string) bool {
586 return strings
.Contains(sub
, "/testdata/") || strings
.HasSuffix(sub
, "/testdata") || strings
.HasPrefix(sub
, "testdata/") || sub
== "testdata"
588 if ctxt
.GOROOT
!= "" {
589 root
:= ctxt
.joinPath(ctxt
.GOROOT
, "src")
590 if sub
, ok
:= ctxt
.hasSubdir(root
, p
.Dir
); ok
&& !inTestdata(sub
) {
594 setPkga() // p.ImportPath changed
599 for i
, root
:= range all
{
600 rootsrc
:= ctxt
.joinPath(root
, "src")
601 if sub
, ok
:= ctxt
.hasSubdir(rootsrc
, p
.Dir
); ok
&& !inTestdata(sub
) {
602 // We found a potential import path for dir,
603 // but check that using it wouldn't find something
605 if ctxt
.GOROOT
!= "" && ctxt
.Compiler
!= "gccgo" {
606 if dir
:= ctxt
.joinPath(ctxt
.GOROOT
, "src", sub
); ctxt
.isDir(dir
) {
611 for _
, earlyRoot
:= range all
[:i
] {
612 if dir
:= ctxt
.joinPath(earlyRoot
, "src", sub
); ctxt
.isDir(dir
) {
618 // sub would not name some other directory instead of this one.
622 setPkga() // p.ImportPath changed
626 // It's okay that we didn't find a root containing dir.
627 // Keep going with the information we have.
629 if strings
.HasPrefix(path
, "/") {
630 return p
, fmt
.Errorf("import %q: cannot import absolute path", path
)
633 if err
:= ctxt
.importGo(p
, path
, srcDir
, mode
); err
== nil {
635 } else if err
!= errNoModules
{
639 gopath
:= ctxt
.gopath() // needed twice below; avoid computing many times
641 // tried records the location of unsuccessful package lookups
648 // Vendor directories get first chance to satisfy import.
649 if mode
&IgnoreVendor
== 0 && srcDir
!= "" {
650 searchVendor
:= func(root
string, isGoroot
bool) bool {
651 sub
, ok
:= ctxt
.hasSubdir(root
, srcDir
)
652 if !ok ||
!strings
.HasPrefix(sub
, "src/") || strings
.Contains(sub
, "/testdata/") {
656 vendor
:= ctxt
.joinPath(root
, sub
, "vendor")
657 if ctxt
.isDir(vendor
) {
658 dir
:= ctxt
.joinPath(vendor
, path
)
659 if ctxt
.isDir(dir
) && hasGoFiles(ctxt
, dir
) {
661 p
.ImportPath
= strings
.TrimPrefix(pathpkg
.Join(sub
, "vendor", path
), "src/")
664 setPkga() // p.ImportPath changed
667 tried
.vendor
= append(tried
.vendor
, dir
)
669 i
:= strings
.LastIndex(sub
, "/")
677 if ctxt
.Compiler
!= "gccgo" && searchVendor(ctxt
.GOROOT
, true) {
680 for _
, root
:= range gopath
{
681 if searchVendor(root
, false) {
687 // Determine directory from import path.
688 if ctxt
.GOROOT
!= "" {
689 // If the package path starts with "vendor/", only search GOROOT before
690 // GOPATH if the importer is also within GOROOT. That way, if the user has
691 // vendored in a package that is subsequently included in the standard
692 // distribution, they'll continue to pick up their own vendored copy.
693 gorootFirst
:= srcDir
== "" ||
!strings
.HasPrefix(path
, "vendor/")
695 _
, gorootFirst
= ctxt
.hasSubdir(ctxt
.GOROOT
, srcDir
)
698 dir
:= ctxt
.joinPath(ctxt
.GOROOT
, "src", path
)
699 if ctxt
.Compiler
!= "gccgo" {
700 isDir
:= ctxt
.isDir(dir
)
701 binaryOnly
= !isDir
&& mode
&AllowBinary
!= 0 && pkga
!= "" && ctxt
.isFile(ctxt
.joinPath(ctxt
.GOROOT
, pkga
))
702 if isDir || binaryOnly
{
712 if ctxt
.Compiler
== "gccgo" && goroot
.IsStandardPackage(ctxt
.GOROOT
, ctxt
.Compiler
, path
) {
713 p
.Dir
= ctxt
.joinPath(ctxt
.GOROOT
, "src", path
)
718 for _
, root
:= range gopath
{
719 dir
:= ctxt
.joinPath(root
, "src", path
)
720 isDir
:= ctxt
.isDir(dir
)
721 binaryOnly
= !isDir
&& mode
&AllowBinary
!= 0 && pkga
!= "" && ctxt
.isFile(ctxt
.joinPath(root
, pkga
))
722 if isDir || binaryOnly
{
727 tried
.gopath
= append(tried
.gopath
, dir
)
730 // If we tried GOPATH first due to a "vendor/" prefix, fall back to GOPATH.
731 // That way, the user can still get useful results from 'go list' for
732 // standard-vendored paths passed on the command line.
733 if ctxt
.GOROOT
!= "" && tried
.goroot
== "" {
734 dir
:= ctxt
.joinPath(ctxt
.GOROOT
, "src", path
)
735 if ctxt
.Compiler
!= "gccgo" {
736 isDir
:= ctxt
.isDir(dir
)
737 binaryOnly
= !isDir
&& mode
&AllowBinary
!= 0 && pkga
!= "" && ctxt
.isFile(ctxt
.joinPath(ctxt
.GOROOT
, pkga
))
738 if isDir || binaryOnly
{
748 // package was not found
750 format
:= "\t%s (vendor tree)"
751 for _
, dir
:= range tried
.vendor
{
752 paths
= append(paths
, fmt
.Sprintf(format
, dir
))
755 if tried
.goroot
!= "" {
756 paths
= append(paths
, fmt
.Sprintf("\t%s (from $GOROOT)", tried
.goroot
))
758 paths
= append(paths
, "\t($GOROOT not set)")
760 format
= "\t%s (from $GOPATH)"
761 for _
, dir
:= range tried
.gopath
{
762 paths
= append(paths
, fmt
.Sprintf(format
, dir
))
765 if len(tried
.gopath
) == 0 {
766 paths
= append(paths
, "\t($GOPATH not set. For more details see: 'go help gopath')")
768 return p
, fmt
.Errorf("cannot find package %q in any of:\n%s", path
, strings
.Join(paths
, "\n"))
773 p
.SrcRoot
= ctxt
.joinPath(p
.Root
, "src")
774 p
.PkgRoot
= ctxt
.joinPath(p
.Root
, "pkg")
775 p
.BinDir
= ctxt
.joinPath(p
.Root
, "bin")
777 p
.PkgTargetRoot
= ctxt
.joinPath(p
.Root
, pkgtargetroot
)
778 p
.PkgObj
= ctxt
.joinPath(p
.Root
, pkga
)
782 // If it's a local import path, by the time we get here, we still haven't checked
783 // that p.Dir directory exists. This is the right time to do that check.
784 // We can't do it earlier, because we want to gather partial information for the
785 // non-nil *Package returned when an error occurs.
786 // We need to do this before we return early on FindOnly flag.
787 if IsLocalImport(path
) && !ctxt
.isDir(p
.Dir
) {
788 if ctxt
.Compiler
== "gccgo" && p
.Goroot
{
789 // gccgo has no sources for GOROOT packages.
793 // package was not found
794 return p
, fmt
.Errorf("cannot find package %q in:\n\t%s", p
.ImportPath
, p
.Dir
)
797 if mode
&FindOnly
!= 0 {
800 if binaryOnly
&& (mode
&AllowBinary
) != 0 {
804 if ctxt
.Compiler
== "gccgo" && p
.Goroot
{
805 // gccgo has no sources for GOROOT packages.
809 dirs
, err
:= ctxt
.readDir(p
.Dir
)
815 badFiles
:= make(map[string]bool)
816 badFile
:= func(name
string, err error
) {
817 if badGoError
== nil {
821 p
.InvalidGoFiles
= append(p
.InvalidGoFiles
, name
)
822 badFiles
[name
] = true
826 var Sfiles
[]string // files with ".S"(capital S)/.sx(capital s equivalent for case insensitive filesystems)
827 var firstFile
, firstCommentFile
string
828 embedPos
:= make(map[string][]token
.Position
)
829 testEmbedPos
:= make(map[string][]token
.Position
)
830 xTestEmbedPos
:= make(map[string][]token
.Position
)
831 importPos
:= make(map[string][]token
.Position
)
832 testImportPos
:= make(map[string][]token
.Position
)
833 xTestImportPos
:= make(map[string][]token
.Position
)
834 allTags
:= make(map[string]bool)
835 fset
:= token
.NewFileSet()
836 for _
, d
:= range dirs
{
840 if d
.Mode()&fs
.ModeSymlink
!= 0 {
841 if ctxt
.isDir(ctxt
.joinPath(p
.Dir
, d
.Name())) {
842 // Symlinks to directories are not source files.
850 info
, err
:= ctxt
.matchFile(p
.Dir
, name
, allTags
, &p
.BinaryOnly
, fset
)
856 if strings
.HasPrefix(name
, "_") || strings
.HasPrefix(name
, ".") {
857 // not due to build constraints - don't report
858 } else if ext
== ".go" {
859 p
.IgnoredGoFiles
= append(p
.IgnoredGoFiles
, name
)
860 } else if fileListForExt(p
, ext
) != nil {
861 p
.IgnoredOtherFiles
= append(p
.IgnoredOtherFiles
, name
)
865 data
, filename
:= info
.header
, info
.name
867 // Going to save the file. For non-Go files, can stop here.
872 // special case for cgo, handled at end
873 Sfiles
= append(Sfiles
, name
)
876 if list
:= fileListForExt(p
, ext
); list
!= nil {
877 *list
= append(*list
, name
)
882 if info
.parseErr
!= nil {
883 badFile(name
, info
.parseErr
)
884 // Fall through: we might still have a partial AST in info.parsed,
885 // and we want to list files with parse errors anyway.
889 if info
.parsed
!= nil {
890 pkg
= info
.parsed
.Name
.Name
891 if pkg
== "documentation" {
892 p
.IgnoredGoFiles
= append(p
.IgnoredGoFiles
, name
)
897 isTest
:= strings
.HasSuffix(name
, "_test.go")
899 if isTest
&& strings
.HasSuffix(pkg
, "_test") && p
.Name
!= pkg
{
901 pkg
= pkg
[:len(pkg
)-len("_test")]
907 } else if pkg
!= p
.Name
{
908 // TODO(#45999): The choice of p.Name is arbitrary based on file iteration
909 // order. Instead of resolving p.Name arbitrarily, we should clear out the
910 // existing name and mark the existing files as also invalid.
911 badFile(name
, &MultiplePackageError
{
913 Packages
: []string{p
.Name
, pkg
},
914 Files
: []string{firstFile
, name
},
917 // Grab the first package comment as docs, provided it is not from a test file.
918 if info
.parsed
!= nil && info
.parsed
.Doc
!= nil && p
.Doc
== "" && !isTest
&& !isXTest
{
919 p
.Doc
= doc
.Synopsis(info
.parsed
.Doc
.Text())
922 if mode
&ImportComment
!= 0 {
923 qcom
, line
:= findImportComment(data
)
925 com
, err
:= strconv
.Unquote(qcom
)
927 badFile(name
, fmt
.Errorf("%s:%d: cannot parse import comment", filename
, line
))
928 } else if p
.ImportComment
== "" {
929 p
.ImportComment
= com
930 firstCommentFile
= name
931 } else if p
.ImportComment
!= com
{
932 badFile(name
, fmt
.Errorf("found import comments %q (%s) and %q (%s) in %s", p
.ImportComment
, firstCommentFile
, com
, name
, p
.Dir
))
937 // Record imports and information about cgo.
939 for _
, imp
:= range info
.imports
{
942 badFile(name
, fmt
.Errorf("use of cgo in test %s not supported", filename
))
947 if err
:= ctxt
.saveCgo(filename
, p
, imp
.doc
); err
!= nil {
954 var fileList
*[]string
955 var importMap
, embedMap
map[string][]token
.Position
958 allTags
["cgo"] = true
960 fileList
= &p
.CgoFiles
961 importMap
= importPos
964 // Ignore imports and embeds from cgo files if cgo is disabled.
965 fileList
= &p
.IgnoredGoFiles
968 fileList
= &p
.XTestGoFiles
969 importMap
= xTestImportPos
970 embedMap
= xTestEmbedPos
972 fileList
= &p
.TestGoFiles
973 importMap
= testImportPos
974 embedMap
= testEmbedPos
976 fileList
= &p
.GoFiles
977 importMap
= importPos
980 *fileList
= append(*fileList
, name
)
981 if importMap
!= nil {
982 for _
, imp
:= range info
.imports
{
983 importMap
[imp
.path
] = append(importMap
[imp
.path
], fset
.Position(imp
.pos
))
987 for _
, emb
:= range info
.embeds
{
988 embedMap
[emb
.pattern
] = append(embedMap
[emb
.pattern
], emb
.pos
)
993 for tag
:= range allTags
{
994 p
.AllTags
= append(p
.AllTags
, tag
)
996 sort
.Strings(p
.AllTags
)
998 p
.EmbedPatterns
, p
.EmbedPatternPos
= cleanDecls(embedPos
)
999 p
.TestEmbedPatterns
, p
.TestEmbedPatternPos
= cleanDecls(testEmbedPos
)
1000 p
.XTestEmbedPatterns
, p
.XTestEmbedPatternPos
= cleanDecls(xTestEmbedPos
)
1002 p
.Imports
, p
.ImportPos
= cleanDecls(importPos
)
1003 p
.TestImports
, p
.TestImportPos
= cleanDecls(testImportPos
)
1004 p
.XTestImports
, p
.XTestImportPos
= cleanDecls(xTestImportPos
)
1006 // add the .S/.sx files only if we are using cgo
1007 // (which means gcc will compile them).
1008 // The standard assemblers expect .s files.
1009 if len(p
.CgoFiles
) > 0 {
1010 p
.SFiles
= append(p
.SFiles
, Sfiles
...)
1011 sort
.Strings(p
.SFiles
)
1013 p
.IgnoredOtherFiles
= append(p
.IgnoredOtherFiles
, Sfiles
...)
1014 sort
.Strings(p
.IgnoredOtherFiles
)
1017 if badGoError
!= nil {
1018 return p
, badGoError
1020 if len(p
.GoFiles
)+len(p
.CgoFiles
)+len(p
.TestGoFiles
)+len(p
.XTestGoFiles
) == 0 {
1021 return p
, &NoGoError
{p
.Dir
}
1026 func fileListForExt(p
*Package
, ext
string) *[]string {
1030 case ".cc", ".cpp", ".cxx":
1034 case ".h", ".hh", ".hpp", ".hxx":
1036 case ".f", ".F", ".for", ".f90":
1038 case ".s", ".S", ".sx":
1043 return &p
.SwigCXXFiles
1050 func uniq(list
[]string) []string {
1054 out
:= make([]string, len(list
))
1058 for _
, x
:= range out
{
1059 if len(uniq
) == 0 || uniq
[len(uniq
)-1] != x
{
1060 uniq
= append(uniq
, x
)
1066 var errNoModules
= errors
.New("not using modules")
1068 // importGo checks whether it can use the go command to find the directory for path.
1069 // If using the go command is not appropriate, importGo returns errNoModules.
1070 // Otherwise, importGo tries using the go command and reports whether that succeeded.
1071 // Using the go command lets build.Import and build.Context.Import find code
1072 // in Go modules. In the long term we want tools to use go/packages (currently golang.org/x/tools/go/packages),
1073 // which will also use the go command.
1074 // Invoking the go command here is not very efficient in that it computes information
1075 // about the requested package and all dependencies and then only reports about the requested package.
1076 // Then we reinvoke it for every dependency. But this is still better than not working at all.
1077 // See golang.org/issue/26504.
1078 func (ctxt
*Context
) importGo(p
*Package
, path
, srcDir
string, mode ImportMode
) error
{
1079 // To invoke the go command,
1080 // we must not being doing special things like AllowBinary or IgnoreVendor,
1081 // and all the file system callbacks must be nil (we're meant to use the local file system).
1082 if mode
&AllowBinary
!= 0 || mode
&IgnoreVendor
!= 0 ||
1083 ctxt
.JoinPath
!= nil || ctxt
.SplitPathList
!= nil || ctxt
.IsAbsPath
!= nil || ctxt
.IsDir
!= nil || ctxt
.HasSubdir
!= nil || ctxt
.ReadDir
!= nil || ctxt
.OpenFile
!= nil ||
!equal(ctxt
.ToolTags
, defaultToolTags
) ||
!equal(ctxt
.ReleaseTags
, defaultReleaseTags
) {
1087 // Predict whether module aware mode is enabled by checking the value of
1088 // GO111MODULE and looking for a go.mod file in the source directory or
1089 // one of its parents. Running 'go env GOMOD' in the source directory would
1090 // give a canonical answer, but we'd prefer not to execute another command.
1091 go111Module
:= os
.Getenv("GO111MODULE")
1092 switch go111Module
{
1095 default: // "", "on", "auto", anything else
1096 // Maybe use modules.
1100 var absSrcDir
string
1101 if filepath
.IsAbs(srcDir
) {
1103 } else if ctxt
.Dir
!= "" {
1104 return fmt
.Errorf("go/build: Dir is non-empty, so relative srcDir is not allowed: %v", srcDir
)
1106 // Find the absolute source directory. hasSubdir does not handle
1107 // relative paths (and can't because the callbacks don't support this).
1109 absSrcDir
, err
= filepath
.Abs(srcDir
)
1115 // If the source directory is in GOROOT, then the in-process code works fine
1116 // and we should keep using it. Moreover, the 'go list' approach below doesn't
1117 // take standard-library vendoring into account and will fail.
1118 if _
, ok
:= ctxt
.hasSubdir(filepath
.Join(ctxt
.GOROOT
, "src"), absSrcDir
); ok
{
1123 // For efficiency, if path is a standard library package, let the usual lookup code handle it.
1124 if ctxt
.GOROOT
!= "" {
1125 dir
:= ctxt
.joinPath(ctxt
.GOROOT
, "src", path
)
1126 if ctxt
.isDir(dir
) {
1131 // If GO111MODULE=auto, look to see if there is a go.mod.
1132 // Since go1.13, it doesn't matter if we're inside GOPATH.
1133 if go111Module
== "auto" {
1139 parent
, err
= os
.Getwd()
1141 // A nonexistent working directory can't be in a module.
1145 parent
, err
= filepath
.Abs(ctxt
.Dir
)
1147 // If the caller passed a bogus Dir explicitly, that's materially
1148 // different from not having modules enabled.
1153 if f
, err
:= ctxt
.openFile(ctxt
.joinPath(parent
, "go.mod")); err
== nil {
1154 buf
:= make([]byte, 100)
1155 _
, err
:= f
.Read(buf
)
1157 if err
== nil || err
== io
.EOF
{
1158 // go.mod exists and is readable (is a file, not a directory).
1162 d
:= filepath
.Dir(parent
)
1163 if len(d
) >= len(parent
) {
1164 return errNoModules
// reached top of file system, no go.mod
1170 cmd
:= exec
.Command("go", "list", "-e", "-compiler="+ctxt
.Compiler
, "-tags="+strings
.Join(ctxt
.BuildTags
, ","), "-installsuffix="+ctxt
.InstallSuffix
, "-f={{.Dir}}\n{{.ImportPath}}\n{{.Root}}\n{{.Goroot}}\n{{if .Error}}{{.Error}}{{end}}\n", "--", path
)
1176 var stdout
, stderr strings
.Builder
1177 cmd
.Stdout
= &stdout
1178 cmd
.Stderr
= &stderr
1181 if ctxt
.CgoEnabled
{
1184 cmd
.Env
= append(os
.Environ(),
1186 "GOARCH="+ctxt
.GOARCH
,
1187 "GOROOT="+ctxt
.GOROOT
,
1188 "GOPATH="+ctxt
.GOPATH
,
1192 if err
:= cmd
.Run(); err
!= nil {
1193 return fmt
.Errorf("go/build: go list %s: %v\n%s\n", path
, err
, stderr
.String())
1196 f
:= strings
.SplitN(stdout
.String(), "\n", 5)
1198 return fmt
.Errorf("go/build: importGo %s: unexpected output:\n%s\n", path
, stdout
.String())
1201 errStr
:= strings
.TrimSpace(f
[4])
1202 if errStr
!= "" && dir
== "" {
1203 // If 'go list' could not locate the package (dir is empty),
1204 // return the same error that 'go list' reported.
1205 return errors
.New(errStr
)
1208 // If 'go list' did locate the package, ignore the error.
1209 // It was probably related to loading source files, and we'll
1210 // encounter it ourselves shortly if the FindOnly flag isn't set.
1214 p
.Goroot
= f
[3] == "true"
1218 func equal(x
, y
[]string) bool {
1219 if len(x
) != len(y
) {
1222 for i
, xi
:= range x
{
1230 // hasGoFiles reports whether dir contains any files with names ending in .go.
1231 // For a vendor check we must exclude directories that contain no .go files.
1232 // Otherwise it is not possible to vendor just a/b/c and still import the
1233 // non-vendored a/b. See golang.org/issue/13832.
1234 func hasGoFiles(ctxt
*Context
, dir
string) bool {
1235 ents
, _
:= ctxt
.readDir(dir
)
1236 for _
, ent
:= range ents
{
1237 if !ent
.IsDir() && strings
.HasSuffix(ent
.Name(), ".go") {
1244 func findImportComment(data
[]byte) (s
string, line
int) {
1245 // expect keyword package
1246 word
, data
:= parseWord(data
)
1247 if string(word
) != "package" {
1251 // expect package name
1252 _
, data
= parseWord(data
)
1254 // now ready for import comment, a // or /* */ comment
1255 // beginning and ending on the current line.
1256 for len(data
) > 0 && (data
[0] == ' ' || data
[0] == '\t' || data
[0] == '\r') {
1262 case bytes
.HasPrefix(data
, slashSlash
):
1263 comment
, _
, _
= bytes
.Cut(data
[2:], newline
)
1264 case bytes
.HasPrefix(data
, slashStar
):
1266 comment
, _
, ok
= bytes
.Cut(data
[2:], starSlash
)
1268 // malformed comment
1271 if bytes
.Contains(comment
, newline
) {
1275 comment
= bytes
.TrimSpace(comment
)
1277 // split comment into `import`, `"pkg"`
1278 word
, arg
:= parseWord(comment
)
1279 if string(word
) != "import" {
1283 line
= 1 + bytes
.Count(data
[:cap(data
)-cap(arg
)], newline
)
1284 return strings
.TrimSpace(string(arg
)), line
1288 slashSlash
= []byte("//")
1289 slashStar
= []byte("/*")
1290 starSlash
= []byte("*/")
1291 newline
= []byte("\n")
1294 // skipSpaceOrComment returns data with any leading spaces or comments removed.
1295 func skipSpaceOrComment(data
[]byte) []byte {
1298 case ' ', '\t', '\r', '\n':
1302 if bytes
.HasPrefix(data
, slashSlash
) {
1303 i
:= bytes
.Index(data
, newline
)
1310 if bytes
.HasPrefix(data
, slashStar
) {
1312 i
:= bytes
.Index(data
, starSlash
)
1325 // parseWord skips any leading spaces or comments in data
1326 // and then parses the beginning of data as an identifier or keyword,
1327 // returning that word and what remains after the word.
1328 func parseWord(data
[]byte) (word
, rest
[]byte) {
1329 data
= skipSpaceOrComment(data
)
1331 // Parse past leading word characters.
1334 r
, size
:= utf8
.DecodeRune(rest
)
1335 if unicode
.IsLetter(r
) ||
'0' <= r
&& r
<= '9' || r
== '_' {
1342 word
= data
[:len(data
)-len(rest
)]
1350 // MatchFile reports whether the file with the given name in the given directory
1351 // matches the context and would be included in a Package created by ImportDir
1352 // of that directory.
1354 // MatchFile considers the name of the file and may use ctxt.OpenFile to
1355 // read some or all of the file's content.
1356 func (ctxt
*Context
) MatchFile(dir
, name
string) (match
bool, err error
) {
1357 info
, err
:= ctxt
.matchFile(dir
, name
, nil, nil, nil)
1358 return info
!= nil, err
1361 var dummyPkg Package
1363 // fileInfo records information learned about a file included in a build.
1364 type fileInfo
struct {
1365 name
string // full name including dir
1370 imports
[]fileImport
1375 type fileImport
struct {
1378 doc
*ast
.CommentGroup
1381 type fileEmbed
struct {
1386 // matchFile determines whether the file with the given name in the given directory
1387 // should be included in the package being constructed.
1388 // If the file should be included, matchFile returns a non-nil *fileInfo (and a nil error).
1389 // Non-nil errors are reserved for unexpected problems.
1391 // If name denotes a Go program, matchFile reads until the end of the
1392 // imports and returns that section of the file in the fileInfo's header field,
1393 // even though it only considers text until the first non-comment
1394 // for +build lines.
1396 // If allTags is non-nil, matchFile records any encountered build tag
1397 // by setting allTags[tag] = true.
1398 func (ctxt
*Context
) matchFile(dir
, name
string, allTags
map[string]bool, binaryOnly
*bool, fset
*token
.FileSet
) (*fileInfo
, error
) {
1399 if strings
.HasPrefix(name
, "_") ||
1400 strings
.HasPrefix(name
, ".") {
1404 i
:= strings
.LastIndex(name
, ".")
1410 if !ctxt
.goodOSArchFile(name
, allTags
) && !ctxt
.UseAllFiles
{
1414 if ext
!= ".go" && fileListForExt(&dummyPkg
, ext
) == nil {
1419 info
:= &fileInfo
{name
: ctxt
.joinPath(dir
, name
), fset
: fset
}
1421 // binary, no reading
1425 f
, err
:= ctxt
.openFile(info
.name
)
1430 if strings
.HasSuffix(name
, ".go") {
1431 err
= readGoInfo(f
, info
)
1432 if strings
.HasSuffix(name
, "_test.go") {
1433 binaryOnly
= nil // ignore //go:binary-only-package comments in _test.go files
1436 binaryOnly
= nil // ignore //go:binary-only-package comments in non-Go sources
1437 info
.header
, err
= readComments(f
)
1441 return nil, fmt
.Errorf("read %s: %v", info
.name
, err
)
1444 // Look for +build comments to accept or reject the file.
1445 ok
, sawBinaryOnly
, err
:= ctxt
.shouldBuild(info
.header
, allTags
)
1447 return nil, fmt
.Errorf("%s: %v", name
, err
)
1449 if !ok
&& !ctxt
.UseAllFiles
{
1453 if binaryOnly
!= nil && sawBinaryOnly
{
1460 func cleanDecls(m
map[string][]token
.Position
) ([]string, map[string][]token
.Position
) {
1461 all
:= make([]string, 0, len(m
))
1462 for path
:= range m
{
1463 all
= append(all
, path
)
1469 // Import is shorthand for Default.Import.
1470 func Import(path
, srcDir
string, mode ImportMode
) (*Package
, error
) {
1471 return Default
.Import(path
, srcDir
, mode
)
1474 // ImportDir is shorthand for Default.ImportDir.
1475 func ImportDir(dir
string, mode ImportMode
) (*Package
, error
) {
1476 return Default
.ImportDir(dir
, mode
)
1480 bSlashSlash
= []byte(slashSlash
)
1481 bStarSlash
= []byte(starSlash
)
1482 bSlashStar
= []byte(slashStar
)
1483 bPlusBuild
= []byte("+build")
1485 goBuildComment
= []byte("//go:build")
1487 errGoBuildWithoutBuild
= errors
.New("//go:build comment without // +build comment")
1488 errMultipleGoBuild
= errors
.New("multiple //go:build comments")
1491 func isGoBuildComment(line
[]byte) bool {
1492 if !bytes
.HasPrefix(line
, goBuildComment
) {
1495 line
= bytes
.TrimSpace(line
)
1496 rest
:= line
[len(goBuildComment
):]
1497 return len(rest
) == 0 ||
len(bytes
.TrimSpace(rest
)) < len(rest
)
1500 // Special comment denoting a binary-only package.
1501 // See https://golang.org/design/2775-binary-only-packages
1502 // for more about the design of binary-only packages.
1503 var binaryOnlyComment
= []byte("//go:binary-only-package")
1505 // shouldBuild reports whether it is okay to use this file,
1506 // The rule is that in the file's leading run of // comments
1507 // and blank lines, which must be followed by a blank line
1508 // (to avoid including a Go package clause doc comment),
1509 // lines beginning with '// +build' are taken as build directives.
1511 // The file is accepted only if each such line lists something
1512 // matching the file. For example:
1514 // // +build windows linux
1516 // marks the file as applicable only on Windows and Linux.
1518 // For each build tag it consults, shouldBuild sets allTags[tag] = true.
1520 // shouldBuild reports whether the file should be built
1521 // and whether a //go:binary-only-package comment was found.
1522 func (ctxt
*Context
) shouldBuild(content
[]byte, allTags
map[string]bool) (shouldBuild
, binaryOnly
bool, err error
) {
1523 // Identify leading run of // comments and blank lines,
1524 // which must be followed by a blank line.
1525 // Also identify any //go:build comments.
1526 content
, goBuild
, sawBinaryOnly
, err
:= parseFileHeader(content
)
1528 return false, false, err
1531 // If //go:build line is present, it controls.
1532 // Otherwise fall back to +build processing.
1534 case goBuild
!= nil:
1535 x
, err
:= constraint
.Parse(string(goBuild
))
1537 return false, false, fmt
.Errorf("parsing //go:build line: %v", err
)
1539 shouldBuild
= ctxt
.eval(x
, allTags
)
1546 if i
:= bytes
.IndexByte(line
, '\n'); i
>= 0 {
1547 line
, p
= line
[:i
], p
[i
+1:]
1551 line
= bytes
.TrimSpace(line
)
1552 if !bytes
.HasPrefix(line
, bSlashSlash
) ||
!bytes
.Contains(line
, bPlusBuild
) {
1555 text
:= string(line
)
1556 if !constraint
.IsPlusBuild(text
) {
1559 if x
, err
:= constraint
.Parse(text
); err
== nil {
1560 if !ctxt
.eval(x
, allTags
) {
1567 return shouldBuild
, sawBinaryOnly
, nil
1570 func parseFileHeader(content
[]byte) (trimmed
, goBuild
[]byte, sawBinaryOnly
bool, err error
) {
1573 ended
:= false // found non-blank, non-// line, so stopped accepting // +build lines
1574 inSlashStar
:= false // in /* */ comment
1579 if i
:= bytes
.IndexByte(line
, '\n'); i
>= 0 {
1580 line
, p
= line
[:i
], p
[i
+1:]
1584 line
= bytes
.TrimSpace(line
)
1585 if len(line
) == 0 && !ended
{ // Blank line
1586 // Remember position of most recent blank line.
1587 // When we find the first non-blank, non-// line,
1588 // this "end" position marks the latest file position
1589 // where a // +build line can appear.
1590 // (It must appear _before_ a blank line before the non-blank, non-// line.
1591 // Yes, that's confusing, which is part of why we moved to //go:build lines.)
1592 // Note that ended==false here means that inSlashStar==false,
1593 // since seeing a /* would have set ended==true.
1594 end
= len(content
) - len(p
)
1597 if !bytes
.HasPrefix(line
, slashSlash
) { // Not comment line
1601 if !inSlashStar
&& isGoBuildComment(line
) {
1603 return nil, nil, false, errMultipleGoBuild
1607 if !inSlashStar
&& bytes
.Equal(line
, binaryOnlyComment
) {
1608 sawBinaryOnly
= true
1614 if i
:= bytes
.Index(line
, starSlash
); i
>= 0 {
1616 line
= bytes
.TrimSpace(line
[i
+len(starSlash
):])
1621 if bytes
.HasPrefix(line
, bSlashSlash
) {
1624 if bytes
.HasPrefix(line
, bSlashStar
) {
1626 line
= bytes
.TrimSpace(line
[len(bSlashStar
):])
1629 // Found non-comment text.
1634 return content
[:end
], goBuild
, sawBinaryOnly
, nil
1637 // saveCgo saves the information from the #cgo lines in the import "C" comment.
1638 // These lines set CFLAGS, CPPFLAGS, CXXFLAGS and LDFLAGS and pkg-config directives
1639 // that affect the way cgo's C code is built.
1640 func (ctxt
*Context
) saveCgo(filename
string, di
*Package
, cg
*ast
.CommentGroup
) error
{
1642 for _
, line
:= range strings
.Split(text
, "\n") {
1646 // #cgo [GOOS/GOARCH...] LDFLAGS: stuff
1648 line
= strings
.TrimSpace(line
)
1649 if len(line
) < 5 || line
[:4] != "#cgo" ||
(line
[4] != ' ' && line
[4] != '\t') {
1654 line
, argstr
, ok
:= strings
.Cut(strings
.TrimSpace(line
[4:]), ":")
1656 return fmt
.Errorf("%s: invalid #cgo line: %s", filename
, orig
)
1659 // Parse GOOS/GOARCH stuff.
1660 f
:= strings
.Fields(line
)
1662 return fmt
.Errorf("%s: invalid #cgo line: %s", filename
, orig
)
1665 cond
, verb
:= f
[:len(f
)-1], f
[len(f
)-1]
1668 for _
, c
:= range cond
{
1669 if ctxt
.matchAuto(c
, nil) {
1679 args
, err
:= splitQuoted(argstr
)
1681 return fmt
.Errorf("%s: invalid #cgo line: %s", filename
, orig
)
1683 for i
, arg
:= range args
{
1684 if arg
, ok
= expandSrcDir(arg
, di
.Dir
); !ok
{
1685 return fmt
.Errorf("%s: malformed #cgo argument: %s", filename
, arg
)
1691 case "CFLAGS", "CPPFLAGS", "CXXFLAGS", "FFLAGS", "LDFLAGS":
1692 // Change relative paths to absolute.
1693 ctxt
.makePathsAbsolute(args
, di
.Dir
)
1698 di
.CgoCFLAGS
= append(di
.CgoCFLAGS
, args
...)
1700 di
.CgoCPPFLAGS
= append(di
.CgoCPPFLAGS
, args
...)
1702 di
.CgoCXXFLAGS
= append(di
.CgoCXXFLAGS
, args
...)
1704 di
.CgoFFLAGS
= append(di
.CgoFFLAGS
, args
...)
1706 di
.CgoLDFLAGS
= append(di
.CgoLDFLAGS
, args
...)
1708 di
.CgoPkgConfig
= append(di
.CgoPkgConfig
, args
...)
1710 return fmt
.Errorf("%s: invalid #cgo verb: %s", filename
, orig
)
1716 // expandSrcDir expands any occurrence of ${SRCDIR}, making sure
1717 // the result is safe for the shell.
1718 func expandSrcDir(str
string, srcdir
string) (string, bool) {
1719 // "\" delimited paths cause safeCgoName to fail
1720 // so convert native paths with a different delimiter
1721 // to "/" before starting (eg: on windows).
1722 srcdir
= filepath
.ToSlash(srcdir
)
1724 chunks
:= strings
.Split(str
, "${SRCDIR}")
1725 if len(chunks
) < 2 {
1726 return str
, safeCgoName(str
)
1729 for _
, chunk
:= range chunks
{
1730 ok
= ok
&& (chunk
== "" ||
safeCgoName(chunk
))
1732 ok
= ok
&& (srcdir
== "" ||
safeCgoName(srcdir
))
1733 res
:= strings
.Join(chunks
, srcdir
)
1734 return res
, ok
&& res
!= ""
1737 // makePathsAbsolute looks for compiler options that take paths and
1738 // makes them absolute. We do this because through the 1.8 release we
1739 // ran the compiler in the package directory, so any relative -I or -L
1740 // options would be relative to that directory. In 1.9 we changed to
1741 // running the compiler in the build directory, to get consistent
1742 // build results (issue #19964). To keep builds working, we change any
1743 // relative -I or -L options to be absolute.
1745 // Using filepath.IsAbs and filepath.Join here means the results will be
1746 // different on different systems, but that's OK: -I and -L options are
1747 // inherently system-dependent.
1748 func (ctxt
*Context
) makePathsAbsolute(args
[]string, srcDir
string) {
1750 for i
, arg
:= range args
{
1752 if !filepath
.IsAbs(arg
) {
1753 args
[i
] = filepath
.Join(srcDir
, arg
)
1756 } else if strings
.HasPrefix(arg
, "-I") || strings
.HasPrefix(arg
, "-L") {
1760 if !filepath
.IsAbs(arg
[2:]) {
1761 args
[i
] = arg
[:2] + filepath
.Join(srcDir
, arg
[2:])
1768 // NOTE: $ is not safe for the shell, but it is allowed here because of linker options like -Wl,$ORIGIN.
1769 // We never pass these arguments to a shell (just to programs we construct argv for), so this should be okay.
1770 // See golang.org/issue/6038.
1771 // The @ is for OS X. See golang.org/issue/13720.
1772 // The % is for Jenkins. See golang.org/issue/16959.
1773 // The ! is because module paths may use them. See golang.org/issue/26716.
1774 // The ~ and ^ are for sr.ht. See golang.org/issue/32260.
1775 const safeString
= "+-.,/0123456789=ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz:$@%! ~^"
1777 func safeCgoName(s
string) bool {
1781 for i
:= 0; i
< len(s
); i
++ {
1782 if c
:= s
[i
]; c
< utf8
.RuneSelf
&& strings
.IndexByte(safeString
, c
) < 0 {
1789 // splitQuoted splits the string s around each instance of one or more consecutive
1790 // white space characters while taking into account quotes and escaping, and
1791 // returns an array of substrings of s or an empty list if s contains only white space.
1792 // Single quotes and double quotes are recognized to prevent splitting within the
1793 // quoted region, and are removed from the resulting substrings. If a quote in s
1794 // isn't closed err will be set and r will have the unclosed argument as the
1795 // last element. The backslash is used for escaping.
1797 // For example, the following string:
1799 // a b:"c d" 'e''f' "g\""
1801 // Would be parsed as:
1803 // []string{"a", "b:c d", "ef", `g"`}
1805 func splitQuoted(s
string) (r
[]string, err error
) {
1807 arg
:= make([]rune
, len(s
))
1812 for _
, rune
:= range s
{
1819 case quote
!= '\x00':
1824 case rune
== '"' || rune
== '\'':
1828 case unicode
.IsSpace(rune
):
1829 if quoted || i
> 0 {
1831 args
= append(args
, string(arg
[:i
]))
1839 if quoted || i
> 0 {
1840 args
= append(args
, string(arg
[:i
]))
1843 err
= errors
.New("unclosed quote")
1845 err
= errors
.New("unfinished escaping")
1850 // matchAuto interprets text as either a +build or //go:build expression (whichever works),
1851 // reporting whether the expression matches the build context.
1853 // matchAuto is only used for testing of tag evaluation
1854 // and in #cgo lines, which accept either syntax.
1855 func (ctxt
*Context
) matchAuto(text
string, allTags
map[string]bool) bool {
1856 if strings
.ContainsAny(text
, "&|()") {
1857 text
= "//go:build " + text
1859 text
= "// +build " + text
1861 x
, err
:= constraint
.Parse(text
)
1865 return ctxt
.eval(x
, allTags
)
1868 func (ctxt
*Context
) eval(x constraint
.Expr
, allTags
map[string]bool) bool {
1869 return x
.Eval(func(tag
string) bool { return ctxt
.matchTag(tag
, allTags
) })
1872 // matchTag reports whether the name is one of:
1874 // cgo (if cgo is enabled)
1878 // linux (if GOOS = android)
1879 // solaris (if GOOS = illumos)
1880 // tag (if tag is listed in ctxt.BuildTags or ctxt.ReleaseTags)
1882 // It records all consulted tags in allTags.
1883 func (ctxt
*Context
) matchTag(name
string, allTags
map[string]bool) bool {
1885 allTags
[name
] = true
1889 if ctxt
.CgoEnabled
&& name
== "cgo" {
1892 if name
== ctxt
.GOOS || name
== ctxt
.GOARCH || name
== ctxt
.Compiler
{
1895 if ctxt
.GOOS
== "android" && name
== "linux" {
1898 if ctxt
.GOOS
== "illumos" && name
== "solaris" {
1901 if ctxt
.GOOS
== "ios" && name
== "darwin" {
1906 for _
, tag
:= range ctxt
.BuildTags
{
1911 for _
, tag
:= range ctxt
.ToolTags
{
1916 for _
, tag
:= range ctxt
.ReleaseTags
{
1925 // goodOSArchFile returns false if the name contains a $GOOS or $GOARCH
1926 // suffix which does not match the current system.
1927 // The recognized name formats are:
1931 // name_$(GOOS)_$(GOARCH).*
1932 // name_$(GOOS)_test.*
1933 // name_$(GOARCH)_test.*
1934 // name_$(GOOS)_$(GOARCH)_test.*
1937 // if GOOS=android, then files with GOOS=linux are also matched.
1938 // if GOOS=illumos, then files with GOOS=solaris are also matched.
1939 // if GOOS=ios, then files with GOOS=darwin are also matched.
1940 func (ctxt
*Context
) goodOSArchFile(name
string, allTags
map[string]bool) bool {
1941 name
, _
, _
= strings
.Cut(name
, ".")
1943 // Before Go 1.4, a file called "linux.go" would be equivalent to having a
1944 // build tag "linux" in that file. For Go 1.4 and beyond, we require this
1945 // auto-tagging to apply only to files with a non-empty prefix, so
1946 // "foo_linux.go" is tagged but "linux.go" is not. This allows new operating
1947 // systems, such as android, to arrive without breaking existing code with
1948 // innocuous source code in "android.go". The easiest fix: cut everything
1949 // in the name before the initial _.
1950 i
:= strings
.Index(name
, "_")
1954 name
= name
[i
:] // ignore everything before first _
1956 l
:= strings
.Split(name
, "_")
1957 if n
:= len(l
); n
> 0 && l
[n
-1] == "test" {
1961 if n
>= 2 && knownOS
[l
[n
-2]] && knownArch
[l
[n
-1]] {
1962 return ctxt
.matchTag(l
[n
-1], allTags
) && ctxt
.matchTag(l
[n
-2], allTags
)
1964 if n
>= 1 && (knownOS
[l
[n
-1]] || knownArch
[l
[n
-1]]) {
1965 return ctxt
.matchTag(l
[n
-1], allTags
)
1970 var knownOS
= make(map[string]bool)
1971 var knownArch
= make(map[string]bool)
1974 for _
, v
:= range strings
.Fields(goosList
) {
1977 for _
, v
:= range strings
.Fields(goarchList
) {
1982 // ToolDir is the directory containing build tools.
1983 var ToolDir
= getToolDir()
1985 // IsLocalImport reports whether the import path is
1986 // a local import path, like ".", "..", "./foo", or "../foo".
1987 func IsLocalImport(path
string) bool {
1988 return path
== "." || path
== ".." ||
1989 strings
.HasPrefix(path
, "./") || strings
.HasPrefix(path
, "../")
1992 // ArchChar returns "?" and an error.
1993 // In earlier versions of Go, the returned string was used to derive
1994 // the compiler and linker tool names, the default object file suffix,
1995 // and the default linker output name. As of Go 1.5, those strings
1996 // no longer vary by architecture; they are compile, link, .o, and a.out, respectively.
1997 func ArchChar(goarch
string) (string, error
) {
1998 return "?", errors
.New("architecture letter no longer used")