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