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