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