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