1
2
3
4
5
6 package load
7
8 import (
9 "bytes"
10 "context"
11 "crypto/sha256"
12 "encoding/json"
13 "errors"
14 "fmt"
15 "go/build"
16 "go/scanner"
17 "go/token"
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"
32
33 "cmd/go/internal/base"
34 "cmd/go/internal/cfg"
35 "cmd/go/internal/fsys"
36 "cmd/go/internal/gover"
37 "cmd/go/internal/imports"
38 "cmd/go/internal/modfetch"
39 "cmd/go/internal/modindex"
40 "cmd/go/internal/modinfo"
41 "cmd/go/internal/modload"
42 "cmd/go/internal/search"
43 "cmd/go/internal/str"
44 "cmd/go/internal/trace"
45 "cmd/go/internal/vcs"
46 "cmd/internal/par"
47 "cmd/internal/pathcache"
48 "cmd/internal/pkgpattern"
49
50 "golang.org/x/mod/modfile"
51 "golang.org/x/mod/module"
52 )
53
54
55 type Package struct {
56 PackagePublic
57 Internal PackageInternal
58 }
59
60 type PackagePublic struct {
61
62
63
64 Dir string `json:",omitempty"`
65 ImportPath string `json:",omitempty"`
66 ImportComment string `json:",omitempty"`
67 Name string `json:",omitempty"`
68 Doc string `json:",omitempty"`
69 Target string `json:",omitempty"`
70 Shlib string `json:",omitempty"`
71 Root string `json:",omitempty"`
72 ConflictDir string `json:",omitempty"`
73 ForTest string `json:",omitempty"`
74 Export string `json:",omitempty"`
75 BuildID string `json:",omitempty"`
76 Module *modinfo.ModulePublic `json:",omitempty"`
77 Match []string `json:",omitempty"`
78 Goroot bool `json:",omitempty"`
79 Standard bool `json:",omitempty"`
80 DepOnly bool `json:",omitempty"`
81 BinaryOnly bool `json:",omitempty"`
82 Incomplete bool `json:",omitempty"`
83
84 DefaultGODEBUG string `json:",omitempty"`
85
86
87
88
89 Stale bool `json:",omitempty"`
90 StaleReason string `json:",omitempty"`
91
92
93
94
95 GoFiles []string `json:",omitempty"`
96 CgoFiles []string `json:",omitempty"`
97 CompiledGoFiles []string `json:",omitempty"`
98 IgnoredGoFiles []string `json:",omitempty"`
99 InvalidGoFiles []string `json:",omitempty"`
100 IgnoredOtherFiles []string `json:",omitempty"`
101 CFiles []string `json:",omitempty"`
102 CXXFiles []string `json:",omitempty"`
103 MFiles []string `json:",omitempty"`
104 HFiles []string `json:",omitempty"`
105 FFiles []string `json:",omitempty"`
106 SFiles []string `json:",omitempty"`
107 SwigFiles []string `json:",omitempty"`
108 SwigCXXFiles []string `json:",omitempty"`
109 SysoFiles []string `json:",omitempty"`
110
111
112 EmbedPatterns []string `json:",omitempty"`
113 EmbedFiles []string `json:",omitempty"`
114
115
116 CgoCFLAGS []string `json:",omitempty"`
117 CgoCPPFLAGS []string `json:",omitempty"`
118 CgoCXXFLAGS []string `json:",omitempty"`
119 CgoFFLAGS []string `json:",omitempty"`
120 CgoLDFLAGS []string `json:",omitempty"`
121 CgoPkgConfig []string `json:",omitempty"`
122
123
124 Imports []string `json:",omitempty"`
125 ImportMap map[string]string `json:",omitempty"`
126 Deps []string `json:",omitempty"`
127
128
129
130 Error *PackageError `json:",omitempty"`
131 DepsErrors []*PackageError `json:",omitempty"`
132
133
134
135
136 TestGoFiles []string `json:",omitempty"`
137 TestImports []string `json:",omitempty"`
138 TestEmbedPatterns []string `json:",omitempty"`
139 TestEmbedFiles []string `json:",omitempty"`
140 XTestGoFiles []string `json:",omitempty"`
141 XTestImports []string `json:",omitempty"`
142 XTestEmbedPatterns []string `json:",omitempty"`
143 XTestEmbedFiles []string `json:",omitempty"`
144 }
145
146
147
148
149
150
151 func (p *Package) AllFiles() []string {
152 files := str.StringList(
153 p.GoFiles,
154 p.CgoFiles,
155
156 p.IgnoredGoFiles,
157
158 p.IgnoredOtherFiles,
159 p.CFiles,
160 p.CXXFiles,
161 p.MFiles,
162 p.HFiles,
163 p.FFiles,
164 p.SFiles,
165 p.SwigFiles,
166 p.SwigCXXFiles,
167 p.SysoFiles,
168 p.TestGoFiles,
169 p.XTestGoFiles,
170 )
171
172
173
174
175
176 var have map[string]bool
177 for _, file := range p.EmbedFiles {
178 if !strings.Contains(file, "/") {
179 if have == nil {
180 have = make(map[string]bool)
181 for _, file := range files {
182 have[file] = true
183 }
184 }
185 if have[file] {
186 continue
187 }
188 }
189 files = append(files, file)
190 }
191 return files
192 }
193
194
195 func (p *Package) Desc() string {
196 if p.ForTest != "" {
197 return p.ImportPath + " [" + p.ForTest + ".test]"
198 }
199 if p.Internal.ForMain != "" {
200 return p.ImportPath + " [" + p.Internal.ForMain + "]"
201 }
202 return p.ImportPath
203 }
204
205
206
207
208
209
210
211 func (p *Package) IsTestOnly() bool {
212 return p.ForTest != "" ||
213 p.Internal.TestmainGo != nil ||
214 len(p.TestGoFiles)+len(p.XTestGoFiles) > 0 && len(p.GoFiles)+len(p.CgoFiles) == 0
215 }
216
217 type PackageInternal struct {
218
219 Build *build.Package
220 Imports []*Package
221 CompiledImports []string
222 RawImports []string
223 ForceLibrary bool
224 CmdlineFiles bool
225 CmdlinePkg bool
226 CmdlinePkgLiteral bool
227 Local bool
228 LocalPrefix string
229 ExeName string
230 FuzzInstrument bool
231 Cover CoverSetup
232 CoverVars map[string]*CoverVar
233 OmitDebug bool
234 GobinSubdir bool
235 BuildInfo *debug.BuildInfo
236 TestmainGo *[]byte
237 Embed map[string][]string
238 OrigImportPath string
239 PGOProfile string
240 ForMain string
241
242 Asmflags []string
243 Gcflags []string
244 Ldflags []string
245 Gccgoflags []string
246 }
247
248
249
250
251
252
253 type NoGoError struct {
254 Package *Package
255 }
256
257 func (e *NoGoError) Error() string {
258 if len(e.Package.IgnoredGoFiles) > 0 {
259
260 return "build constraints exclude all Go files in " + e.Package.Dir
261 }
262 if len(e.Package.TestGoFiles)+len(e.Package.XTestGoFiles) > 0 {
263
264
265
266 return "no non-test Go files in " + e.Package.Dir
267 }
268 return "no Go files in " + e.Package.Dir
269 }
270
271
272
273
274
275
276
277
278 func (p *Package) setLoadPackageDataError(err error, path string, stk *ImportStack, importPos []token.Position) {
279 matchErr, isMatchErr := err.(*search.MatchError)
280 if isMatchErr && matchErr.Match.Pattern() == path {
281 if matchErr.Match.IsLiteral() {
282
283
284
285
286 err = matchErr.Err
287 }
288 }
289
290
291
292 var nogoErr *build.NoGoError
293 if errors.As(err, &nogoErr) {
294 if p.Dir == "" && nogoErr.Dir != "" {
295 p.Dir = nogoErr.Dir
296 }
297 err = &NoGoError{Package: p}
298 }
299
300
301
302
303 var pos string
304 var isScanErr bool
305 if scanErr, ok := err.(scanner.ErrorList); ok && len(scanErr) > 0 {
306 isScanErr = true
307
308 scanPos := scanErr[0].Pos
309 scanPos.Filename = base.ShortPath(scanPos.Filename)
310 pos = scanPos.String()
311 err = errors.New(scanErr[0].Msg)
312 }
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329 if !isMatchErr && (nogoErr != nil || isScanErr) {
330 stk.Push(ImportInfo{Pkg: path, Pos: extractFirstImport(importPos)})
331 defer stk.Pop()
332 }
333
334 p.Error = &PackageError{
335 ImportStack: stk.Copy(),
336 Pos: pos,
337 Err: err,
338 }
339 p.Incomplete = true
340
341 top, ok := stk.Top()
342 if ok && path != top.Pkg {
343 p.Error.setPos(importPos)
344 }
345 }
346
347
348
349
350
351
352
353
354
355
356
357 func (p *Package) Resolve(imports []string) []string {
358 if len(imports) > 0 && len(p.Imports) > 0 && &imports[0] == &p.Imports[0] {
359 panic("internal error: p.Resolve(p.Imports) called")
360 }
361 seen := make(map[string]bool)
362 var all []string
363 for _, path := range imports {
364 path = ResolveImportPath(p, path)
365 if !seen[path] {
366 seen[path] = true
367 all = append(all, path)
368 }
369 }
370 sort.Strings(all)
371 return all
372 }
373
374
375 type CoverVar struct {
376 File string
377 Var string
378 }
379
380
381 type CoverSetup struct {
382 Mode string
383 Cfg string
384 GenMeta bool
385 }
386
387 func (p *Package) copyBuild(opts PackageOpts, pp *build.Package) {
388 p.Internal.Build = pp
389
390 if pp.PkgTargetRoot != "" && cfg.BuildPkgdir != "" {
391 old := pp.PkgTargetRoot
392 pp.PkgRoot = cfg.BuildPkgdir
393 pp.PkgTargetRoot = cfg.BuildPkgdir
394 if pp.PkgObj != "" {
395 pp.PkgObj = filepath.Join(cfg.BuildPkgdir, strings.TrimPrefix(pp.PkgObj, old))
396 }
397 }
398
399 p.Dir = pp.Dir
400 p.ImportPath = pp.ImportPath
401 p.ImportComment = pp.ImportComment
402 p.Name = pp.Name
403 p.Doc = pp.Doc
404 p.Root = pp.Root
405 p.ConflictDir = pp.ConflictDir
406 p.BinaryOnly = pp.BinaryOnly
407
408
409 p.Goroot = pp.Goroot
410 p.Standard = p.Goroot && p.ImportPath != "" && search.IsStandardImportPath(p.ImportPath)
411 p.GoFiles = pp.GoFiles
412 p.CgoFiles = pp.CgoFiles
413 p.IgnoredGoFiles = pp.IgnoredGoFiles
414 p.InvalidGoFiles = pp.InvalidGoFiles
415 p.IgnoredOtherFiles = pp.IgnoredOtherFiles
416 p.CFiles = pp.CFiles
417 p.CXXFiles = pp.CXXFiles
418 p.MFiles = pp.MFiles
419 p.HFiles = pp.HFiles
420 p.FFiles = pp.FFiles
421 p.SFiles = pp.SFiles
422 p.SwigFiles = pp.SwigFiles
423 p.SwigCXXFiles = pp.SwigCXXFiles
424 p.SysoFiles = pp.SysoFiles
425 if cfg.BuildMSan {
426
427
428
429 p.SysoFiles = nil
430 }
431 p.CgoCFLAGS = pp.CgoCFLAGS
432 p.CgoCPPFLAGS = pp.CgoCPPFLAGS
433 p.CgoCXXFLAGS = pp.CgoCXXFLAGS
434 p.CgoFFLAGS = pp.CgoFFLAGS
435 p.CgoLDFLAGS = pp.CgoLDFLAGS
436 p.CgoPkgConfig = pp.CgoPkgConfig
437
438 p.Imports = make([]string, len(pp.Imports))
439 copy(p.Imports, pp.Imports)
440 p.Internal.RawImports = pp.Imports
441 p.TestGoFiles = pp.TestGoFiles
442 p.TestImports = pp.TestImports
443 p.XTestGoFiles = pp.XTestGoFiles
444 p.XTestImports = pp.XTestImports
445 if opts.IgnoreImports {
446 p.Imports = nil
447 p.Internal.RawImports = nil
448 p.TestImports = nil
449 p.XTestImports = nil
450 }
451 p.EmbedPatterns = pp.EmbedPatterns
452 p.TestEmbedPatterns = pp.TestEmbedPatterns
453 p.XTestEmbedPatterns = pp.XTestEmbedPatterns
454 p.Internal.OrigImportPath = pp.ImportPath
455 }
456
457
458 type PackageError struct {
459 ImportStack ImportStack
460 Pos string
461 Err error
462 IsImportCycle bool
463 alwaysPrintStack bool
464 }
465
466 func (p *PackageError) Error() string {
467
468
469
470 if p.Pos != "" && (len(p.ImportStack) == 0 || !p.alwaysPrintStack) {
471
472
473 return p.Pos + ": " + p.Err.Error()
474 }
475
476
477
478
479
480
481
482 if len(p.ImportStack) == 0 {
483 return p.Err.Error()
484 }
485 var optpos string
486 if p.Pos != "" {
487 optpos = "\n\t" + p.Pos
488 }
489 imports := p.ImportStack.Pkgs()
490 if p.IsImportCycle {
491 imports = p.ImportStack.PkgsWithPos()
492 }
493 return "package " + strings.Join(imports, "\n\timports ") + optpos + ": " + p.Err.Error()
494 }
495
496 func (p *PackageError) Unwrap() error { return p.Err }
497
498
499
500 func (p *PackageError) MarshalJSON() ([]byte, error) {
501 perr := struct {
502 ImportStack []string
503 Pos string
504 Err string
505 }{p.ImportStack.Pkgs(), p.Pos, p.Err.Error()}
506 return json.Marshal(perr)
507 }
508
509 func (p *PackageError) setPos(posList []token.Position) {
510 if len(posList) == 0 {
511 return
512 }
513 pos := posList[0]
514 pos.Filename = base.ShortPath(pos.Filename)
515 p.Pos = pos.String()
516 }
517
518
519
520
521
522
523
524
525
526 type ImportPathError interface {
527 error
528 ImportPath() string
529 }
530
531 var (
532 _ ImportPathError = (*importError)(nil)
533 _ ImportPathError = (*mainPackageError)(nil)
534 _ ImportPathError = (*modload.ImportMissingError)(nil)
535 _ ImportPathError = (*modload.ImportMissingSumError)(nil)
536 _ ImportPathError = (*modload.DirectImportFromImplicitDependencyError)(nil)
537 )
538
539 type importError struct {
540 importPath string
541 err error
542 }
543
544 func ImportErrorf(path, format string, args ...any) ImportPathError {
545 err := &importError{importPath: path, err: fmt.Errorf(format, args...)}
546 if errStr := err.Error(); !strings.Contains(errStr, path) && !strings.Contains(errStr, strconv.Quote(path)) {
547 panic(fmt.Sprintf("path %q not in error %q", path, errStr))
548 }
549 return err
550 }
551
552 func (e *importError) Error() string {
553 return e.err.Error()
554 }
555
556 func (e *importError) Unwrap() error {
557
558
559 return errors.Unwrap(e.err)
560 }
561
562 func (e *importError) ImportPath() string {
563 return e.importPath
564 }
565
566 type ImportInfo struct {
567 Pkg string
568 Pos *token.Position
569 }
570
571
572
573
574 type ImportStack []ImportInfo
575
576 func NewImportInfo(pkg string, pos *token.Position) ImportInfo {
577 return ImportInfo{Pkg: pkg, Pos: pos}
578 }
579
580 func (s *ImportStack) Push(p ImportInfo) {
581 *s = append(*s, p)
582 }
583
584 func (s *ImportStack) Pop() {
585 *s = (*s)[0 : len(*s)-1]
586 }
587
588 func (s *ImportStack) Copy() ImportStack {
589 return slices.Clone(*s)
590 }
591
592 func (s *ImportStack) Pkgs() []string {
593 ss := make([]string, 0, len(*s))
594 for _, v := range *s {
595 ss = append(ss, v.Pkg)
596 }
597 return ss
598 }
599
600 func (s *ImportStack) PkgsWithPos() []string {
601 ss := make([]string, 0, len(*s))
602 for _, v := range *s {
603 if v.Pos != nil {
604 ss = append(ss, v.Pkg+" from "+filepath.Base(v.Pos.Filename))
605 } else {
606 ss = append(ss, v.Pkg)
607 }
608 }
609 return ss
610 }
611
612 func (s *ImportStack) Top() (ImportInfo, bool) {
613 if len(*s) == 0 {
614 return ImportInfo{}, false
615 }
616 return (*s)[len(*s)-1], true
617 }
618
619
620
621
622 func (sp *ImportStack) shorterThan(t []string) bool {
623 s := *sp
624 if len(s) != len(t) {
625 return len(s) < len(t)
626 }
627
628 for i := range s {
629 siPkg := s[i].Pkg
630 if siPkg != t[i] {
631 return siPkg < t[i]
632 }
633 }
634 return false
635 }
636
637
638
639
640 var packageCache = map[string]*Package{}
641
642
643
644
645
646
647
648
649 func dirToImportPath(dir string) string {
650 return pathpkg.Join("_", strings.Map(makeImportValid, filepath.ToSlash(dir)))
651 }
652
653 func makeImportValid(r rune) rune {
654
655 const illegalChars = `!"#$%&'()*,:;<=>?[\]^{|}` + "`\uFFFD"
656 if !unicode.IsGraphic(r) || unicode.IsSpace(r) || strings.ContainsRune(illegalChars, r) {
657 return '_'
658 }
659 return r
660 }
661
662
663 const (
664
665
666
667
668
669
670
671
672
673 ResolveImport = 1 << iota
674
675
676
677 ResolveModule
678
679
680
681 GetTestDeps
682
683
684
685
686 cmdlinePkg
687
688
689
690 cmdlinePkgLiteral
691 )
692
693
694 func LoadPackage(ctx context.Context, opts PackageOpts, path, srcDir string, stk *ImportStack, importPos []token.Position, mode int) *Package {
695 p, err := loadImport(ctx, opts, nil, path, srcDir, nil, stk, importPos, mode)
696 if err != nil {
697 base.Fatalf("internal error: loadImport of %q with nil parent returned an error", path)
698 }
699 return p
700 }
701
702
703
704
705
706
707
708
709
710
711 func loadImport(ctx context.Context, opts PackageOpts, pre *preload, path, srcDir string, parent *Package, stk *ImportStack, importPos []token.Position, mode int) (*Package, *PackageError) {
712 ctx, span := trace.StartSpan(ctx, "modload.loadImport "+path)
713 defer span.Done()
714
715 if path == "" {
716 panic("LoadImport called with empty package path")
717 }
718
719 var parentPath, parentRoot string
720 parentIsStd := false
721 if parent != nil {
722 parentPath = parent.ImportPath
723 parentRoot = parent.Root
724 parentIsStd = parent.Standard
725 }
726 bp, loaded, err := loadPackageData(ctx, path, parentPath, srcDir, parentRoot, parentIsStd, mode)
727 if loaded && pre != nil && !opts.IgnoreImports {
728 pre.preloadImports(ctx, opts, bp.Imports, bp)
729 }
730 if bp == nil {
731 p := &Package{
732 PackagePublic: PackagePublic{
733 ImportPath: path,
734 Incomplete: true,
735 },
736 }
737 if importErr, ok := err.(ImportPathError); !ok || importErr.ImportPath() != path {
738
739
740
741
742
743
744
745 stk.Push(ImportInfo{Pkg: path, Pos: extractFirstImport(importPos)})
746 defer stk.Pop()
747 }
748 p.setLoadPackageDataError(err, path, stk, nil)
749 return p, nil
750 }
751
752 setCmdline := func(p *Package) {
753 if mode&cmdlinePkg != 0 {
754 p.Internal.CmdlinePkg = true
755 }
756 if mode&cmdlinePkgLiteral != 0 {
757 p.Internal.CmdlinePkgLiteral = true
758 }
759 }
760
761 importPath := bp.ImportPath
762 p := packageCache[importPath]
763 if p != nil {
764 stk.Push(ImportInfo{Pkg: path, Pos: extractFirstImport(importPos)})
765 p = reusePackage(p, stk)
766 stk.Pop()
767 setCmdline(p)
768 } else {
769 p = new(Package)
770 p.Internal.Local = build.IsLocalImport(path)
771 p.ImportPath = importPath
772 packageCache[importPath] = p
773
774 setCmdline(p)
775
776
777
778
779 p.load(ctx, opts, path, stk, importPos, bp, err)
780
781 if !cfg.ModulesEnabled && path != cleanImport(path) {
782 p.Error = &PackageError{
783 ImportStack: stk.Copy(),
784 Err: ImportErrorf(path, "non-canonical import path %q: should be %q", path, pathpkg.Clean(path)),
785 }
786 p.Incomplete = true
787 p.Error.setPos(importPos)
788 }
789 }
790
791
792 if perr := disallowInternal(ctx, srcDir, parent, parentPath, p, stk); perr != nil {
793 perr.setPos(importPos)
794 return p, perr
795 }
796 if mode&ResolveImport != 0 {
797 if perr := disallowVendor(srcDir, path, parentPath, p, stk); perr != nil {
798 perr.setPos(importPos)
799 return p, perr
800 }
801 }
802
803 if p.Name == "main" && parent != nil && parent.Dir != p.Dir {
804 perr := &PackageError{
805 ImportStack: stk.Copy(),
806 Err: ImportErrorf(path, "import %q is a program, not an importable package", path),
807 }
808 perr.setPos(importPos)
809 return p, perr
810 }
811
812 if p.Internal.Local && parent != nil && !parent.Internal.Local {
813 var err error
814 if path == "." {
815 err = ImportErrorf(path, "%s: cannot import current directory", path)
816 } else {
817 err = ImportErrorf(path, "local import %q in non-local package", path)
818 }
819 perr := &PackageError{
820 ImportStack: stk.Copy(),
821 Err: err,
822 }
823 perr.setPos(importPos)
824 return p, perr
825 }
826
827 return p, nil
828 }
829
830 func extractFirstImport(importPos []token.Position) *token.Position {
831 if len(importPos) == 0 {
832 return nil
833 }
834 return &importPos[0]
835 }
836
837
838
839
840
841
842
843
844
845
846 func loadPackageData(ctx context.Context, path, parentPath, parentDir, parentRoot string, parentIsStd bool, mode int) (bp *build.Package, loaded bool, err error) {
847 ctx, span := trace.StartSpan(ctx, "load.loadPackageData "+path)
848 defer span.Done()
849
850 if path == "" {
851 panic("loadPackageData called with empty package path")
852 }
853
854 if strings.HasPrefix(path, "mod/") {
855
856
857
858
859
860 return nil, false, fmt.Errorf("disallowed import path %q", path)
861 }
862
863 if strings.Contains(path, "@") {
864 return nil, false, errors.New("can only use path@version syntax with 'go get' and 'go install' in module-aware mode")
865 }
866
867
868
869
870
871
872
873
874
875
876
877 importKey := importSpec{
878 path: path,
879 parentPath: parentPath,
880 parentDir: parentDir,
881 parentRoot: parentRoot,
882 parentIsStd: parentIsStd,
883 mode: mode,
884 }
885 r := resolvedImportCache.Do(importKey, func() resolvedImport {
886 var r resolvedImport
887 if cfg.ModulesEnabled {
888 r.dir, r.path, r.err = modload.Lookup(parentPath, parentIsStd, path)
889 } else if build.IsLocalImport(path) {
890 r.dir = filepath.Join(parentDir, path)
891 r.path = dirToImportPath(r.dir)
892 } else if mode&ResolveImport != 0 {
893
894
895
896
897 r.path = resolveImportPath(path, parentPath, parentDir, parentRoot, parentIsStd)
898 } else if mode&ResolveModule != 0 {
899 r.path = moduleImportPath(path, parentPath, parentDir, parentRoot)
900 }
901 if r.path == "" {
902 r.path = path
903 }
904 return r
905 })
906
907
908
909
910
911
912 p, err := packageDataCache.Do(r.path, func() (*build.Package, error) {
913 loaded = true
914 var data struct {
915 p *build.Package
916 err error
917 }
918 if r.dir != "" {
919 var buildMode build.ImportMode
920 buildContext := cfg.BuildContext
921 if !cfg.ModulesEnabled {
922 buildMode = build.ImportComment
923 } else {
924 buildContext.GOPATH = ""
925 }
926 modroot := modload.PackageModRoot(ctx, r.path)
927 if modroot == "" && str.HasPathPrefix(r.dir, cfg.GOROOTsrc) {
928 modroot = cfg.GOROOTsrc
929 gorootSrcCmd := filepath.Join(cfg.GOROOTsrc, "cmd")
930 if str.HasPathPrefix(r.dir, gorootSrcCmd) {
931 modroot = gorootSrcCmd
932 }
933 }
934 if modroot != "" {
935 if rp, err := modindex.GetPackage(modroot, r.dir); err == nil {
936 data.p, data.err = rp.Import(cfg.BuildContext, buildMode)
937 goto Happy
938 } else if !errors.Is(err, modindex.ErrNotIndexed) {
939 base.Fatal(err)
940 }
941 }
942 data.p, data.err = buildContext.ImportDir(r.dir, buildMode)
943 Happy:
944 if cfg.ModulesEnabled {
945
946
947 if info := modload.PackageModuleInfo(ctx, path); info != nil {
948 data.p.Root = info.Dir
949 }
950 }
951 if r.err != nil {
952 if data.err != nil {
953
954
955
956
957 } else if errors.Is(r.err, imports.ErrNoGo) {
958
959
960
961
962
963
964
965
966
967
968 } else {
969 data.err = r.err
970 }
971 }
972 } else if r.err != nil {
973 data.p = new(build.Package)
974 data.err = r.err
975 } else if cfg.ModulesEnabled && path != "unsafe" {
976 data.p = new(build.Package)
977 data.err = fmt.Errorf("unknown import path %q: internal error: module loader did not resolve import", r.path)
978 } else {
979 buildMode := build.ImportComment
980 if mode&ResolveImport == 0 || r.path != path {
981
982 buildMode |= build.IgnoreVendor
983 }
984 data.p, data.err = cfg.BuildContext.Import(r.path, parentDir, buildMode)
985 }
986 data.p.ImportPath = r.path
987
988
989
990 if !data.p.Goroot {
991 if cfg.GOBIN != "" {
992 data.p.BinDir = cfg.GOBIN
993 } else if cfg.ModulesEnabled {
994 data.p.BinDir = modload.BinDir()
995 }
996 }
997
998 if !cfg.ModulesEnabled && data.err == nil &&
999 data.p.ImportComment != "" && data.p.ImportComment != path &&
1000 !strings.Contains(path, "/vendor/") && !strings.HasPrefix(path, "vendor/") {
1001 data.err = fmt.Errorf("code in directory %s expects import %q", data.p.Dir, data.p.ImportComment)
1002 }
1003 return data.p, data.err
1004 })
1005
1006 return p, loaded, err
1007 }
1008
1009
1010
1011 type importSpec struct {
1012 path string
1013 parentPath, parentDir, parentRoot string
1014 parentIsStd bool
1015 mode int
1016 }
1017
1018
1019
1020
1021 type resolvedImport struct {
1022 path, dir string
1023 err error
1024 }
1025
1026
1027 var resolvedImportCache par.Cache[importSpec, resolvedImport]
1028
1029
1030 var packageDataCache par.ErrCache[string, *build.Package]
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044 var preloadWorkerCount = runtime.GOMAXPROCS(0)
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055 type preload struct {
1056 cancel chan struct{}
1057 sema chan struct{}
1058 }
1059
1060
1061
1062 func newPreload() *preload {
1063 pre := &preload{
1064 cancel: make(chan struct{}),
1065 sema: make(chan struct{}, preloadWorkerCount),
1066 }
1067 return pre
1068 }
1069
1070
1071
1072
1073 func (pre *preload) preloadMatches(ctx context.Context, opts PackageOpts, matches []*search.Match) {
1074 for _, m := range matches {
1075 for _, pkg := range m.Pkgs {
1076 select {
1077 case <-pre.cancel:
1078 return
1079 case pre.sema <- struct{}{}:
1080 go func(pkg string) {
1081 mode := 0
1082 bp, loaded, err := loadPackageData(ctx, pkg, "", base.Cwd(), "", false, mode)
1083 <-pre.sema
1084 if bp != nil && loaded && err == nil && !opts.IgnoreImports {
1085 pre.preloadImports(ctx, opts, bp.Imports, bp)
1086 }
1087 }(pkg)
1088 }
1089 }
1090 }
1091 }
1092
1093
1094
1095
1096 func (pre *preload) preloadImports(ctx context.Context, opts PackageOpts, imports []string, parent *build.Package) {
1097 parentIsStd := parent.Goroot && parent.ImportPath != "" && search.IsStandardImportPath(parent.ImportPath)
1098 for _, path := range imports {
1099 if path == "C" || path == "unsafe" {
1100 continue
1101 }
1102 select {
1103 case <-pre.cancel:
1104 return
1105 case pre.sema <- struct{}{}:
1106 go func(path string) {
1107 bp, loaded, err := loadPackageData(ctx, path, parent.ImportPath, parent.Dir, parent.Root, parentIsStd, ResolveImport)
1108 <-pre.sema
1109 if bp != nil && loaded && err == nil && !opts.IgnoreImports {
1110 pre.preloadImports(ctx, opts, bp.Imports, bp)
1111 }
1112 }(path)
1113 }
1114 }
1115 }
1116
1117
1118
1119
1120 func (pre *preload) flush() {
1121
1122
1123 if v := recover(); v != nil {
1124 panic(v)
1125 }
1126
1127 close(pre.cancel)
1128 for i := 0; i < preloadWorkerCount; i++ {
1129 pre.sema <- struct{}{}
1130 }
1131 }
1132
1133 func cleanImport(path string) string {
1134 orig := path
1135 path = pathpkg.Clean(path)
1136 if strings.HasPrefix(orig, "./") && path != ".." && !strings.HasPrefix(path, "../") {
1137 path = "./" + path
1138 }
1139 return path
1140 }
1141
1142 var isDirCache par.Cache[string, bool]
1143
1144 func isDir(path string) bool {
1145 return isDirCache.Do(path, func() bool {
1146 fi, err := fsys.Stat(path)
1147 return err == nil && fi.IsDir()
1148 })
1149 }
1150
1151
1152
1153
1154
1155
1156 func ResolveImportPath(parent *Package, path string) (found string) {
1157 var parentPath, parentDir, parentRoot string
1158 parentIsStd := false
1159 if parent != nil {
1160 parentPath = parent.ImportPath
1161 parentDir = parent.Dir
1162 parentRoot = parent.Root
1163 parentIsStd = parent.Standard
1164 }
1165 return resolveImportPath(path, parentPath, parentDir, parentRoot, parentIsStd)
1166 }
1167
1168 func resolveImportPath(path, parentPath, parentDir, parentRoot string, parentIsStd bool) (found string) {
1169 if cfg.ModulesEnabled {
1170 if _, p, e := modload.Lookup(parentPath, parentIsStd, path); e == nil {
1171 return p
1172 }
1173 return path
1174 }
1175 found = vendoredImportPath(path, parentPath, parentDir, parentRoot)
1176 if found != path {
1177 return found
1178 }
1179 return moduleImportPath(path, parentPath, parentDir, parentRoot)
1180 }
1181
1182
1183
1184 func dirAndRoot(path string, dir, root string) (string, string) {
1185 origDir, origRoot := dir, root
1186 dir = filepath.Clean(dir)
1187 root = filepath.Join(root, "src")
1188 if !str.HasFilePathPrefix(dir, root) || path != "command-line-arguments" && filepath.Join(root, path) != dir {
1189
1190 dir = expandPath(dir)
1191 root = expandPath(root)
1192 }
1193
1194 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 {
1195 debug.PrintStack()
1196 base.Fatalf("unexpected directory layout:\n"+
1197 " import path: %s\n"+
1198 " root: %s\n"+
1199 " dir: %s\n"+
1200 " expand root: %s\n"+
1201 " expand dir: %s\n"+
1202 " separator: %s",
1203 path,
1204 filepath.Join(origRoot, "src"),
1205 filepath.Clean(origDir),
1206 origRoot,
1207 origDir,
1208 string(filepath.Separator))
1209 }
1210
1211 return dir, root
1212 }
1213
1214
1215
1216
1217
1218 func vendoredImportPath(path, parentPath, parentDir, parentRoot string) (found string) {
1219 if parentRoot == "" {
1220 return path
1221 }
1222
1223 dir, root := dirAndRoot(parentPath, parentDir, parentRoot)
1224
1225 vpath := "vendor/" + path
1226 for i := len(dir); i >= len(root); i-- {
1227 if i < len(dir) && dir[i] != filepath.Separator {
1228 continue
1229 }
1230
1231
1232
1233
1234 if !isDir(filepath.Join(dir[:i], "vendor")) {
1235 continue
1236 }
1237 targ := filepath.Join(dir[:i], vpath)
1238 if isDir(targ) && hasGoFiles(targ) {
1239 importPath := parentPath
1240 if importPath == "command-line-arguments" {
1241
1242
1243 importPath = dir[len(root)+1:]
1244 }
1245
1246
1247
1248
1249
1250
1251
1252
1253 chopped := len(dir) - i
1254 if chopped == len(importPath)+1 {
1255
1256
1257
1258
1259 return vpath
1260 }
1261 return importPath[:len(importPath)-chopped] + "/" + vpath
1262 }
1263 }
1264 return path
1265 }
1266
1267 var (
1268 modulePrefix = []byte("\nmodule ")
1269 goModPathCache par.Cache[string, string]
1270 )
1271
1272
1273 func goModPath(dir string) (path string) {
1274 return goModPathCache.Do(dir, func() string {
1275 data, err := os.ReadFile(filepath.Join(dir, "go.mod"))
1276 if err != nil {
1277 return ""
1278 }
1279 var i int
1280 if bytes.HasPrefix(data, modulePrefix[1:]) {
1281 i = 0
1282 } else {
1283 i = bytes.Index(data, modulePrefix)
1284 if i < 0 {
1285 return ""
1286 }
1287 i++
1288 }
1289 line := data[i:]
1290
1291
1292 if j := bytes.IndexByte(line, '\n'); j >= 0 {
1293 line = line[:j]
1294 }
1295 if line[len(line)-1] == '\r' {
1296 line = line[:len(line)-1]
1297 }
1298 line = line[len("module "):]
1299
1300
1301 path = strings.TrimSpace(string(line))
1302 if path != "" && path[0] == '"' {
1303 s, err := strconv.Unquote(path)
1304 if err != nil {
1305 return ""
1306 }
1307 path = s
1308 }
1309 return path
1310 })
1311 }
1312
1313
1314
1315 func findVersionElement(path string) (i, j int) {
1316 j = len(path)
1317 for i = len(path) - 1; i >= 0; i-- {
1318 if path[i] == '/' {
1319 if isVersionElement(path[i+1 : j]) {
1320 return i, j
1321 }
1322 j = i
1323 }
1324 }
1325 return -1, -1
1326 }
1327
1328
1329
1330 func isVersionElement(s string) bool {
1331 if len(s) < 2 || s[0] != 'v' || s[1] == '0' || s[1] == '1' && len(s) == 2 {
1332 return false
1333 }
1334 for i := 1; i < len(s); i++ {
1335 if s[i] < '0' || '9' < s[i] {
1336 return false
1337 }
1338 }
1339 return true
1340 }
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350 func moduleImportPath(path, parentPath, parentDir, parentRoot string) (found string) {
1351 if parentRoot == "" {
1352 return path
1353 }
1354
1355
1356
1357
1358
1359 if i, _ := findVersionElement(path); i < 0 {
1360 return path
1361 }
1362
1363 dir, root := dirAndRoot(parentPath, parentDir, parentRoot)
1364
1365
1366 for i := len(dir); i >= len(root); i-- {
1367 if i < len(dir) && dir[i] != filepath.Separator {
1368 continue
1369 }
1370 if goModPath(dir[:i]) != "" {
1371 goto HaveGoMod
1372 }
1373 }
1374
1375
1376 return path
1377
1378 HaveGoMod:
1379
1380
1381
1382
1383
1384 if bp, _ := cfg.BuildContext.Import(path, "", build.IgnoreVendor); bp.Dir != "" {
1385 return path
1386 }
1387
1388
1389
1390
1391
1392
1393 limit := len(path)
1394 for limit > 0 {
1395 i, j := findVersionElement(path[:limit])
1396 if i < 0 {
1397 return path
1398 }
1399 if bp, _ := cfg.BuildContext.Import(path[:i], "", build.IgnoreVendor); bp.Dir != "" {
1400 if mpath := goModPath(bp.Dir); mpath != "" {
1401
1402
1403
1404 if mpath == path[:j] {
1405 return path[:i] + path[j:]
1406 }
1407
1408
1409
1410
1411 return path
1412 }
1413 }
1414 limit = i
1415 }
1416 return path
1417 }
1418
1419
1420
1421
1422
1423 func hasGoFiles(dir string) bool {
1424 files, _ := os.ReadDir(dir)
1425 for _, f := range files {
1426 if !f.IsDir() && strings.HasSuffix(f.Name(), ".go") {
1427 return true
1428 }
1429 }
1430 return false
1431 }
1432
1433
1434
1435
1436 func reusePackage(p *Package, stk *ImportStack) *Package {
1437
1438
1439
1440 if p.Internal.Imports == nil {
1441 if p.Error == nil {
1442 p.Error = &PackageError{
1443 ImportStack: stk.Copy(),
1444 Err: errors.New("import cycle not allowed"),
1445 IsImportCycle: true,
1446 }
1447 } else if !p.Error.IsImportCycle {
1448
1449
1450
1451 p.Error.IsImportCycle = true
1452 }
1453 p.Incomplete = true
1454 }
1455
1456
1457 if p.Error != nil && p.Error.ImportStack != nil &&
1458 !p.Error.IsImportCycle && stk.shorterThan(p.Error.ImportStack.Pkgs()) {
1459 p.Error.ImportStack = stk.Copy()
1460 }
1461 return p
1462 }
1463
1464
1465
1466
1467
1468 func disallowInternal(ctx context.Context, srcDir string, importer *Package, importerPath string, p *Package, stk *ImportStack) *PackageError {
1469
1470
1471
1472
1473
1474
1475 if p.Error != nil {
1476 return nil
1477 }
1478
1479
1480
1481
1482
1483 if str.HasPathPrefix(p.ImportPath, "testing/internal") && importerPath == "testmain" {
1484 return nil
1485 }
1486
1487
1488 if cfg.BuildContext.Compiler == "gccgo" && p.Standard {
1489 return nil
1490 }
1491
1492
1493
1494
1495 if p.Standard && strings.HasPrefix(importerPath, "bootstrap/") {
1496 return nil
1497 }
1498
1499
1500
1501
1502 if importerPath == "" {
1503 return nil
1504 }
1505
1506
1507 i, ok := findInternal(p.ImportPath)
1508 if !ok {
1509 return nil
1510 }
1511
1512
1513
1514 if i > 0 {
1515 i--
1516 }
1517
1518 if p.Module == nil {
1519 parent := p.Dir[:i+len(p.Dir)-len(p.ImportPath)]
1520
1521 if str.HasFilePathPrefix(filepath.Clean(srcDir), filepath.Clean(parent)) {
1522 return nil
1523 }
1524
1525
1526 srcDir = expandPath(srcDir)
1527 parent = expandPath(parent)
1528 if str.HasFilePathPrefix(filepath.Clean(srcDir), filepath.Clean(parent)) {
1529 return nil
1530 }
1531 } else {
1532
1533
1534 if importer.Internal.CmdlineFiles {
1535
1536
1537
1538
1539
1540 importerPath, _ = modload.MainModules.DirImportPath(ctx, importer.Dir)
1541 }
1542 parentOfInternal := p.ImportPath[:i]
1543 if str.HasPathPrefix(importerPath, parentOfInternal) {
1544 return nil
1545 }
1546 }
1547
1548
1549 perr := &PackageError{
1550 alwaysPrintStack: true,
1551 ImportStack: stk.Copy(),
1552 Err: ImportErrorf(p.ImportPath, "use of internal package %s not allowed", p.ImportPath),
1553 }
1554 return perr
1555 }
1556
1557
1558
1559
1560 func findInternal(path string) (index int, ok bool) {
1561
1562
1563
1564
1565 switch {
1566 case strings.HasSuffix(path, "/internal"):
1567 return len(path) - len("internal"), true
1568 case strings.Contains(path, "/internal/"):
1569 return strings.LastIndex(path, "/internal/") + 1, true
1570 case path == "internal", strings.HasPrefix(path, "internal/"):
1571 return 0, true
1572 }
1573 return 0, false
1574 }
1575
1576
1577
1578
1579 func disallowVendor(srcDir string, path string, importerPath string, p *Package, stk *ImportStack) *PackageError {
1580
1581
1582
1583 if importerPath == "" {
1584 return nil
1585 }
1586
1587 if perr := disallowVendorVisibility(srcDir, p, importerPath, stk); perr != nil {
1588 return perr
1589 }
1590
1591
1592 if i, ok := FindVendor(path); ok {
1593 perr := &PackageError{
1594 ImportStack: stk.Copy(),
1595 Err: ImportErrorf(path, "%s must be imported as %s", path, path[i+len("vendor/"):]),
1596 }
1597 return perr
1598 }
1599
1600 return nil
1601 }
1602
1603
1604
1605
1606
1607
1608 func disallowVendorVisibility(srcDir string, p *Package, importerPath string, stk *ImportStack) *PackageError {
1609
1610
1611
1612
1613 if importerPath == "" {
1614 return nil
1615 }
1616
1617
1618 i, ok := FindVendor(p.ImportPath)
1619 if !ok {
1620 return nil
1621 }
1622
1623
1624
1625 if i > 0 {
1626 i--
1627 }
1628 truncateTo := i + len(p.Dir) - len(p.ImportPath)
1629 if truncateTo < 0 || len(p.Dir) < truncateTo {
1630 return nil
1631 }
1632 parent := p.Dir[:truncateTo]
1633 if str.HasFilePathPrefix(filepath.Clean(srcDir), filepath.Clean(parent)) {
1634 return nil
1635 }
1636
1637
1638 srcDir = expandPath(srcDir)
1639 parent = expandPath(parent)
1640 if str.HasFilePathPrefix(filepath.Clean(srcDir), filepath.Clean(parent)) {
1641 return nil
1642 }
1643
1644
1645
1646 perr := &PackageError{
1647 ImportStack: stk.Copy(),
1648 Err: errors.New("use of vendored package not allowed"),
1649 }
1650 return perr
1651 }
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661 func FindVendor(path string) (index int, ok bool) {
1662
1663
1664
1665 switch {
1666 case strings.Contains(path, "/vendor/"):
1667 return strings.LastIndex(path, "/vendor/") + 1, true
1668 case strings.HasPrefix(path, "vendor/"):
1669 return 0, true
1670 }
1671 return 0, false
1672 }
1673
1674 type TargetDir int
1675
1676 const (
1677 ToTool TargetDir = iota
1678 ToBin
1679 StalePath
1680 )
1681
1682
1683 func InstallTargetDir(p *Package) TargetDir {
1684 if strings.HasPrefix(p.ImportPath, "code.google.com/p/go.tools/cmd/") {
1685 return StalePath
1686 }
1687 if p.Goroot && strings.HasPrefix(p.ImportPath, "cmd/") && p.Name == "main" {
1688 switch p.ImportPath {
1689 case "cmd/go", "cmd/gofmt":
1690 return ToBin
1691 }
1692 return ToTool
1693 }
1694 return ToBin
1695 }
1696
1697 var cgoExclude = map[string]bool{
1698 "runtime/cgo": true,
1699 }
1700
1701 var cgoSyscallExclude = map[string]bool{
1702 "runtime/cgo": true,
1703 "runtime/race": true,
1704 "runtime/msan": true,
1705 "runtime/asan": true,
1706 }
1707
1708 var foldPath = make(map[string]string)
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718 func (p *Package) exeFromImportPath() string {
1719 _, elem := pathpkg.Split(p.ImportPath)
1720 if cfg.ModulesEnabled {
1721
1722
1723 if elem != p.ImportPath && isVersionElement(elem) {
1724 _, elem = pathpkg.Split(pathpkg.Dir(p.ImportPath))
1725 }
1726 }
1727 return elem
1728 }
1729
1730
1731
1732
1733
1734 func (p *Package) exeFromFiles() string {
1735 var src string
1736 if len(p.GoFiles) > 0 {
1737 src = p.GoFiles[0]
1738 } else if len(p.CgoFiles) > 0 {
1739 src = p.CgoFiles[0]
1740 } else {
1741 return ""
1742 }
1743 _, elem := filepath.Split(src)
1744 return elem[:len(elem)-len(".go")]
1745 }
1746
1747
1748 func (p *Package) DefaultExecName() string {
1749 if p.Internal.CmdlineFiles {
1750 return p.exeFromFiles()
1751 }
1752 return p.exeFromImportPath()
1753 }
1754
1755
1756
1757
1758 func (p *Package) load(ctx context.Context, opts PackageOpts, path string, stk *ImportStack, importPos []token.Position, bp *build.Package, err error) {
1759 p.copyBuild(opts, bp)
1760
1761
1762
1763
1764 if p.Internal.Local && !cfg.ModulesEnabled {
1765 p.Internal.LocalPrefix = dirToImportPath(p.Dir)
1766 }
1767
1768
1769
1770
1771 setError := func(err error) {
1772 if p.Error == nil {
1773 p.Error = &PackageError{
1774 ImportStack: stk.Copy(),
1775 Err: err,
1776 }
1777 p.Incomplete = true
1778
1779
1780
1781
1782
1783
1784
1785 top, ok := stk.Top()
1786 if ok && path != top.Pkg && len(importPos) > 0 {
1787 p.Error.setPos(importPos)
1788 }
1789 }
1790 }
1791
1792 if err != nil {
1793 p.Incomplete = true
1794 p.setLoadPackageDataError(err, path, stk, importPos)
1795 }
1796
1797 useBindir := p.Name == "main"
1798 if !p.Standard {
1799 switch cfg.BuildBuildmode {
1800 case "c-archive", "c-shared", "plugin":
1801 useBindir = false
1802 }
1803 }
1804
1805 if useBindir {
1806
1807 if InstallTargetDir(p) == StalePath {
1808
1809
1810 newPath := strings.Replace(p.ImportPath, "code.google.com/p/go.", "golang.org/x/", 1)
1811 e := ImportErrorf(p.ImportPath, "the %v command has moved; use %v instead.", p.ImportPath, newPath)
1812 setError(e)
1813 return
1814 }
1815 elem := p.DefaultExecName() + cfg.ExeSuffix
1816 full := filepath.Join(cfg.BuildContext.GOOS+"_"+cfg.BuildContext.GOARCH, elem)
1817 if cfg.BuildContext.GOOS != runtime.GOOS || cfg.BuildContext.GOARCH != runtime.GOARCH {
1818
1819 elem = full
1820 }
1821 if p.Internal.Build.BinDir == "" && cfg.ModulesEnabled {
1822 p.Internal.Build.BinDir = modload.BinDir()
1823 }
1824 if p.Internal.Build.BinDir != "" {
1825
1826 p.Target = filepath.Join(p.Internal.Build.BinDir, elem)
1827 if !p.Goroot && strings.Contains(elem, string(filepath.Separator)) && cfg.GOBIN != "" {
1828
1829 p.Target = ""
1830 p.Internal.GobinSubdir = true
1831 }
1832 }
1833 if InstallTargetDir(p) == ToTool {
1834
1835
1836 if cfg.BuildToolchainName == "gccgo" {
1837 p.Target = filepath.Join(build.ToolDir, elem)
1838 } else {
1839 p.Target = filepath.Join(cfg.GOROOTpkg, "tool", full)
1840 }
1841 }
1842 } else if p.Internal.Local {
1843
1844
1845 p.Target = ""
1846 } else if p.Standard && cfg.BuildContext.Compiler == "gccgo" {
1847
1848 p.Target = ""
1849 } else {
1850 p.Target = p.Internal.Build.PkgObj
1851 if cfg.BuildBuildmode == "shared" && p.Internal.Build.PkgTargetRoot != "" {
1852
1853
1854
1855 p.Target = filepath.Join(p.Internal.Build.PkgTargetRoot, p.ImportPath+".a")
1856 }
1857 if cfg.BuildLinkshared && p.Internal.Build.PkgTargetRoot != "" {
1858
1859
1860
1861 targetPrefix := filepath.Join(p.Internal.Build.PkgTargetRoot, p.ImportPath)
1862 p.Target = targetPrefix + ".a"
1863 shlibnamefile := targetPrefix + ".shlibname"
1864 shlib, err := os.ReadFile(shlibnamefile)
1865 if err != nil && !os.IsNotExist(err) {
1866 base.Fatalf("reading shlibname: %v", err)
1867 }
1868 if err == nil {
1869 libname := strings.TrimSpace(string(shlib))
1870 if cfg.BuildContext.Compiler == "gccgo" {
1871 p.Shlib = filepath.Join(p.Internal.Build.PkgTargetRoot, "shlibs", libname)
1872 } else {
1873 p.Shlib = filepath.Join(p.Internal.Build.PkgTargetRoot, libname)
1874 }
1875 }
1876 }
1877 }
1878
1879
1880
1881 importPaths := p.Imports
1882 addImport := func(path string, forCompiler bool) {
1883 for _, p := range importPaths {
1884 if path == p {
1885 return
1886 }
1887 }
1888 importPaths = append(importPaths, path)
1889 if forCompiler {
1890 p.Internal.CompiledImports = append(p.Internal.CompiledImports, path)
1891 }
1892 }
1893
1894 if !opts.IgnoreImports {
1895
1896
1897 if p.UsesCgo() {
1898 addImport("unsafe", true)
1899 }
1900 if p.UsesCgo() && (!p.Standard || !cgoExclude[p.ImportPath]) && cfg.BuildContext.Compiler != "gccgo" {
1901 addImport("runtime/cgo", true)
1902 }
1903 if p.UsesCgo() && (!p.Standard || !cgoSyscallExclude[p.ImportPath]) {
1904 addImport("syscall", true)
1905 }
1906
1907
1908 if p.UsesSwig() {
1909 addImport("unsafe", true)
1910 if cfg.BuildContext.Compiler != "gccgo" {
1911 addImport("runtime/cgo", true)
1912 }
1913 addImport("syscall", true)
1914 addImport("sync", true)
1915
1916
1917
1918 }
1919
1920
1921 if p.Name == "main" && !p.Internal.ForceLibrary {
1922 ldDeps, err := LinkerDeps(p)
1923 if err != nil {
1924 setError(err)
1925 return
1926 }
1927 for _, dep := range ldDeps {
1928 addImport(dep, false)
1929 }
1930 }
1931 }
1932
1933
1934
1935
1936 fold := str.ToFold(p.ImportPath)
1937 if other := foldPath[fold]; other == "" {
1938 foldPath[fold] = p.ImportPath
1939 } else if other != p.ImportPath {
1940 setError(ImportErrorf(p.ImportPath, "case-insensitive import collision: %q and %q", p.ImportPath, other))
1941 return
1942 }
1943
1944 if !SafeArg(p.ImportPath) {
1945 setError(ImportErrorf(p.ImportPath, "invalid import path %q", p.ImportPath))
1946 return
1947 }
1948
1949
1950
1951
1952 stk.Push(ImportInfo{Pkg: path, Pos: extractFirstImport(importPos)})
1953 defer stk.Pop()
1954
1955 pkgPath := p.ImportPath
1956 if p.Internal.CmdlineFiles {
1957 pkgPath = "command-line-arguments"
1958 }
1959 if cfg.ModulesEnabled {
1960 p.Module = modload.PackageModuleInfo(ctx, pkgPath)
1961 }
1962 p.DefaultGODEBUG = defaultGODEBUG(p, nil, nil, nil)
1963
1964 if !opts.SuppressEmbedFiles {
1965 p.EmbedFiles, p.Internal.Embed, err = resolveEmbed(p.Dir, p.EmbedPatterns)
1966 if err != nil {
1967 p.Incomplete = true
1968 setError(err)
1969 embedErr := err.(*EmbedError)
1970 p.Error.setPos(p.Internal.Build.EmbedPatternPos[embedErr.Pattern])
1971 }
1972 }
1973
1974
1975
1976
1977
1978 inputs := p.AllFiles()
1979 f1, f2 := str.FoldDup(inputs)
1980 if f1 != "" {
1981 setError(fmt.Errorf("case-insensitive file name collision: %q and %q", f1, f2))
1982 return
1983 }
1984
1985
1986
1987
1988
1989
1990
1991
1992 for _, file := range inputs {
1993 if !SafeArg(file) || strings.HasPrefix(file, "_cgo_") {
1994 setError(fmt.Errorf("invalid input file name %q", file))
1995 return
1996 }
1997 }
1998 if name := pathpkg.Base(p.ImportPath); !SafeArg(name) {
1999 setError(fmt.Errorf("invalid input directory name %q", name))
2000 return
2001 }
2002 if strings.ContainsAny(p.Dir, "\r\n") {
2003 setError(fmt.Errorf("invalid package directory %q", p.Dir))
2004 return
2005 }
2006
2007
2008 imports := make([]*Package, 0, len(p.Imports))
2009 for i, path := range importPaths {
2010 if path == "C" {
2011 continue
2012 }
2013 p1, err := loadImport(ctx, opts, nil, path, p.Dir, p, stk, p.Internal.Build.ImportPos[path], ResolveImport)
2014 if err != nil && p.Error == nil {
2015 p.Error = err
2016 p.Incomplete = true
2017 }
2018
2019 path = p1.ImportPath
2020 importPaths[i] = path
2021 if i < len(p.Imports) {
2022 p.Imports[i] = path
2023 }
2024
2025 imports = append(imports, p1)
2026 if p1.Incomplete {
2027 p.Incomplete = true
2028 }
2029 }
2030 p.Internal.Imports = imports
2031 if p.Error == nil && p.Name == "main" && !p.Internal.ForceLibrary && !p.Incomplete && !opts.SuppressBuildInfo {
2032
2033
2034
2035
2036 p.setBuildInfo(ctx, opts.AutoVCS)
2037 }
2038
2039
2040
2041 if !cfg.BuildContext.CgoEnabled {
2042 p.CFiles = nil
2043 p.CXXFiles = nil
2044 p.MFiles = nil
2045 p.SwigFiles = nil
2046 p.SwigCXXFiles = nil
2047
2048
2049
2050
2051 }
2052
2053
2054 if len(p.CFiles) > 0 && !p.UsesCgo() && !p.UsesSwig() && cfg.BuildContext.Compiler == "gc" {
2055 setError(fmt.Errorf("C source files not allowed when not using cgo or SWIG: %s", strings.Join(p.CFiles, " ")))
2056 return
2057 }
2058
2059
2060
2061 if len(p.CXXFiles) > 0 && !p.UsesCgo() && !p.UsesSwig() {
2062 setError(fmt.Errorf("C++ source files not allowed when not using cgo or SWIG: %s", strings.Join(p.CXXFiles, " ")))
2063 return
2064 }
2065 if len(p.MFiles) > 0 && !p.UsesCgo() && !p.UsesSwig() {
2066 setError(fmt.Errorf("Objective-C source files not allowed when not using cgo or SWIG: %s", strings.Join(p.MFiles, " ")))
2067 return
2068 }
2069 if len(p.FFiles) > 0 && !p.UsesCgo() && !p.UsesSwig() {
2070 setError(fmt.Errorf("Fortran source files not allowed when not using cgo or SWIG: %s", strings.Join(p.FFiles, " ")))
2071 return
2072 }
2073 }
2074
2075
2076 type EmbedError struct {
2077 Pattern string
2078 Err error
2079 }
2080
2081 func (e *EmbedError) Error() string {
2082 return fmt.Sprintf("pattern %s: %v", e.Pattern, e.Err)
2083 }
2084
2085 func (e *EmbedError) Unwrap() error {
2086 return e.Err
2087 }
2088
2089
2090
2091
2092
2093
2094 func ResolveEmbed(dir string, patterns []string) ([]string, error) {
2095 files, _, err := resolveEmbed(dir, patterns)
2096 return files, err
2097 }
2098
2099
2100
2101
2102
2103 func resolveEmbed(pkgdir string, patterns []string) (files []string, pmap map[string][]string, err error) {
2104 var pattern string
2105 defer func() {
2106 if err != nil {
2107 err = &EmbedError{
2108 Pattern: pattern,
2109 Err: err,
2110 }
2111 }
2112 }()
2113
2114
2115 pmap = make(map[string][]string)
2116 have := make(map[string]int)
2117 dirOK := make(map[string]bool)
2118 pid := 0
2119 for _, pattern = range patterns {
2120 pid++
2121
2122 glob, all := strings.CutPrefix(pattern, "all:")
2123
2124 if _, err := pathpkg.Match(glob, ""); err != nil || !validEmbedPattern(glob) {
2125 return nil, nil, fmt.Errorf("invalid pattern syntax")
2126 }
2127
2128
2129 match, err := fsys.Glob(str.QuoteGlob(str.WithFilePathSeparator(pkgdir)) + filepath.FromSlash(glob))
2130 if err != nil {
2131 return nil, nil, err
2132 }
2133
2134
2135
2136
2137
2138 var list []string
2139 for _, file := range match {
2140
2141 rel := filepath.ToSlash(str.TrimFilePathPrefix(file, pkgdir))
2142
2143 what := "file"
2144 info, err := fsys.Lstat(file)
2145 if err != nil {
2146 return nil, nil, err
2147 }
2148 if info.IsDir() {
2149 what = "directory"
2150 }
2151
2152
2153
2154 for dir := file; len(dir) > len(pkgdir)+1 && !dirOK[dir]; dir = filepath.Dir(dir) {
2155 if _, err := fsys.Stat(filepath.Join(dir, "go.mod")); err == nil {
2156 return nil, nil, fmt.Errorf("cannot embed %s %s: in different module", what, rel)
2157 }
2158 if dir != file {
2159 if info, err := fsys.Lstat(dir); err == nil && !info.IsDir() {
2160 return nil, nil, fmt.Errorf("cannot embed %s %s: in non-directory %s", what, rel, dir[len(pkgdir)+1:])
2161 }
2162 }
2163 dirOK[dir] = true
2164 if elem := filepath.Base(dir); isBadEmbedName(elem) {
2165 if dir == file {
2166 return nil, nil, fmt.Errorf("cannot embed %s %s: invalid name %s", what, rel, elem)
2167 } else {
2168 return nil, nil, fmt.Errorf("cannot embed %s %s: in invalid directory %s", what, rel, elem)
2169 }
2170 }
2171 }
2172
2173 switch {
2174 default:
2175 return nil, nil, fmt.Errorf("cannot embed irregular file %s", rel)
2176
2177 case info.Mode().IsRegular():
2178 if have[rel] != pid {
2179 have[rel] = pid
2180 list = append(list, rel)
2181 }
2182
2183 case info.IsDir():
2184
2185
2186 count := 0
2187 err := fsys.Walk(file, func(path string, info os.FileInfo, err error) error {
2188 if err != nil {
2189 return err
2190 }
2191 rel := filepath.ToSlash(str.TrimFilePathPrefix(path, pkgdir))
2192 name := info.Name()
2193 if path != file && (isBadEmbedName(name) || ((name[0] == '.' || name[0] == '_') && !all)) {
2194
2195
2196
2197 if info.IsDir() {
2198 return fs.SkipDir
2199 }
2200 return nil
2201 }
2202 if info.IsDir() {
2203 if _, err := fsys.Stat(filepath.Join(path, "go.mod")); err == nil {
2204 return filepath.SkipDir
2205 }
2206 return nil
2207 }
2208 if !info.Mode().IsRegular() {
2209 return nil
2210 }
2211 count++
2212 if have[rel] != pid {
2213 have[rel] = pid
2214 list = append(list, rel)
2215 }
2216 return nil
2217 })
2218 if err != nil {
2219 return nil, nil, err
2220 }
2221 if count == 0 {
2222 return nil, nil, fmt.Errorf("cannot embed directory %s: contains no embeddable files", rel)
2223 }
2224 }
2225 }
2226
2227 if len(list) == 0 {
2228 return nil, nil, fmt.Errorf("no matching files found")
2229 }
2230 sort.Strings(list)
2231 pmap[pattern] = list
2232 }
2233
2234 for file := range have {
2235 files = append(files, file)
2236 }
2237 sort.Strings(files)
2238 return files, pmap, nil
2239 }
2240
2241 func validEmbedPattern(pattern string) bool {
2242 return pattern != "." && fs.ValidPath(pattern)
2243 }
2244
2245
2246
2247
2248 func isBadEmbedName(name string) bool {
2249 if err := module.CheckFilePath(name); err != nil {
2250 return true
2251 }
2252 switch name {
2253
2254 case "":
2255 return true
2256
2257 case ".bzr", ".hg", ".git", ".svn":
2258 return true
2259 }
2260 return false
2261 }
2262
2263
2264
2265 var vcsStatusCache par.ErrCache[string, vcs.Status]
2266
2267 func appendBuildSetting(info *debug.BuildInfo, key, value string) {
2268 value = strings.ReplaceAll(value, "\n", " ")
2269 info.Settings = append(info.Settings, debug.BuildSetting{Key: key, Value: value})
2270 }
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281 func (p *Package) setBuildInfo(ctx context.Context, autoVCS bool) {
2282 setPkgErrorf := func(format string, args ...any) {
2283 if p.Error == nil {
2284 p.Error = &PackageError{Err: fmt.Errorf(format, args...)}
2285 p.Incomplete = true
2286 }
2287 }
2288
2289 var debugModFromModinfo func(*modinfo.ModulePublic) *debug.Module
2290 debugModFromModinfo = func(mi *modinfo.ModulePublic) *debug.Module {
2291 version := mi.Version
2292 if version == "" {
2293 version = "(devel)"
2294 }
2295 dm := &debug.Module{
2296 Path: mi.Path,
2297 Version: version,
2298 }
2299 if mi.Replace != nil {
2300 dm.Replace = debugModFromModinfo(mi.Replace)
2301 } else if mi.Version != "" && cfg.BuildMod != "vendor" {
2302 dm.Sum = modfetch.Sum(ctx, module.Version{Path: mi.Path, Version: mi.Version})
2303 }
2304 return dm
2305 }
2306
2307 var main debug.Module
2308 if p.Module != nil {
2309 main = *debugModFromModinfo(p.Module)
2310 }
2311
2312 visited := make(map[*Package]bool)
2313 mdeps := make(map[module.Version]*debug.Module)
2314 var q []*Package
2315 q = append(q, p.Internal.Imports...)
2316 for len(q) > 0 {
2317 p1 := q[0]
2318 q = q[1:]
2319 if visited[p1] {
2320 continue
2321 }
2322 visited[p1] = true
2323 if p1.Module != nil {
2324 m := module.Version{Path: p1.Module.Path, Version: p1.Module.Version}
2325 if p1.Module.Path != main.Path && mdeps[m] == nil {
2326 mdeps[m] = debugModFromModinfo(p1.Module)
2327 }
2328 }
2329 q = append(q, p1.Internal.Imports...)
2330 }
2331 sortedMods := make([]module.Version, 0, len(mdeps))
2332 for mod := range mdeps {
2333 sortedMods = append(sortedMods, mod)
2334 }
2335 gover.ModSort(sortedMods)
2336 deps := make([]*debug.Module, len(sortedMods))
2337 for i, mod := range sortedMods {
2338 deps[i] = mdeps[mod]
2339 }
2340
2341 pkgPath := p.ImportPath
2342 if p.Internal.CmdlineFiles {
2343 pkgPath = "command-line-arguments"
2344 }
2345 info := &debug.BuildInfo{
2346 Path: pkgPath,
2347 Main: main,
2348 Deps: deps,
2349 }
2350 appendSetting := func(key, value string) {
2351 appendBuildSetting(info, key, value)
2352 }
2353
2354
2355
2356
2357 if cfg.BuildASan {
2358 appendSetting("-asan", "true")
2359 }
2360 if BuildAsmflags.present {
2361 appendSetting("-asmflags", BuildAsmflags.String())
2362 }
2363 buildmode := cfg.BuildBuildmode
2364 if buildmode == "default" {
2365 if p.Name == "main" {
2366 buildmode = "exe"
2367 } else {
2368 buildmode = "archive"
2369 }
2370 }
2371 appendSetting("-buildmode", buildmode)
2372 appendSetting("-compiler", cfg.BuildContext.Compiler)
2373 if gccgoflags := BuildGccgoflags.String(); gccgoflags != "" && cfg.BuildContext.Compiler == "gccgo" {
2374 appendSetting("-gccgoflags", gccgoflags)
2375 }
2376 if gcflags := BuildGcflags.String(); gcflags != "" && cfg.BuildContext.Compiler == "gc" {
2377 appendSetting("-gcflags", gcflags)
2378 }
2379 if ldflags := BuildLdflags.String(); ldflags != "" {
2380
2381
2382
2383
2384
2385
2386
2387
2388 if !cfg.BuildTrimpath {
2389 appendSetting("-ldflags", ldflags)
2390 }
2391 }
2392 if cfg.BuildCover {
2393 appendSetting("-cover", "true")
2394 }
2395 if cfg.BuildMSan {
2396 appendSetting("-msan", "true")
2397 }
2398
2399 if cfg.BuildRace {
2400 appendSetting("-race", "true")
2401 }
2402 if tags := cfg.BuildContext.BuildTags; len(tags) > 0 {
2403 appendSetting("-tags", strings.Join(tags, ","))
2404 }
2405 if cfg.BuildTrimpath {
2406 appendSetting("-trimpath", "true")
2407 }
2408 if p.DefaultGODEBUG != "" {
2409 appendSetting("DefaultGODEBUG", p.DefaultGODEBUG)
2410 }
2411 cgo := "0"
2412 if cfg.BuildContext.CgoEnabled {
2413 cgo = "1"
2414 }
2415 appendSetting("CGO_ENABLED", cgo)
2416
2417
2418
2419
2420
2421
2422
2423 if cfg.BuildContext.CgoEnabled && !cfg.BuildTrimpath {
2424 for _, name := range []string{"CGO_CFLAGS", "CGO_CPPFLAGS", "CGO_CXXFLAGS", "CGO_LDFLAGS"} {
2425 appendSetting(name, cfg.Getenv(name))
2426 }
2427 }
2428 appendSetting("GOARCH", cfg.BuildContext.GOARCH)
2429 if cfg.RawGOEXPERIMENT != "" {
2430 appendSetting("GOEXPERIMENT", cfg.RawGOEXPERIMENT)
2431 }
2432 appendSetting("GOOS", cfg.BuildContext.GOOS)
2433 if key, val, _ := cfg.GetArchEnv(); key != "" && val != "" {
2434 appendSetting(key, val)
2435 }
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445 setVCSError := func(err error) {
2446 setPkgErrorf("error obtaining VCS status: %v\n\tUse -buildvcs=false to disable VCS stamping.", err)
2447 }
2448
2449 var repoDir string
2450 var vcsCmd *vcs.Cmd
2451 var err error
2452 const allowNesting = true
2453
2454 wantVCS := false
2455 switch cfg.BuildBuildvcs {
2456 case "true":
2457 wantVCS = true
2458 case "auto":
2459 wantVCS = autoVCS && !p.IsTestOnly()
2460 case "false":
2461 default:
2462 panic(fmt.Sprintf("unexpected value for cfg.BuildBuildvcs: %q", cfg.BuildBuildvcs))
2463 }
2464
2465 if wantVCS && p.Module != nil && p.Module.Version == "" && !p.Standard {
2466 if p.Module.Path == "bootstrap" && cfg.GOROOT == os.Getenv("GOROOT_BOOTSTRAP") {
2467
2468
2469
2470 goto omitVCS
2471 }
2472 repoDir, vcsCmd, err = vcs.FromDir(base.Cwd(), "", allowNesting)
2473 if err != nil && !errors.Is(err, os.ErrNotExist) {
2474 setVCSError(err)
2475 return
2476 }
2477 if !str.HasFilePathPrefix(p.Module.Dir, repoDir) &&
2478 !str.HasFilePathPrefix(repoDir, p.Module.Dir) {
2479
2480
2481
2482
2483 goto omitVCS
2484 }
2485 if cfg.BuildBuildvcs == "auto" && vcsCmd != nil && vcsCmd.Cmd != "" {
2486 if _, err := pathcache.LookPath(vcsCmd.Cmd); err != nil {
2487
2488
2489 goto omitVCS
2490 }
2491 }
2492 }
2493 if repoDir != "" && vcsCmd.Status != nil {
2494
2495
2496
2497
2498 pkgRepoDir, _, err := vcs.FromDir(p.Dir, "", allowNesting)
2499 if err != nil {
2500 setVCSError(err)
2501 return
2502 }
2503 if pkgRepoDir != repoDir {
2504 if cfg.BuildBuildvcs != "auto" {
2505 setVCSError(fmt.Errorf("main package is in repository %q but current directory is in repository %q", pkgRepoDir, repoDir))
2506 return
2507 }
2508 goto omitVCS
2509 }
2510 modRepoDir, _, err := vcs.FromDir(p.Module.Dir, "", allowNesting)
2511 if err != nil {
2512 setVCSError(err)
2513 return
2514 }
2515 if modRepoDir != repoDir {
2516 if cfg.BuildBuildvcs != "auto" {
2517 setVCSError(fmt.Errorf("main module is in repository %q but current directory is in repository %q", modRepoDir, repoDir))
2518 return
2519 }
2520 goto omitVCS
2521 }
2522
2523 st, err := vcsStatusCache.Do(repoDir, func() (vcs.Status, error) {
2524 return vcsCmd.Status(vcsCmd, repoDir)
2525 })
2526 if err != nil {
2527 setVCSError(err)
2528 return
2529 }
2530
2531 appendSetting("vcs", vcsCmd.Cmd)
2532 if st.Revision != "" {
2533 appendSetting("vcs.revision", st.Revision)
2534 }
2535 if !st.CommitTime.IsZero() {
2536 stamp := st.CommitTime.UTC().Format(time.RFC3339Nano)
2537 appendSetting("vcs.time", stamp)
2538 }
2539 appendSetting("vcs.modified", strconv.FormatBool(st.Uncommitted))
2540
2541 repo := modfetch.LookupLocal(ctx, repoDir)
2542 revInfo, err := repo.Stat(ctx, st.Revision)
2543 if err != nil {
2544 goto omitVCS
2545 }
2546 vers := revInfo.Version
2547 if vers != "" {
2548 if st.Uncommitted {
2549 vers += "+dirty"
2550 }
2551 info.Main.Version = vers
2552 }
2553 }
2554 omitVCS:
2555
2556 p.Internal.BuildInfo = info
2557 }
2558
2559
2560
2561
2562
2563
2564
2565
2566
2567
2568 func SafeArg(name string) bool {
2569 if name == "" {
2570 return false
2571 }
2572 c := name[0]
2573 return '0' <= c && c <= '9' || 'A' <= c && c <= 'Z' || 'a' <= c && c <= 'z' || c == '.' || c == '_' || c == '/' || c >= utf8.RuneSelf
2574 }
2575
2576
2577 func LinkerDeps(p *Package) ([]string, error) {
2578
2579 deps := []string{"runtime"}
2580
2581
2582 if what := externalLinkingReason(p); what != "" && cfg.BuildContext.Compiler != "gccgo" {
2583 if !cfg.BuildContext.CgoEnabled {
2584 return nil, fmt.Errorf("%s requires external (cgo) linking, but cgo is not enabled", what)
2585 }
2586 deps = append(deps, "runtime/cgo")
2587 }
2588
2589 if cfg.Goarch == "arm" {
2590 deps = append(deps, "math")
2591 }
2592
2593 if cfg.BuildRace {
2594 deps = append(deps, "runtime/race")
2595 }
2596
2597 if cfg.BuildMSan {
2598 deps = append(deps, "runtime/msan")
2599 }
2600
2601 if cfg.BuildASan {
2602 deps = append(deps, "runtime/asan")
2603 }
2604
2605 if cfg.BuildCover && cfg.Experiment.CoverageRedesign {
2606 deps = append(deps, "runtime/coverage")
2607 }
2608
2609 return deps, nil
2610 }
2611
2612
2613
2614
2615 func externalLinkingReason(p *Package) (what string) {
2616
2617 if platform.MustLinkExternal(cfg.Goos, cfg.Goarch, false) {
2618 return cfg.Goos + "/" + cfg.Goarch
2619 }
2620
2621
2622 switch cfg.BuildBuildmode {
2623 case "c-shared":
2624 if cfg.BuildContext.GOARCH == "wasm" {
2625 break
2626 }
2627 fallthrough
2628 case "plugin":
2629 return "-buildmode=" + cfg.BuildBuildmode
2630 }
2631
2632
2633 if cfg.BuildLinkshared {
2634 return "-linkshared"
2635 }
2636
2637
2638
2639 isPIE := false
2640 if cfg.BuildBuildmode == "pie" {
2641 isPIE = true
2642 } else if cfg.BuildBuildmode == "default" && platform.DefaultPIE(cfg.BuildContext.GOOS, cfg.BuildContext.GOARCH, cfg.BuildRace) {
2643 isPIE = true
2644 }
2645
2646
2647
2648 if isPIE && !platform.InternalLinkPIESupported(cfg.BuildContext.GOOS, cfg.BuildContext.GOARCH) {
2649 if cfg.BuildBuildmode == "pie" {
2650 return "-buildmode=pie"
2651 }
2652 return "default PIE binary"
2653 }
2654
2655
2656
2657 if p != nil {
2658 ldflags := BuildLdflags.For(p)
2659 for i := len(ldflags) - 1; i >= 0; i-- {
2660 a := ldflags[i]
2661 if a == "-linkmode=external" ||
2662 a == "-linkmode" && i+1 < len(ldflags) && ldflags[i+1] == "external" {
2663 return a
2664 } else if a == "-linkmode=internal" ||
2665 a == "-linkmode" && i+1 < len(ldflags) && ldflags[i+1] == "internal" {
2666 return ""
2667 }
2668 }
2669 }
2670
2671 return ""
2672 }
2673
2674
2675
2676
2677 func (p *Package) mkAbs(list []string) []string {
2678 for i, f := range list {
2679 list[i] = filepath.Join(p.Dir, f)
2680 }
2681 sort.Strings(list)
2682 return list
2683 }
2684
2685
2686
2687 func (p *Package) InternalGoFiles() []string {
2688 return p.mkAbs(str.StringList(p.GoFiles, p.CgoFiles, p.TestGoFiles))
2689 }
2690
2691
2692
2693 func (p *Package) InternalXGoFiles() []string {
2694 return p.mkAbs(p.XTestGoFiles)
2695 }
2696
2697
2698
2699
2700 func (p *Package) InternalAllGoFiles() []string {
2701 return p.mkAbs(str.StringList(p.IgnoredGoFiles, p.GoFiles, p.CgoFiles, p.TestGoFiles, p.XTestGoFiles))
2702 }
2703
2704
2705 func (p *Package) UsesSwig() bool {
2706 return len(p.SwigFiles) > 0 || len(p.SwigCXXFiles) > 0
2707 }
2708
2709
2710 func (p *Package) UsesCgo() bool {
2711 return len(p.CgoFiles) > 0
2712 }
2713
2714
2715
2716 func PackageList(roots []*Package) []*Package {
2717 seen := map[*Package]bool{}
2718 all := []*Package{}
2719 var walk func(*Package)
2720 walk = func(p *Package) {
2721 if seen[p] {
2722 return
2723 }
2724 seen[p] = true
2725 for _, p1 := range p.Internal.Imports {
2726 walk(p1)
2727 }
2728 all = append(all, p)
2729 }
2730 for _, root := range roots {
2731 walk(root)
2732 }
2733 return all
2734 }
2735
2736
2737
2738
2739 func TestPackageList(ctx context.Context, opts PackageOpts, roots []*Package) []*Package {
2740 seen := map[*Package]bool{}
2741 all := []*Package{}
2742 var walk func(*Package)
2743 walk = func(p *Package) {
2744 if seen[p] {
2745 return
2746 }
2747 seen[p] = true
2748 for _, p1 := range p.Internal.Imports {
2749 walk(p1)
2750 }
2751 all = append(all, p)
2752 }
2753 walkTest := func(root *Package, path string) {
2754 var stk ImportStack
2755 p1, err := loadImport(ctx, opts, nil, path, root.Dir, root, &stk, root.Internal.Build.TestImportPos[path], ResolveImport)
2756 if err != nil && root.Error == nil {
2757
2758 root.Error = err
2759 root.Incomplete = true
2760 }
2761 if p1.Error == nil {
2762 walk(p1)
2763 }
2764 }
2765 for _, root := range roots {
2766 walk(root)
2767 for _, path := range root.TestImports {
2768 walkTest(root, path)
2769 }
2770 for _, path := range root.XTestImports {
2771 walkTest(root, path)
2772 }
2773 }
2774 return all
2775 }
2776
2777
2778
2779
2780
2781
2782 func LoadImportWithFlags(path, srcDir string, parent *Package, stk *ImportStack, importPos []token.Position, mode int) (*Package, *PackageError) {
2783 p, err := loadImport(context.TODO(), PackageOpts{}, nil, path, srcDir, parent, stk, importPos, mode)
2784 setToolFlags(p)
2785 return p, err
2786 }
2787
2788
2789
2790 func LoadPackageWithFlags(path, srcDir string, stk *ImportStack, importPos []token.Position, mode int) *Package {
2791 p := LoadPackage(context.TODO(), PackageOpts{}, path, srcDir, stk, importPos, mode)
2792 setToolFlags(p)
2793 return p
2794 }
2795
2796
2797
2798 type PackageOpts struct {
2799
2800
2801
2802 IgnoreImports bool
2803
2804
2805
2806
2807
2808
2809
2810
2811 ModResolveTests bool
2812
2813
2814
2815
2816
2817
2818 MainOnly bool
2819
2820
2821
2822 AutoVCS bool
2823
2824
2825
2826 SuppressBuildInfo bool
2827
2828
2829
2830 SuppressEmbedFiles bool
2831 }
2832
2833
2834
2835
2836
2837
2838
2839
2840
2841 func PackagesAndErrors(ctx context.Context, opts PackageOpts, patterns []string) []*Package {
2842 ctx, span := trace.StartSpan(ctx, "load.PackagesAndErrors")
2843 defer span.Done()
2844
2845 for _, p := range patterns {
2846
2847
2848
2849 if strings.HasSuffix(p, ".go") {
2850
2851
2852 if fi, err := fsys.Stat(p); err == nil && !fi.IsDir() {
2853 pkgs := []*Package{GoFilesPackage(ctx, opts, patterns)}
2854 setPGOProfilePath(pkgs)
2855 return pkgs
2856 }
2857 }
2858 }
2859
2860 var matches []*search.Match
2861 if modload.Init(); cfg.ModulesEnabled {
2862 modOpts := modload.PackageOpts{
2863 ResolveMissingImports: true,
2864 LoadTests: opts.ModResolveTests,
2865 SilencePackageErrors: true,
2866 }
2867 matches, _ = modload.LoadPackages(ctx, modOpts, patterns...)
2868 } else {
2869 noModRoots := []string{}
2870 matches = search.ImportPaths(patterns, noModRoots)
2871 }
2872
2873 var (
2874 pkgs []*Package
2875 stk ImportStack
2876 seenPkg = make(map[*Package]bool)
2877 )
2878
2879 pre := newPreload()
2880 defer pre.flush()
2881 pre.preloadMatches(ctx, opts, matches)
2882
2883 for _, m := range matches {
2884 for _, pkg := range m.Pkgs {
2885 if pkg == "" {
2886 panic(fmt.Sprintf("ImportPaths returned empty package for pattern %s", m.Pattern()))
2887 }
2888 mode := cmdlinePkg
2889 if m.IsLiteral() {
2890
2891
2892
2893 mode |= cmdlinePkgLiteral
2894 }
2895 p, perr := loadImport(ctx, opts, pre, pkg, base.Cwd(), nil, &stk, nil, mode)
2896 if perr != nil {
2897 base.Fatalf("internal error: loadImport of %q with nil parent returned an error", pkg)
2898 }
2899 p.Match = append(p.Match, m.Pattern())
2900 if seenPkg[p] {
2901 continue
2902 }
2903 seenPkg[p] = true
2904 pkgs = append(pkgs, p)
2905 }
2906
2907 if len(m.Errs) > 0 {
2908
2909
2910
2911 p := new(Package)
2912 p.ImportPath = m.Pattern()
2913
2914 var stk ImportStack
2915 var importPos []token.Position
2916 p.setLoadPackageDataError(m.Errs[0], m.Pattern(), &stk, importPos)
2917 p.Incomplete = true
2918 p.Match = append(p.Match, m.Pattern())
2919 p.Internal.CmdlinePkg = true
2920 if m.IsLiteral() {
2921 p.Internal.CmdlinePkgLiteral = true
2922 }
2923 pkgs = append(pkgs, p)
2924 }
2925 }
2926
2927 if opts.MainOnly {
2928 pkgs = mainPackagesOnly(pkgs, matches)
2929 }
2930
2931
2932
2933
2934
2935 setToolFlags(pkgs...)
2936
2937 setPGOProfilePath(pkgs)
2938
2939 return pkgs
2940 }
2941
2942
2943
2944 func setPGOProfilePath(pkgs []*Package) {
2945 updateBuildInfo := func(p *Package, file string) {
2946
2947 if p.Internal.BuildInfo == nil {
2948 return
2949 }
2950
2951 if cfg.BuildTrimpath {
2952 appendBuildSetting(p.Internal.BuildInfo, "-pgo", filepath.Base(file))
2953 } else {
2954 appendBuildSetting(p.Internal.BuildInfo, "-pgo", file)
2955 }
2956
2957 slices.SortFunc(p.Internal.BuildInfo.Settings, func(x, y debug.BuildSetting) int {
2958 return strings.Compare(x.Key, y.Key)
2959 })
2960 }
2961
2962 switch cfg.BuildPGO {
2963 case "off":
2964 return
2965
2966 case "auto":
2967
2968
2969
2970
2971
2972
2973
2974 for _, p := range pkgs {
2975 if p.Name != "main" {
2976 continue
2977 }
2978 pmain := p
2979 file := filepath.Join(pmain.Dir, "default.pgo")
2980 if _, err := os.Stat(file); err != nil {
2981 continue
2982 }
2983
2984
2985
2986
2987 visited := make(map[*Package]*Package)
2988 var split func(p *Package) *Package
2989 split = func(p *Package) *Package {
2990 if p1 := visited[p]; p1 != nil {
2991 return p1
2992 }
2993
2994 if len(pkgs) > 1 && p != pmain {
2995
2996
2997
2998
2999 if p.Internal.PGOProfile != "" {
3000 panic("setPGOProfilePath: already have profile")
3001 }
3002 p1 := new(Package)
3003 *p1 = *p
3004
3005
3006
3007 p1.Imports = slices.Clone(p.Imports)
3008 p1.Internal.Imports = slices.Clone(p.Internal.Imports)
3009 p1.Internal.ForMain = pmain.ImportPath
3010 visited[p] = p1
3011 p = p1
3012 } else {
3013 visited[p] = p
3014 }
3015 p.Internal.PGOProfile = file
3016 updateBuildInfo(p, file)
3017
3018 for i, pp := range p.Internal.Imports {
3019 p.Internal.Imports[i] = split(pp)
3020 }
3021 return p
3022 }
3023
3024
3025 split(pmain)
3026 }
3027
3028 default:
3029
3030
3031 file, err := filepath.Abs(cfg.BuildPGO)
3032 if err != nil {
3033 base.Fatalf("fail to get absolute path of PGO file %s: %v", cfg.BuildPGO, err)
3034 }
3035
3036 for _, p := range PackageList(pkgs) {
3037 p.Internal.PGOProfile = file
3038 updateBuildInfo(p, file)
3039 }
3040 }
3041 }
3042
3043
3044
3045 func CheckPackageErrors(pkgs []*Package) {
3046 var anyIncomplete bool
3047 for _, pkg := range pkgs {
3048 if pkg.Incomplete {
3049 anyIncomplete = true
3050 }
3051 }
3052 if anyIncomplete {
3053 all := PackageList(pkgs)
3054 for _, p := range all {
3055 if p.Error != nil {
3056 base.Errorf("%v", p.Error)
3057 }
3058 }
3059 }
3060 base.ExitIfErrors()
3061
3062
3063
3064
3065
3066
3067 seen := map[string]bool{}
3068 reported := map[string]bool{}
3069 for _, pkg := range PackageList(pkgs) {
3070
3071
3072
3073 key := pkg.ImportPath
3074 if pkg.Internal.PGOProfile != "" {
3075 key += " pgo:" + pkg.Internal.PGOProfile
3076 }
3077 if seen[key] && !reported[key] {
3078 reported[key] = true
3079 base.Errorf("internal error: duplicate loads of %s", pkg.ImportPath)
3080 }
3081 seen[key] = true
3082 }
3083 base.ExitIfErrors()
3084 }
3085
3086
3087
3088
3089
3090
3091
3092
3093
3094
3095
3096
3097 func mainPackagesOnly(pkgs []*Package, matches []*search.Match) []*Package {
3098 treatAsMain := map[string]bool{}
3099 for _, m := range matches {
3100 if m.IsLiteral() {
3101 for _, path := range m.Pkgs {
3102 treatAsMain[path] = true
3103 }
3104 }
3105 }
3106
3107 var mains []*Package
3108 for _, pkg := range pkgs {
3109 if pkg.Name == "main" || (pkg.Name == "" && pkg.Error != nil) {
3110 treatAsMain[pkg.ImportPath] = true
3111 mains = append(mains, pkg)
3112 continue
3113 }
3114
3115 if len(pkg.InvalidGoFiles) > 0 {
3116
3117
3118
3119 treatAsMain[pkg.ImportPath] = true
3120 }
3121 if treatAsMain[pkg.ImportPath] {
3122 if pkg.Error == nil {
3123 pkg.Error = &PackageError{Err: &mainPackageError{importPath: pkg.ImportPath}}
3124 pkg.Incomplete = true
3125 }
3126 mains = append(mains, pkg)
3127 }
3128 }
3129
3130 for _, m := range matches {
3131 if m.IsLiteral() || len(m.Pkgs) == 0 {
3132 continue
3133 }
3134 foundMain := false
3135 for _, path := range m.Pkgs {
3136 if treatAsMain[path] {
3137 foundMain = true
3138 break
3139 }
3140 }
3141 if !foundMain {
3142 fmt.Fprintf(os.Stderr, "go: warning: %q matched only non-main packages\n", m.Pattern())
3143 }
3144 }
3145
3146 return mains
3147 }
3148
3149 type mainPackageError struct {
3150 importPath string
3151 }
3152
3153 func (e *mainPackageError) Error() string {
3154 return fmt.Sprintf("package %s is not a main package", e.importPath)
3155 }
3156
3157 func (e *mainPackageError) ImportPath() string {
3158 return e.importPath
3159 }
3160
3161 func setToolFlags(pkgs ...*Package) {
3162 for _, p := range PackageList(pkgs) {
3163 p.Internal.Asmflags = BuildAsmflags.For(p)
3164 p.Internal.Gcflags = BuildGcflags.For(p)
3165 p.Internal.Ldflags = BuildLdflags.For(p)
3166 p.Internal.Gccgoflags = BuildGccgoflags.For(p)
3167 }
3168 }
3169
3170
3171
3172
3173 func GoFilesPackage(ctx context.Context, opts PackageOpts, gofiles []string) *Package {
3174 modload.Init()
3175
3176 for _, f := range gofiles {
3177 if !strings.HasSuffix(f, ".go") {
3178 pkg := new(Package)
3179 pkg.Internal.Local = true
3180 pkg.Internal.CmdlineFiles = true
3181 pkg.Name = f
3182 pkg.Error = &PackageError{
3183 Err: fmt.Errorf("named files must be .go files: %s", pkg.Name),
3184 }
3185 pkg.Incomplete = true
3186 return pkg
3187 }
3188 }
3189
3190 var stk ImportStack
3191 ctxt := cfg.BuildContext
3192 ctxt.UseAllFiles = true
3193
3194
3195
3196
3197
3198 var dirent []fs.FileInfo
3199 var dir string
3200 for _, file := range gofiles {
3201 fi, err := fsys.Stat(file)
3202 if err != nil {
3203 base.Fatalf("%s", err)
3204 }
3205 if fi.IsDir() {
3206 base.Fatalf("%s is a directory, should be a Go file", file)
3207 }
3208 dir1 := filepath.Dir(file)
3209 if dir == "" {
3210 dir = dir1
3211 } else if dir != dir1 {
3212 base.Fatalf("named files must all be in one directory; have %s and %s", dir, dir1)
3213 }
3214 dirent = append(dirent, fi)
3215 }
3216 ctxt.ReadDir = func(string) ([]fs.FileInfo, error) { return dirent, nil }
3217
3218 if cfg.ModulesEnabled {
3219 modload.ImportFromFiles(ctx, gofiles)
3220 }
3221
3222 var err error
3223 if dir == "" {
3224 dir = base.Cwd()
3225 }
3226 dir, err = filepath.Abs(dir)
3227 if err != nil {
3228 base.Fatalf("%s", err)
3229 }
3230
3231 bp, err := ctxt.ImportDir(dir, 0)
3232 pkg := new(Package)
3233 pkg.Internal.Local = true
3234 pkg.Internal.CmdlineFiles = true
3235 pkg.load(ctx, opts, "command-line-arguments", &stk, nil, bp, err)
3236 if !cfg.ModulesEnabled {
3237 pkg.Internal.LocalPrefix = dirToImportPath(dir)
3238 }
3239 pkg.ImportPath = "command-line-arguments"
3240 pkg.Target = ""
3241 pkg.Match = gofiles
3242
3243 if pkg.Name == "main" {
3244 exe := pkg.DefaultExecName() + cfg.ExeSuffix
3245
3246 if cfg.GOBIN != "" {
3247 pkg.Target = filepath.Join(cfg.GOBIN, exe)
3248 } else if cfg.ModulesEnabled {
3249 pkg.Target = filepath.Join(modload.BinDir(), exe)
3250 }
3251 }
3252
3253 if opts.MainOnly && pkg.Name != "main" && pkg.Error == nil {
3254 pkg.Error = &PackageError{Err: &mainPackageError{importPath: pkg.ImportPath}}
3255 pkg.Incomplete = true
3256 }
3257 setToolFlags(pkg)
3258
3259 return pkg
3260 }
3261
3262
3263
3264
3265
3266
3267
3268
3269
3270
3271
3272
3273
3274
3275
3276
3277 func PackagesAndErrorsOutsideModule(ctx context.Context, opts PackageOpts, args []string) ([]*Package, error) {
3278 if !modload.ForceUseModules {
3279 panic("modload.ForceUseModules must be true")
3280 }
3281 if modload.RootMode != modload.NoRoot {
3282 panic("modload.RootMode must be NoRoot")
3283 }
3284
3285
3286 var version string
3287 var firstPath string
3288 for _, arg := range args {
3289 if i := strings.Index(arg, "@"); i >= 0 {
3290 firstPath, version = arg[:i], arg[i+1:]
3291 if version == "" {
3292 return nil, fmt.Errorf("%s: version must not be empty", arg)
3293 }
3294 break
3295 }
3296 }
3297 patterns := make([]string, len(args))
3298 for i, arg := range args {
3299 p, found := strings.CutSuffix(arg, "@"+version)
3300 if !found {
3301 return nil, fmt.Errorf("%s: all arguments must refer to packages in the same module at the same version (@%s)", arg, version)
3302 }
3303 switch {
3304 case build.IsLocalImport(p):
3305 return nil, fmt.Errorf("%s: argument must be a package path, not a relative path", arg)
3306 case filepath.IsAbs(p):
3307 return nil, fmt.Errorf("%s: argument must be a package path, not an absolute path", arg)
3308 case search.IsMetaPackage(p):
3309 return nil, fmt.Errorf("%s: argument must be a package path, not a meta-package", arg)
3310 case pathpkg.Clean(p) != p:
3311 return nil, fmt.Errorf("%s: argument must be a clean package path", arg)
3312 case !strings.Contains(p, "...") && search.IsStandardImportPath(p) && modindex.IsStandardPackage(cfg.GOROOT, cfg.BuildContext.Compiler, p):
3313 return nil, fmt.Errorf("%s: argument must not be a package in the standard library", arg)
3314 default:
3315 patterns[i] = p
3316 }
3317 }
3318
3319
3320
3321
3322
3323
3324
3325
3326
3327 allowed := modload.CheckAllowed
3328 if modload.IsRevisionQuery(firstPath, version) {
3329
3330 allowed = nil
3331 }
3332 noneSelected := func(path string) (version string) { return "none" }
3333 qrs, err := modload.QueryPackages(ctx, patterns[0], version, noneSelected, allowed)
3334 if err != nil {
3335 return nil, fmt.Errorf("%s: %w", args[0], err)
3336 }
3337 rootMod := qrs[0].Mod
3338 deprecation, err := modload.CheckDeprecation(ctx, rootMod)
3339 if err != nil {
3340 return nil, fmt.Errorf("%s: %w", args[0], err)
3341 }
3342 if deprecation != "" {
3343 fmt.Fprintf(os.Stderr, "go: module %s is deprecated: %s\n", rootMod.Path, modload.ShortMessage(deprecation, ""))
3344 }
3345 data, err := modfetch.GoMod(ctx, rootMod.Path, rootMod.Version)
3346 if err != nil {
3347 return nil, fmt.Errorf("%s: %w", args[0], err)
3348 }
3349 f, err := modfile.Parse("go.mod", data, nil)
3350 if err != nil {
3351 return nil, fmt.Errorf("%s (in %s): %w", args[0], rootMod, err)
3352 }
3353 directiveFmt := "%s (in %s):\n" +
3354 "\tThe go.mod file for the module providing named packages contains one or\n" +
3355 "\tmore %s directives. It must not contain directives that would cause\n" +
3356 "\tit to be interpreted differently than if it were the main module."
3357 if len(f.Replace) > 0 {
3358 return nil, fmt.Errorf(directiveFmt, args[0], rootMod, "replace")
3359 }
3360 if len(f.Exclude) > 0 {
3361 return nil, fmt.Errorf(directiveFmt, args[0], rootMod, "exclude")
3362 }
3363
3364
3365
3366
3367 if _, err := modload.EditBuildList(ctx, nil, []module.Version{rootMod}); err != nil {
3368 return nil, fmt.Errorf("%s: %w", args[0], err)
3369 }
3370
3371
3372 pkgs := PackagesAndErrors(ctx, opts, patterns)
3373
3374
3375 for _, pkg := range pkgs {
3376 var pkgErr error
3377 if pkg.Module == nil {
3378
3379
3380 pkgErr = fmt.Errorf("package %s not provided by module %s", pkg.ImportPath, rootMod)
3381 } else if pkg.Module.Path != rootMod.Path || pkg.Module.Version != rootMod.Version {
3382 pkgErr = fmt.Errorf("package %s provided by module %s@%s\n\tAll packages must be provided by the same module (%s).", pkg.ImportPath, pkg.Module.Path, pkg.Module.Version, rootMod)
3383 }
3384 if pkgErr != nil && pkg.Error == nil {
3385 pkg.Error = &PackageError{Err: pkgErr}
3386 pkg.Incomplete = true
3387 }
3388 }
3389
3390 matchers := make([]func(string) bool, len(patterns))
3391 for i, p := range patterns {
3392 if strings.Contains(p, "...") {
3393 matchers[i] = pkgpattern.MatchPattern(p)
3394 }
3395 }
3396 return pkgs, nil
3397 }
3398
3399
3400 func EnsureImport(p *Package, pkg string) {
3401 for _, d := range p.Internal.Imports {
3402 if d.Name == pkg {
3403 return
3404 }
3405 }
3406
3407 p1, err := LoadImportWithFlags(pkg, p.Dir, p, &ImportStack{}, nil, 0)
3408 if err != nil {
3409 base.Fatalf("load %s: %v", pkg, err)
3410 }
3411 if p1.Error != nil {
3412 base.Fatalf("load %s: %v", pkg, p1.Error)
3413 }
3414
3415 p.Internal.Imports = append(p.Internal.Imports, p1)
3416 }
3417
3418
3419
3420
3421
3422
3423 func PrepareForCoverageBuild(pkgs []*Package) {
3424 var match []func(*Package) bool
3425
3426 matchMainModAndCommandLine := func(p *Package) bool {
3427
3428 return p.Internal.CmdlineFiles || p.Internal.CmdlinePkg || (p.Module != nil && p.Module.Main)
3429 }
3430
3431 if len(cfg.BuildCoverPkg) != 0 {
3432
3433
3434 match = make([]func(*Package) bool, len(cfg.BuildCoverPkg))
3435 for i := range cfg.BuildCoverPkg {
3436 match[i] = MatchPackage(cfg.BuildCoverPkg[i], base.Cwd())
3437 }
3438 } else {
3439
3440
3441
3442 match = []func(*Package) bool{matchMainModAndCommandLine}
3443 }
3444
3445
3446
3447
3448 SelectCoverPackages(PackageList(pkgs), match, "build")
3449 }
3450
3451 func SelectCoverPackages(roots []*Package, match []func(*Package) bool, op string) []*Package {
3452 var warntag string
3453 var includeMain bool
3454 switch op {
3455 case "build":
3456 warntag = "built"
3457 includeMain = true
3458 case "test":
3459 warntag = "tested"
3460 default:
3461 panic("internal error, bad mode passed to SelectCoverPackages")
3462 }
3463
3464 covered := []*Package{}
3465 matched := make([]bool, len(match))
3466 for _, p := range roots {
3467 haveMatch := false
3468 for i := range match {
3469 if match[i](p) {
3470 matched[i] = true
3471 haveMatch = true
3472 }
3473 }
3474 if !haveMatch {
3475 continue
3476 }
3477
3478
3479
3480 if p.ImportPath == "unsafe" {
3481 continue
3482 }
3483
3484
3485
3486
3487
3488
3489
3490
3491 if len(p.GoFiles)+len(p.CgoFiles) == 0 {
3492 continue
3493 }
3494
3495
3496
3497
3498
3499 if cfg.BuildCoverMode == "atomic" && p.Standard &&
3500 (p.ImportPath == "sync/atomic" || p.ImportPath == "internal/runtime/atomic") {
3501 continue
3502 }
3503
3504
3505
3506
3507
3508
3509
3510
3511
3512 cmode := cfg.BuildCoverMode
3513 if cfg.BuildRace && p.Standard && (p.ImportPath == "runtime" || strings.HasPrefix(p.ImportPath, "runtime/internal")) {
3514 cmode = "regonly"
3515 }
3516
3517
3518
3519
3520 if includeMain && p.Name == "main" && !haveMatch {
3521 haveMatch = true
3522 cmode = "regonly"
3523 }
3524
3525
3526 p.Internal.Cover.Mode = cmode
3527 covered = append(covered, p)
3528
3529
3530 if cfg.BuildCoverMode == "atomic" {
3531 EnsureImport(p, "sync/atomic")
3532 }
3533
3534
3535 if !cfg.Experiment.CoverageRedesign {
3536 var coverFiles []string
3537 coverFiles = append(coverFiles, p.GoFiles...)
3538 coverFiles = append(coverFiles, p.CgoFiles...)
3539 p.Internal.CoverVars = DeclareCoverVars(p, coverFiles...)
3540 }
3541 }
3542
3543
3544 for i := range cfg.BuildCoverPkg {
3545 if !matched[i] {
3546 fmt.Fprintf(os.Stderr, "warning: no packages being %s depend on matches for pattern %s\n", warntag, cfg.BuildCoverPkg[i])
3547 }
3548 }
3549
3550 return covered
3551 }
3552
3553
3554
3555
3556
3557 func DeclareCoverVars(p *Package, files ...string) map[string]*CoverVar {
3558 coverVars := make(map[string]*CoverVar)
3559 coverIndex := 0
3560
3561
3562
3563
3564
3565
3566 sum := sha256.Sum256([]byte(p.ImportPath))
3567 h := fmt.Sprintf("%x", sum[:6])
3568 for _, file := range files {
3569 if base.IsTestFile(file) {
3570 continue
3571 }
3572
3573
3574
3575
3576
3577 var longFile string
3578 if p.Internal.Local {
3579 longFile = filepath.Join(p.Dir, file)
3580 } else {
3581 longFile = pathpkg.Join(p.ImportPath, file)
3582 }
3583 coverVars[file] = &CoverVar{
3584 File: longFile,
3585 Var: fmt.Sprintf("GoCover_%d_%x", coverIndex, h),
3586 }
3587 coverIndex++
3588 }
3589 return coverVars
3590 }
3591
View as plain text