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