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 "container/heap" 13 "debug/elf" 14 "encoding/json" 15 "fmt" 16 "internal/xcoff" 17 "io/ioutil" 18 "os" 19 "path/filepath" 20 "runtime" 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/internal/buildid" 30) 31 32// A Builder holds global state about a build. 33// It does not hold per-package state, because we 34// build packages in parallel, and the builder is shared. 35type Builder struct { 36 WorkDir string // the temporary work directory (ends in filepath.Separator) 37 actionCache map[cacheKey]*Action // a cache of already-constructed actions 38 mkdirCache map[string]bool // a cache of created directories 39 flagCache map[[2]string]bool // a cache of supported compiler flags 40 Print func(args ...interface{}) (int, error) 41 42 IsCmdList bool // running as part of go list; set p.Stale and additional fields below 43 NeedError bool // list needs p.Error 44 NeedExport bool // list needs p.Export 45 NeedCompiledGoFiles bool // list needs p.CompiledGoFIles 46 47 objdirSeq int // counter for NewObjdir 48 pkgSeq int 49 50 output sync.Mutex 51 scriptDir string // current directory in printed script 52 53 exec sync.Mutex 54 readySema chan bool 55 ready actionQueue 56 57 id sync.Mutex 58 toolIDCache map[string]string // tool name -> tool ID 59 buildIDCache map[string]string // file name -> build ID 60} 61 62// NOTE: Much of Action would not need to be exported if not for test. 63// Maybe test functionality should move into this package too? 64 65// An Action represents a single action in the action graph. 66type Action struct { 67 Mode string // description of action operation 68 Package *load.Package // the package this action works on 69 Deps []*Action // actions that must happen before this one 70 Func func(*Builder, *Action) error // the action itself (nil = no-op) 71 IgnoreFail bool // whether to run f even if dependencies fail 72 TestOutput *bytes.Buffer // test output buffer 73 Args []string // additional args for runProgram 74 75 triggers []*Action // inverse of deps 76 77 buggyInstall bool // is this a buggy install (see -linkshared)? 78 79 TryCache func(*Builder, *Action) bool // callback for cache bypass 80 81 // Generated files, directories. 82 Objdir string // directory for intermediate objects 83 Target string // goal of the action: the created package or executable 84 built string // the actual created package or executable 85 actionID cache.ActionID // cache ID of action input 86 buildID string // build ID of action output 87 88 VetxOnly bool // Mode=="vet": only being called to supply info about dependencies 89 needVet bool // Mode=="build": need to fill in vet config 90 needBuild bool // Mode=="build": need to do actual build (can be false if needVet is true) 91 vetCfg *vetConfig // vet config 92 output []byte // output redirect buffer (nil means use b.Print) 93 94 // Execution state. 95 pending int // number of deps yet to complete 96 priority int // relative execution priority 97 Failed bool // whether the action failed 98 json *actionJSON // action graph information 99} 100 101// BuildActionID returns the action ID section of a's build ID. 102func (a *Action) BuildActionID() string { return actionID(a.buildID) } 103 104// BuildContentID returns the content ID section of a's build ID. 105func (a *Action) BuildContentID() string { return contentID(a.buildID) } 106 107// BuildID returns a's build ID. 108func (a *Action) BuildID() string { return a.buildID } 109 110// BuiltTarget returns the actual file that was built. This differs 111// from Target when the result was cached. 112func (a *Action) BuiltTarget() string { return a.built } 113 114// An actionQueue is a priority queue of actions. 115type actionQueue []*Action 116 117// Implement heap.Interface 118func (q *actionQueue) Len() int { return len(*q) } 119func (q *actionQueue) Swap(i, j int) { (*q)[i], (*q)[j] = (*q)[j], (*q)[i] } 120func (q *actionQueue) Less(i, j int) bool { return (*q)[i].priority < (*q)[j].priority } 121func (q *actionQueue) Push(x interface{}) { *q = append(*q, x.(*Action)) } 122func (q *actionQueue) Pop() interface{} { 123 n := len(*q) - 1 124 x := (*q)[n] 125 *q = (*q)[:n] 126 return x 127} 128 129func (q *actionQueue) push(a *Action) { 130 if a.json != nil { 131 a.json.TimeReady = time.Now() 132 } 133 heap.Push(q, a) 134} 135 136func (q *actionQueue) pop() *Action { 137 return heap.Pop(q).(*Action) 138} 139 140type actionJSON struct { 141 ID int 142 Mode string 143 Package string 144 Deps []int `json:",omitempty"` 145 IgnoreFail bool `json:",omitempty"` 146 Args []string `json:",omitempty"` 147 Link bool `json:",omitempty"` 148 Objdir string `json:",omitempty"` 149 Target string `json:",omitempty"` 150 Priority int `json:",omitempty"` 151 Failed bool `json:",omitempty"` 152 Built string `json:",omitempty"` 153 VetxOnly bool `json:",omitempty"` 154 NeedVet bool `json:",omitempty"` 155 NeedBuild bool `json:",omitempty"` 156 ActionID string `json:",omitempty"` 157 BuildID string `json:",omitempty"` 158 TimeReady time.Time `json:",omitempty"` 159 TimeStart time.Time `json:",omitempty"` 160 TimeDone time.Time `json:",omitempty"` 161 162 Cmd []string // `json:",omitempty"` 163 CmdReal time.Duration `json:",omitempty"` 164 CmdUser time.Duration `json:",omitempty"` 165 CmdSys time.Duration `json:",omitempty"` 166} 167 168// cacheKey is the key for the action cache. 169type cacheKey struct { 170 mode string 171 p *load.Package 172} 173 174func actionGraphJSON(a *Action) string { 175 var workq []*Action 176 var inWorkq = make(map[*Action]int) 177 178 add := func(a *Action) { 179 if _, ok := inWorkq[a]; ok { 180 return 181 } 182 inWorkq[a] = len(workq) 183 workq = append(workq, a) 184 } 185 add(a) 186 187 for i := 0; i < len(workq); i++ { 188 for _, dep := range workq[i].Deps { 189 add(dep) 190 } 191 } 192 193 var list []*actionJSON 194 for id, a := range workq { 195 if a.json == nil { 196 a.json = &actionJSON{ 197 Mode: a.Mode, 198 ID: id, 199 IgnoreFail: a.IgnoreFail, 200 Args: a.Args, 201 Objdir: a.Objdir, 202 Target: a.Target, 203 Failed: a.Failed, 204 Priority: a.priority, 205 Built: a.built, 206 VetxOnly: a.VetxOnly, 207 NeedBuild: a.needBuild, 208 NeedVet: a.needVet, 209 } 210 if a.Package != nil { 211 // TODO(rsc): Make this a unique key for a.Package somehow. 212 a.json.Package = a.Package.ImportPath 213 } 214 for _, a1 := range a.Deps { 215 a.json.Deps = append(a.json.Deps, inWorkq[a1]) 216 } 217 } 218 list = append(list, a.json) 219 } 220 221 js, err := json.MarshalIndent(list, "", "\t") 222 if err != nil { 223 fmt.Fprintf(os.Stderr, "go: writing debug action graph: %v\n", err) 224 return "" 225 } 226 return string(js) 227} 228 229// BuildMode specifies the build mode: 230// are we just building things or also installing the results? 231type BuildMode int 232 233const ( 234 ModeBuild BuildMode = iota 235 ModeInstall 236 ModeBuggyInstall 237 238 ModeVetOnly = 1 << 8 239) 240 241func (b *Builder) Init() { 242 b.Print = func(a ...interface{}) (int, error) { 243 return fmt.Fprint(os.Stderr, a...) 244 } 245 b.actionCache = make(map[cacheKey]*Action) 246 b.mkdirCache = make(map[string]bool) 247 b.toolIDCache = make(map[string]string) 248 b.buildIDCache = make(map[string]string) 249 250 if cfg.BuildN { 251 b.WorkDir = "$WORK" 252 } else { 253 tmp, err := ioutil.TempDir(cfg.Getenv("GOTMPDIR"), "go-build") 254 if err != nil { 255 base.Fatalf("go: creating work dir: %v", err) 256 } 257 if !filepath.IsAbs(tmp) { 258 abs, err := filepath.Abs(tmp) 259 if err != nil { 260 os.RemoveAll(tmp) 261 base.Fatalf("go: creating work dir: %v", err) 262 } 263 tmp = abs 264 } 265 b.WorkDir = tmp 266 if cfg.BuildX || cfg.BuildWork { 267 fmt.Fprintf(os.Stderr, "WORK=%s\n", b.WorkDir) 268 } 269 if !cfg.BuildWork { 270 workdir := b.WorkDir 271 base.AtExit(func() { 272 start := time.Now() 273 for { 274 err := os.RemoveAll(workdir) 275 if err == nil { 276 return 277 } 278 279 // On some configurations of Windows, directories containing executable 280 // files may be locked for a while after the executable exits (perhaps 281 // due to antivirus scans?). It's probably worth a little extra latency 282 // on exit to avoid filling up the user's temporary directory with leaked 283 // files. (See golang.org/issue/30789.) 284 if runtime.GOOS != "windows" || time.Since(start) >= 500*time.Millisecond { 285 fmt.Fprintf(os.Stderr, "go: failed to remove work dir: %s\n", err) 286 return 287 } 288 time.Sleep(5 * time.Millisecond) 289 } 290 }) 291 } 292 } 293 294 if err := CheckGOOSARCHPair(cfg.Goos, cfg.Goarch); err != nil { 295 fmt.Fprintf(os.Stderr, "cmd/go: %v\n", err) 296 base.SetExitStatus(2) 297 base.Exit() 298 } 299 300 for _, tag := range cfg.BuildContext.BuildTags { 301 if strings.Contains(tag, ",") { 302 fmt.Fprintf(os.Stderr, "cmd/go: -tags space-separated list contains comma\n") 303 base.SetExitStatus(2) 304 base.Exit() 305 } 306 } 307} 308 309func CheckGOOSARCHPair(goos, goarch string) error { 310 if _, ok := cfg.OSArchSupportsCgo[goos+"/"+goarch]; !ok && cfg.BuildContext.Compiler == "gc" { 311 return fmt.Errorf("unsupported GOOS/GOARCH pair %s/%s", goos, goarch) 312 } 313 return nil 314} 315 316// NewObjdir returns the name of a fresh object directory under b.WorkDir. 317// It is up to the caller to call b.Mkdir on the result at an appropriate time. 318// The result ends in a slash, so that file names in that directory 319// can be constructed with direct string addition. 320// 321// NewObjdir must be called only from a single goroutine at a time, 322// so it is safe to call during action graph construction, but it must not 323// be called during action graph execution. 324func (b *Builder) NewObjdir() string { 325 b.objdirSeq++ 326 return filepath.Join(b.WorkDir, fmt.Sprintf("b%03d", b.objdirSeq)) + string(filepath.Separator) 327} 328 329// readpkglist returns the list of packages that were built into the shared library 330// at shlibpath. For the native toolchain this list is stored, newline separated, in 331// an ELF note with name "Go\x00\x00" and type 1. For GCCGO it is extracted from the 332// .go_export section. 333func readpkglist(shlibpath string) (pkgs []*load.Package) { 334 var stk load.ImportStack 335 if cfg.BuildToolchainName == "gccgo" { 336 var data []byte 337 if f, err := elf.Open(shlibpath); err == nil { 338 sect := f.Section(".go_export") 339 data, _ = sect.Data() 340 } else if f, err := xcoff.Open(shlibpath); err == nil { 341 data = f.CSect(".go_export") 342 } 343 scanner := bufio.NewScanner(bytes.NewBuffer(data)) 344 for scanner.Scan() { 345 t := scanner.Text() 346 if strings.HasPrefix(t, "pkgpath ") { 347 t = strings.TrimPrefix(t, "pkgpath ") 348 t = strings.TrimSuffix(t, ";") 349 pkgs = append(pkgs, load.LoadImportWithFlags(t, base.Cwd, nil, &stk, nil, 0)) 350 } 351 } 352 } else { 353 pkglistbytes, err := buildid.ReadELFNote(shlibpath, "Go\x00\x00", 1) 354 if err != nil { 355 base.Fatalf("readELFNote failed: %v", err) 356 } 357 scanner := bufio.NewScanner(bytes.NewBuffer(pkglistbytes)) 358 for scanner.Scan() { 359 t := scanner.Text() 360 pkgs = append(pkgs, load.LoadImportWithFlags(t, base.Cwd, nil, &stk, nil, 0)) 361 } 362 } 363 return 364} 365 366// cacheAction looks up {mode, p} in the cache and returns the resulting action. 367// If the cache has no such action, f() is recorded and returned. 368// TODO(rsc): Change the second key from *load.Package to interface{}, 369// to make the caching in linkShared less awkward? 370func (b *Builder) cacheAction(mode string, p *load.Package, f func() *Action) *Action { 371 a := b.actionCache[cacheKey{mode, p}] 372 if a == nil { 373 a = f() 374 b.actionCache[cacheKey{mode, p}] = a 375 } 376 return a 377} 378 379// AutoAction returns the "right" action for go build or go install of p. 380func (b *Builder) AutoAction(mode, depMode BuildMode, p *load.Package) *Action { 381 if p.Name == "main" { 382 return b.LinkAction(mode, depMode, p) 383 } 384 return b.CompileAction(mode, depMode, p) 385} 386 387// CompileAction returns the action for compiling and possibly installing 388// (according to mode) the given package. The resulting action is only 389// for building packages (archives), never for linking executables. 390// depMode is the action (build or install) to use when building dependencies. 391// To turn package main into an executable, call b.Link instead. 392func (b *Builder) CompileAction(mode, depMode BuildMode, p *load.Package) *Action { 393 vetOnly := mode&ModeVetOnly != 0 394 mode &^= ModeVetOnly 395 396 if mode != ModeBuild && (p.Internal.Local || p.Module != nil) && p.Target == "" { 397 // Imported via local path or using modules. No permanent target. 398 mode = ModeBuild 399 } 400 if mode != ModeBuild && p.Name == "main" { 401 // We never install the .a file for a main package. 402 mode = ModeBuild 403 } 404 405 // Construct package build action. 406 a := b.cacheAction("build", p, func() *Action { 407 a := &Action{ 408 Mode: "build", 409 Package: p, 410 Func: (*Builder).build, 411 Objdir: b.NewObjdir(), 412 } 413 414 if p.Error == nil || !p.Error.IsImportCycle { 415 for _, p1 := range p.Internal.Imports { 416 a.Deps = append(a.Deps, b.CompileAction(depMode, depMode, p1)) 417 } 418 } 419 420 if p.Standard { 421 switch p.ImportPath { 422 case "builtin", "unsafe": 423 // Fake packages - nothing to build. 424 a.Mode = "built-in package" 425 a.Func = nil 426 return a 427 } 428 429 // gccgo standard library is "fake" too. 430 if cfg.BuildToolchainName == "gccgo" { 431 // the target name is needed for cgo. 432 a.Mode = "gccgo stdlib" 433 a.Target = p.Target 434 a.Func = nil 435 return a 436 } 437 } 438 439 return a 440 }) 441 442 // Find the build action; the cache entry may have been replaced 443 // by the install action during (*Builder).installAction. 444 buildAction := a 445 switch buildAction.Mode { 446 case "build", "built-in package", "gccgo stdlib": 447 // ok 448 case "build-install": 449 buildAction = a.Deps[0] 450 default: 451 panic("lost build action: " + buildAction.Mode) 452 } 453 buildAction.needBuild = buildAction.needBuild || !vetOnly 454 455 // Construct install action. 456 if mode == ModeInstall || mode == ModeBuggyInstall { 457 a = b.installAction(a, mode) 458 } 459 460 return a 461} 462 463// VetAction returns the action for running go vet on package p. 464// It depends on the action for compiling p. 465// If the caller may be causing p to be installed, it is up to the caller 466// to make sure that the install depends on (runs after) vet. 467func (b *Builder) VetAction(mode, depMode BuildMode, p *load.Package) *Action { 468 a := b.vetAction(mode, depMode, p) 469 a.VetxOnly = false 470 return a 471} 472 473func (b *Builder) vetAction(mode, depMode BuildMode, p *load.Package) *Action { 474 // Construct vet action. 475 a := b.cacheAction("vet", p, func() *Action { 476 a1 := b.CompileAction(mode|ModeVetOnly, depMode, p) 477 478 // vet expects to be able to import "fmt". 479 var stk load.ImportStack 480 stk.Push("vet") 481 p1 := load.LoadImportWithFlags("fmt", p.Dir, p, &stk, nil, 0) 482 stk.Pop() 483 aFmt := b.CompileAction(ModeBuild, depMode, p1) 484 485 var deps []*Action 486 if a1.buggyInstall { 487 // (*Builder).vet expects deps[0] to be the package 488 // and deps[1] to be "fmt". If we see buggyInstall 489 // here then a1 is an install of a shared library, 490 // and the real package is a1.Deps[0]. 491 deps = []*Action{a1.Deps[0], aFmt, a1} 492 } else { 493 deps = []*Action{a1, aFmt} 494 } 495 for _, p1 := range p.Internal.Imports { 496 deps = append(deps, b.vetAction(mode, depMode, p1)) 497 } 498 499 a := &Action{ 500 Mode: "vet", 501 Package: p, 502 Deps: deps, 503 Objdir: a1.Objdir, 504 VetxOnly: true, 505 IgnoreFail: true, // it's OK if vet of dependencies "fails" (reports problems) 506 } 507 if a1.Func == nil { 508 // Built-in packages like unsafe. 509 return a 510 } 511 deps[0].needVet = true 512 a.Func = (*Builder).vet 513 return a 514 }) 515 return a 516} 517 518// LinkAction returns the action for linking p into an executable 519// and possibly installing the result (according to mode). 520// depMode is the action (build or install) to use when compiling dependencies. 521func (b *Builder) LinkAction(mode, depMode BuildMode, p *load.Package) *Action { 522 // Construct link action. 523 a := b.cacheAction("link", p, func() *Action { 524 a := &Action{ 525 Mode: "link", 526 Package: p, 527 } 528 529 a1 := b.CompileAction(ModeBuild, depMode, p) 530 a.Func = (*Builder).link 531 a.Deps = []*Action{a1} 532 a.Objdir = a1.Objdir 533 534 // An executable file. (This is the name of a temporary file.) 535 // Because we run the temporary file in 'go run' and 'go test', 536 // the name will show up in ps listings. If the caller has specified 537 // a name, use that instead of a.out. The binary is generated 538 // in an otherwise empty subdirectory named exe to avoid 539 // naming conflicts. The only possible conflict is if we were 540 // to create a top-level package named exe. 541 name := "a.out" 542 if p.Internal.ExeName != "" { 543 name = p.Internal.ExeName 544 } else if (cfg.Goos == "darwin" || cfg.Goos == "windows") && cfg.BuildBuildmode == "c-shared" && p.Target != "" { 545 // On OS X, the linker output name gets recorded in the 546 // shared library's LC_ID_DYLIB load command. 547 // The code invoking the linker knows to pass only the final 548 // path element. Arrange that the path element matches what 549 // we'll install it as; otherwise the library is only loadable as "a.out". 550 // On Windows, DLL file name is recorded in PE file 551 // export section, so do like on OS X. 552 _, name = filepath.Split(p.Target) 553 } 554 a.Target = a.Objdir + filepath.Join("exe", name) + cfg.ExeSuffix 555 a.built = a.Target 556 b.addTransitiveLinkDeps(a, a1, "") 557 558 // Sequence the build of the main package (a1) strictly after the build 559 // of all other dependencies that go into the link. It is likely to be after 560 // them anyway, but just make sure. This is required by the build ID-based 561 // shortcut in (*Builder).useCache(a1), which will call b.linkActionID(a). 562 // In order for that linkActionID call to compute the right action ID, all the 563 // dependencies of a (except a1) must have completed building and have 564 // recorded their build IDs. 565 a1.Deps = append(a1.Deps, &Action{Mode: "nop", Deps: a.Deps[1:]}) 566 return a 567 }) 568 569 if mode == ModeInstall || mode == ModeBuggyInstall { 570 a = b.installAction(a, mode) 571 } 572 573 return a 574} 575 576// installAction returns the action for installing the result of a1. 577func (b *Builder) installAction(a1 *Action, mode BuildMode) *Action { 578 // Because we overwrite the build action with the install action below, 579 // a1 may already be an install action fetched from the "build" cache key, 580 // and the caller just doesn't realize. 581 if strings.HasSuffix(a1.Mode, "-install") { 582 if a1.buggyInstall && mode == ModeInstall { 583 // Congratulations! The buggy install is now a proper install. 584 a1.buggyInstall = false 585 } 586 return a1 587 } 588 589 // If there's no actual action to build a1, 590 // there's nothing to install either. 591 // This happens if a1 corresponds to reusing an already-built object. 592 if a1.Func == nil { 593 return a1 594 } 595 596 p := a1.Package 597 return b.cacheAction(a1.Mode+"-install", p, func() *Action { 598 // The install deletes the temporary build result, 599 // so we need all other actions, both past and future, 600 // that attempt to depend on the build to depend instead 601 // on the install. 602 603 // Make a private copy of a1 (the build action), 604 // no longer accessible to any other rules. 605 buildAction := new(Action) 606 *buildAction = *a1 607 608 // Overwrite a1 with the install action. 609 // This takes care of updating past actions that 610 // point at a1 for the build action; now they will 611 // point at a1 and get the install action. 612 // We also leave a1 in the action cache as the result 613 // for "build", so that actions not yet created that 614 // try to depend on the build will instead depend 615 // on the install. 616 *a1 = Action{ 617 Mode: buildAction.Mode + "-install", 618 Func: BuildInstallFunc, 619 Package: p, 620 Objdir: buildAction.Objdir, 621 Deps: []*Action{buildAction}, 622 Target: p.Target, 623 built: p.Target, 624 625 buggyInstall: mode == ModeBuggyInstall, 626 } 627 628 b.addInstallHeaderAction(a1) 629 return a1 630 }) 631} 632 633// addTransitiveLinkDeps adds to the link action a all packages 634// that are transitive dependencies of a1.Deps. 635// That is, if a is a link of package main, a1 is the compile of package main 636// and a1.Deps is the actions for building packages directly imported by 637// package main (what the compiler needs). The linker needs all packages 638// transitively imported by the whole program; addTransitiveLinkDeps 639// makes sure those are present in a.Deps. 640// If shlib is non-empty, then a corresponds to the build and installation of shlib, 641// so any rebuild of shlib should not be added as a dependency. 642func (b *Builder) addTransitiveLinkDeps(a, a1 *Action, shlib string) { 643 // Expand Deps to include all built packages, for the linker. 644 // Use breadth-first search to find rebuilt-for-test packages 645 // before the standard ones. 646 // TODO(rsc): Eliminate the standard ones from the action graph, 647 // which will require doing a little bit more rebuilding. 648 workq := []*Action{a1} 649 haveDep := map[string]bool{} 650 if a1.Package != nil { 651 haveDep[a1.Package.ImportPath] = true 652 } 653 for i := 0; i < len(workq); i++ { 654 a1 := workq[i] 655 for _, a2 := range a1.Deps { 656 // TODO(rsc): Find a better discriminator than the Mode strings, once the dust settles. 657 if a2.Package == nil || (a2.Mode != "build-install" && a2.Mode != "build") || haveDep[a2.Package.ImportPath] { 658 continue 659 } 660 haveDep[a2.Package.ImportPath] = true 661 a.Deps = append(a.Deps, a2) 662 if a2.Mode == "build-install" { 663 a2 = a2.Deps[0] // walk children of "build" action 664 } 665 workq = append(workq, a2) 666 } 667 } 668 669 // If this is go build -linkshared, then the link depends on the shared libraries 670 // in addition to the packages themselves. (The compile steps do not.) 671 if cfg.BuildLinkshared { 672 haveShlib := map[string]bool{shlib: true} 673 for _, a1 := range a.Deps { 674 p1 := a1.Package 675 if p1 == nil || p1.Shlib == "" || haveShlib[filepath.Base(p1.Shlib)] { 676 continue 677 } 678 haveShlib[filepath.Base(p1.Shlib)] = true 679 // TODO(rsc): The use of ModeInstall here is suspect, but if we only do ModeBuild, 680 // we'll end up building an overall library or executable that depends at runtime 681 // on other libraries that are out-of-date, which is clearly not good either. 682 // We call it ModeBuggyInstall to make clear that this is not right. 683 a.Deps = append(a.Deps, b.linkSharedAction(ModeBuggyInstall, ModeBuggyInstall, p1.Shlib, nil)) 684 } 685 } 686} 687 688// addInstallHeaderAction adds an install header action to a, if needed. 689// The action a should be an install action as generated by either 690// b.CompileAction or b.LinkAction with mode=ModeInstall, 691// and so a.Deps[0] is the corresponding build action. 692func (b *Builder) addInstallHeaderAction(a *Action) { 693 // Install header for cgo in c-archive and c-shared modes. 694 p := a.Package 695 if p.UsesCgo() && (cfg.BuildBuildmode == "c-archive" || cfg.BuildBuildmode == "c-shared") { 696 hdrTarget := a.Target[:len(a.Target)-len(filepath.Ext(a.Target))] + ".h" 697 if cfg.BuildContext.Compiler == "gccgo" && cfg.BuildO == "" { 698 // For the header file, remove the "lib" 699 // added by go/build, so we generate pkg.h 700 // rather than libpkg.h. 701 dir, file := filepath.Split(hdrTarget) 702 file = strings.TrimPrefix(file, "lib") 703 hdrTarget = filepath.Join(dir, file) 704 } 705 ah := &Action{ 706 Mode: "install header", 707 Package: a.Package, 708 Deps: []*Action{a.Deps[0]}, 709 Func: (*Builder).installHeader, 710 Objdir: a.Deps[0].Objdir, 711 Target: hdrTarget, 712 } 713 a.Deps = append(a.Deps, ah) 714 } 715} 716 717// buildmodeShared takes the "go build" action a1 into the building of a shared library of a1.Deps. 718// That is, the input a1 represents "go build pkgs" and the result represents "go build -buildmode=shared pkgs". 719func (b *Builder) buildmodeShared(mode, depMode BuildMode, args []string, pkgs []*load.Package, a1 *Action) *Action { 720 name, err := libname(args, pkgs) 721 if err != nil { 722 base.Fatalf("%v", err) 723 } 724 return b.linkSharedAction(mode, depMode, name, a1) 725} 726 727// linkSharedAction takes a grouping action a1 corresponding to a list of built packages 728// and returns an action that links them together into a shared library with the name shlib. 729// If a1 is nil, shlib should be an absolute path to an existing shared library, 730// and then linkSharedAction reads that library to find out the package list. 731func (b *Builder) linkSharedAction(mode, depMode BuildMode, shlib string, a1 *Action) *Action { 732 fullShlib := shlib 733 shlib = filepath.Base(shlib) 734 a := b.cacheAction("build-shlib "+shlib, nil, func() *Action { 735 if a1 == nil { 736 // TODO(rsc): Need to find some other place to store config, 737 // not in pkg directory. See golang.org/issue/22196. 738 pkgs := readpkglist(fullShlib) 739 a1 = &Action{ 740 Mode: "shlib packages", 741 } 742 for _, p := range pkgs { 743 a1.Deps = append(a1.Deps, b.CompileAction(mode, depMode, p)) 744 } 745 } 746 747 // Fake package to hold ldflags. 748 // As usual shared libraries are a kludgy, abstraction-violating special case: 749 // we let them use the flags specified for the command-line arguments. 750 p := &load.Package{} 751 p.Internal.CmdlinePkg = true 752 p.Internal.Ldflags = load.BuildLdflags.For(p) 753 p.Internal.Gccgoflags = load.BuildGccgoflags.For(p) 754 755 // Add implicit dependencies to pkgs list. 756 // Currently buildmode=shared forces external linking mode, and 757 // external linking mode forces an import of runtime/cgo (and 758 // math on arm). So if it was not passed on the command line and 759 // it is not present in another shared library, add it here. 760 // TODO(rsc): Maybe this should only happen if "runtime" is in the original package set. 761 // TODO(rsc): This should probably be changed to use load.LinkerDeps(p). 762 // TODO(rsc): We don't add standard library imports for gccgo 763 // because they are all always linked in anyhow. 764 // Maybe load.LinkerDeps should be used and updated. 765 a := &Action{ 766 Mode: "go build -buildmode=shared", 767 Package: p, 768 Objdir: b.NewObjdir(), 769 Func: (*Builder).linkShared, 770 Deps: []*Action{a1}, 771 } 772 a.Target = filepath.Join(a.Objdir, shlib) 773 if cfg.BuildToolchainName != "gccgo" { 774 add := func(a1 *Action, pkg string, force bool) { 775 for _, a2 := range a1.Deps { 776 if a2.Package != nil && a2.Package.ImportPath == pkg { 777 return 778 } 779 } 780 var stk load.ImportStack 781 p := load.LoadImportWithFlags(pkg, base.Cwd, nil, &stk, nil, 0) 782 if p.Error != nil { 783 base.Fatalf("load %s: %v", pkg, p.Error) 784 } 785 // Assume that if pkg (runtime/cgo or math) 786 // is already accounted for in a different shared library, 787 // then that shared library also contains runtime, 788 // so that anything we do will depend on that library, 789 // so we don't need to include pkg in our shared library. 790 if force || p.Shlib == "" || filepath.Base(p.Shlib) == pkg { 791 a1.Deps = append(a1.Deps, b.CompileAction(depMode, depMode, p)) 792 } 793 } 794 add(a1, "runtime/cgo", false) 795 if cfg.Goarch == "arm" { 796 add(a1, "math", false) 797 } 798 799 // The linker step still needs all the usual linker deps. 800 // (For example, the linker always opens runtime.a.) 801 for _, dep := range load.LinkerDeps(nil) { 802 add(a, dep, true) 803 } 804 } 805 b.addTransitiveLinkDeps(a, a1, shlib) 806 return a 807 }) 808 809 // Install result. 810 if (mode == ModeInstall || mode == ModeBuggyInstall) && a.Func != nil { 811 buildAction := a 812 813 a = b.cacheAction("install-shlib "+shlib, nil, func() *Action { 814 // Determine the eventual install target. 815 // The install target is root/pkg/shlib, where root is the source root 816 // in which all the packages lie. 817 // TODO(rsc): Perhaps this cross-root check should apply to the full 818 // transitive package dependency list, not just the ones named 819 // on the command line? 820 pkgDir := a1.Deps[0].Package.Internal.Build.PkgTargetRoot 821 for _, a2 := range a1.Deps { 822 if dir := a2.Package.Internal.Build.PkgTargetRoot; dir != pkgDir { 823 base.Fatalf("installing shared library: cannot use packages %s and %s from different roots %s and %s", 824 a1.Deps[0].Package.ImportPath, 825 a2.Package.ImportPath, 826 pkgDir, 827 dir) 828 } 829 } 830 // TODO(rsc): Find out and explain here why gccgo is different. 831 if cfg.BuildToolchainName == "gccgo" { 832 pkgDir = filepath.Join(pkgDir, "shlibs") 833 } 834 target := filepath.Join(pkgDir, shlib) 835 836 a := &Action{ 837 Mode: "go install -buildmode=shared", 838 Objdir: buildAction.Objdir, 839 Func: BuildInstallFunc, 840 Deps: []*Action{buildAction}, 841 Target: target, 842 } 843 for _, a2 := range buildAction.Deps[0].Deps { 844 p := a2.Package 845 if p.Target == "" { 846 continue 847 } 848 a.Deps = append(a.Deps, &Action{ 849 Mode: "shlibname", 850 Package: p, 851 Func: (*Builder).installShlibname, 852 Target: strings.TrimSuffix(p.Target, ".a") + ".shlibname", 853 Deps: []*Action{a.Deps[0]}, 854 }) 855 } 856 return a 857 }) 858 } 859 860 return a 861} 862