libgo: update to Go1.10rc1
[official-gcc.git] / libgo / go / cmd / go / internal / work / action.go
blob803a6bd4611c3d1cd8e8e1a6101e4b2075b7b592
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.
5 // Action graph creation (planning).
7 package work
9 import (
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"
23 "cmd/go/internal/base"
24 "cmd/go/internal/cache"
25 "cmd/go/internal/cfg"
26 "cmd/go/internal/load"
27 "cmd/internal/buildid"
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.
33 type 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)
40 ComputeStaleOnly bool // compute staleness for go list; no actual build
42 objdirSeq int // counter for NewObjdir
43 pkgSeq int
45 output sync.Mutex
46 scriptDir string // current directory in printed script
48 exec sync.Mutex
49 readySema chan bool
50 ready actionQueue
52 id sync.Mutex
53 toolIDCache map[string]string // tool name -> tool ID
54 buildIDCache map[string]string // file name -> build ID
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?
60 // An Action represents a single action in the action graph.
61 type 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
70 triggers []*Action // inverse of deps
72 buggyInstall bool // is this a buggy install (see -linkshared)?
74 TryCache func(*Builder, *Action) bool // callback for cache bypass
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
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)
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
93 // BuildActionID returns the action ID section of a's build ID.
94 func (a *Action) BuildActionID() string { return actionID(a.buildID) }
96 // BuildContentID returns the content ID section of a's build ID.
97 func (a *Action) BuildContentID() string { return contentID(a.buildID) }
99 // BuildID returns a's build ID.
100 func (a *Action) BuildID() string { return a.buildID }
102 // BuiltTarget returns the actual file that was built. This differs
103 // from Target when the result was cached.
104 func (a *Action) BuiltTarget() string { return a.built }
106 // An actionQueue is a priority queue of actions.
107 type actionQueue []*Action
109 // Implement heap.Interface
110 func (q *actionQueue) Len() int { return len(*q) }
111 func (q *actionQueue) Swap(i, j int) { (*q)[i], (*q)[j] = (*q)[j], (*q)[i] }
112 func (q *actionQueue) Less(i, j int) bool { return (*q)[i].priority < (*q)[j].priority }
113 func (q *actionQueue) Push(x interface{}) { *q = append(*q, x.(*Action)) }
114 func (q *actionQueue) Pop() interface{} {
115 n := len(*q) - 1
116 x := (*q)[n]
117 *q = (*q)[:n]
118 return x
121 func (q *actionQueue) push(a *Action) {
122 heap.Push(q, a)
125 func (q *actionQueue) pop() *Action {
126 return heap.Pop(q).(*Action)
129 type 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"`
144 // cacheKey is the key for the action cache.
145 type cacheKey struct {
146 mode string
147 p *load.Package
150 func actionGraphJSON(a *Action) string {
151 var workq []*Action
152 var inWorkq = make(map[*Action]int)
154 add := func(a *Action) {
155 if _, ok := inWorkq[a]; ok {
156 return
158 inWorkq[a] = len(workq)
159 workq = append(workq, a)
161 add(a)
163 for i := 0; i < len(workq); i++ {
164 for _, dep := range workq[i].Deps {
165 add(dep)
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,
182 if a.Package != nil {
183 // TODO(rsc): Make this a unique key for a.Package somehow.
184 aj.Package = a.Package.ImportPath
186 for _, a1 := range a.Deps {
187 aj.Deps = append(aj.Deps, inWorkq[a1])
189 list = append(list, aj)
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 ""
197 return string(js)
200 // BuildMode specifies the build mode:
201 // are we just building things or also installing the results?
202 type BuildMode int
204 const (
205 ModeBuild BuildMode = iota
206 ModeInstall
207 ModeBuggyInstall
210 func (b *Builder) Init() {
211 var err error
212 b.Print = func(a ...interface{}) (int, error) {
213 return fmt.Fprint(os.Stderr, a...)
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)
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)
227 if cfg.BuildX || cfg.BuildWork {
228 fmt.Fprintf(os.Stderr, "WORK=%s\n", b.WorkDir)
230 if !cfg.BuildWork {
231 workdir := b.WorkDir
232 base.AtExit(func() { os.RemoveAll(workdir) })
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)
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)
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.
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.
256 func (b *Builder) NewObjdir() string {
257 b.objdirSeq++
258 return filepath.Join(b.WorkDir, fmt.Sprintf("b%03d", b.objdirSeq)) + string(filepath.Separator)
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.
265 func 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")
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))
284 } else {
285 pkglistbytes, err := buildid.ReadELFNote(shlibpath, "Go\x00\x00", 1)
286 if err != nil {
287 base.Fatalf("readELFNote failed: %v", err)
289 scanner := bufio.NewScanner(bytes.NewBuffer(pkglistbytes))
290 for scanner.Scan() {
291 t := scanner.Text()
292 pkgs = append(pkgs, load.LoadPackage(t, &stk))
295 return
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?
302 func (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
308 return a
311 // AutoAction returns the "right" action for go build or go install of p.
312 func (b *Builder) AutoAction(mode, depMode BuildMode, p *load.Package) *Action {
313 if p.Name == "main" {
314 return b.LinkAction(mode, depMode, p)
316 return b.CompileAction(mode, depMode, p)
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.
324 func (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
329 if mode != ModeBuild && p.Name == "main" {
330 // We never install the .a file for a main package.
331 mode = ModeBuild
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(),
343 for _, p1 := range p.Internal.Imports {
344 a.Deps = append(a.Deps, b.CompileAction(depMode, depMode, p1))
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
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
366 return a
369 // Construct install action.
370 if mode == ModeInstall || mode == ModeBuggyInstall {
371 a = b.installAction(a, mode)
374 return a
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.
381 func (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)
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)
393 a := &Action{
394 Mode: "vet",
395 Package: p,
396 Deps: []*Action{a1, aFmt},
397 Objdir: a1.Objdir,
399 if a1.Func == nil {
400 // Built-in packages like unsafe.
401 return a
403 a1.needVet = true
404 a.Func = (*Builder).vet
406 return a
408 return a
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.
414 func (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,
422 a1 := b.CompileAction(ModeBuild, depMode, p)
423 a.Func = (*Builder).link
424 a.Deps = []*Action{a1}
425 a.Objdir = a1.Objdir
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)
447 a.Target = a.Objdir + filepath.Join("exe", name) + cfg.ExeSuffix
448 a.built = a.Target
449 b.addTransitiveLinkDeps(a, a1, "")
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
462 if mode == ModeInstall || mode == ModeBuggyInstall {
463 a = b.installAction(a, mode)
466 return a
469 // installAction returns the action for installing the result of a1.
470 func (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
479 return a1
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
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.
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
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,
518 buggyInstall: mode == ModeBuggyInstall,
521 b.addInstallHeaderAction(a1)
522 return a1
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.
535 func (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
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
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
558 workq = append(workq, a2)
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
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))
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.
585 func (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)
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,
606 a.Deps = append(a.Deps, ah)
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".
612 func (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)
617 return b.linkSharedAction(mode, depMode, name, a1)
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.
624 func (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",
635 for _, p := range pkgs {
636 a1.Deps = append(a1.Deps, b.CompileAction(mode, depMode, p))
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)
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},
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
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)
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))
687 add(a1, "runtime/cgo", false)
688 if cfg.Goarch == "arm" {
689 add(a1, "math", false)
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)
698 b.addTransitiveLinkDeps(a, a1, shlib)
699 return a
702 // Install result.
703 if (mode == ModeInstall || mode == ModeBuggyInstall) && a.Func != nil {
704 buildAction := a
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)
723 // TODO(rsc): Find out and explain here why gccgo is different.
724 if cfg.BuildToolchainName == "gccgo" {
725 pkgDir = filepath.Join(pkgDir, "shlibs")
727 target := filepath.Join(pkgDir, shlib)
729 a := &Action{
730 Mode: "go install -buildmode=shared",
731 Objdir: buildAction.Objdir,
732 Func: BuildInstallFunc,
733 Deps: []*Action{buildAction},
734 Target: target,
736 for _, a2 := range buildAction.Deps[0].Deps {
737 p := a2.Package
738 if p.Target == "" {
739 continue
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]},
749 return a
753 return a