1// Copyright 2011 The Go Authors. All rights reserved.2// Use of this source code is governed by a BSD-style3// license that can be found in the LICENSE file.45// Package load loads packages.6package load78import (9 "bytes"10 "context"11 "encoding/json"12 "errors"13 "fmt"14 "go/build"15 "go/scanner"16 "go/token"17 "internal/godebug"18 "internal/platform"19 "io/fs"20 "os"21 pathpkg "path"22 "path/filepath"23 "runtime"24 "runtime/debug"25 "slices"26 "sort"27 "strconv"28 "strings"29 "time"30 "unicode"31 "unicode/utf8"3233 "cmd/internal/objabi"3435 "cmd/go/internal/base"36 "cmd/go/internal/cfg"37 "cmd/go/internal/fips140"38 "cmd/go/internal/fsys"39 "cmd/go/internal/gover"40 "cmd/go/internal/imports"41 "cmd/go/internal/modfetch"42 "cmd/go/internal/modindex"43 "cmd/go/internal/modinfo"44 "cmd/go/internal/modload"45 "cmd/go/internal/search"46 "cmd/go/internal/str"47 "cmd/go/internal/trace"48 "cmd/go/internal/vcs"49 "cmd/internal/par"50 "cmd/internal/pathcache"51 "cmd/internal/pkgpattern"5253 "golang.org/x/mod/modfile"54 "golang.org/x/mod/module"55)5657// A Package describes a single package found in a directory.58type Package struct {59 PackagePublic // visible in 'go list'60 Internal PackageInternal // for use inside go command only61}6263type PackagePublic struct {64 // Note: These fields are part of the go command's public API.65 // See list.go. It is okay to add fields, but not to change or66 // remove existing ones. Keep in sync with ../list/list.go67 Dir string `json:",omitempty"` // directory containing package sources68 ImportPath string `json:",omitempty"` // import path of package in dir69 ImportComment string `json:",omitempty"` // path in import comment on package statement70 Name string `json:",omitempty"` // package name71 Doc string `json:",omitempty"` // package documentation string72 Target string `json:",omitempty"` // installed target for this package (may be executable)73 Shlib string `json:",omitempty"` // the shared library that contains this package (only set when -linkshared)74 Root string `json:",omitempty"` // Go root, Go path dir, or module root dir containing this package75 ConflictDir string `json:",omitempty"` // Dir is hidden by this other directory76 ForTest string `json:",omitempty"` // package is only for use in named test77 Export string `json:",omitempty"` // file containing export data (set by go list -export)78 BuildID string `json:",omitempty"` // build ID of the compiled package (set by go list -export)79 Module *modinfo.ModulePublic `json:",omitempty"` // info about package's module, if any80 Match []string `json:",omitempty"` // command-line patterns matching this package81 Goroot bool `json:",omitempty"` // is this package found in the Go root?82 Standard bool `json:",omitempty"` // is this package part of the standard Go library?83 DepOnly bool `json:",omitempty"` // package is only as a dependency, not explicitly listed84 BinaryOnly bool `json:",omitempty"` // package cannot be recompiled85 Incomplete bool `json:",omitempty"` // was there an error loading this package or dependencies?8687 DefaultGODEBUG string `json:",omitempty"` // default GODEBUG setting (only for Name=="main")8889 // Stale and StaleReason remain here *only* for the list command.90 // They are only initialized in preparation for list execution.91 // The regular build determines staleness on the fly during action execution.92 Stale bool `json:",omitempty"` // would 'go install' do anything for this package?93 StaleReason string `json:",omitempty"` // why is Stale true?9495 // Source files96 // If you add to this list you MUST add to p.AllFiles (below) too.97 // Otherwise file name security lists will not apply to any new additions.98 GoFiles []string `json:",omitempty"` // .go source files (excluding CgoFiles, TestGoFiles, XTestGoFiles)99 CgoFiles []string `json:",omitempty"` // .go source files that import "C"100 CompiledGoFiles []string `json:",omitempty"` // .go output from running cgo on CgoFiles101 IgnoredGoFiles []string `json:",omitempty"` // .go source files ignored due to build constraints102 InvalidGoFiles []string `json:",omitempty"` // .go source files with detected problems (parse error, wrong package name, and so on)103 IgnoredOtherFiles []string `json:",omitempty"` // non-.go source files ignored due to build constraints104 CFiles []string `json:",omitempty"` // .c source files105 CXXFiles []string `json:",omitempty"` // .cc, .cpp and .cxx source files106 MFiles []string `json:",omitempty"` // .m source files107 HFiles []string `json:",omitempty"` // .h, .hh, .hpp and .hxx source files108 FFiles []string `json:",omitempty"` // .f, .F, .for and .f90 Fortran source files109 SFiles []string `json:",omitempty"` // .s source files110 SwigFiles []string `json:",omitempty"` // .swig files111 SwigCXXFiles []string `json:",omitempty"` // .swigcxx files112 SysoFiles []string `json:",omitempty"` // .syso system object files added to package113114 // Embedded files115 EmbedPatterns []string `json:",omitempty"` // //go:embed patterns116 EmbedFiles []string `json:",omitempty"` // files matched by EmbedPatterns117118 // Cgo directives119 CgoCFLAGS []string `json:",omitempty"` // cgo: flags for C compiler120 CgoCPPFLAGS []string `json:",omitempty"` // cgo: flags for C preprocessor121 CgoCXXFLAGS []string `json:",omitempty"` // cgo: flags for C++ compiler122 CgoFFLAGS []string `json:",omitempty"` // cgo: flags for Fortran compiler123 CgoLDFLAGS []string `json:",omitempty"` // cgo: flags for linker124 CgoPkgConfig []string `json:",omitempty"` // cgo: pkg-config names125126 // Dependency information127 Imports []string `json:",omitempty"` // import paths used by this package128 ImportMap map[string]string `json:",omitempty"` // map from source import to ImportPath (identity entries omitted)129 Deps []string `json:",omitempty"` // all (recursively) imported dependencies130131 // Error information132 // Incomplete is above, packed into the other bools133 Error *PackageError `json:",omitempty"` // error loading this package (not dependencies)134 DepsErrors []*PackageError `json:",omitempty"` // errors loading dependencies, collected by go list before output135136 // Test information137 // If you add to this list you MUST add to p.AllFiles (below) too.138 // Otherwise file name security lists will not apply to any new additions.139 TestGoFiles []string `json:",omitempty"` // _test.go files in package140 TestImports []string `json:",omitempty"` // imports from TestGoFiles141 TestEmbedPatterns []string `json:",omitempty"` // //go:embed patterns142 TestEmbedFiles []string `json:",omitempty"` // files matched by TestEmbedPatterns143 XTestGoFiles []string `json:",omitempty"` // _test.go files outside package144 XTestImports []string `json:",omitempty"` // imports from XTestGoFiles145 XTestEmbedPatterns []string `json:",omitempty"` // //go:embed patterns146 XTestEmbedFiles []string `json:",omitempty"` // files matched by XTestEmbedPatterns147}148149// AllFiles returns the names of all the files considered for the package.150// This is used for sanity and security checks, so we include all files,151// even IgnoredGoFiles, because some subcommands consider them.152// The go/build package filtered others out (like foo_wrongGOARCH.s)153// and that's OK.154func (p *Package) AllFiles() []string {155 files := str.StringList(156 p.GoFiles,157 p.CgoFiles,158 // no p.CompiledGoFiles, because they are from GoFiles or generated by us159 p.IgnoredGoFiles,160 // no p.InvalidGoFiles, because they are from GoFiles161 p.IgnoredOtherFiles,162 p.CFiles,163 p.CXXFiles,164 p.MFiles,165 p.HFiles,166 p.FFiles,167 p.SFiles,168 p.SwigFiles,169 p.SwigCXXFiles,170 p.SysoFiles,171 p.TestGoFiles,172 p.XTestGoFiles,173 )174175 // EmbedFiles may overlap with the other files.176 // Dedup, but delay building the map as long as possible.177 // Only files in the current directory (no slash in name)178 // need to be checked against the files variable above.179 var have map[string]bool180 for _, file := range p.EmbedFiles {181 if !strings.Contains(file, "/") {182 if have == nil {183 have = make(map[string]bool)184 for _, file := range files {185 have[file] = true186 }187 }188 if have[file] {189 continue190 }191 }192 files = append(files, file)193 }194 return files195}196197// Desc returns the package "description", for use in b.showOutput.198func (p *Package) Desc() string {199 if p.ForTest != "" {200 return p.ImportPath + " [" + p.ForTest + ".test]"201 }202 if p.Internal.ForMain != "" {203 return p.ImportPath + " [" + p.Internal.ForMain + "]"204 }205 return p.ImportPath206}207208// IsTestOnly reports whether p is a test-only package.209//210// A “test-only” package is one that:211// - is a test-only variant of an ordinary package, or212// - is a synthesized "main" package for a test binary, or213// - contains only _test.go files.214func (p *Package) IsTestOnly() bool {215 return p.ForTest != "" ||216 p.Internal.TestmainGo != nil ||217 len(p.TestGoFiles)+len(p.XTestGoFiles) > 0 && len(p.GoFiles)+len(p.CgoFiles) == 0218}219220type PackageInternal struct {221 // Unexported fields are not part of the public API.222 Build *build.Package223 Imports []*Package // this package's direct imports224 CompiledImports []string // additional Imports necessary when using CompiledGoFiles (all from standard library); 1:1 with the end of PackagePublic.Imports225 RawImports []string // this package's original imports as they appear in the text of the program; 1:1 with the end of PackagePublic.Imports226 ForceLibrary bool // this package is a library (even if named "main")227 CmdlineFiles bool // package built from files listed on command line228 CmdlinePkg bool // package listed on command line229 CmdlinePkgLiteral bool // package listed as literal on command line (not via wildcard)230 Local bool // imported via local path (./ or ../)231 LocalPrefix string // interpret ./ and ../ imports relative to this prefix232 ExeName string // desired name for temporary executable233 FuzzInstrument bool // package should be instrumented for fuzzing234 Cover CoverSetup // coverage mode and other setup info of -cover is being applied to this package235 OmitDebug bool // tell linker not to write debug information236 GobinSubdir bool // install target would be subdir of GOBIN237 InternalImportOk bool // this package may be imported even though it is internal238 BuildInfo *debug.BuildInfo // add this info to package main239 TestmainGo *[]byte // content for _testmain.go240 Embed map[string][]string // //go:embed comment mapping241 OrigImportPath string // original import path before adding '_test' suffix242 PGOProfile string // path to PGO profile243 ForMain string // the main package if this package is built specifically for it244245 Asmflags []string // -asmflags for this package246 Gcflags []string // -gcflags for this package247 Ldflags []string // -ldflags for this package248 Gccgoflags []string // -gccgoflags for this package249}250251// A NoGoError indicates that no Go files for the package were applicable to the252// build for that package.253//254// That may be because there were no files whatsoever, or because all files were255// excluded, or because all non-excluded files were test sources.256type NoGoError struct {257 Package *Package258}259260func (e *NoGoError) Error() string {261 if len(e.Package.IgnoredGoFiles) > 0 {262 // Go files exist, but they were ignored due to build constraints.263 return "build constraints exclude all Go files in " + e.Package.Dir264 }265 if len(e.Package.TestGoFiles)+len(e.Package.XTestGoFiles) > 0 {266 // Test Go files exist, but we're not interested in them.267 // The double-negative is unfortunate but we want e.Package.Dir268 // to appear at the end of error message.269 return "no non-test Go files in " + e.Package.Dir270 }271 return "no Go files in " + e.Package.Dir272}273274// setLoadPackageDataError presents an error found when loading package data275// as a *PackageError. It has special cases for some common errors to improve276// messages shown to users and reduce redundancy.277//278// setLoadPackageDataError returns true if it's safe to load information about279// imported packages, for example, if there was a parse error loading imports280// in one file, but other files are okay.281func (p *Package) setLoadPackageDataError(err error, path string, stk *ImportStack, importPos []token.Position) {282 matchErr, isMatchErr := err.(*search.MatchError)283 if isMatchErr && matchErr.Match.Pattern() == path {284 if matchErr.Match.IsLiteral() {285 // The error has a pattern has a pattern similar to the import path.286 // It may be slightly different (./foo matching example.com/foo),287 // but close enough to seem redundant.288 // Unwrap the error so we don't show the pattern.289 err = matchErr.Err290 }291 }292293 // Replace (possibly wrapped) *build.NoGoError with *load.NoGoError.294 // The latter is more specific about the cause.295 nogoErr, ok := errors.AsType[*build.NoGoError](err)296 if ok {297 if p.Dir == "" && nogoErr.Dir != "" {298 p.Dir = nogoErr.Dir299 }300 err = &NoGoError{Package: p}301 }302303 // Take only the first error from a scanner.ErrorList. PackageError only304 // has room for one position, so we report the first error with a position305 // instead of all of the errors without a position.306 var pos string307 var isScanErr bool308 if scanErr, ok := err.(scanner.ErrorList); ok && len(scanErr) > 0 {309 isScanErr = true // For stack push/pop below.310311 scanPos := scanErr[0].Pos312 scanPos.Filename = base.ShortPath(scanPos.Filename)313 pos = scanPos.String()314 err = errors.New(scanErr[0].Msg)315 }316317 // Report the error on the importing package if the problem is with the import declaration318 // for example, if the package doesn't exist or if the import path is malformed.319 // On the other hand, don't include a position if the problem is with the imported package,320 // for example there are no Go files (NoGoError), or there's a problem in the imported321 // package's source files themselves (scanner errors).322 //323 // TODO(matloob): Perhaps make each of those the errors in the first group324 // (including modload.ImportMissingError, ImportMissingSumError, and the325 // corresponding "cannot find package %q in any of" GOPATH-mode error326 // produced in build.(*Context).Import; modload.AmbiguousImportError,327 // and modload.PackageNotInModuleError; and the malformed module path errors328 // produced in golang.org/x/mod/module.CheckMod) implement an interface329 // to make it easier to check for them? That would save us from having to330 // move the modload errors into this package to avoid a package import cycle,331 // and from having to export an error type for the errors produced in build.332 if !isMatchErr && (nogoErr != nil || isScanErr) {333 stk.Push(ImportInfo{Pkg: path, Pos: extractFirstImport(importPos)})334 defer stk.Pop()335 }336337 p.Error = &PackageError{338 ImportStack: stk.Copy(),339 Pos: pos,340 Err: err,341 }342 p.Incomplete = true343344 top, ok := stk.Top()345 if ok && path != top.Pkg {346 p.Error.setPos(importPos)347 }348}349350// Resolve returns the resolved version of imports,351// which should be p.TestImports or p.XTestImports, NOT p.Imports.352// The imports in p.TestImports and p.XTestImports are not recursively353// loaded during the initial load of p, so they list the imports found in354// the source file, but most processing should be over the vendor-resolved355// import paths. We do this resolution lazily both to avoid file system work356// and because the eventual real load of the test imports (during 'go test')357// can produce better error messages if it starts with the original paths.358// The initial load of p loads all the non-test imports and rewrites359// the vendored paths, so nothing should ever call p.vendored(p.Imports).360func (p *Package) Resolve(s *modload.Loader, imports []string) []string {361 if len(imports) > 0 && len(p.Imports) > 0 && &imports[0] == &p.Imports[0] {362 panic("internal error: p.Resolve(p.Imports) called")363 }364 seen := make(map[string]bool)365 var all []string366 for _, path := range imports {367 path = ResolveImportPath(s, p, path)368 if !seen[path] {369 seen[path] = true370 all = append(all, path)371 }372 }373 sort.Strings(all)374 return all375}376377// CoverSetup holds parameters related to coverage setup for a given package (covermode, etc).378type CoverSetup struct {379 Mode string // coverage mode for this package380 Cfg string // path to config file to pass to "go tool cover"381 GenMeta bool // ask cover tool to emit a static meta data if set382}383384func (p *Package) copyBuild(opts PackageOpts, pp *build.Package) {385 p.Internal.Build = pp386387 if pp.PkgTargetRoot != "" && cfg.BuildPkgdir != "" {388 old := pp.PkgTargetRoot389 pp.PkgRoot = cfg.BuildPkgdir390 pp.PkgTargetRoot = cfg.BuildPkgdir391 if pp.PkgObj != "" {392 pp.PkgObj = filepath.Join(cfg.BuildPkgdir, strings.TrimPrefix(pp.PkgObj, old))393 }394 }395396 p.Dir = pp.Dir397 p.ImportPath = pp.ImportPath398 p.ImportComment = pp.ImportComment399 p.Name = pp.Name400 p.Doc = pp.Doc401 p.Root = pp.Root402 p.ConflictDir = pp.ConflictDir403 p.BinaryOnly = pp.BinaryOnly404405 // TODO? Target406 p.Goroot = pp.Goroot || fips140.Snapshot() && str.HasFilePathPrefix(p.Dir, fips140.Dir())407 p.Standard = p.Goroot && p.ImportPath != "" && search.IsStandardImportPath(p.ImportPath)408 p.GoFiles = pp.GoFiles409 p.CgoFiles = pp.CgoFiles410 p.IgnoredGoFiles = pp.IgnoredGoFiles411 p.InvalidGoFiles = pp.InvalidGoFiles412 p.IgnoredOtherFiles = pp.IgnoredOtherFiles413 p.CFiles = pp.CFiles414 p.CXXFiles = pp.CXXFiles415 p.MFiles = pp.MFiles416 p.HFiles = pp.HFiles417 p.FFiles = pp.FFiles418 p.SFiles = pp.SFiles419 p.SwigFiles = pp.SwigFiles420 p.SwigCXXFiles = pp.SwigCXXFiles421 p.SysoFiles = pp.SysoFiles422 if cfg.BuildMSan {423 // There's no way for .syso files to be built both with and without424 // support for memory sanitizer. Assume they are built without,425 // and drop them.426 p.SysoFiles = nil427 }428 p.CgoCFLAGS = pp.CgoCFLAGS429 p.CgoCPPFLAGS = pp.CgoCPPFLAGS430 p.CgoCXXFLAGS = pp.CgoCXXFLAGS431 p.CgoFFLAGS = pp.CgoFFLAGS432 p.CgoLDFLAGS = pp.CgoLDFLAGS433 p.CgoPkgConfig = pp.CgoPkgConfig434 // We modify p.Imports in place, so make copy now.435 p.Imports = make([]string, len(pp.Imports))436 copy(p.Imports, pp.Imports)437 p.Internal.RawImports = pp.Imports438 p.TestGoFiles = pp.TestGoFiles439 p.TestImports = pp.TestImports440 p.XTestGoFiles = pp.XTestGoFiles441 p.XTestImports = pp.XTestImports442 if opts.IgnoreImports {443 p.Imports = nil444 p.Internal.RawImports = nil445 p.TestImports = nil446 p.XTestImports = nil447 }448 p.EmbedPatterns = pp.EmbedPatterns449 p.TestEmbedPatterns = pp.TestEmbedPatterns450 p.XTestEmbedPatterns = pp.XTestEmbedPatterns451 p.Internal.OrigImportPath = pp.ImportPath452}453454// A PackageError describes an error loading information about a package.455type PackageError struct {456 ImportStack ImportStack // shortest path from package named on command line to this one with position457 Pos string // position of error458 Err error // the error itself459 IsImportCycle bool // the error is an import cycle460 alwaysPrintStack bool // whether to always print the ImportStack461}462463func (p *PackageError) Error() string {464 // TODO(#43696): decide when to print the stack or the position based on465 // the error type and whether the package is in the main module.466 // Document the rationale.467 if p.Pos != "" && (len(p.ImportStack) == 0 || !p.alwaysPrintStack) {468 // Omit import stack. The full path to the file where the error469 // is the most important thing.470 return p.Pos + ": " + p.Err.Error()471 }472473 // If the error is an ImportPathError, and the last path on the stack appears474 // in the error message, omit that path from the stack to avoid repetition.475 // If an ImportPathError wraps another ImportPathError that matches the476 // last path on the stack, we don't omit the path. An error like477 // "package A imports B: error loading C caused by B" would not be clearer478 // if "imports B" were omitted.479 if len(p.ImportStack) == 0 {480 return p.Err.Error()481 }482 var optpos string483 if p.Pos != "" {484 optpos = "\n\t" + p.Pos485 }486 imports := p.ImportStack.Pkgs()487 if p.IsImportCycle {488 imports = p.ImportStack.PkgsWithPos()489 }490 return "package " + strings.Join(imports, "\n\timports ") + optpos + ": " + p.Err.Error()491}492493func (p *PackageError) Unwrap() error { return p.Err }494495// PackageError implements MarshalJSON so that Err is marshaled as a string496// and non-essential fields are omitted.497func (p *PackageError) MarshalJSON() ([]byte, error) {498 perr := struct {499 ImportStack []string // use []string for package names500 Pos string501 Err string502 }{p.ImportStack.Pkgs(), p.Pos, p.Err.Error()}503 return json.Marshal(perr)504}505506func (p *PackageError) setPos(posList []token.Position) {507 if len(posList) == 0 {508 return509 }510 pos := posList[0]511 pos.Filename = base.ShortPath(pos.Filename)512 p.Pos = pos.String()513}514515// ImportPathError is a type of error that prevents a package from being loaded516// for a given import path. When such a package is loaded, a *Package is517// returned with Err wrapping an ImportPathError: the error is attached to518// the imported package, not the importing package.519//520// The string returned by ImportPath must appear in the string returned by521// Error. Errors that wrap ImportPathError (such as PackageError) may omit522// the import path.523type ImportPathError interface {524 error525 ImportPath() string526}527528var (529 _ ImportPathError = (*importError)(nil)530 _ ImportPathError = (*mainPackageError)(nil)531 _ ImportPathError = (*modload.ImportMissingError)(nil)532 _ ImportPathError = (*modload.ImportMissingSumError)(nil)533 _ ImportPathError = (*modload.DirectImportFromImplicitDependencyError)(nil)534)535536type importError struct {537 importPath string538 err error // created with fmt.Errorf539}540541func ImportErrorf(path, format string, args ...any) ImportPathError {542 err := &importError{importPath: path, err: fmt.Errorf(format, args...)}543 if errStr := err.Error(); !strings.Contains(errStr, path) && !strings.Contains(errStr, strconv.Quote(path)) {544 panic(fmt.Sprintf("path %q not in error %q", path, errStr))545 }546 return err547}548549func (e *importError) Error() string {550 return e.err.Error()551}552553func (e *importError) Unwrap() error {554 // Don't return e.err directly, since we're only wrapping an error if %w555 // was passed to ImportErrorf.556 return errors.Unwrap(e.err)557}558559func (e *importError) ImportPath() string {560 return e.importPath561}562563type ImportInfo struct {564 Pkg string565 Pos *token.Position566}567568// An ImportStack is a stack of import paths, possibly with the suffix " (test)" appended.569// The import path of a test package is the import path of the corresponding570// non-test package with the suffix "_test" added.571type ImportStack []ImportInfo572573func NewImportInfo(pkg string, pos *token.Position) ImportInfo {574 return ImportInfo{Pkg: pkg, Pos: pos}575}576577func (s *ImportStack) Push(p ImportInfo) {578 *s = append(*s, p)579}580581func (s *ImportStack) Pop() {582 *s = (*s)[0 : len(*s)-1]583}584585func (s *ImportStack) Copy() ImportStack {586 return slices.Clone(*s)587}588589func (s *ImportStack) Pkgs() []string {590 ss := make([]string, 0, len(*s))591 for _, v := range *s {592 ss = append(ss, v.Pkg)593 }594 return ss595}596597func (s *ImportStack) PkgsWithPos() []string {598 ss := make([]string, 0, len(*s))599 for _, v := range *s {600 if v.Pos != nil {601 ss = append(ss, v.Pkg+" from "+filepath.Base(v.Pos.Filename))602 } else {603 ss = append(ss, v.Pkg)604 }605 }606 return ss607}608609func (s *ImportStack) Top() (ImportInfo, bool) {610 if len(*s) == 0 {611 return ImportInfo{}, false612 }613 return (*s)[len(*s)-1], true614}615616// shorterThan reports whether sp is shorter than t.617// We use this to record the shortest import sequence618// that leads to a particular package.619func (sp *ImportStack) shorterThan(t []string) bool {620 s := *sp621 if len(s) != len(t) {622 return len(s) < len(t)623 }624 // If they are the same length, settle ties using string ordering.625 for i := range s {626 siPkg := s[i].Pkg627 if siPkg != t[i] {628 return siPkg < t[i]629 }630 }631 return false // they are equal632}633634// packageCache is a lookup cache for LoadImport,635// so that if we look up a package multiple times636// we return the same pointer each time.637//638// TODO: associate the packageCache with the module loader state, so that639// different module loaders use different caches.640var packageCache = map[string]*Package{}641642// ClearPackageCache clears the package cache.643// It cannot be used concurrently with calls to LoadImport or other functions644// that use packageCache without synchronization.645func ClearPackageCache() {646 clear(packageCache)647}648649// dirToImportPath returns the pseudo-import path we use for a package650// outside the Go path. It begins with _/ and then contains the full path651// to the directory. If the package lives in c:\home\gopher\my\pkg then652// the pseudo-import path is _/c_/home/gopher/my/pkg.653// Using a pseudo-import path like this makes the ./ imports no longer654// a special case, so that all the code to deal with ordinary imports works655// automatically.656func dirToImportPath(dir string) string {657 return pathpkg.Join("_", strings.Map(makeImportValid, filepath.ToSlash(dir)))658}659660func makeImportValid(r rune) rune {661 // Should match Go spec, compilers, and ../../go/parser/parser.go:/isValidImport.662 const illegalChars = `!"#$%&'()*,:;<=>?[\]^{|}` + "`\uFFFD"663 if !unicode.IsGraphic(r) || unicode.IsSpace(r) || strings.ContainsRune(illegalChars, r) {664 return '_'665 }666 return r667}668669// Mode flags for loadImport and download (in get.go).670const (671 // ResolveImport means that loadImport should do import path expansion.672 // That is, ResolveImport means that the import path came from673 // a source file and has not been expanded yet to account for674 // vendoring or possible module adjustment.675 // Every import path should be loaded initially with ResolveImport,676 // and then the expanded version (for example with the /vendor/ in it)677 // gets recorded as the canonical import path. At that point, future loads678 // of that package must not pass ResolveImport, because679 // disallowVendor will reject direct use of paths containing /vendor/.680 ResolveImport = 1 << iota681682 // ResolveModule is for download (part of "go get") and indicates683 // that the module adjustment should be done, but not vendor adjustment.684 ResolveModule685686 // GetTestDeps is for download (part of "go get") and indicates687 // that test dependencies should be fetched too.688 GetTestDeps689690 // The remainder are internal modes for calls to loadImport.691692 // cmdlinePkg is for a package mentioned on the command line.693 cmdlinePkg694695 // cmdlinePkgLiteral is for a package mentioned on the command line696 // without using any wildcards or meta-patterns.697 cmdlinePkgLiteral698699 // allow simd/internal/bridge700 allowSimdInternalBridge701)702703// LoadPackage does Load import, but without a parent package load context704func LoadPackage(ld *modload.Loader, ctx context.Context, opts PackageOpts, path, srcDir string, stk *ImportStack, importPos []token.Position, mode int) *Package {705 p, err := loadImport(ld, ctx, opts, nil, path, srcDir, nil, stk, importPos, mode)706 if err != nil {707 base.Fatalf("internal error: loadImport of %q with nil parent returned an error", path)708 }709 return p710}711712// loadImport scans the directory named by path, which must be an import path,713// but possibly a local import path (an absolute file system path or one beginning714// with ./ or ../). A local relative path is interpreted relative to srcDir.715// It returns a *Package describing the package found in that directory.716// loadImport does not set tool flags and should only be used by717// this package, as part of a bigger load operation.718// The returned PackageError, if any, describes why parent is not allowed719// to import the named package, with the error referring to importPos.720// The PackageError can only be non-nil when parent is not nil.721func loadImport(ld *modload.Loader, ctx context.Context, opts PackageOpts, pre *preload, path, srcDir string, parent *Package, stk *ImportStack, importPos []token.Position, mode int) (*Package, *PackageError) {722 ctx, span := trace.StartSpan(ctx, "modload.loadImport "+path)723 defer span.Done()724725 if path == "" {726 panic("LoadImport called with empty package path")727 }728729 var parentPath, parentRoot string730 parentIsStd := false731 if parent != nil {732 parentPath = parent.ImportPath733 parentRoot = parent.Root734 parentIsStd = parent.Standard735 }736 bp, loaded, err := loadPackageData(ld, ctx, path, parentPath, srcDir, parentRoot, parentIsStd, mode)737 if loaded && pre != nil && !opts.IgnoreImports {738 pre.preloadImports(ld, ctx, opts, bp.Imports, bp)739 }740 if bp == nil {741 p := &Package{742 PackagePublic: PackagePublic{743 ImportPath: path,744 Incomplete: true,745 },746 }747 if importErr, ok := err.(ImportPathError); !ok || importErr.ImportPath() != path {748 // Only add path to the error's import stack if it's not already present749 // in the error.750 //751 // TODO(bcmills): setLoadPackageDataError itself has a similar Push / Pop752 // sequence that empirically doesn't trigger for these errors, guarded by753 // a somewhat complex condition. Figure out how to generalize that754 // condition and eliminate the explicit calls here.755 stk.Push(ImportInfo{Pkg: path, Pos: extractFirstImport(importPos)})756 defer stk.Pop()757 }758 p.setLoadPackageDataError(err, path, stk, nil)759 setToolFlags(ld, p)760 return p, nil761 }762763 setCmdline := func(p *Package) {764 if mode&cmdlinePkg != 0 {765 p.Internal.CmdlinePkg = true766 }767 if mode&cmdlinePkgLiteral != 0 {768 p.Internal.CmdlinePkgLiteral = true769 }770 }771772 importPath := bp.ImportPath773 p := packageCache[importPath]774 if p != nil {775 stk.Push(ImportInfo{Pkg: path, Pos: extractFirstImport(importPos)})776 p = reusePackage(p, stk)777 stk.Pop()778 setCmdline(p)779 } else {780 p = new(Package)781 p.Internal.Local = build.IsLocalImport(path)782 p.ImportPath = importPath783 packageCache[importPath] = p784785 setCmdline(p)786 setToolFlags(ld, p)787788 // Load package.789 // loadPackageData may return bp != nil even if an error occurs,790 // in order to return partial information.791 p.load(ld, ctx, opts, path, stk, importPos, bp, err)792793 if !cfg.ModulesEnabled && path != cleanImport(path) {794 p.Error = &PackageError{795 ImportStack: stk.Copy(),796 Err: ImportErrorf(path, "non-canonical import path %q: should be %q", path, pathpkg.Clean(path)),797 }798 p.Incomplete = true799 p.Error.setPos(importPos)800 }801 }802803 if mode&allowSimdInternalBridge == 0 || path != SimdBridgePkg { // Special case for just this import.804 // Checked on every import because the rules depend on the code doing the importing.805 if perr := disallowInternal(ld, ctx, srcDir, parent, parentPath, p, stk); perr != nil {806 perr.setPos(importPos)807 return p, perr808 }809 }810 if mode&ResolveImport != 0 {811 if perr := disallowVendor(srcDir, path, parentPath, p, stk); perr != nil {812 perr.setPos(importPos)813 return p, perr814 }815 }816817 if p.Name == "main" && parent != nil && parent.Dir != p.Dir {818 perr := &PackageError{819 ImportStack: stk.Copy(),820 Err: ImportErrorf(path, "import %q is a program, not an importable package", path),821 }822 perr.setPos(importPos)823 return p, perr824 }825826 if p.Internal.Local && parent != nil && !parent.Internal.Local {827 var err error828 if path == "." {829 err = ImportErrorf(path, "%s: cannot import current directory", path)830 } else {831 err = ImportErrorf(path, "local import %q in non-local package", path)832 }833 perr := &PackageError{834 ImportStack: stk.Copy(),835 Err: err,836 }837 perr.setPos(importPos)838 return p, perr839 }840841 return p, nil842}843844func extractFirstImport(importPos []token.Position) *token.Position {845 if len(importPos) == 0 {846 return nil847 }848 return &importPos[0]849}850851// loadPackageData loads information needed to construct a *Package. The result852// is cached, and later calls to loadPackageData for the same package will return853// the same data.854//855// loadPackageData returns a non-nil package even if err is non-nil unless856// the package path is malformed (for example, the path contains "mod/" or "@").857//858// loadPackageData returns a boolean, loaded, which is true if this is the859// first time the package was loaded. Callers may preload imports in this case.860func loadPackageData(ld *modload.Loader, ctx context.Context, path, parentPath, parentDir, parentRoot string, parentIsStd bool, mode int) (bp *build.Package, loaded bool, err error) {861 ctx, span := trace.StartSpan(ctx, "load.loadPackageData "+path)862 defer span.Done()863864 if path == "" {865 panic("loadPackageData called with empty package path")866 }867868 if strings.HasPrefix(path, "mod/") {869 // Paths beginning with "mod/" might accidentally870 // look in the module cache directory tree in $GOPATH/pkg/mod/.871 // This prefix is owned by the Go core for possible use in the872 // standard library (since it does not begin with a domain name),873 // so it's OK to disallow entirely.874 return nil, false, fmt.Errorf("disallowed import path %q", path)875 }876877 if strings.Contains(path, "@") {878 return nil, false, errors.New("can only use path@version syntax with 'go get' and 'go install' in module-aware mode")879 }880881 // Determine canonical package path and directory.882 // For a local import the identifier is the pseudo-import path883 // we create from the full directory to the package.884 // Otherwise it is the usual import path.885 // For vendored imports, it is the expanded form.886 //887 // Note that when modules are enabled, local import paths are normally888 // canonicalized by modload.LoadPackages before now. However, if there's an889 // error resolving a local path, it will be returned untransformed890 // so that 'go list -e' reports something useful.891 importKey := importSpec{892 path: path,893 parentPath: parentPath,894 parentDir: parentDir,895 parentRoot: parentRoot,896 parentIsStd: parentIsStd,897 mode: mode,898 }899 r := resolvedImportCache.Do(importKey, func() resolvedImport {900 var r resolvedImport901 if newPath, dir, ok := fips140.ResolveImport(path); ok {902 r.path = newPath903 r.dir = dir904 } else if cfg.ModulesEnabled {905 r.dir, r.path, r.err = modload.Lookup(ld, parentPath, parentIsStd, path)906 } else if build.IsLocalImport(path) {907 r.dir = filepath.Join(parentDir, path)908 r.path = dirToImportPath(r.dir)909 } else if mode&ResolveImport != 0 {910 // We do our own path resolution, because we want to911 // find out the key to use in packageCache without the912 // overhead of repeated calls to buildContext.Import.913 // The code is also needed in a few other places anyway.914 r.path = resolveImportPath(ld, path, parentPath, parentDir, parentRoot, parentIsStd)915 } else if mode&ResolveModule != 0 {916 r.path = moduleImportPath(path, parentPath, parentDir, parentRoot)917 }918 if r.path == "" {919 r.path = path920 }921 return r922 })923 // Invariant: r.path is set to the resolved import path. If the path cannot924 // be resolved, r.path is set to path, the source import path.925 // r.path is never empty.926927 // Load the package from its directory. If we already found the package's928 // directory when resolving its import path, use that.929 p, err := packageDataCache.Do(r.path, func() (*build.Package, error) {930 loaded = true931 var data struct {932 p *build.Package933 err error934 }935 if r.dir != "" {936 var buildMode build.ImportMode937 buildContext := cfg.BuildContext938 if !cfg.ModulesEnabled {939 buildMode = build.ImportComment940 } else {941 buildContext.GOPATH = "" // Clear GOPATH so packages are imported as pure module packages942 }943 modroot := modload.PackageModRoot(ld, ctx, r.path)944 if modroot == "" && str.HasFilePathPrefix(r.dir, cfg.GOROOTsrc) {945 modroot = cfg.GOROOTsrc946 gorootSrcCmd := filepath.Join(cfg.GOROOTsrc, "cmd")947 if str.HasFilePathPrefix(r.dir, gorootSrcCmd) {948 modroot = gorootSrcCmd949 }950 }951 if modroot != "" {952 if rp, err := modindex.GetPackage(modroot, r.dir); err == nil {953 data.p, data.err = rp.Import(cfg.BuildContext, buildMode)954 goto Happy955 } else if !errors.Is(err, modindex.ErrNotIndexed) {956 base.Fatal(err)957 }958 }959 data.p, data.err = buildContext.ImportDir(r.dir, buildMode)960 Happy:961 if cfg.ModulesEnabled {962 // Override data.p.Root, since ImportDir sets it to $GOPATH, if963 // the module is inside $GOPATH/src.964 if info := modload.PackageModuleInfo(ld, ctx, path); info != nil {965 data.p.Root = info.Dir966 }967 }968 if r.err != nil {969 if data.err != nil {970 // ImportDir gave us one error, and the module loader gave us another.971 // We arbitrarily choose to keep the error from ImportDir because972 // that's what our tests already expect, and it seems to provide a bit973 // more detail in most cases.974 } else if errors.Is(r.err, imports.ErrNoGo) {975 // ImportDir said there were files in the package, but the module976 // loader said there weren't. Which one is right?977 // Without this special-case hack, the TestScript/test_vet case fails978 // on the vetfail/p1 package (added in CL 83955).979 // Apparently, imports.ShouldBuild biases toward rejecting files980 // with invalid build constraints, whereas ImportDir biases toward981 // accepting them.982 //983 // TODO(#41410: Figure out how this actually ought to work and fix984 // this mess).985 } else {986 data.err = r.err987 }988 }989 } else if r.err != nil {990 data.p = new(build.Package)991 data.err = r.err992 } else if cfg.ModulesEnabled && path != "unsafe" {993 data.p = new(build.Package)994 data.err = fmt.Errorf("unknown import path %q: internal error: module loader did not resolve import", r.path)995 } else {996 buildMode := build.ImportComment997 if mode&ResolveImport == 0 || r.path != path {998 // Not vendoring, or we already found the vendored path.999 buildMode |= build.IgnoreVendor1000 }1001 data.p, data.err = cfg.BuildContext.Import(r.path, parentDir, buildMode)1002 }1003 data.p.ImportPath = r.path10041005 // Set data.p.BinDir in cases where go/build.Context.Import1006 // may give us a path we don't want.1007 if !data.p.Goroot {1008 if cfg.GOBIN != "" {1009 data.p.BinDir = cfg.GOBIN1010 } else if cfg.ModulesEnabled {1011 data.p.BinDir = modload.BinDir(ld)1012 }1013 }10141015 if !cfg.ModulesEnabled && data.err == nil &&1016 data.p.ImportComment != "" && data.p.ImportComment != path &&1017 !strings.Contains(path, "/vendor/") && !strings.HasPrefix(path, "vendor/") {1018 data.err = fmt.Errorf("code in directory %s expects import %q", data.p.Dir, data.p.ImportComment)1019 }1020 return data.p, data.err1021 })10221023 return p, loaded, err1024}10251026// importSpec describes an import declaration in source code. It is used as a1027// cache key for resolvedImportCache.1028type importSpec struct {1029 path string1030 parentPath, parentDir, parentRoot string1031 parentIsStd bool1032 mode int1033}10341035// resolvedImport holds a canonical identifier for a package. It may also contain1036// a path to the package's directory and an error if one occurred. resolvedImport1037// is the value type in resolvedImportCache.1038type resolvedImport struct {1039 path, dir string1040 err error1041}10421043// resolvedImportCache maps import strings to canonical package names.1044var resolvedImportCache par.Cache[importSpec, resolvedImport]10451046// packageDataCache maps canonical package names (string) to package metadata.1047var packageDataCache par.ErrCache[string, *build.Package]10481049// preloadWorkerCount is the number of concurrent goroutines that can load1050// packages. Experimentally, there are diminishing returns with more than1051// 4 workers. This was measured on the following machines.1052//1053// * MacBookPro with a 4-core Intel Core i7 CPU1054// * Linux workstation with 6-core Intel Xeon CPU1055// * Linux workstation with 24-core Intel Xeon CPU1056//1057// It is very likely (though not confirmed) that this workload is limited1058// by memory bandwidth. We don't have a good way to determine the number of1059// workers that would saturate the bus though, so runtime.GOMAXPROCS1060// seems like a reasonable default.1061var preloadWorkerCount = runtime.GOMAXPROCS(0)10621063// preload holds state for managing concurrent preloading of package data.1064//1065// A preload should be created with newPreload before loading a large1066// package graph. flush must be called when package loading is complete1067// to ensure preload goroutines are no longer active. This is necessary1068// because of global mutable state that cannot safely be read and written1069// concurrently. In particular, packageDataCache may be cleared by "go get"1070// in GOPATH mode, and modload.loaded (accessed via modload.Lookup) may be1071// modified by modload.LoadPackages.1072type preload struct {1073 cancel chan struct{}1074 sema chan struct{}1075}10761077// newPreload creates a new preloader. flush must be called later to avoid1078// accessing global state while it is being modified.1079func newPreload() *preload {1080 pre := &preload{1081 cancel: make(chan struct{}),1082 sema: make(chan struct{}, preloadWorkerCount),1083 }1084 return pre1085}10861087// preloadMatches loads data for package paths matched by patterns.1088// When preloadMatches returns, some packages may not be loaded yet, but1089// loadPackageData and loadImport are always safe to call.1090func (pre *preload) preloadMatches(ld *modload.Loader, ctx context.Context, opts PackageOpts, matches []*search.Match) {1091 for _, m := range matches {1092 for _, pkg := range m.Pkgs {1093 select {1094 case <-pre.cancel:1095 return1096 case pre.sema <- struct{}{}:1097 go func(pkg string) {1098 mode := 0 // don't use vendoring or module import resolution1099 bp, loaded, err := loadPackageData(ld, ctx, pkg, "", base.Cwd(), "", false, mode)1100 <-pre.sema1101 if bp != nil && loaded && err == nil && !opts.IgnoreImports {1102 pre.preloadImports(ld, ctx, opts, bp.Imports, bp)1103 }1104 }(pkg)1105 }1106 }1107 }1108}11091110// preloadImports queues a list of imports for preloading.1111// When preloadImports returns, some packages may not be loaded yet,1112// but loadPackageData and loadImport are always safe to call.1113func (pre *preload) preloadImports(ld *modload.Loader, ctx context.Context, opts PackageOpts, imports []string, parent *build.Package) {1114 parentIsStd := parent.Goroot && parent.ImportPath != "" && search.IsStandardImportPath(parent.ImportPath)1115 for _, path := range imports {1116 if path == "C" || path == "unsafe" {1117 continue1118 }1119 select {1120 case <-pre.cancel:1121 return1122 case pre.sema <- struct{}{}:1123 go func(path string) {1124 bp, loaded, err := loadPackageData(ld, ctx, path, parent.ImportPath, parent.Dir, parent.Root, parentIsStd, ResolveImport)1125 <-pre.sema1126 if bp != nil && loaded && err == nil && !opts.IgnoreImports {1127 pre.preloadImports(ld, ctx, opts, bp.Imports, bp)1128 }1129 }(path)1130 }1131 }1132}11331134// flush stops pending preload operations. flush blocks until preload calls to1135// loadPackageData have completed. The preloader will not make any new calls1136// to loadPackageData.1137func (pre *preload) flush() {1138 // flush is usually deferred.1139 // Don't hang program waiting for workers on panic.1140 if v := recover(); v != nil {1141 panic(v)1142 }11431144 close(pre.cancel)1145 for i := 0; i < preloadWorkerCount; i++ {1146 pre.sema <- struct{}{}1147 }1148}11491150func cleanImport(path string) string {1151 orig := path1152 path = pathpkg.Clean(path)1153 if strings.HasPrefix(orig, "./") && path != ".." && !strings.HasPrefix(path, "../") {1154 path = "./" + path1155 }1156 return path1157}11581159var isDirCache par.Cache[string, bool]11601161func isDir(path string) bool {1162 return isDirCache.Do(path, func() bool {1163 fi, err := fsys.Stat(path)1164 return err == nil && fi.IsDir()1165 })1166}11671168// ResolveImportPath returns the true meaning of path when it appears in parent.1169// There are two different resolutions applied.1170// First, there is Go 1.5 vendoring (golang.org/s/go15vendor).1171// If vendor expansion doesn't trigger, then the path is also subject to1172// Go 1.11 module legacy conversion (golang.org/issue/25069).1173func ResolveImportPath(s *modload.Loader, parent *Package, path string) (found string) {1174 var parentPath, parentDir, parentRoot string1175 parentIsStd := false1176 if parent != nil {1177 parentPath = parent.ImportPath1178 parentDir = parent.Dir1179 parentRoot = parent.Root1180 parentIsStd = parent.Standard1181 }1182 return resolveImportPath(s, path, parentPath, parentDir, parentRoot, parentIsStd)1183}11841185func resolveImportPath(s *modload.Loader, path, parentPath, parentDir, parentRoot string, parentIsStd bool) (found string) {1186 if cfg.ModulesEnabled {1187 if _, p, e := modload.Lookup(s, parentPath, parentIsStd, path); e == nil {1188 return p1189 }1190 return path1191 }1192 found = vendoredImportPath(path, parentPath, parentDir, parentRoot)1193 if found != path {1194 return found1195 }1196 return moduleImportPath(path, parentPath, parentDir, parentRoot)1197}11981199// dirAndRoot returns the source directory and workspace root1200// for the package p, guaranteeing that root is a path prefix of dir.1201func dirAndRoot(path string, dir, root string) (string, string) {1202 origDir, origRoot := dir, root1203 dir = filepath.Clean(dir)1204 root = filepath.Join(root, "src")1205 if !str.HasFilePathPrefix(dir, root) || path != "command-line-arguments" && filepath.Join(root, path) != dir {1206 // Look for symlinks before reporting error.1207 dir = expandPath(dir)1208 root = expandPath(root)1209 }12101211 if !str.HasFilePathPrefix(dir, root) || len(dir) <= len(root) || dir[len(root)] != filepath.Separator || path != "command-line-arguments" && !build.IsLocalImport(path) && filepath.Join(root, path) != dir {1212 debug.PrintStack()1213 base.Fatalf("unexpected directory layout:\n"+1214 " import path: %s\n"+1215 " root: %s\n"+1216 " dir: %s\n"+1217 " expand root: %s\n"+1218 " expand dir: %s\n"+1219 " separator: %s",1220 path,1221 filepath.Join(origRoot, "src"),1222 filepath.Clean(origDir),1223 origRoot,1224 origDir,1225 string(filepath.Separator))1226 }12271228 return dir, root1229}12301231// vendoredImportPath returns the vendor-expansion of path when it appears in parent.1232// If parent is x/y/z, then path might expand to x/y/z/vendor/path, x/y/vendor/path,1233// x/vendor/path, vendor/path, or else stay path if none of those exist.1234// vendoredImportPath returns the expanded path or, if no expansion is found, the original.1235func vendoredImportPath(path, parentPath, parentDir, parentRoot string) (found string) {1236 if parentRoot == "" {1237 return path1238 }12391240 dir, root := dirAndRoot(parentPath, parentDir, parentRoot)12411242 vpath := "vendor/" + path1243 for i := len(dir); i >= len(root); i-- {1244 if i < len(dir) && dir[i] != filepath.Separator {1245 continue1246 }1247 // Note: checking for the vendor directory before checking1248 // for the vendor/path directory helps us hit the1249 // isDir cache more often. It also helps us prepare a more useful1250 // list of places we looked, to report when an import is not found.1251 if !isDir(filepath.Join(dir[:i], "vendor")) {1252 continue1253 }1254 targ := filepath.Join(dir[:i], vpath)1255 if isDir(targ) && hasGoFiles(targ) {1256 importPath := parentPath1257 if importPath == "command-line-arguments" {1258 // If parent.ImportPath is 'command-line-arguments'.1259 // set to relative directory to root (also chopped root directory)1260 importPath = dir[len(root)+1:]1261 }1262 // We started with parent's dir c:\gopath\src\foo\bar\baz\quux\xyzzy.1263 // We know the import path for parent's dir.1264 // We chopped off some number of path elements and1265 // added vendor\path to produce c:\gopath\src\foo\bar\baz\vendor\path.1266 // Now we want to know the import path for that directory.1267 // Construct it by chopping the same number of path elements1268 // (actually the same number of bytes) from parent's import path1269 // and then append /vendor/path.1270 chopped := len(dir) - i1271 if chopped == len(importPath)+1 {1272 // We walked up from c:\gopath\src\foo\bar1273 // and found c:\gopath\src\vendor\path.1274 // We chopped \foo\bar (length 8) but the import path is "foo/bar" (length 7).1275 // Use "vendor/path" without any prefix.1276 return vpath1277 }1278 return importPath[:len(importPath)-chopped] + "/" + vpath1279 }1280 }1281 return path1282}12831284var (1285 modulePrefix = []byte("\nmodule ")1286 goModPathCache par.Cache[string, string]1287)12881289// goModPath returns the module path in the go.mod in dir, if any.1290func goModPath(dir string) (path string) {1291 return goModPathCache.Do(dir, func() string {1292 data, err := os.ReadFile(filepath.Join(dir, "go.mod"))1293 if err != nil {1294 return ""1295 }1296 var i int1297 if bytes.HasPrefix(data, modulePrefix[1:]) {1298 i = 01299 } else {1300 i = bytes.Index(data, modulePrefix)1301 if i < 0 {1302 return ""1303 }1304 i++1305 }1306 line := data[i:]13071308 // Cut line at \n, drop trailing \r if present.1309 if j := bytes.IndexByte(line, '\n'); j >= 0 {1310 line = line[:j]1311 }1312 if line[len(line)-1] == '\r' {1313 line = line[:len(line)-1]1314 }1315 line = line[len("module "):]13161317 // If quoted, unquote.1318 path = strings.TrimSpace(string(line))1319 if path != "" && path[0] == '"' {1320 s, err := strconv.Unquote(path)1321 if err != nil {1322 return ""1323 }1324 path = s1325 }1326 return path1327 })1328}13291330// findVersionElement returns the slice indices of the final version element /vN in path.1331// If there is no such element, it returns -1, -1.1332func findVersionElement(path string) (i, j int) {1333 j = len(path)1334 for i = len(path) - 1; i >= 0; i-- {1335 if path[i] == '/' {1336 if isVersionElement(path[i+1 : j]) {1337 return i, j1338 }1339 j = i1340 }1341 }1342 return -1, -11343}13441345// isVersionElement reports whether s is a well-formed path version element:1346// v2, v3, v10, etc, but not v0, v05, v1.1347func isVersionElement(s string) bool {1348 if len(s) < 2 || s[0] != 'v' || s[1] == '0' || s[1] == '1' && len(s) == 2 {1349 return false1350 }1351 for i := 1; i < len(s); i++ {1352 if s[i] < '0' || '9' < s[i] {1353 return false1354 }1355 }1356 return true1357}13581359// moduleImportPath translates import paths found in go modules1360// back down to paths that can be resolved in ordinary builds.1361//1362// Define “new” code as code with a go.mod file in the same directory1363// or a parent directory. If an import in new code says x/y/v2/z but1364// x/y/v2/z does not exist and x/y/go.mod says “module x/y/v2”,1365// then go build will read the import as x/y/z instead.1366// See golang.org/issue/25069.1367func moduleImportPath(path, parentPath, parentDir, parentRoot string) (found string) {1368 if parentRoot == "" {1369 return path1370 }13711372 // If there are no vN elements in path, leave it alone.1373 // (The code below would do the same, but only after1374 // some other file system accesses that we can avoid1375 // here by returning early.)1376 if i, _ := findVersionElement(path); i < 0 {1377 return path1378 }13791380 dir, root := dirAndRoot(parentPath, parentDir, parentRoot)13811382 // Consider dir and parents, up to and including root.1383 for i := len(dir); i >= len(root); i-- {1384 if i < len(dir) && dir[i] != filepath.Separator {1385 continue1386 }1387 if goModPath(dir[:i]) != "" {1388 goto HaveGoMod1389 }1390 }1391 // This code is not in a tree with a go.mod,1392 // so apply no changes to the path.1393 return path13941395HaveGoMod:1396 // This import is in a tree with a go.mod.1397 // Allow it to refer to code in GOPATH/src/x/y/z as x/y/v2/z1398 // if GOPATH/src/x/y/go.mod says module "x/y/v2",13991400 // If x/y/v2/z exists, use it unmodified.1401 if bp, _ := cfg.BuildContext.Import(path, "", build.IgnoreVendor); bp.Dir != "" {1402 return path1403 }14041405 // Otherwise look for a go.mod supplying a version element.1406 // Some version-like elements may appear in paths but not1407 // be module versions; we skip over those to look for module1408 // versions. For example the module m/v2 might have a1409 // package m/v2/api/v1/foo.1410 limit := len(path)1411 for limit > 0 {1412 i, j := findVersionElement(path[:limit])1413 if i < 0 {1414 return path1415 }1416 if bp, _ := cfg.BuildContext.Import(path[:i], "", build.IgnoreVendor); bp.Dir != "" {1417 if mpath := goModPath(bp.Dir); mpath != "" {1418 // Found a valid go.mod file, so we're stopping the search.1419 // If the path is m/v2/p and we found m/go.mod that says1420 // "module m/v2", then we return "m/p".1421 if mpath == path[:j] {1422 return path[:i] + path[j:]1423 }1424 // Otherwise just return the original path.1425 // We didn't find anything worth rewriting,1426 // and the go.mod indicates that we should1427 // not consider parent directories.1428 return path1429 }1430 }1431 limit = i1432 }1433 return path1434}14351436// hasGoFiles reports whether dir contains any files with names ending in .go.1437// For a vendor check we must exclude directories that contain no .go files.1438// Otherwise it is not possible to vendor just a/b/c and still import the1439// non-vendored a/b. See golang.org/issue/13832.1440func hasGoFiles(dir string) bool {1441 files, _ := os.ReadDir(dir)1442 for _, f := range files {1443 if !f.IsDir() && strings.HasSuffix(f.Name(), ".go") {1444 return true1445 }1446 }1447 return false1448}14491450// reusePackage reuses package p to satisfy the import at the top1451// of the import stack stk. If this use causes an import loop,1452// reusePackage updates p's error information to record the loop.1453func reusePackage(p *Package, stk *ImportStack) *Package {1454 // We use p.Internal.Imports==nil to detect a package that1455 // is in the midst of its own loadPackage call1456 // (all the recursion below happens before p.Internal.Imports gets set).1457 if p.Internal.Imports == nil {1458 if p.Error == nil {1459 p.Error = &PackageError{1460 ImportStack: stk.Copy(),1461 Err: errors.New("import cycle not allowed"),1462 IsImportCycle: true,1463 }1464 } else if !p.Error.IsImportCycle {1465 // If the error is already set, but it does not indicate that1466 // we are in an import cycle, set IsImportCycle so that we don't1467 // end up stuck in a loop down the road.1468 p.Error.IsImportCycle = true1469 }1470 p.Incomplete = true1471 }1472 // Don't rewrite the import stack in the error if we have an import cycle.1473 // If we do, we'll lose the path that describes the cycle.1474 if p.Error != nil && p.Error.ImportStack != nil &&1475 !p.Error.IsImportCycle && stk.shorterThan(p.Error.ImportStack.Pkgs()) {1476 p.Error.ImportStack = stk.Copy()1477 }1478 return p1479}14801481// disallowInternal checks that srcDir (containing package importerPath, if non-empty)1482// is allowed to import p.1483// If the import is allowed, disallowInternal returns the original package p.1484// If not, it returns a new package containing just an appropriate error.1485func disallowInternal(ld *modload.Loader, ctx context.Context, srcDir string, importer *Package, importerPath string, p *Package, stk *ImportStack) *PackageError {1486 // golang.org/s/go14internal:1487 // An import of a path containing the element “internal”1488 // is disallowed if the importing code is outside the tree1489 // rooted at the parent of the “internal” directory.14901491 // There was an error loading the package; stop here.1492 if p.Error != nil {1493 return nil1494 }14951496 // The generated 'testmain' package is allowed to access testing/internal/...,1497 // as if it were generated into the testing directory tree1498 // (it's actually in a temporary directory outside any Go tree).1499 // This cleans up a former kludge in passing functionality to the testing package.1500 if str.HasPathPrefix(p.ImportPath, "testing/internal") && importerPath == "testmain" {1501 return nil1502 }15031504 // We can't check standard packages with gccgo.1505 if cfg.BuildContext.Compiler == "gccgo" && p.Standard {1506 return nil1507 }15081509 // The sort package depends on internal/reflectlite, but during bootstrap1510 // the path rewriting causes the normal internal checks to fail.1511 // Instead, just ignore the internal rules during bootstrap.1512 if p.Standard && strings.HasPrefix(importerPath, "bootstrap/") {1513 return nil1514 }15151516 // importerPath is empty: we started1517 // with a name given on the command line, not an1518 // import. Anything listed on the command line is fine.1519 if importerPath == "" {1520 return nil1521 }15221523 // Check for "internal" element: three cases depending on begin of string and/or end of string.1524 i, ok := findInternal(p.ImportPath)1525 if !ok {1526 return nil1527 }15281529 // Internal is present.1530 // Map import path back to directory corresponding to parent of internal.1531 if i > 0 {1532 i-- // rewind over slash in ".../internal"1533 }15341535 // FIPS-140 snapshots are special, because they comes from a non-GOROOT1536 // directory, so the usual directory rules don't work apply, or rather they1537 // apply differently depending on whether we are using a snapshot or the1538 // in-tree copy of the code. We apply a consistent rule here:1539 // crypto/internal/fips140 can only see crypto/internal, never top-of-tree internal.1540 // Similarly, crypto/... can see crypto/internal/fips140 even though the usual rules1541 // would not allow it in snapshot mode.1542 if str.HasPathPrefix(importerPath, "crypto") && str.HasPathPrefix(p.ImportPath, "crypto/internal/fips140") {1543 return nil // crypto can use crypto/internal/fips1401544 }1545 if str.HasPathPrefix(importerPath, "crypto/internal/fips140") {1546 if str.HasPathPrefix(p.ImportPath, "crypto/internal") {1547 return nil // crypto/internal/fips140 can use crypto/internal1548 }1549 goto Error1550 }15511552 if p.Module == nil {1553 parent := p.Dir[:i+len(p.Dir)-len(p.ImportPath)]15541555 if str.HasFilePathPrefix(filepath.Clean(srcDir), filepath.Clean(parent)) {1556 return nil1557 }15581559 // Look for symlinks before reporting error.1560 srcDir = expandPath(srcDir)1561 parent = expandPath(parent)1562 if str.HasFilePathPrefix(filepath.Clean(srcDir), filepath.Clean(parent)) {1563 return nil1564 }1565 } else {1566 // p is in a module, so make it available based on the importer's import path instead1567 // of the file path (https://golang.org/issue/23970).1568 if importer.Internal.CmdlineFiles {1569 // The importer is a list of command-line files.1570 // Pretend that the import path is the import path of the1571 // directory containing them.1572 // If the directory is outside the main modules, this will resolve to ".",1573 // which is not a prefix of any valid module.1574 importerPath, _ = ld.MainModules.DirImportPath(ld, ctx, importer.Dir)1575 }1576 parentOfInternal := p.ImportPath[:i]1577 if str.HasPathPrefix(importerPath, parentOfInternal) {1578 return nil1579 }1580 }15811582Error:1583 // Internal is present, and srcDir is outside parent's tree. Not allowed.1584 perr := &PackageError{1585 alwaysPrintStack: true,1586 ImportStack: stk.Copy(),1587 Err: ImportErrorf(p.ImportPath, "use of internal package %s not allowed", p.ImportPath),1588 }1589 return perr1590}15911592// findInternal looks for the final "internal" path element in the given import path.1593// If there isn't one, findInternal returns ok=false.1594// Otherwise, findInternal returns ok=true and the index of the "internal".1595func findInternal(path string) (index int, ok bool) {1596 // Three cases, depending on internal at start/end of string or not.1597 // The order matters: we must return the index of the final element,1598 // because the final one produces the most restrictive requirement1599 // on the importer.1600 switch {1601 case strings.HasSuffix(path, "/internal"):1602 return len(path) - len("internal"), true1603 case strings.Contains(path, "/internal/"):1604 return strings.LastIndex(path, "/internal/") + 1, true1605 case path == "internal", strings.HasPrefix(path, "internal/"):1606 return 0, true1607 }1608 return 0, false1609}16101611// disallowVendor checks that srcDir is allowed to import p as path.1612// If the import is allowed, disallowVendor returns the original package p.1613// If not, it returns a PackageError.1614func disallowVendor(srcDir string, path string, importerPath string, p *Package, stk *ImportStack) *PackageError {1615 // If the importerPath is empty, we started1616 // with a name given on the command line, not an1617 // import. Anything listed on the command line is fine.1618 if importerPath == "" {1619 return nil1620 }16211622 if perr := disallowVendorVisibility(srcDir, p, importerPath, stk); perr != nil {1623 return perr1624 }16251626 // Paths like x/vendor/y must be imported as y, never as x/vendor/y.1627 if i, ok := FindVendor(path); ok {1628 perr := &PackageError{1629 ImportStack: stk.Copy(),1630 Err: ImportErrorf(path, "%s must be imported as %s", path, path[i+len("vendor/"):]),1631 }1632 return perr1633 }16341635 return nil1636}16371638// disallowVendorVisibility checks that srcDir is allowed to import p.1639// The rules are the same as for /internal/ except that a path ending in /vendor1640// is not subject to the rules, only subdirectories of vendor.1641// This allows people to have packages and commands named vendor,1642// for maximal compatibility with existing source trees.1643func disallowVendorVisibility(srcDir string, p *Package, importerPath string, stk *ImportStack) *PackageError {1644 // The stack does not include p.ImportPath.1645 // If there's nothing on the stack, we started1646 // with a name given on the command line, not an1647 // import. Anything listed on the command line is fine.1648 if importerPath == "" {1649 return nil1650 }16511652 // Check for "vendor" element.1653 i, ok := FindVendor(p.ImportPath)1654 if !ok {1655 return nil1656 }16571658 // Vendor is present.1659 // Map import path back to directory corresponding to parent of vendor.1660 if i > 0 {1661 i-- // rewind over slash in ".../vendor"1662 }1663 truncateTo := i + len(p.Dir) - len(p.ImportPath)1664 if truncateTo < 0 || len(p.Dir) < truncateTo {1665 return nil1666 }1667 parent := p.Dir[:truncateTo]1668 if str.HasFilePathPrefix(filepath.Clean(srcDir), filepath.Clean(parent)) {1669 return nil1670 }16711672 // Look for symlinks before reporting error.1673 srcDir = expandPath(srcDir)1674 parent = expandPath(parent)1675 if str.HasFilePathPrefix(filepath.Clean(srcDir), filepath.Clean(parent)) {1676 return nil1677 }16781679 // Vendor is present, and srcDir is outside parent's tree. Not allowed.16801681 perr := &PackageError{1682 ImportStack: stk.Copy(),1683 Err: errors.New("use of vendored package not allowed"),1684 }1685 return perr1686}16871688// FindVendor looks for the last non-terminating "vendor" path element in the given import path.1689// If there isn't one, FindVendor returns ok=false.1690// Otherwise, FindVendor returns ok=true and the index of the "vendor".1691//1692// Note that terminating "vendor" elements don't count: "x/vendor" is its own package,1693// not the vendored copy of an import "" (the empty import path).1694// This will allow people to have packages or commands named vendor.1695// This may help reduce breakage, or it may just be confusing. We'll see.1696func FindVendor(path string) (index int, ok bool) {1697 // Two cases, depending on internal at start of string or not.1698 // The order matters: we must return the index of the final element,1699 // because the final one is where the effective import path starts.1700 switch {1701 case strings.Contains(path, "/vendor/"):1702 return strings.LastIndex(path, "/vendor/") + 1, true1703 case strings.HasPrefix(path, "vendor/"):1704 return 0, true1705 }1706 return 0, false1707}17081709type TargetDir int17101711const (1712 ToTool TargetDir = iota // to GOROOT/pkg/tool (default for cmd/*)1713 ToBin // to bin dir inside package root (default for non-cmd/*)1714 StalePath // an old import path; fail to build1715)17161717// InstallTargetDir reports the target directory for installing the command p.1718func InstallTargetDir(p *Package) TargetDir {1719 if strings.HasPrefix(p.ImportPath, "code.google.com/p/go.tools/cmd/") {1720 return StalePath1721 }1722 if p.Goroot && strings.HasPrefix(p.ImportPath, "cmd/") && p.Name == "main" {1723 switch p.ImportPath {1724 case "cmd/go", "cmd/gofmt":1725 return ToBin1726 }1727 return ToTool1728 }1729 return ToBin1730}17311732var cgoExclude = map[string]bool{1733 "runtime/cgo": true,1734}17351736var cgoSyscallExclude = map[string]bool{1737 "runtime/cgo": true,1738 "runtime/race": true,1739 "runtime/msan": true,1740 "runtime/asan": true,1741}17421743var foldPath = make(map[string]string)17441745// exeFromImportPath returns an executable name1746// for a package using the import path.1747//1748// The executable name is the last element of the import path.1749// In module-aware mode, an additional rule is used on import paths1750// consisting of two or more path elements. If the last element is1751// a vN path element specifying the major version, then the1752// second last element of the import path is used instead.1753func (p *Package) exeFromImportPath() string {1754 _, elem := pathpkg.Split(p.ImportPath)1755 if cfg.ModulesEnabled {1756 // If this is example.com/mycmd/v2, it's more useful to1757 // install it as mycmd than as v2. See golang.org/issue/24667.1758 if elem != p.ImportPath && isVersionElement(elem) {1759 _, elem = pathpkg.Split(pathpkg.Dir(p.ImportPath))1760 }1761 }1762 return elem1763}17641765// exeFromFiles returns an executable name for a package1766// using the first element in GoFiles or CgoFiles collections without the prefix.1767//1768// Returns empty string in case of empty collection.1769func (p *Package) exeFromFiles() string {1770 var src string1771 if len(p.GoFiles) > 0 {1772 src = p.GoFiles[0]1773 } else if len(p.CgoFiles) > 0 {1774 src = p.CgoFiles[0]1775 } else {1776 return ""1777 }1778 _, elem := filepath.Split(src)1779 return elem[:len(elem)-len(".go")]1780}17811782// DefaultExecName returns the default executable name for a package1783func (p *Package) DefaultExecName() string {1784 if p.Internal.CmdlineFiles {1785 return p.exeFromFiles()1786 }1787 return p.exeFromImportPath()1788}17891790// The package used for rewriting "simd"1791const SimdBridgePkg = "simd/internal/bridge"17921793// hasSimd encodes the conditions under which the presence/absence of1794// imports of "simd" is interesting, i.e., if there is intrinsic1795// support, and hence some rewriting of AST to use the intrinsics.1796// This is used for both build and test (and perhaps in other contexts to1797// be discovered later).1798func hasSimd(imports []string) (hasSimd bool) {1799 if cfg.BuildContext.GOARCH == "wasm" || cfg.BuildContext.GOARCH == "amd64" || cfg.BuildContext.GOARCH == "arm64" {1800 for _, imp := range imports {1801 if imp == "simd" {1802 hasSimd = true1803 }1804 }1805 }1806 return1807}18081809// load populates p using information from bp, err, which should1810// be the result of calling build.Context.Import.1811// stk contains the import stack, not including path itself.1812func (p *Package) load(ld *modload.Loader, ctx context.Context, opts PackageOpts, path string, stk *ImportStack, importPos []token.Position, bp *build.Package, err error) {1813 p.copyBuild(opts, bp)18141815 // The localPrefix is the path we interpret ./ imports relative to,1816 // if we support them at all (not in module mode!).1817 // Synthesized main packages sometimes override this.1818 if p.Internal.Local && !cfg.ModulesEnabled {1819 p.Internal.LocalPrefix = dirToImportPath(p.Dir)1820 }18211822 // setError sets p.Error if it hasn't already been set. We may proceed1823 // after encountering some errors so that 'go list -e' has more complete1824 // output. If there's more than one error, we should report the first.1825 setError := func(err error) {1826 if p.Error == nil {1827 p.Error = &PackageError{1828 ImportStack: stk.Copy(),1829 Err: err,1830 }1831 p.Incomplete = true18321833 // Add the importer's position information if the import position exists, and1834 // the current package being examined is the importer.1835 // If we have not yet accepted package p onto the import stack,1836 // then the cause of the error is not within p itself: the error1837 // must be either in an explicit command-line argument,1838 // or on the importer side (indicated by a non-empty importPos).1839 top, ok := stk.Top()1840 if ok && path != top.Pkg && len(importPos) > 0 {1841 p.Error.setPos(importPos)1842 }1843 }1844 }18451846 if err != nil {1847 p.Incomplete = true1848 p.setLoadPackageDataError(err, path, stk, importPos)1849 }18501851 useBindir := p.Name == "main"1852 if !p.Standard {1853 switch cfg.BuildBuildmode {1854 case "c-archive", "c-shared", "plugin":1855 useBindir = false1856 }1857 }18581859 if useBindir {1860 // Report an error when the old code.google.com/p/go.tools paths are used.1861 if InstallTargetDir(p) == StalePath {1862 // TODO(matloob): remove this branch, and StalePath itself. code.google.com/p/go is so1863 // old, even this code checking for it is stale now!1864 newPath := strings.Replace(p.ImportPath, "code.google.com/p/go.", "golang.org/x/", 1)1865 e := ImportErrorf(p.ImportPath, "the %v command has moved; use %v instead.", p.ImportPath, newPath)1866 setError(e)1867 return1868 }1869 elem := p.DefaultExecName() + cfg.ExeSuffix1870 full := filepath.Join(cfg.BuildContext.GOOS+"_"+cfg.BuildContext.GOARCH, elem)1871 if cfg.BuildContext.GOOS != runtime.GOOS || cfg.BuildContext.GOARCH != runtime.GOARCH {1872 // Install cross-compiled binaries to subdirectories of bin.1873 elem = full1874 }1875 if p.Internal.Build.BinDir == "" && cfg.ModulesEnabled {1876 p.Internal.Build.BinDir = modload.BinDir(ld)1877 }1878 if p.Internal.Build.BinDir != "" {1879 // Install to GOBIN or bin of GOPATH entry.1880 p.Target = filepath.Join(p.Internal.Build.BinDir, elem)1881 if !p.Goroot && strings.Contains(elem, string(filepath.Separator)) && cfg.GOBIN != "" {1882 // Do not create $GOBIN/goos_goarch/elem.1883 p.Target = ""1884 p.Internal.GobinSubdir = true1885 }1886 }1887 if InstallTargetDir(p) == ToTool {1888 // This is for 'go tool'.1889 // Override all the usual logic and force it into the tool directory.1890 if cfg.BuildToolchainName == "gccgo" {1891 p.Target = filepath.Join(build.ToolDir, elem)1892 } else {1893 p.Target = filepath.Join(cfg.GOROOTpkg, "tool", full)1894 }1895 }1896 } else if p.Internal.Local {1897 // Local import turned into absolute path.1898 // No permanent install target.1899 p.Target = ""1900 } else if p.Standard && cfg.BuildContext.Compiler == "gccgo" {1901 // gccgo has a preinstalled standard library that cmd/go cannot rebuild.1902 p.Target = ""1903 } else {1904 p.Target = p.Internal.Build.PkgObj1905 if cfg.BuildBuildmode == "shared" && p.Internal.Build.PkgTargetRoot != "" {1906 // TODO(matloob): This shouldn't be necessary, but the cmd/cgo/internal/testshared1907 // test fails without Target set for this condition. Figure out why and1908 // fix it.1909 p.Target = filepath.Join(p.Internal.Build.PkgTargetRoot, p.ImportPath+".a")1910 }1911 if cfg.BuildLinkshared && p.Internal.Build.PkgTargetRoot != "" {1912 // TODO(bcmills): The reliance on PkgTargetRoot implies that -linkshared does1913 // not work for any package that lacks a PkgTargetRoot — such as a non-main1914 // package in module mode. We should probably fix that.1915 targetPrefix := filepath.Join(p.Internal.Build.PkgTargetRoot, p.ImportPath)1916 p.Target = targetPrefix + ".a"1917 shlibnamefile := targetPrefix + ".shlibname"1918 shlib, err := os.ReadFile(shlibnamefile)1919 if err != nil && !os.IsNotExist(err) {1920 base.Fatalf("reading shlibname: %v", err)1921 }1922 if err == nil {1923 libname := strings.TrimSpace(string(shlib))1924 if cfg.BuildContext.Compiler == "gccgo" {1925 p.Shlib = filepath.Join(p.Internal.Build.PkgTargetRoot, "shlibs", libname)1926 } else {1927 p.Shlib = filepath.Join(p.Internal.Build.PkgTargetRoot, libname)1928 }1929 }1930 }1931 }19321933 // Build augmented import list to add implicit dependencies.1934 // Be careful not to add imports twice, just to avoid confusion.1935 importPaths := p.Imports1936 addImport := func(path string, forCompiler bool) {1937 for _, p := range importPaths {1938 if path == p {1939 return1940 }1941 }1942 importPaths = append(importPaths, path)1943 if forCompiler {1944 p.Internal.CompiledImports = append(p.Internal.CompiledImports, path)1945 }1946 }19471948 allowInternalSimdImport := 01949 if hasSimd := hasSimd(p.Imports); hasSimd {1950 addImport(SimdBridgePkg, true)1951 allowInternalSimdImport = allowSimdInternalBridge1952 }19531954 if !opts.IgnoreImports {1955 // Cgo translation adds imports of "unsafe", "runtime/cgo" and "syscall",1956 // except for certain packages, to avoid circular dependencies.1957 if p.UsesCgo() {1958 addImport("unsafe", true)1959 }1960 if p.UsesCgo() && (!p.Standard || !cgoExclude[p.ImportPath]) && cfg.BuildContext.Compiler != "gccgo" {1961 addImport("runtime/cgo", true)1962 }1963 if p.UsesCgo() && (!p.Standard || !cgoSyscallExclude[p.ImportPath]) {1964 addImport("syscall", true)1965 }19661967 // SWIG adds imports of some standard packages.1968 if p.UsesSwig() {1969 addImport("unsafe", true)1970 if cfg.BuildContext.Compiler != "gccgo" {1971 addImport("runtime/cgo", true)1972 }1973 addImport("syscall", true)1974 addImport("sync", true)19751976 // TODO: The .swig and .swigcxx files can use1977 // %go_import directives to import other packages.1978 }19791980 // The linker loads implicit dependencies.1981 if p.Name == "main" && !p.Internal.ForceLibrary {1982 ldDeps, err := LinkerDeps(ld, p)1983 if err != nil {1984 setError(err)1985 return1986 }1987 for _, dep := range ldDeps {1988 addImport(dep, false)1989 }1990 }1991 }19921993 // Check for case-insensitive collisions of import paths.1994 // If modifying, consider changing checkPathCollisions() in1995 // src/cmd/go/internal/modcmd/vendor.go1996 fold := str.ToFold(p.ImportPath)1997 if other := foldPath[fold]; other == "" {1998 foldPath[fold] = p.ImportPath1999 } else if other != p.ImportPath {2000 setError(ImportErrorf(p.ImportPath, "case-insensitive import collision: %q and %q", p.ImportPath, other))
Findings
✓ No findings reported for this file.