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