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