1// Copyright 2011 The Go Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style 3// license that can be found in the LICENSE file. 4 5// Action graph creation (planning). 6 7package work 8 9import ( 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// A Builder holds global state about a build. 36// It does not hold per-package state, because we 37// build packages in parallel, and the builder is shared. 38type Builder struct { 39 WorkDir string // the temporary work directory (ends in filepath.Separator) 40 actionCache map[cacheKey]*Action // a cache of already-constructed actions 41 flagCache map[[2]string]bool // a cache of supported compiler flags 42 gccCompilerIDCache map[string]cache.ActionID // cache for gccCompilerID 43 44 IsCmdList bool // running as part of go list; set p.Stale and additional fields below 45 NeedError bool // list needs p.Error 46 NeedExport bool // list needs p.Export 47 NeedCompiledGoFiles bool // list needs p.CompiledGoFiles 48 AllowErrors bool // errors don't immediately exit the program 49 50 objdirSeq int // counter for NewObjdir 51 pkgSeq int 52 53 backgroundSh *Shell // Shell that per-Action Shells are derived from 54 55 exec sync.Mutex 56 readySema chan bool 57 ready actionQueue 58 59 id sync.Mutex 60 toolIDCache map[string]string // tool name -> tool ID 61 buildIDCache map[string]string // file name -> build ID 62} 63 64// NOTE: Much of Action would not need to be exported if not for test. 65// Maybe test functionality should move into this package too? 66 67// An Actor runs an action. 68type Actor interface { 69 Act(*Builder, context.Context, *Action) error 70} 71 72// An ActorFunc is an Actor that calls the function. 73type ActorFunc func(*Builder, context.Context, *Action) error 74 75func (f ActorFunc) Act(b *Builder, ctx context.Context, a *Action) error { 76 return f(b, ctx, a) 77} 78 79// An Action represents a single action in the action graph. 80type Action struct { 81 Mode string // description of action operation 82 Package *load.Package // the package this action works on 83 Deps []*Action // actions that must happen before this one 84 Actor Actor // the action itself (nil = no-op) 85 IgnoreFail bool // whether to run f even if dependencies fail 86 TestOutput *bytes.Buffer // test output buffer 87 Args []string // additional args for runProgram 88 89 triggers []*Action // inverse of deps 90 91 buggyInstall bool // is this a buggy install (see -linkshared)? 92 93 TryCache func(*Builder, *Action) bool // callback for cache bypass 94 95 // Generated files, directories. 96 Objdir string // directory for intermediate objects 97 Target string // goal of the action: the created package or executable 98 built string // the actual created package or executable 99 actionID cache.ActionID // cache ID of action input 100 buildID string // build ID of action output 101 102 VetxOnly bool // Mode=="vet": only being called to supply info about dependencies 103 needVet bool // Mode=="build": need to fill in vet config 104 needBuild bool // Mode=="build": need to do actual build (can be false if needVet is true) 105 vetCfg *vetConfig // vet config 106 output []byte // output redirect buffer (nil means use b.Print) 107 108 sh *Shell // lazily created per-Action shell; see Builder.Shell 109 110 // Execution state. 111 pending int // number of deps yet to complete 112 priority int // relative execution priority 113 Failed bool // whether the action failed 114 json *actionJSON // action graph information 115 nonGoOverlay map[string]string // map from non-.go source files to copied files in objdir. Nil if no overlay is used. 116 traceSpan *trace.Span 117} 118 119// BuildActionID returns the action ID section of a's build ID. 120func (a *Action) BuildActionID() string { return actionID(a.buildID) } 121 122// BuildContentID returns the content ID section of a's build ID. 123func (a *Action) BuildContentID() string { return contentID(a.buildID) } 124 125// BuildID returns a's build ID. 126func (a *Action) BuildID() string { return a.buildID } 127 128// BuiltTarget returns the actual file that was built. This differs 129// from Target when the result was cached. 130func (a *Action) BuiltTarget() string { return a.built } 131 132// An actionQueue is a priority queue of actions. 133type actionQueue []*Action 134 135// Implement heap.Interface 136func (q *actionQueue) Len() int { return len(*q) } 137func (q *actionQueue) Swap(i, j int) { (*q)[i], (*q)[j] = (*q)[j], (*q)[i] } 138func (q *actionQueue) Less(i, j int) bool { return (*q)[i].priority < (*q)[j].priority } 139func (q *actionQueue) Push(x any) { *q = append(*q, x.(*Action)) } 140func (q *actionQueue) Pop() any { 141 n := len(*q) - 1 142 x := (*q)[n] 143 *q = (*q)[:n] 144 return x 145} 146 147func (q *actionQueue) push(a *Action) { 148 if a.json != nil { 149 a.json.TimeReady = time.Now() 150 } 151 heap.Push(q, a) 152} 153 154func (q *actionQueue) pop() *Action { 155 return heap.Pop(q).(*Action) 156} 157 158type 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 // `json:",omitempty"` 181 CmdReal time.Duration `json:",omitempty"` 182 CmdUser time.Duration `json:",omitempty"` 183 CmdSys time.Duration `json:",omitempty"` 184} 185 186// cacheKey is the key for the action cache. 187type cacheKey struct { 188 mode string 189 p *load.Package 190} 191 192func 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 // TODO(rsc): Make this a unique key for a.Package somehow. 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// BuildMode specifies the build mode: 248// are we just building things or also installing the results? 249type BuildMode int 250 251const ( 252 ModeBuild BuildMode = iota 253 ModeInstall 254 ModeBuggyInstall 255 256 ModeVetOnly = 1 << 8 257) 258 259// NewBuilder returns a new Builder ready for use. 260// 261// If workDir is the empty string, NewBuilder creates a WorkDir if needed 262// and arranges for it to be removed in case of an unclean exit. 263// The caller must Close the builder explicitly to clean up the WorkDir 264// before a clean exit. 265func 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 318var builderWorkDirs sync.Map // *Builder → WorkDir 319 320func (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 340func 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 356func 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// NewObjdir returns the name of a fresh object directory under b.WorkDir. 364// It is up to the caller to call b.Mkdir on the result at an appropriate time. 365// The result ends in a slash, so that file names in that directory 366// can be constructed with direct string addition. 367// 368// NewObjdir must be called only from a single goroutine at a time, 369// so it is safe to call during action graph construction, but it must not 370// be called during action graph execution. 371func (b *Builder) NewObjdir() string { 372 b.objdirSeq++ 373 return str.WithFilePathSeparator(filepath.Join(b.WorkDir, fmt.Sprintf("b%03d", b.objdirSeq))) 374} 375 376// readpkglist returns the list of packages that were built into the shared library 377// at shlibpath. For the native toolchain this list is stored, newline separated, in 378// an ELF note with name "Go\x00\x00" and type 1. For GCCGO it is extracted from the 379// .go_export section. 380func 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 defer f.Close() 388 sect := f.Section(".go_export") 389 if sect == nil { 390 base.Fatal(fmt.Errorf("%s: missing .go_export section", shlibpath)) 391 } 392 data, err := sect.Data() 393 if err != nil { 394 base.Fatal(fmt.Errorf("%s: failed to read .go_export section: %v", shlibpath, err)) 395 } 396 pkgpath := []byte("pkgpath ") 397 for _, line := range bytes.Split(data, []byte{'\n'}) { 398 if path, found := bytes.CutPrefix(line, pkgpath); found { 399 path = bytes.TrimSuffix(path, []byte{';'}) 400 pkgs = append(pkgs, load.LoadPackageWithFlags(string(path), base.Cwd(), &stk, nil, 0)) 401 } 402 } 403 } else { 404 pkglistbytes, err := buildid.ReadELFNote(shlibpath, "Go\x00\x00", 1) 405 if err != nil { 406 base.Fatalf("readELFNote failed: %v", err) 407 } 408 scanner := bufio.NewScanner(bytes.NewBuffer(pkglistbytes)) 409 for scanner.Scan() { 410 t := scanner.Text() 411 pkgs = append(pkgs, load.LoadPackageWithFlags(t, base.Cwd(), &stk, nil, 0)) 412 } 413 } 414 return 415} 416 417// cacheAction looks up {mode, p} in the cache and returns the resulting action. 418// If the cache has no such action, f() is recorded and returned. 419// TODO(rsc): Change the second key from *load.Package to interface{}, 420// to make the caching in linkShared less awkward? 421func (b *Builder) cacheAction(mode string, p *load.Package, f func() *Action) *Action { 422 a := b.actionCache[cacheKey{mode, p}] 423 if a == nil { 424 a = f() 425 b.actionCache[cacheKey{mode, p}] = a 426 } 427 return a 428} 429 430// AutoAction returns the "right" action for go build or go install of p. 431func (b *Builder) AutoAction(mode, depMode BuildMode, p *load.Package) *Action { 432 if p.Name == "main" { 433 return b.LinkAction(mode, depMode, p) 434 } 435 return b.CompileAction(mode, depMode, p) 436} 437 438// buildActor implements the Actor interface for package build 439// actions. For most package builds this simply means invoking th 440// *Builder.build method; in the case of "go test -cover" for 441// a package with no test files, we stores some additional state 442// information in the build actor to help with reporting. 443type buildActor struct { 444 // name of static meta-data file fragment emitted by the cover 445 // tool as part of the package build action, for selected 446 // "go test -cover" runs. 447 covMetaFileName string 448} 449 450// newBuildActor returns a new buildActor object, setting up the 451// covMetaFileName field if 'genCoverMeta' flag is set. 452func newBuildActor(p *load.Package, genCoverMeta bool) *buildActor { 453 ba := &buildActor{} 454 if genCoverMeta { 455 ba.covMetaFileName = covcmd.MetaFileForPackage(p.ImportPath) 456 } 457 return ba 458} 459 460func (ba *buildActor) Act(b *Builder, ctx context.Context, a *Action) error { 461 return b.build(ctx, a) 462} 463 464// pgoActionID computes the action ID for a preprocess PGO action. 465func (b *Builder) pgoActionID(input string) cache.ActionID { 466 h := cache.NewHash("preprocess PGO profile " + input) 467 468 fmt.Fprintf(h, "preprocess PGO profile\n") 469 fmt.Fprintf(h, "preprofile %s\n", b.toolID("preprofile")) 470 fmt.Fprintf(h, "input %q\n", b.fileHash(input)) 471 472 return h.Sum() 473} 474 475// pgoActor implements the Actor interface for preprocessing PGO profiles. 476type pgoActor struct { 477 // input is the path to the original pprof profile. 478 input string 479} 480 481func (p *pgoActor) Act(b *Builder, ctx context.Context, a *Action) error { 482 if b.useCache(a, b.pgoActionID(p.input), a.Target, !b.IsCmdList) || b.IsCmdList { 483 return nil 484 } 485 defer b.flushOutput(a) 486 487 sh := b.Shell(a) 488 489 if err := sh.Mkdir(a.Objdir); err != nil { 490 return err 491 } 492 493 if err := sh.run(".", p.input, nil, cfg.BuildToolexec, base.Tool("preprofile"), "-o", a.Target, "-i", p.input); err != nil { 494 return err 495 } 496 497 // N.B. Builder.build looks for the out in a.built, regardless of 498 // whether this came from cache. 499 a.built = a.Target 500 501 if !cfg.BuildN { 502 // Cache the output. 503 // 504 // N.B. We don't use updateBuildID here, as preprocessed PGO profiles 505 // do not contain a build ID. updateBuildID is typically responsible 506 // for adding to the cache, thus we must do so ourselves instead. 507 508 r, err := os.Open(a.Target) 509 if err != nil { 510 return fmt.Errorf("error opening target for caching: %w", err) 511 } 512 513 c := cache.Default() 514 outputID, _, err := c.Put(a.actionID, r) 515 r.Close() 516 if err != nil { 517 return fmt.Errorf("error adding target to cache: %w", err) 518 } 519 if cfg.BuildX { 520 sh.ShowCmd("", "%s # internal", joinUnambiguously(str.StringList("cp", a.Target, c.OutputFile(outputID)))) 521 } 522 } 523 524 return nil 525} 526 527// CompileAction returns the action for compiling and possibly installing 528// (according to mode) the given package. The resulting action is only 529// for building packages (archives), never for linking executables. 530// depMode is the action (build or install) to use when building dependencies. 531// To turn package main into an executable, call b.Link instead. 532func (b *Builder) CompileAction(mode, depMode BuildMode, p *load.Package) *Action { 533 vetOnly := mode&ModeVetOnly != 0 534 mode &^= ModeVetOnly 535 536 if mode != ModeBuild && p.Target == "" { 537 // No permanent target. 538 mode = ModeBuild 539 } 540 if mode != ModeBuild && p.Name == "main" { 541 // We never install the .a file for a main package. 542 mode = ModeBuild 543 } 544 545 // Construct package build action. 546 a := b.cacheAction("build", p, func() *Action { 547 a := &Action{ 548 Mode: "build", 549 Package: p, 550 Actor: newBuildActor(p, p.Internal.Cover.GenMeta), 551 Objdir: b.NewObjdir(), 552 } 553 554 if p.Error == nil || !p.Error.IsImportCycle { 555 for _, p1 := range p.Internal.Imports { 556 a.Deps = append(a.Deps, b.CompileAction(depMode, depMode, p1)) 557 } 558 } 559 560 if p.Internal.PGOProfile != "" { 561 pgoAction := b.cacheAction("preprocess PGO profile "+p.Internal.PGOProfile, nil, func() *Action { 562 a := &Action{ 563 Mode: "preprocess PGO profile", 564 Actor: &pgoActor{input: p.Internal.PGOProfile}, 565 Objdir: b.NewObjdir(), 566 } 567 a.Target = filepath.Join(a.Objdir, "pgo.preprofile") 568 569 return a 570 }) 571 a.Deps = append(a.Deps, pgoAction) 572 } 573 574 if p.Standard { 575 switch p.ImportPath { 576 case "builtin", "unsafe": 577 // Fake packages - nothing to build. 578 a.Mode = "built-in package" 579 a.Actor = nil 580 return a 581 } 582 583 // gccgo standard library is "fake" too. 584 if cfg.BuildToolchainName == "gccgo" { 585 // the target name is needed for cgo. 586 a.Mode = "gccgo stdlib" 587 a.Target = p.Target 588 a.Actor = nil 589 return a 590 } 591 } 592 593 return a 594 }) 595 596 // Find the build action; the cache entry may have been replaced 597 // by the install action during (*Builder).installAction. 598 buildAction := a 599 switch buildAction.Mode { 600 case "build", "built-in package", "gccgo stdlib": 601 // ok 602 case "build-install": 603 buildAction = a.Deps[0] 604 default: 605 panic("lost build action: " + buildAction.Mode) 606 } 607 buildAction.needBuild = buildAction.needBuild || !vetOnly 608 609 // Construct install action. 610 if mode == ModeInstall || mode == ModeBuggyInstall { 611 a = b.installAction(a, mode) 612 } 613 614 return a 615} 616 617// VetAction returns the action for running go vet on package p. 618// It depends on the action for compiling p. 619// If the caller may be causing p to be installed, it is up to the caller 620// to make sure that the install depends on (runs after) vet. 621func (b *Builder) VetAction(mode, depMode BuildMode, p *load.Package) *Action { 622 a := b.vetAction(mode, depMode, p) 623 a.VetxOnly = false 624 return a 625} 626 627func (b *Builder) vetAction(mode, depMode BuildMode, p *load.Package) *Action { 628 // Construct vet action. 629 a := b.cacheAction("vet", p, func() *Action { 630 a1 := b.CompileAction(mode|ModeVetOnly, depMode, p) 631 632 // vet expects to be able to import "fmt". 633 var stk load.ImportStack 634 stk.Push("vet") 635 p1, err := load.LoadImportWithFlags("fmt", p.Dir, p, &stk, nil, 0) 636 if err != nil { 637 base.Fatalf("unexpected error loading fmt package from package %s: %v", p.ImportPath, err) 638 } 639 stk.Pop() 640 aFmt := b.CompileAction(ModeBuild, depMode, p1) 641 642 var deps []*Action 643 if a1.buggyInstall { 644 // (*Builder).vet expects deps[0] to be the package 645 // and deps[1] to be "fmt". If we see buggyInstall 646 // here then a1 is an install of a shared library, 647 // and the real package is a1.Deps[0]. 648 deps = []*Action{a1.Deps[0], aFmt, a1} 649 } else { 650 deps = []*Action{a1, aFmt} 651 } 652 for _, p1 := range p.Internal.Imports { 653 deps = append(deps, b.vetAction(mode, depMode, p1)) 654 } 655 656 a := &Action{ 657 Mode: "vet", 658 Package: p, 659 Deps: deps, 660 Objdir: a1.Objdir, 661 VetxOnly: true, 662 IgnoreFail: true, // it's OK if vet of dependencies "fails" (reports problems) 663 } 664 if a1.Actor == nil { 665 // Built-in packages like unsafe. 666 return a 667 } 668 deps[0].needVet = true 669 a.Actor = ActorFunc((*Builder).vet) 670 return a 671 }) 672 return a 673} 674 675// LinkAction returns the action for linking p into an executable 676// and possibly installing the result (according to mode). 677// depMode is the action (build or install) to use when compiling dependencies. 678func (b *Builder) LinkAction(mode, depMode BuildMode, p *load.Package) *Action { 679 // Construct link action. 680 a := b.cacheAction("link", p, func() *Action { 681 a := &Action{ 682 Mode: "link", 683 Package: p, 684 } 685 686 a1 := b.CompileAction(ModeBuild, depMode, p) 687 a.Actor = ActorFunc((*Builder).link) 688 a.Deps = []*Action{a1} 689 a.Objdir = a1.Objdir 690 691 // An executable file. (This is the name of a temporary file.) 692 // Because we run the temporary file in 'go run' and 'go test', 693 // the name will show up in ps listings. If the caller has specified 694 // a name, use that instead of a.out. The binary is generated 695 // in an otherwise empty subdirectory named exe to avoid 696 // naming conflicts. The only possible conflict is if we were 697 // to create a top-level package named exe. 698 name := "a.out" 699 if p.Internal.ExeName != "" { 700 name = p.Internal.ExeName 701 } else if (cfg.Goos == "darwin" || cfg.Goos == "windows") && cfg.BuildBuildmode == "c-shared" && p.Target != "" { 702 // On OS X, the linker output name gets recorded in the 703 // shared library's LC_ID_DYLIB load command. 704 // The code invoking the linker knows to pass only the final 705 // path element. Arrange that the path element matches what 706 // we'll install it as; otherwise the library is only loadable as "a.out". 707 // On Windows, DLL file name is recorded in PE file 708 // export section, so do like on OS X. 709 _, name = filepath.Split(p.Target) 710 } 711 a.Target = a.Objdir + filepath.Join("exe", name) + cfg.ExeSuffix 712 a.built = a.Target 713 b.addTransitiveLinkDeps(a, a1, "") 714 715 // Sequence the build of the main package (a1) strictly after the build 716 // of all other dependencies that go into the link. It is likely to be after 717 // them anyway, but just make sure. This is required by the build ID-based 718 // shortcut in (*Builder).useCache(a1), which will call b.linkActionID(a). 719 // In order for that linkActionID call to compute the right action ID, all the 720 // dependencies of a (except a1) must have completed building and have 721 // recorded their build IDs. 722 a1.Deps = append(a1.Deps, &Action{Mode: "nop", Deps: a.Deps[1:]}) 723 return a 724 }) 725 726 if mode == ModeInstall || mode == ModeBuggyInstall { 727 a = b.installAction(a, mode) 728 } 729 730 return a 731} 732 733// installAction returns the action for installing the result of a1. 734func (b *Builder) installAction(a1 *Action, mode BuildMode) *Action { 735 // Because we overwrite the build action with the install action below, 736 // a1 may already be an install action fetched from the "build" cache key, 737 // and the caller just doesn't realize. 738 if strings.HasSuffix(a1.Mode, "-install") { 739 if a1.buggyInstall && mode == ModeInstall { 740 // Congratulations! The buggy install is now a proper install. 741 a1.buggyInstall = false 742 } 743 return a1 744 } 745 746 // If there's no actual action to build a1, 747 // there's nothing to install either. 748 // This happens if a1 corresponds to reusing an already-built object. 749 if a1.Actor == nil { 750 return a1 751 } 752 753 p := a1.Package 754 return b.cacheAction(a1.Mode+"-install", p, func() *Action { 755 // The install deletes the temporary build result, 756 // so we need all other actions, both past and future, 757 // that attempt to depend on the build to depend instead 758 // on the install. 759 760 // Make a private copy of a1 (the build action), 761 // no longer accessible to any other rules. 762 buildAction := new(Action) 763 *buildAction = *a1 764 765 // Overwrite a1 with the install action. 766 // This takes care of updating past actions that 767 // point at a1 for the build action; now they will 768 // point at a1 and get the install action. 769 // We also leave a1 in the action cache as the result 770 // for "build", so that actions not yet created that 771 // try to depend on the build will instead depend 772 // on the install. 773 *a1 = Action{ 774 Mode: buildAction.Mode + "-install", 775 Actor: ActorFunc(BuildInstallFunc), 776 Package: p, 777 Objdir: buildAction.Objdir, 778 Deps: []*Action{buildAction}, 779 Target: p.Target, 780 built: p.Target, 781 782 buggyInstall: mode == ModeBuggyInstall, 783 } 784 785 b.addInstallHeaderAction(a1) 786 return a1 787 }) 788} 789 790// addTransitiveLinkDeps adds to the link action a all packages 791// that are transitive dependencies of a1.Deps. 792// That is, if a is a link of package main, a1 is the compile of package main 793// and a1.Deps is the actions for building packages directly imported by 794// package main (what the compiler needs). The linker needs all packages 795// transitively imported by the whole program; addTransitiveLinkDeps 796// makes sure those are present in a.Deps. 797// If shlib is non-empty, then a corresponds to the build and installation of shlib, 798// so any rebuild of shlib should not be added as a dependency. 799func (b *Builder) addTransitiveLinkDeps(a, a1 *Action, shlib string) { 800 // Expand Deps to include all built packages, for the linker. 801 // Use breadth-first search to find rebuilt-for-test packages 802 // before the standard ones. 803 // TODO(rsc): Eliminate the standard ones from the action graph, 804 // which will require doing a little bit more rebuilding. 805 workq := []*Action{a1} 806 haveDep := map[string]bool{} 807 if a1.Package != nil { 808 haveDep[a1.Package.ImportPath] = true 809 } 810 for i := 0; i < len(workq); i++ { 811 a1 := workq[i] 812 for _, a2 := range a1.Deps { 813 // TODO(rsc): Find a better discriminator than the Mode strings, once the dust settles. 814 if a2.Package == nil || (a2.Mode != "build-install" && a2.Mode != "build") || haveDep[a2.Package.ImportPath] { 815 continue 816 } 817 haveDep[a2.Package.ImportPath] = true 818 a.Deps = append(a.Deps, a2) 819 if a2.Mode == "build-install" { 820 a2 = a2.Deps[0] // walk children of "build" action 821 } 822 workq = append(workq, a2) 823 } 824 } 825 826 // If this is go build -linkshared, then the link depends on the shared libraries 827 // in addition to the packages themselves. (The compile steps do not.) 828 if cfg.BuildLinkshared { 829 haveShlib := map[string]bool{shlib: true} 830 for _, a1 := range a.Deps { 831 p1 := a1.Package 832 if p1 == nil || p1.Shlib == "" || haveShlib[filepath.Base(p1.Shlib)] { 833 continue 834 } 835 haveShlib[filepath.Base(p1.Shlib)] = true 836 // TODO(rsc): The use of ModeInstall here is suspect, but if we only do ModeBuild, 837 // we'll end up building an overall library or executable that depends at runtime 838 // on other libraries that are out-of-date, which is clearly not good either. 839 // We call it ModeBuggyInstall to make clear that this is not right. 840 a.Deps = append(a.Deps, b.linkSharedAction(ModeBuggyInstall, ModeBuggyInstall, p1.Shlib, nil)) 841 } 842 } 843} 844 845// addInstallHeaderAction adds an install header action to a, if needed. 846// The action a should be an install action as generated by either 847// b.CompileAction or b.LinkAction with mode=ModeInstall, 848// and so a.Deps[0] is the corresponding build action. 849func (b *Builder) addInstallHeaderAction(a *Action) { 850 // Install header for cgo in c-archive and c-shared modes. 851 p := a.Package 852 if p.UsesCgo() && (cfg.BuildBuildmode == "c-archive" || cfg.BuildBuildmode == "c-shared") { 853 hdrTarget := a.Target[:len(a.Target)-len(filepath.Ext(a.Target))] + ".h" 854 if cfg.BuildContext.Compiler == "gccgo" && cfg.BuildO == "" { 855 // For the header file, remove the "lib" 856 // added by go/build, so we generate pkg.h 857 // rather than libpkg.h. 858 dir, file := filepath.Split(hdrTarget) 859 file = strings.TrimPrefix(file, "lib") 860 hdrTarget = filepath.Join(dir, file) 861 } 862 ah := &Action{ 863 Mode: "install header", 864 Package: a.Package, 865 Deps: []*Action{a.Deps[0]}, 866 Actor: ActorFunc((*Builder).installHeader), 867 Objdir: a.Deps[0].Objdir, 868 Target: hdrTarget, 869 } 870 a.Deps = append(a.Deps, ah) 871 } 872} 873 874// buildmodeShared takes the "go build" action a1 into the building of a shared library of a1.Deps. 875// That is, the input a1 represents "go build pkgs" and the result represents "go build -buildmode=shared pkgs". 876func (b *Builder) buildmodeShared(mode, depMode BuildMode, args []string, pkgs []*load.Package, a1 *Action) *Action { 877 name, err := libname(args, pkgs) 878 if err != nil { 879 base.Fatalf("%v", err) 880 } 881 return b.linkSharedAction(mode, depMode, name, a1) 882} 883 884// linkSharedAction takes a grouping action a1 corresponding to a list of built packages 885// and returns an action that links them together into a shared library with the name shlib. 886// If a1 is nil, shlib should be an absolute path to an existing shared library, 887// and then linkSharedAction reads that library to find out the package list. 888func (b *Builder) linkSharedAction(mode, depMode BuildMode, shlib string, a1 *Action) *Action { 889 fullShlib := shlib 890 shlib = filepath.Base(shlib) 891 a := b.cacheAction("build-shlib "+shlib, nil, func() *Action { 892 if a1 == nil { 893 // TODO(rsc): Need to find some other place to store config, 894 // not in pkg directory. See golang.org/issue/22196. 895 pkgs := readpkglist(fullShlib) 896 a1 = &Action{ 897 Mode: "shlib packages", 898 } 899 for _, p := range pkgs { 900 a1.Deps = append(a1.Deps, b.CompileAction(mode, depMode, p)) 901 } 902 } 903 904 // Fake package to hold ldflags. 905 // As usual shared libraries are a kludgy, abstraction-violating special case: 906 // we let them use the flags specified for the command-line arguments. 907 p := &load.Package{} 908 p.Internal.CmdlinePkg = true 909 p.Internal.Ldflags = load.BuildLdflags.For(p) 910 p.Internal.Gccgoflags = load.BuildGccgoflags.For(p) 911 912 // Add implicit dependencies to pkgs list. 913 // Currently buildmode=shared forces external linking mode, and 914 // external linking mode forces an import of runtime/cgo (and 915 // math on arm). So if it was not passed on the command line and 916 // it is not present in another shared library, add it here. 917 // TODO(rsc): Maybe this should only happen if "runtime" is in the original package set. 918 // TODO(rsc): This should probably be changed to use load.LinkerDeps(p). 919 // TODO(rsc): We don't add standard library imports for gccgo 920 // because they are all always linked in anyhow. 921 // Maybe load.LinkerDeps should be used and updated. 922 a := &Action{ 923 Mode: "go build -buildmode=shared", 924 Package: p, 925 Objdir: b.NewObjdir(), 926 Actor: ActorFunc((*Builder).linkShared), 927 Deps: []*Action{a1}, 928 } 929 a.Target = filepath.Join(a.Objdir, shlib) 930 if cfg.BuildToolchainName != "gccgo" { 931 add := func(a1 *Action, pkg string, force bool) { 932 for _, a2 := range a1.Deps { 933 if a2.Package != nil && a2.Package.ImportPath == pkg { 934 return 935 } 936 } 937 var stk load.ImportStack 938 p := load.LoadPackageWithFlags(pkg, base.Cwd(), &stk, nil, 0) 939 if p.Error != nil { 940 base.Fatalf("load %s: %v", pkg, p.Error) 941 } 942 // Assume that if pkg (runtime/cgo or math) 943 // is already accounted for in a different shared library, 944 // then that shared library also contains runtime, 945 // so that anything we do will depend on that library, 946 // so we don't need to include pkg in our shared library. 947 if force || p.Shlib == "" || filepath.Base(p.Shlib) == pkg { 948 a1.Deps = append(a1.Deps, b.CompileAction(depMode, depMode, p)) 949 } 950 } 951 add(a1, "runtime/cgo", false) 952 if cfg.Goarch == "arm" { 953 add(a1, "math", false) 954 } 955 956 // The linker step still needs all the usual linker deps. 957 // (For example, the linker always opens runtime.a.) 958 ldDeps, err := load.LinkerDeps(nil) 959 if err != nil { 960 base.Error(err) 961 } 962 for _, dep := range ldDeps { 963 add(a, dep, true) 964 } 965 } 966 b.addTransitiveLinkDeps(a, a1, shlib) 967 return a 968 }) 969 970 // Install result. 971 if (mode == ModeInstall || mode == ModeBuggyInstall) && a.Actor != nil { 972 buildAction := a 973 974 a = b.cacheAction("install-shlib "+shlib, nil, func() *Action { 975 // Determine the eventual install target. 976 // The install target is root/pkg/shlib, where root is the source root 977 // in which all the packages lie. 978 // TODO(rsc): Perhaps this cross-root check should apply to the full 979 // transitive package dependency list, not just the ones named 980 // on the command line? 981 pkgDir := a1.Deps[0].Package.Internal.Build.PkgTargetRoot 982 for _, a2 := range a1.Deps { 983 if dir := a2.Package.Internal.Build.PkgTargetRoot; dir != pkgDir { 984 base.Fatalf("installing shared library: cannot use packages %s and %s from different roots %s and %s", 985 a1.Deps[0].Package.ImportPath, 986 a2.Package.ImportPath, 987 pkgDir, 988 dir) 989 } 990 } 991 // TODO(rsc): Find out and explain here why gccgo is different. 992 if cfg.BuildToolchainName == "gccgo" { 993 pkgDir = filepath.Join(pkgDir, "shlibs") 994 } 995 target := filepath.Join(pkgDir, shlib) 996 997 a := &Action{ 998 Mode: "go install -buildmode=shared", 999 Objdir: buildAction.Objdir, 1000 Actor: ActorFunc(BuildInstallFunc), 1001 Deps: []*Action{buildAction}, 1002 Target: target, 1003 } 1004 for _, a2 := range buildAction.Deps[0].Deps { 1005 p := a2.Package 1006 pkgTargetRoot := p.Internal.Build.PkgTargetRoot 1007 if pkgTargetRoot == "" { 1008 continue 1009 } 1010 a.Deps = append(a.Deps, &Action{ 1011 Mode: "shlibname", 1012 Package: p, 1013 Actor: ActorFunc((*Builder).installShlibname), 1014 Target: filepath.Join(pkgTargetRoot, p.ImportPath+".shlibname"), 1015 Deps: []*Action{a.Deps[0]}, 1016 }) 1017 } 1018 return a 1019 }) 1020 } 1021 1022 return a 1023} 1024