Source File
build.go
Belonging Package
go/build
Dir string
CgoEnabled bool // whether cgo files are included
UseAllFiles bool // use files regardless of +build lines, file names
Compiler string // compiler to assume when computing target paths
SplitPathList func(list string) []string
OpenFile func(path string) (io.ReadCloser, error)
}
if , = hasSubdir(, ); {
return
}
, := filepath.EvalSymlinks()
, := filepath.EvalSymlinks()
if , = hasSubdir(, ); {
return
}
if , = hasSubdir(, ); {
return
}
return hasSubdir(, )
}
func ( *Context) () []string {
var []string
for , := range .splitPathList(.GOPATH) {
continue
}
continue
}
= append(, )
}
return
}
for := 1; <= goversion.Version; ++ {
.ReleaseTags = append(.ReleaseTags, "go1."+strconv.Itoa())
}
defaultReleaseTags = append([]string{}, .ReleaseTags...) // our own private copy
:= os.Getenv("CGO_ENABLED")
if == "" {
= defaultCGO_ENABLED
}
switch {
case "1":
.CgoEnabled = true
case "0":
.CgoEnabled = false
type ImportMode uint
FindOnly ImportMode = 1 << iota
type Package struct {
Dir string // directory containing package sources
Name string // package name
ImportComment string // path in import comment on package statement
Doc string // documentation synopsis
ImportPath string // import path of package ("" if unknown)
Root string // root of Go tree where this package lives
SrcRoot string // package source root directory ("" if unknown)
PkgRoot string // package install root directory ("" if unknown)
PkgTargetRoot string // architecture dependent install root directory ("" if unknown)
BinDir string // command install directory ("" if unknown)
Goroot bool // package found in Go root
PkgObj string // installed .a file
AllTags []string // tags that can influence file selection in this directory
ConflictDir string // this directory shadows Dir in $GOPATH
BinaryOnly bool // cannot be rebuilt from source (has //go:binary-only-package comment)
GoFiles []string // .go source files (excluding CgoFiles, TestGoFiles, XTestGoFiles)
CgoFiles []string // .go source files that import "C"
IgnoredGoFiles []string // .go source files ignored for this build (including ignored _test.go files)
InvalidGoFiles []string // .go source files with detected problems (parse error, wrong package name, and so on)
IgnoredOtherFiles []string // non-.go source files ignored for this build
CFiles []string // .c source files
CXXFiles []string // .cc, .cpp and .cxx source files
MFiles []string // .m (Objective-C) source files
HFiles []string // .h, .hh, .hpp and .hxx source files
FFiles []string // .f, .F, .for and .f90 Fortran source files
SFiles []string // .s source files
SwigFiles []string // .swig files
SwigCXXFiles []string // .swigcxx files
SysoFiles []string // .syso system object files to add to archive
CgoCFLAGS []string // Cgo CFLAGS directives
CgoCPPFLAGS []string // Cgo CPPFLAGS directives
CgoCXXFLAGS []string // Cgo CXXFLAGS directives
CgoFFLAGS []string // Cgo FFLAGS directives
CgoLDFLAGS []string // Cgo LDFLAGS directives
CgoPkgConfig []string // Cgo pkg-config directives
TestGoFiles []string // _test.go files in package
XTestGoFiles []string // _test.go files outside package
Imports []string // import paths from GoFiles, CgoFiles
ImportPos map[string][]token.Position // line information for Imports
TestImports []string // import paths from TestGoFiles
TestImportPos map[string][]token.Position // line information for TestImports
XTestImports []string // import paths from XTestGoFiles
XTestImportPos map[string][]token.Position // line information for XTestImports
EmbedPatterns []string // patterns from GoFiles, CgoFiles
EmbedPatternPos map[string][]token.Position // line information for EmbedPatterns
TestEmbedPatterns []string // patterns from TestGoFiles
TestEmbedPatternPos map[string][]token.Position // line information for TestEmbedPatterns
XTestEmbedPatterns []string // patterns from XTestGoFiles
XTestEmbedPatternPos map[string][]token.Position // line information for XTestEmbedPatternPos
}
func ( *Context) ( string, string, ImportMode) (*Package, error) {
:= &Package{
ImportPath: ,
}
if == "" {
return , fmt.Errorf("import %q: invalid import path", )
}
var string
var string
var error
:= ""
if .InstallSuffix != "" {
= "_" + .InstallSuffix
}
switch .Compiler {
case "gccgo":
= "pkg/gccgo_" + .GOOS + "_" + .GOARCH +
case "gc":
= "pkg/" + .GOOS + "_" + .GOARCH +
= fmt.Errorf("import %q: unknown compiler %q", , .Compiler)
}
:= func() {
switch .Compiler {
case "gccgo":
, := pathpkg.Split(.ImportPath)
= + "/" + + "lib" + + ".a"
case "gc":
= + "/" + .ImportPath + ".a"
}
}
()
:= false
if IsLocalImport() {
= "" // local imports have no installed path
if == "" {
return , fmt.Errorf("import %q: import relative to unknown directory", )
}
if !.isAbsPath() {
.Dir = .joinPath(, )
:= func( string) bool {
return strings.Contains(, "/testdata/") || strings.HasSuffix(, "/testdata") || strings.HasPrefix(, "testdata/") || == "testdata"
}
if .GOROOT != "" {
:= .joinPath(.GOROOT, "src")
if , := .hasSubdir(, .Dir); && !() {
.Goroot = true
.ImportPath =
.Root = .GOROOT
() // p.ImportPath changed
goto
}
}
:= .gopath()
for , := range {
:= .joinPath(, "src")
if .GOROOT != "" && .Compiler != "gccgo" {
if := .joinPath(.GOROOT, "src", ); .isDir() {
.ConflictDir =
goto
}
}
for , := range [:] {
if := .joinPath(, "src", ); .isDir() {
.ConflictDir =
goto
}
}
.ImportPath =
.Root =
() // p.ImportPath changed
goto
}
if &IgnoreVendor == 0 && != "" {
:= func( string, bool) bool {
, := .hasSubdir(, )
if ! || !strings.HasPrefix(, "src/") || strings.Contains(, "/testdata/") {
return false
}
for {
:= .joinPath(, , "vendor")
if .isDir() {
:= .joinPath(, )
if .isDir() && hasGoFiles(, ) {
.Dir =
.ImportPath = strings.TrimPrefix(pathpkg.Join(, "vendor", ), "src/")
.Goroot =
.Root =
() // p.ImportPath changed
return true
}
. = append(., )
}
:= strings.LastIndex(, "/")
if < 0 {
break
}
= [:]
}
return false
}
if .Compiler != "gccgo" && (.GOROOT, true) {
goto
}
for , := range {
if (, false) {
goto
}
}
}
:= == "" || !strings.HasPrefix(, "vendor/")
if ! {
_, = .hasSubdir(.GOROOT, )
}
if {
:= .joinPath(.GOROOT, "src", )
if .Compiler != "gccgo" {
:= .isDir()
= ! && &AllowBinary != 0 && != "" && .isFile(.joinPath(.GOROOT, ))
if || {
.Dir =
.Goroot = true
.Root = .GOROOT
goto
}
}
. =
}
}
if .Compiler == "gccgo" && goroot.IsStandardPackage(.GOROOT, .Compiler, ) {
.Dir = .joinPath(.GOROOT, "src", )
.Goroot = true
.Root = .GOROOT
goto
}
for , := range {
:= .joinPath(, "src", )
:= .isDir()
= ! && &AllowBinary != 0 && != "" && .isFile(.joinPath(, ))
if || {
.Dir =
.Root =
goto
}
. = append(., )
}
var []string
:= "\t%s (vendor tree)"
for , := range . {
= append(, fmt.Sprintf(, ))
= "\t%s"
}
if . != "" {
= append(, fmt.Sprintf("\t%s (from $GOROOT)", .))
} else {
= append(, "\t($GOROOT not set)")
}
= "\t%s (from $GOPATH)"
for , := range . {
= append(, fmt.Sprintf(, ))
= "\t%s"
}
if len(.) == 0 {
= append(, "\t($GOPATH not set. For more details see: 'go help gopath')")
}
return , fmt.Errorf("cannot find package %q in any of:\n%s", , strings.Join(, "\n"))
}
:
if .Root != "" {
.SrcRoot = .joinPath(.Root, "src")
.PkgRoot = .joinPath(.Root, "pkg")
.BinDir = .joinPath(.Root, "bin")
if != "" {
.PkgTargetRoot = .joinPath(.Root, )
.PkgObj = .joinPath(.Root, )
}
}
if IsLocalImport() && !.isDir(.Dir) {
return , nil
}
return , fmt.Errorf("cannot find package %q in:\n\t%s", , .Dir)
}
if &FindOnly != 0 {
return ,
}
if && (&AllowBinary) != 0 {
return ,
}
return , nil
}
, := .readDir(.Dir)
if != nil {
return ,
}
var error
var []string // files with ".S"(capital S)/.sx(capital s equivalent for case insensitive filesystems)
var , string
:= make(map[string][]token.Position)
:= make(map[string][]token.Position)
:= make(map[string][]token.Position)
:= make(map[string][]token.Position)
:= make(map[string][]token.Position)
:= make(map[string][]token.Position)
:= make(map[string]bool)
:= token.NewFileSet()
for , := range {
if .IsDir() {
continue
}
if .Mode()&fs.ModeSymlink != 0 {
continue
}
}
:= .Name()
:= nameExt()
:= func( error) {
if == nil {
=
}
.InvalidGoFiles = append(.InvalidGoFiles, )
}
, := .matchFile(.Dir, , , &.BinaryOnly, )
if != nil {
()
continue
}
if == nil {
} else if == ".go" {
.IgnoredGoFiles = append(.IgnoredGoFiles, )
} else if fileListForExt(, ) != nil {
.IgnoredOtherFiles = append(.IgnoredOtherFiles, )
}
continue
}
, := .header, .name
switch {
= append(, )
continue
default:
if := fileListForExt(, ); != nil {
* = append(*, )
}
continue
}
if .parseErr != nil {
(.parseErr)
continue
}
:= .parsed
:= .Name.Name
if == "documentation" {
.IgnoredGoFiles = append(.IgnoredGoFiles, )
continue
}
:= strings.HasSuffix(, "_test.go")
:= false
if && strings.HasSuffix(, "_test") {
= true
= [:len()-len("_test")]
}
if .Name == "" {
.Name =
=
} else if != .Name {
(&MultiplePackageError{
Dir: .Dir,
Packages: []string{.Name, },
Files: []string{, },
})
.InvalidGoFiles = append(.InvalidGoFiles, )
if .Doc != nil && .Doc == "" && ! && ! {
.Doc = doc.Synopsis(.Doc.Text())
}
if &ImportComment != 0 {
, := findImportComment()
if != 0 {
, := strconv.Unquote()
if != nil {
(fmt.Errorf("%s:%d: cannot parse import comment", , ))
} else if .ImportComment == "" {
.ImportComment =
=
} else if .ImportComment != {
(fmt.Errorf("found import comments %q (%s) and %q (%s) in %s", .ImportComment, , , , .Dir))
}
}
}
:= false
for , := range .imports {
if .path == "C" {
if {
(fmt.Errorf("use of cgo in test %s not supported", ))
continue
}
= true
if .doc != nil {
if := .saveCgo(, , .doc); != nil {
()
}
}
}
}
var *[]string
var , map[string][]token.Position
switch {
case :
["cgo"] = true
if .CgoEnabled {
= &.CgoFiles
=
=
= &.IgnoredGoFiles
}
case :
= &.XTestGoFiles
=
=
case :
= &.TestGoFiles
=
=
default:
= &.GoFiles
=
=
}
* = append(*, )
if != nil {
for , := range .imports {
[.path] = append([.path], .Position(.pos))
}
}
if != nil {
for , := range .embeds {
[.pattern] = append([.pattern], .pos)
}
}
}
for := range {
.AllTags = append(.AllTags, )
}
sort.Strings(.AllTags)
.EmbedPatterns, .EmbedPatternPos = cleanDecls()
.TestEmbedPatterns, .TestEmbedPatternPos = cleanDecls()
.XTestEmbedPatterns, .XTestEmbedPatternPos = cleanDecls()
.Imports, .ImportPos = cleanDecls()
.TestImports, .TestImportPos = cleanDecls()
.XTestImports, .XTestImportPos = cleanDecls()
if len(.CgoFiles) > 0 {
.SFiles = append(.SFiles, ...)
sort.Strings(.SFiles)
} else {
.IgnoredOtherFiles = append(.IgnoredOtherFiles, ...)
sort.Strings(.IgnoredOtherFiles)
}
if != nil {
return ,
}
if len(.GoFiles)+len(.CgoFiles)+len(.TestGoFiles)+len(.XTestGoFiles) == 0 {
return , &NoGoError{.Dir}
}
return ,
}
func ( *Package, string) *[]string {
switch {
case ".c":
return &.CFiles
case ".cc", ".cpp", ".cxx":
return &.CXXFiles
case ".m":
return &.MFiles
case ".h", ".hh", ".hpp", ".hxx":
return &.HFiles
case ".f", ".F", ".for", ".f90":
return &.FFiles
case ".s", ".S", ".sx":
return &.SFiles
case ".swig":
return &.SwigFiles
case ".swigcxx":
return &.SwigCXXFiles
case ".syso":
return &.SysoFiles
}
return nil
}
func ( []string) []string {
if == nil {
return nil
}
:= make([]string, len())
copy(, )
sort.Strings()
:= [:0]
for , := range {
if len() == 0 || [len()-1] != {
= append(, )
}
}
return
}
var errNoModules = errors.New("not using modules")
if &AllowBinary != 0 || &IgnoreVendor != 0 ||
.JoinPath != nil || .SplitPathList != nil || .IsAbsPath != nil || .IsDir != nil || .HasSubdir != nil || .ReadDir != nil || .OpenFile != nil || !equal(.ReleaseTags, defaultReleaseTags) {
return errNoModules
}
:= os.Getenv("GO111MODULE")
switch {
case "off":
return errNoModules
var error
, = filepath.Abs()
if != nil {
return errNoModules
}
}
if , := .hasSubdir(filepath.Join(.GOROOT, "src"), ); {
return errNoModules
}
}
if .GOROOT != "" {
:= .joinPath(.GOROOT, "src", )
if .isDir() {
return errNoModules
}
}
return errNoModules
}
} else {
, = filepath.Abs(.Dir)
break
}
}
:= filepath.Dir()
if len() >= len() {
return errNoModules // reached top of file system, no go.mod
}
=
}
}
:= exec.Command("go", "list", "-e", "-compiler="+.Compiler, "-tags="+strings.Join(.BuildTags, ","), "-installsuffix="+.InstallSuffix, "-f={{.Dir}}\n{{.ImportPath}}\n{{.Root}}\n{{.Goroot}}\n{{if .Error}}{{.Error}}{{end}}\n", "--", )
if .Dir != "" {
.Dir = .Dir
}
var , strings.Builder
.Stdout = &
.Stderr = &
:= "0"
if .CgoEnabled {
= "1"
}
.Env = append(os.Environ(),
"GOOS="+.GOOS,
"GOARCH="+.GOARCH,
"GOROOT="+.GOROOT,
"GOPATH="+.GOPATH,
"CGO_ENABLED="+,
)
if := .Run(); != nil {
return fmt.Errorf("go/build: go list %s: %v\n%s\n", , , .String())
}
:= strings.SplitN(.String(), "\n", 5)
if len() != 5 {
return fmt.Errorf("go/build: importGo %s: unexpected output:\n%s\n", , .String())
}
:= [0]
:= strings.TrimSpace([4])
_, = parseWord()
func ( []byte) []byte {
for len() > 0 {
switch [0] {
case ' ', '\t', '\r', '\n':
= [1:]
continue
case '/':
if bytes.HasPrefix(, slashSlash) {
:= bytes.Index(, newline)
if < 0 {
return nil
}
= [+1:]
continue
}
if bytes.HasPrefix(, slashStar) {
= [2:]
:= bytes.Index(, starSlash)
if < 0 {
return nil
}
= [+2:]
continue
}
}
break
}
return
}
func ( []byte) (, []byte) {
= skipSpaceOrComment()
type fileInfo struct {
name string // full name including dir
header []byte
fset *token.FileSet
parsed *ast.File
parseErr error
imports []fileImport
embeds []fileEmbed
embedErr error
}
type fileImport struct {
path string
pos token.Pos
doc *ast.CommentGroup
}
type fileEmbed struct {
pattern string
pos token.Position
}
return , nil
}
, := .openFile(.name)
if != nil {
return nil,
}
if strings.HasSuffix(, ".go") {
= readGoInfo(, )
if strings.HasSuffix(, "_test.go") {
= nil // ignore //go:binary-only-package comments in _test.go files
}
} else {
= nil // ignore //go:binary-only-package comments in non-Go sources
.header, = readComments()
}
.Close()
if != nil {
return nil, fmt.Errorf("read %s: %v", .name, )
}
, , := .shouldBuild(.header, )
if != nil {
return nil,
}
if ! && !.UseAllFiles {
return nil, nil
}
if != nil && {
* = true
}
return , nil
}
func ( map[string][]token.Position) ([]string, map[string][]token.Position) {
:= make([]string, 0, len())
for := range {
= append(, )
}
sort.Strings()
return ,
}
func ( string, ImportMode) (*Package, error) {
return Default.ImportDir(, )
}
var (
bSlashSlash = []byte(slashSlash)
bStarSlash = []byte(starSlash)
bSlashStar = []byte(slashStar)
goBuildComment = []byte("//go:build")
errGoBuildWithoutBuild = errors.New("//go:build comment without // +build comment")
errMultipleGoBuild = errors.New("multiple //go:build comments") // unused in Go 1.(N-1)
)
func ( []byte) bool {
if !bytes.HasPrefix(, goBuildComment) {
return false
}
= bytes.TrimSpace()
:= [len(goBuildComment):]
return len() == 0 || len(bytes.TrimSpace()) < len()
}
var binaryOnlyComment = []byte("//go:binary-only-package")
, , , := parseFileHeader()
if != nil {
return false, false,
}
:= strings.Fields(string())
if [0] == "+build" {
= true
:= false
for , := range [1:] {
if .match(, ) {
= true
}
}
if ! {
= false
}
}
}
}
if != nil && ! {
return false, false, errGoBuildWithoutBuild
}
return , , nil
}
func ( []byte) (, []byte, bool, error) {
:= 0
:=
:= false // found non-blank, non-// line, so stopped accepting // +build lines
:= false // in /* */ comment
:
for len() > 0 {
:=
if := bytes.IndexByte(, '\n'); >= 0 {
, = [:], [+1:]
} else {
= [len():]
}
= bytes.TrimSpace()
= len() - len()
continue
}
if !bytes.HasPrefix(, slashSlash) { // Not comment line
= true
}
if ! && isGoBuildComment() {
if false && != nil { // enabled in Go 1.N
return nil, nil, false, errMultipleGoBuild
}
=
}
if ! && bytes.Equal(, binaryOnlyComment) {
= true
}
:
for len() > 0 {
if {
if := bytes.Index(, starSlash); >= 0 {
= false
= bytes.TrimSpace([+len(starSlash):])
continue
}
continue
}
if bytes.HasPrefix(, bSlashSlash) {
continue
}
if bytes.HasPrefix(, bSlashStar) {
= true
= bytes.TrimSpace([len(bSlashStar):])
continue
break
}
}
return [:], , , nil
}
:= strings.Fields()
if len() < 1 {
return fmt.Errorf("%s: invalid #cgo line: %s", , )
}
, := [:len()-1], [len()-1]
if len() > 0 {
:= false
for , := range {
if .match(, nil) {
= true
break
}
}
if ! {
continue
}
}
, := splitQuoted()
if != nil {
return fmt.Errorf("%s: invalid #cgo line: %s", , )
}
var bool
for , := range {
if , = expandSrcDir(, .Dir); ! {
return fmt.Errorf("%s: malformed #cgo argument: %s", , )
}
[] =
}
switch {
.makePathsAbsolute(, .Dir)
}
switch {
case "CFLAGS":
.CgoCFLAGS = append(.CgoCFLAGS, ...)
case "CPPFLAGS":
.CgoCPPFLAGS = append(.CgoCPPFLAGS, ...)
case "CXXFLAGS":
.CgoCXXFLAGS = append(.CgoCXXFLAGS, ...)
case "FFLAGS":
.CgoFFLAGS = append(.CgoFFLAGS, ...)
case "LDFLAGS":
.CgoLDFLAGS = append(.CgoLDFLAGS, ...)
case "pkg-config":
.CgoPkgConfig = append(.CgoPkgConfig, ...)
default:
return fmt.Errorf("%s: invalid #cgo verb: %s", , )
}
}
return nil
}
= filepath.ToSlash()
:= strings.Split(, "${SRCDIR}")
if len() < 2 {
return , safeCgoName()
}
:= true
for , := range {
= && ( == "" || safeCgoName())
}
= && ( == "" || safeCgoName())
:= strings.Join(, )
return , && != ""
}
func ( string) ( []string, error) {
var []string
:= make([]rune, len())
:= false
:= false
:= '\x00'
:= 0
for , := range {
switch {
case :
= false
case == '\\':
= true
continue
case != '\x00':
if == {
= '\x00'
continue
}
case == '"' || == '\'':
= true
=
continue
case unicode.IsSpace():
if || > 0 {
= false
= append(, string([:]))
= 0
}
continue
}
[] =
++
}
if || > 0 {
= append(, string([:]))
}
if != 0 {
= errors.New("unclosed quote")
} else if {
= errors.New("unfinished escaping")
}
return ,
}
for , := range .BuildTags {
if == {
return true
}
}
for , := range .ReleaseTags {
if == {
return true
}
}
return false
}
:= strings.Index(, "_")
if < 0 {
return true
}
= [:] // ignore everything before first _
:= strings.Split(, "_")
if := len(); > 0 && [-1] == "test" {
= [:-1]
}
:= len()
if >= 2 && knownOS[[-2]] && knownArch[[-1]] {
return .match([-1], ) && .match([-2], )
}
if >= 1 && (knownOS[[-1]] || knownArch[[-1]]) {
return .match([-1], )
}
return true
}
var knownOS = make(map[string]bool)
var knownArch = make(map[string]bool)
func () {
for , := range strings.Fields(goosList) {
knownOS[] = true
}
for , := range strings.Fields(goarchList) {
knownArch[] = true
}
}
var ToolDir = getToolDir()
![]() |
The pages are generated with Golds v0.3.2-preview. (GOOS=darwin GOARCH=amd64) Golds is a Go 101 project developed by Tapir Liu. PR and bug reports are welcome and can be submitted to the issue list. Please follow @Go100and1 (reachable from the left QR code) to get the latest news of Golds. |