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