1
2
3
4
5
6
7 package work
8
9 import (
10 "bufio"
11 "bytes"
12 "cmd/internal/cov/covcmd"
13 "container/heap"
14 "context"
15 "debug/elf"
16 "encoding/json"
17 "fmt"
18 "internal/platform"
19 "os"
20 "path/filepath"
21 "strings"
22 "sync"
23 "time"
24
25 "cmd/go/internal/base"
26 "cmd/go/internal/cache"
27 "cmd/go/internal/cfg"
28 "cmd/go/internal/load"
29 "cmd/go/internal/robustio"
30 "cmd/go/internal/str"
31 "cmd/go/internal/trace"
32 "cmd/internal/buildid"
33 )
34
35
36
37
38 type Builder struct {
39 WorkDir string
40 actionCache map[cacheKey]*Action
41 flagCache map[[2]string]bool
42 gccCompilerIDCache map[string]cache.ActionID
43
44 IsCmdList bool
45 NeedError bool
46 NeedExport bool
47 NeedCompiledGoFiles bool
48 AllowErrors bool
49
50 objdirSeq int
51 pkgSeq int
52
53 backgroundSh *Shell
54
55 exec sync.Mutex
56 readySema chan bool
57 ready actionQueue
58
59 id sync.Mutex
60 toolIDCache map[string]string
61 buildIDCache map[string]string
62 }
63
64
65
66
67
68 type Actor interface {
69 Act(*Builder, context.Context, *Action) error
70 }
71
72
73 type ActorFunc func(*Builder, context.Context, *Action) error
74
75 func (f ActorFunc) Act(b *Builder, ctx context.Context, a *Action) error {
76 return f(b, ctx, a)
77 }
78
79
80 type Action struct {
81 Mode string
82 Package *load.Package
83 Deps []*Action
84 Actor Actor
85 IgnoreFail bool
86 TestOutput *bytes.Buffer
87 Args []string
88
89 triggers []*Action
90
91 buggyInstall bool
92
93 TryCache func(*Builder, *Action) bool
94
95
96 Objdir string
97 Target string
98 built string
99 actionID cache.ActionID
100 buildID string
101
102 VetxOnly bool
103 needVet bool
104 needBuild bool
105 vetCfg *vetConfig
106 output []byte
107
108 sh *Shell
109
110
111 pending int
112 priority int
113 Failed bool
114 json *actionJSON
115 nonGoOverlay map[string]string
116 traceSpan *trace.Span
117 }
118
119
120 func (a *Action) BuildActionID() string { return actionID(a.buildID) }
121
122
123 func (a *Action) BuildContentID() string { return contentID(a.buildID) }
124
125
126 func (a *Action) BuildID() string { return a.buildID }
127
128
129
130 func (a *Action) BuiltTarget() string { return a.built }
131
132
133 type actionQueue []*Action
134
135
136 func (q *actionQueue) Len() int { return len(*q) }
137 func (q *actionQueue) Swap(i, j int) { (*q)[i], (*q)[j] = (*q)[j], (*q)[i] }
138 func (q *actionQueue) Less(i, j int) bool { return (*q)[i].priority < (*q)[j].priority }
139 func (q *actionQueue) Push(x any) { *q = append(*q, x.(*Action)) }
140 func (q *actionQueue) Pop() any {
141 n := len(*q) - 1
142 x := (*q)[n]
143 *q = (*q)[:n]
144 return x
145 }
146
147 func (q *actionQueue) push(a *Action) {
148 if a.json != nil {
149 a.json.TimeReady = time.Now()
150 }
151 heap.Push(q, a)
152 }
153
154 func (q *actionQueue) pop() *Action {
155 return heap.Pop(q).(*Action)
156 }
157
158 type actionJSON struct {
159 ID int
160 Mode string
161 Package string
162 Deps []int `json:",omitempty"`
163 IgnoreFail bool `json:",omitempty"`
164 Args []string `json:",omitempty"`
165 Link bool `json:",omitempty"`
166 Objdir string `json:",omitempty"`
167 Target string `json:",omitempty"`
168 Priority int `json:",omitempty"`
169 Failed bool `json:",omitempty"`
170 Built string `json:",omitempty"`
171 VetxOnly bool `json:",omitempty"`
172 NeedVet bool `json:",omitempty"`
173 NeedBuild bool `json:",omitempty"`
174 ActionID string `json:",omitempty"`
175 BuildID string `json:",omitempty"`
176 TimeReady time.Time `json:",omitempty"`
177 TimeStart time.Time `json:",omitempty"`
178 TimeDone time.Time `json:",omitempty"`
179
180 Cmd []string
181 CmdReal time.Duration `json:",omitempty"`
182 CmdUser time.Duration `json:",omitempty"`
183 CmdSys time.Duration `json:",omitempty"`
184 }
185
186
187 type cacheKey struct {
188 mode string
189 p *load.Package
190 }
191
192 func actionGraphJSON(a *Action) string {
193 var workq []*Action
194 var inWorkq = make(map[*Action]int)
195
196 add := func(a *Action) {
197 if _, ok := inWorkq[a]; ok {
198 return
199 }
200 inWorkq[a] = len(workq)
201 workq = append(workq, a)
202 }
203 add(a)
204
205 for i := 0; i < len(workq); i++ {
206 for _, dep := range workq[i].Deps {
207 add(dep)
208 }
209 }
210
211 var list []*actionJSON
212 for id, a := range workq {
213 if a.json == nil {
214 a.json = &actionJSON{
215 Mode: a.Mode,
216 ID: id,
217 IgnoreFail: a.IgnoreFail,
218 Args: a.Args,
219 Objdir: a.Objdir,
220 Target: a.Target,
221 Failed: a.Failed,
222 Priority: a.priority,
223 Built: a.built,
224 VetxOnly: a.VetxOnly,
225 NeedBuild: a.needBuild,
226 NeedVet: a.needVet,
227 }
228 if a.Package != nil {
229
230 a.json.Package = a.Package.ImportPath
231 }
232 for _, a1 := range a.Deps {
233 a.json.Deps = append(a.json.Deps, inWorkq[a1])
234 }
235 }
236 list = append(list, a.json)
237 }
238
239 js, err := json.MarshalIndent(list, "", "\t")
240 if err != nil {
241 fmt.Fprintf(os.Stderr, "go: writing debug action graph: %v\n", err)
242 return ""
243 }
244 return string(js)
245 }
246
247
248
249 type BuildMode int
250
251 const (
252 ModeBuild BuildMode = iota
253 ModeInstall
254 ModeBuggyInstall
255
256 ModeVetOnly = 1 << 8
257 )
258
259
260
261
262
263
264
265 func NewBuilder(workDir string) *Builder {
266 b := new(Builder)
267
268 b.actionCache = make(map[cacheKey]*Action)
269 b.toolIDCache = make(map[string]string)
270 b.buildIDCache = make(map[string]string)
271
272 if workDir != "" {
273 b.WorkDir = workDir
274 } else if cfg.BuildN {
275 b.WorkDir = "$WORK"
276 } else {
277 if !buildInitStarted {
278 panic("internal error: NewBuilder called before BuildInit")
279 }
280 tmp, err := os.MkdirTemp(cfg.Getenv("GOTMPDIR"), "go-build")
281 if err != nil {
282 base.Fatalf("go: creating work dir: %v", err)
283 }
284 if !filepath.IsAbs(tmp) {
285 abs, err := filepath.Abs(tmp)
286 if err != nil {
287 os.RemoveAll(tmp)
288 base.Fatalf("go: creating work dir: %v", err)
289 }
290 tmp = abs
291 }
292 b.WorkDir = tmp
293 builderWorkDirs.Store(b, b.WorkDir)
294 if cfg.BuildX || cfg.BuildWork {
295 fmt.Fprintf(os.Stderr, "WORK=%s\n", b.WorkDir)
296 }
297 }
298
299 b.backgroundSh = NewShell(b.WorkDir, nil)
300
301 if err := CheckGOOSARCHPair(cfg.Goos, cfg.Goarch); err != nil {
302 fmt.Fprintf(os.Stderr, "go: %v\n", err)
303 base.SetExitStatus(2)
304 base.Exit()
305 }
306
307 for _, tag := range cfg.BuildContext.BuildTags {
308 if strings.Contains(tag, ",") {
309 fmt.Fprintf(os.Stderr, "go: -tags space-separated list contains comma\n")
310 base.SetExitStatus(2)
311 base.Exit()
312 }
313 }
314
315 return b
316 }
317
318 var builderWorkDirs sync.Map
319
320 func (b *Builder) Close() error {
321 wd, ok := builderWorkDirs.Load(b)
322 if !ok {
323 return nil
324 }
325 defer builderWorkDirs.Delete(b)
326
327 if b.WorkDir != wd.(string) {
328 base.Errorf("go: internal error: Builder WorkDir unexpectedly changed from %s to %s", wd, b.WorkDir)
329 }
330
331 if !cfg.BuildWork {
332 if err := robustio.RemoveAll(b.WorkDir); err != nil {
333 return err
334 }
335 }
336 b.WorkDir = ""
337 return nil
338 }
339
340 func closeBuilders() {
341 leakedBuilders := 0
342 builderWorkDirs.Range(func(bi, _ any) bool {
343 leakedBuilders++
344 if err := bi.(*Builder).Close(); err != nil {
345 base.Error(err)
346 }
347 return true
348 })
349
350 if leakedBuilders > 0 && base.GetExitStatus() == 0 {
351 fmt.Fprintf(os.Stderr, "go: internal error: Builder leaked on successful exit\n")
352 base.SetExitStatus(1)
353 }
354 }
355
356 func CheckGOOSARCHPair(goos, goarch string) error {
357 if !platform.BuildModeSupported(cfg.BuildContext.Compiler, "default", goos, goarch) {
358 return fmt.Errorf("unsupported GOOS/GOARCH pair %s/%s", goos, goarch)
359 }
360 return nil
361 }
362
363
364
365
366
367
368
369
370
371 func (b *Builder) NewObjdir() string {
372 b.objdirSeq++
373 return str.WithFilePathSeparator(filepath.Join(b.WorkDir, fmt.Sprintf("b%03d", b.objdirSeq)))
374 }
375
376
377
378
379
380 func readpkglist(shlibpath string) (pkgs []*load.Package) {
381 var stk load.ImportStack
382 if cfg.BuildToolchainName == "gccgo" {
383 f, err := elf.Open(shlibpath)
384 if err != nil {
385 base.Fatal(fmt.Errorf("failed to open shared library: %v", err))
386 }
387 sect := f.Section(".go_export")
388 if sect == nil {
389 base.Fatal(fmt.Errorf("%s: missing .go_export section", shlibpath))
390 }
391 data, err := sect.Data()
392 if err != nil {
393 base.Fatal(fmt.Errorf("%s: failed to read .go_export section: %v", shlibpath, err))
394 }
395 pkgpath := []byte("pkgpath ")
396 for _, line := range bytes.Split(data, []byte{'\n'}) {
397 if path, found := bytes.CutPrefix(line, pkgpath); found {
398 path = bytes.TrimSuffix(path, []byte{';'})
399 pkgs = append(pkgs, load.LoadPackageWithFlags(string(path), base.Cwd(), &stk, nil, 0))
400 }
401 }
402 } else {
403 pkglistbytes, err := buildid.ReadELFNote(shlibpath, "Go\x00\x00", 1)
404 if err != nil {
405 base.Fatalf("readELFNote failed: %v", err)
406 }
407 scanner := bufio.NewScanner(bytes.NewBuffer(pkglistbytes))
408 for scanner.Scan() {
409 t := scanner.Text()
410 pkgs = append(pkgs, load.LoadPackageWithFlags(t, base.Cwd(), &stk, nil, 0))
411 }
412 }
413 return
414 }
415
416
417
418
419
420 func (b *Builder) cacheAction(mode string, p *load.Package, f func() *Action) *Action {
421 a := b.actionCache[cacheKey{mode, p}]
422 if a == nil {
423 a = f()
424 b.actionCache[cacheKey{mode, p}] = a
425 }
426 return a
427 }
428
429
430 func (b *Builder) AutoAction(mode, depMode BuildMode, p *load.Package) *Action {
431 if p.Name == "main" {
432 return b.LinkAction(mode, depMode, p)
433 }
434 return b.CompileAction(mode, depMode, p)
435 }
436
437
438
439
440
441
442 type buildActor struct {
443
444
445
446 covMetaFileName string
447 }
448
449
450
451 func newBuildActor(p *load.Package, genCoverMeta bool) *buildActor {
452 ba := &buildActor{}
453 if genCoverMeta {
454 ba.covMetaFileName = covcmd.MetaFileForPackage(p.ImportPath)
455 }
456 return ba
457 }
458
459 func (ba *buildActor) Act(b *Builder, ctx context.Context, a *Action) error {
460 return b.build(ctx, a)
461 }
462
463
464
465
466
467
468 func (b *Builder) CompileAction(mode, depMode BuildMode, p *load.Package) *Action {
469 vetOnly := mode&ModeVetOnly != 0
470 mode &^= ModeVetOnly
471
472 if mode != ModeBuild && p.Target == "" {
473
474 mode = ModeBuild
475 }
476 if mode != ModeBuild && p.Name == "main" {
477
478 mode = ModeBuild
479 }
480
481
482 a := b.cacheAction("build", p, func() *Action {
483 a := &Action{
484 Mode: "build",
485 Package: p,
486 Actor: newBuildActor(p, p.Internal.Cover.GenMeta),
487 Objdir: b.NewObjdir(),
488 }
489
490 if p.Error == nil || !p.Error.IsImportCycle {
491 for _, p1 := range p.Internal.Imports {
492 a.Deps = append(a.Deps, b.CompileAction(depMode, depMode, p1))
493 }
494 }
495
496 if p.Standard {
497 switch p.ImportPath {
498 case "builtin", "unsafe":
499
500 a.Mode = "built-in package"
501 a.Actor = nil
502 return a
503 }
504
505
506 if cfg.BuildToolchainName == "gccgo" {
507
508 a.Mode = "gccgo stdlib"
509 a.Target = p.Target
510 a.Actor = nil
511 return a
512 }
513 }
514
515 return a
516 })
517
518
519
520 buildAction := a
521 switch buildAction.Mode {
522 case "build", "built-in package", "gccgo stdlib":
523
524 case "build-install":
525 buildAction = a.Deps[0]
526 default:
527 panic("lost build action: " + buildAction.Mode)
528 }
529 buildAction.needBuild = buildAction.needBuild || !vetOnly
530
531
532 if mode == ModeInstall || mode == ModeBuggyInstall {
533 a = b.installAction(a, mode)
534 }
535
536 return a
537 }
538
539
540
541
542
543 func (b *Builder) VetAction(mode, depMode BuildMode, p *load.Package) *Action {
544 a := b.vetAction(mode, depMode, p)
545 a.VetxOnly = false
546 return a
547 }
548
549 func (b *Builder) vetAction(mode, depMode BuildMode, p *load.Package) *Action {
550
551 a := b.cacheAction("vet", p, func() *Action {
552 a1 := b.CompileAction(mode|ModeVetOnly, depMode, p)
553
554
555 var stk load.ImportStack
556 stk.Push("vet")
557 p1, err := load.LoadImportWithFlags("fmt", p.Dir, p, &stk, nil, 0)
558 if err != nil {
559 base.Fatalf("unexpected error loading fmt package from package %s: %v", p.ImportPath, err)
560 }
561 stk.Pop()
562 aFmt := b.CompileAction(ModeBuild, depMode, p1)
563
564 var deps []*Action
565 if a1.buggyInstall {
566
567
568
569
570 deps = []*Action{a1.Deps[0], aFmt, a1}
571 } else {
572 deps = []*Action{a1, aFmt}
573 }
574 for _, p1 := range p.Internal.Imports {
575 deps = append(deps, b.vetAction(mode, depMode, p1))
576 }
577
578 a := &Action{
579 Mode: "vet",
580 Package: p,
581 Deps: deps,
582 Objdir: a1.Objdir,
583 VetxOnly: true,
584 IgnoreFail: true,
585 }
586 if a1.Actor == nil {
587
588 return a
589 }
590 deps[0].needVet = true
591 a.Actor = ActorFunc((*Builder).vet)
592 return a
593 })
594 return a
595 }
596
597
598
599
600 func (b *Builder) LinkAction(mode, depMode BuildMode, p *load.Package) *Action {
601
602 a := b.cacheAction("link", p, func() *Action {
603 a := &Action{
604 Mode: "link",
605 Package: p,
606 }
607
608 a1 := b.CompileAction(ModeBuild, depMode, p)
609 a.Actor = ActorFunc((*Builder).link)
610 a.Deps = []*Action{a1}
611 a.Objdir = a1.Objdir
612
613
614
615
616
617
618
619
620 name := "a.out"
621 if p.Internal.ExeName != "" {
622 name = p.Internal.ExeName
623 } else if (cfg.Goos == "darwin" || cfg.Goos == "windows") && cfg.BuildBuildmode == "c-shared" && p.Target != "" {
624
625
626
627
628
629
630
631 _, name = filepath.Split(p.Target)
632 }
633 a.Target = a.Objdir + filepath.Join("exe", name) + cfg.ExeSuffix
634 a.built = a.Target
635 b.addTransitiveLinkDeps(a, a1, "")
636
637
638
639
640
641
642
643
644 a1.Deps = append(a1.Deps, &Action{Mode: "nop", Deps: a.Deps[1:]})
645 return a
646 })
647
648 if mode == ModeInstall || mode == ModeBuggyInstall {
649 a = b.installAction(a, mode)
650 }
651
652 return a
653 }
654
655
656 func (b *Builder) installAction(a1 *Action, mode BuildMode) *Action {
657
658
659
660 if strings.HasSuffix(a1.Mode, "-install") {
661 if a1.buggyInstall && mode == ModeInstall {
662
663 a1.buggyInstall = false
664 }
665 return a1
666 }
667
668
669
670
671 if a1.Actor == nil {
672 return a1
673 }
674
675 p := a1.Package
676 return b.cacheAction(a1.Mode+"-install", p, func() *Action {
677
678
679
680
681
682
683
684 buildAction := new(Action)
685 *buildAction = *a1
686
687
688
689
690
691
692
693
694
695 *a1 = Action{
696 Mode: buildAction.Mode + "-install",
697 Actor: ActorFunc(BuildInstallFunc),
698 Package: p,
699 Objdir: buildAction.Objdir,
700 Deps: []*Action{buildAction},
701 Target: p.Target,
702 built: p.Target,
703
704 buggyInstall: mode == ModeBuggyInstall,
705 }
706
707 b.addInstallHeaderAction(a1)
708 return a1
709 })
710 }
711
712
713
714
715
716
717
718
719
720
721 func (b *Builder) addTransitiveLinkDeps(a, a1 *Action, shlib string) {
722
723
724
725
726
727 workq := []*Action{a1}
728 haveDep := map[string]bool{}
729 if a1.Package != nil {
730 haveDep[a1.Package.ImportPath] = true
731 }
732 for i := 0; i < len(workq); i++ {
733 a1 := workq[i]
734 for _, a2 := range a1.Deps {
735
736 if a2.Package == nil || (a2.Mode != "build-install" && a2.Mode != "build") || haveDep[a2.Package.ImportPath] {
737 continue
738 }
739 haveDep[a2.Package.ImportPath] = true
740 a.Deps = append(a.Deps, a2)
741 if a2.Mode == "build-install" {
742 a2 = a2.Deps[0]
743 }
744 workq = append(workq, a2)
745 }
746 }
747
748
749
750 if cfg.BuildLinkshared {
751 haveShlib := map[string]bool{shlib: true}
752 for _, a1 := range a.Deps {
753 p1 := a1.Package
754 if p1 == nil || p1.Shlib == "" || haveShlib[filepath.Base(p1.Shlib)] {
755 continue
756 }
757 haveShlib[filepath.Base(p1.Shlib)] = true
758
759
760
761
762 a.Deps = append(a.Deps, b.linkSharedAction(ModeBuggyInstall, ModeBuggyInstall, p1.Shlib, nil))
763 }
764 }
765 }
766
767
768
769
770
771 func (b *Builder) addInstallHeaderAction(a *Action) {
772
773 p := a.Package
774 if p.UsesCgo() && (cfg.BuildBuildmode == "c-archive" || cfg.BuildBuildmode == "c-shared") {
775 hdrTarget := a.Target[:len(a.Target)-len(filepath.Ext(a.Target))] + ".h"
776 if cfg.BuildContext.Compiler == "gccgo" && cfg.BuildO == "" {
777
778
779
780 dir, file := filepath.Split(hdrTarget)
781 file = strings.TrimPrefix(file, "lib")
782 hdrTarget = filepath.Join(dir, file)
783 }
784 ah := &Action{
785 Mode: "install header",
786 Package: a.Package,
787 Deps: []*Action{a.Deps[0]},
788 Actor: ActorFunc((*Builder).installHeader),
789 Objdir: a.Deps[0].Objdir,
790 Target: hdrTarget,
791 }
792 a.Deps = append(a.Deps, ah)
793 }
794 }
795
796
797
798 func (b *Builder) buildmodeShared(mode, depMode BuildMode, args []string, pkgs []*load.Package, a1 *Action) *Action {
799 name, err := libname(args, pkgs)
800 if err != nil {
801 base.Fatalf("%v", err)
802 }
803 return b.linkSharedAction(mode, depMode, name, a1)
804 }
805
806
807
808
809
810 func (b *Builder) linkSharedAction(mode, depMode BuildMode, shlib string, a1 *Action) *Action {
811 fullShlib := shlib
812 shlib = filepath.Base(shlib)
813 a := b.cacheAction("build-shlib "+shlib, nil, func() *Action {
814 if a1 == nil {
815
816
817 pkgs := readpkglist(fullShlib)
818 a1 = &Action{
819 Mode: "shlib packages",
820 }
821 for _, p := range pkgs {
822 a1.Deps = append(a1.Deps, b.CompileAction(mode, depMode, p))
823 }
824 }
825
826
827
828
829 p := &load.Package{}
830 p.Internal.CmdlinePkg = true
831 p.Internal.Ldflags = load.BuildLdflags.For(p)
832 p.Internal.Gccgoflags = load.BuildGccgoflags.For(p)
833
834
835
836
837
838
839
840
841
842
843
844 a := &Action{
845 Mode: "go build -buildmode=shared",
846 Package: p,
847 Objdir: b.NewObjdir(),
848 Actor: ActorFunc((*Builder).linkShared),
849 Deps: []*Action{a1},
850 }
851 a.Target = filepath.Join(a.Objdir, shlib)
852 if cfg.BuildToolchainName != "gccgo" {
853 add := func(a1 *Action, pkg string, force bool) {
854 for _, a2 := range a1.Deps {
855 if a2.Package != nil && a2.Package.ImportPath == pkg {
856 return
857 }
858 }
859 var stk load.ImportStack
860 p := load.LoadPackageWithFlags(pkg, base.Cwd(), &stk, nil, 0)
861 if p.Error != nil {
862 base.Fatalf("load %s: %v", pkg, p.Error)
863 }
864
865
866
867
868
869 if force || p.Shlib == "" || filepath.Base(p.Shlib) == pkg {
870 a1.Deps = append(a1.Deps, b.CompileAction(depMode, depMode, p))
871 }
872 }
873 add(a1, "runtime/cgo", false)
874 if cfg.Goarch == "arm" {
875 add(a1, "math", false)
876 }
877
878
879
880 ldDeps, err := load.LinkerDeps(nil)
881 if err != nil {
882 base.Error(err)
883 }
884 for _, dep := range ldDeps {
885 add(a, dep, true)
886 }
887 }
888 b.addTransitiveLinkDeps(a, a1, shlib)
889 return a
890 })
891
892
893 if (mode == ModeInstall || mode == ModeBuggyInstall) && a.Actor != nil {
894 buildAction := a
895
896 a = b.cacheAction("install-shlib "+shlib, nil, func() *Action {
897
898
899
900
901
902
903 pkgDir := a1.Deps[0].Package.Internal.Build.PkgTargetRoot
904 for _, a2 := range a1.Deps {
905 if dir := a2.Package.Internal.Build.PkgTargetRoot; dir != pkgDir {
906 base.Fatalf("installing shared library: cannot use packages %s and %s from different roots %s and %s",
907 a1.Deps[0].Package.ImportPath,
908 a2.Package.ImportPath,
909 pkgDir,
910 dir)
911 }
912 }
913
914 if cfg.BuildToolchainName == "gccgo" {
915 pkgDir = filepath.Join(pkgDir, "shlibs")
916 }
917 target := filepath.Join(pkgDir, shlib)
918
919 a := &Action{
920 Mode: "go install -buildmode=shared",
921 Objdir: buildAction.Objdir,
922 Actor: ActorFunc(BuildInstallFunc),
923 Deps: []*Action{buildAction},
924 Target: target,
925 }
926 for _, a2 := range buildAction.Deps[0].Deps {
927 p := a2.Package
928 pkgTargetRoot := p.Internal.Build.PkgTargetRoot
929 if pkgTargetRoot == "" {
930 continue
931 }
932 a.Deps = append(a.Deps, &Action{
933 Mode: "shlibname",
934 Package: p,
935 Actor: ActorFunc((*Builder).installShlibname),
936 Target: filepath.Join(pkgTargetRoot, p.ImportPath+".shlibname"),
937 Deps: []*Action{a.Deps[0]},
938 })
939 }
940 return a
941 })
942 }
943
944 return a
945 }
946
View as plain text