...

Source file src/pkg/cmd/go/internal/work/action.go

     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	
     7	package work
     8	
     9	import (
    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.
    34	type 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.
    65	type 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.
   101	func (a *Action) BuildActionID() string { return actionID(a.buildID) }
   102	
   103	// BuildContentID returns the content ID section of a's build ID.
   104	func (a *Action) BuildContentID() string { return contentID(a.buildID) }
   105	
   106	// BuildID returns a's build ID.
   107	func (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.
   111	func (a *Action) BuiltTarget() string { return a.built }
   112	
   113	// An actionQueue is a priority queue of actions.
   114	type actionQueue []*Action
   115	
   116	// Implement heap.Interface
   117	func (q *actionQueue) Len() int           { return len(*q) }
   118	func (q *actionQueue) Swap(i, j int)      { (*q)[i], (*q)[j] = (*q)[j], (*q)[i] }
   119	func (q *actionQueue) Less(i, j int) bool { return (*q)[i].priority < (*q)[j].priority }
   120	func (q *actionQueue) Push(x interface{}) { *q = append(*q, x.(*Action)) }
   121	func (q *actionQueue) Pop() interface{} {
   122		n := len(*q) - 1
   123		x := (*q)[n]
   124		*q = (*q)[:n]
   125		return x
   126	}
   127	
   128	func (q *actionQueue) push(a *Action) {
   129		if a.json != nil {
   130			a.json.TimeReady = time.Now()
   131		}
   132		heap.Push(q, a)
   133	}
   134	
   135	func (q *actionQueue) pop() *Action {
   136		return heap.Pop(q).(*Action)
   137	}
   138	
   139	type 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.
   168	type cacheKey struct {
   169		mode string
   170		p    *load.Package
   171	}
   172	
   173	func 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?
   230	type BuildMode int
   231	
   232	const (
   233		ModeBuild BuildMode = iota
   234		ModeInstall
   235		ModeBuggyInstall
   236	
   237		ModeVetOnly = 1 << 8
   238	)
   239	
   240	func (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 _, ok := cfg.OSArchSupportsCgo[cfg.Goos+"/"+cfg.Goarch]; !ok && cfg.BuildContext.Compiler == "gc" {
   294			fmt.Fprintf(os.Stderr, "cmd/go: unsupported GOOS/GOARCH pair %s/%s\n", cfg.Goos, cfg.Goarch)
   295			base.SetExitStatus(2)
   296			base.Exit()
   297		}
   298		for _, tag := range cfg.BuildContext.BuildTags {
   299			if strings.Contains(tag, ",") {
   300				fmt.Fprintf(os.Stderr, "cmd/go: -tags space-separated list contains comma\n")
   301				base.SetExitStatus(2)
   302				base.Exit()
   303			}
   304		}
   305	}
   306	
   307	// NewObjdir returns the name of a fresh object directory under b.WorkDir.
   308	// It is up to the caller to call b.Mkdir on the result at an appropriate time.
   309	// The result ends in a slash, so that file names in that directory
   310	// can be constructed with direct string addition.
   311	//
   312	// NewObjdir must be called only from a single goroutine at a time,
   313	// so it is safe to call during action graph construction, but it must not
   314	// be called during action graph execution.
   315	func (b *Builder) NewObjdir() string {
   316		b.objdirSeq++
   317		return filepath.Join(b.WorkDir, fmt.Sprintf("b%03d", b.objdirSeq)) + string(filepath.Separator)
   318	}
   319	
   320	// readpkglist returns the list of packages that were built into the shared library
   321	// at shlibpath. For the native toolchain this list is stored, newline separated, in
   322	// an ELF note with name "Go\x00\x00" and type 1. For GCCGO it is extracted from the
   323	// .go_export section.
   324	func readpkglist(shlibpath string) (pkgs []*load.Package) {
   325		var stk load.ImportStack
   326		if cfg.BuildToolchainName == "gccgo" {
   327			f, _ := elf.Open(shlibpath)
   328			sect := f.Section(".go_export")
   329			data, _ := sect.Data()
   330			scanner := bufio.NewScanner(bytes.NewBuffer(data))
   331			for scanner.Scan() {
   332				t := scanner.Text()
   333				if strings.HasPrefix(t, "pkgpath ") {
   334					t = strings.TrimPrefix(t, "pkgpath ")
   335					t = strings.TrimSuffix(t, ";")
   336					pkgs = append(pkgs, load.LoadImportWithFlags(t, base.Cwd, nil, &stk, nil, 0))
   337				}
   338			}
   339		} else {
   340			pkglistbytes, err := buildid.ReadELFNote(shlibpath, "Go\x00\x00", 1)
   341			if err != nil {
   342				base.Fatalf("readELFNote failed: %v", err)
   343			}
   344			scanner := bufio.NewScanner(bytes.NewBuffer(pkglistbytes))
   345			for scanner.Scan() {
   346				t := scanner.Text()
   347				pkgs = append(pkgs, load.LoadImportWithFlags(t, base.Cwd, nil, &stk, nil, 0))
   348			}
   349		}
   350		return
   351	}
   352	
   353	// cacheAction looks up {mode, p} in the cache and returns the resulting action.
   354	// If the cache has no such action, f() is recorded and returned.
   355	// TODO(rsc): Change the second key from *load.Package to interface{},
   356	// to make the caching in linkShared less awkward?
   357	func (b *Builder) cacheAction(mode string, p *load.Package, f func() *Action) *Action {
   358		a := b.actionCache[cacheKey{mode, p}]
   359		if a == nil {
   360			a = f()
   361			b.actionCache[cacheKey{mode, p}] = a
   362		}
   363		return a
   364	}
   365	
   366	// AutoAction returns the "right" action for go build or go install of p.
   367	func (b *Builder) AutoAction(mode, depMode BuildMode, p *load.Package) *Action {
   368		if p.Name == "main" {
   369			return b.LinkAction(mode, depMode, p)
   370		}
   371		return b.CompileAction(mode, depMode, p)
   372	}
   373	
   374	// CompileAction returns the action for compiling and possibly installing
   375	// (according to mode) the given package. The resulting action is only
   376	// for building packages (archives), never for linking executables.
   377	// depMode is the action (build or install) to use when building dependencies.
   378	// To turn package main into an executable, call b.Link instead.
   379	func (b *Builder) CompileAction(mode, depMode BuildMode, p *load.Package) *Action {
   380		vetOnly := mode&ModeVetOnly != 0
   381		mode &^= ModeVetOnly
   382	
   383		if mode != ModeBuild && (p.Internal.Local || p.Module != nil) && p.Target == "" {
   384			// Imported via local path or using modules. No permanent target.
   385			mode = ModeBuild
   386		}
   387		if mode != ModeBuild && p.Name == "main" {
   388			// We never install the .a file for a main package.
   389			mode = ModeBuild
   390		}
   391	
   392		// Construct package build action.
   393		a := b.cacheAction("build", p, func() *Action {
   394			a := &Action{
   395				Mode:    "build",
   396				Package: p,
   397				Func:    (*Builder).build,
   398				Objdir:  b.NewObjdir(),
   399			}
   400	
   401			if p.Error == nil || !p.Error.IsImportCycle {
   402				for _, p1 := range p.Internal.Imports {
   403					a.Deps = append(a.Deps, b.CompileAction(depMode, depMode, p1))
   404				}
   405			}
   406	
   407			if p.Standard {
   408				switch p.ImportPath {
   409				case "builtin", "unsafe":
   410					// Fake packages - nothing to build.
   411					a.Mode = "built-in package"
   412					a.Func = nil
   413					return a
   414				}
   415	
   416				// gccgo standard library is "fake" too.
   417				if cfg.BuildToolchainName == "gccgo" {
   418					// the target name is needed for cgo.
   419					a.Mode = "gccgo stdlib"
   420					a.Target = p.Target
   421					a.Func = nil
   422					return a
   423				}
   424			}
   425	
   426			return a
   427		})
   428	
   429		// Find the build action; the cache entry may have been replaced
   430		// by the install action during (*Builder).installAction.
   431		buildAction := a
   432		switch buildAction.Mode {
   433		case "build", "built-in package", "gccgo stdlib":
   434			// ok
   435		case "build-install":
   436			buildAction = a.Deps[0]
   437		default:
   438			panic("lost build action: " + buildAction.Mode)
   439		}
   440		buildAction.needBuild = buildAction.needBuild || !vetOnly
   441	
   442		// Construct install action.
   443		if mode == ModeInstall || mode == ModeBuggyInstall {
   444			a = b.installAction(a, mode)
   445		}
   446	
   447		return a
   448	}
   449	
   450	// VetAction returns the action for running go vet on package p.
   451	// It depends on the action for compiling p.
   452	// If the caller may be causing p to be installed, it is up to the caller
   453	// to make sure that the install depends on (runs after) vet.
   454	func (b *Builder) VetAction(mode, depMode BuildMode, p *load.Package) *Action {
   455		a := b.vetAction(mode, depMode, p)
   456		a.VetxOnly = false
   457		return a
   458	}
   459	
   460	func (b *Builder) vetAction(mode, depMode BuildMode, p *load.Package) *Action {
   461		// Construct vet action.
   462		a := b.cacheAction("vet", p, func() *Action {
   463			a1 := b.CompileAction(mode|ModeVetOnly, depMode, p)
   464	
   465			// vet expects to be able to import "fmt".
   466			var stk load.ImportStack
   467			stk.Push("vet")
   468			p1 := load.LoadImportWithFlags("fmt", p.Dir, p, &stk, nil, 0)
   469			stk.Pop()
   470			aFmt := b.CompileAction(ModeBuild, depMode, p1)
   471	
   472			var deps []*Action
   473			if a1.buggyInstall {
   474				// (*Builder).vet expects deps[0] to be the package
   475				// and deps[1] to be "fmt". If we see buggyInstall
   476				// here then a1 is an install of a shared library,
   477				// and the real package is a1.Deps[0].
   478				deps = []*Action{a1.Deps[0], aFmt, a1}
   479			} else {
   480				deps = []*Action{a1, aFmt}
   481			}
   482			for _, p1 := range p.Internal.Imports {
   483				deps = append(deps, b.vetAction(mode, depMode, p1))
   484			}
   485	
   486			a := &Action{
   487				Mode:       "vet",
   488				Package:    p,
   489				Deps:       deps,
   490				Objdir:     a1.Objdir,
   491				VetxOnly:   true,
   492				IgnoreFail: true, // it's OK if vet of dependencies "fails" (reports problems)
   493			}
   494			if a1.Func == nil {
   495				// Built-in packages like unsafe.
   496				return a
   497			}
   498			deps[0].needVet = true
   499			a.Func = (*Builder).vet
   500			return a
   501		})
   502		return a
   503	}
   504	
   505	// LinkAction returns the action for linking p into an executable
   506	// and possibly installing the result (according to mode).
   507	// depMode is the action (build or install) to use when compiling dependencies.
   508	func (b *Builder) LinkAction(mode, depMode BuildMode, p *load.Package) *Action {
   509		// Construct link action.
   510		a := b.cacheAction("link", p, func() *Action {
   511			a := &Action{
   512				Mode:    "link",
   513				Package: p,
   514			}
   515	
   516			a1 := b.CompileAction(ModeBuild, depMode, p)
   517			a.Func = (*Builder).link
   518			a.Deps = []*Action{a1}
   519			a.Objdir = a1.Objdir
   520	
   521			// An executable file. (This is the name of a temporary file.)
   522			// Because we run the temporary file in 'go run' and 'go test',
   523			// the name will show up in ps listings. If the caller has specified
   524			// a name, use that instead of a.out. The binary is generated
   525			// in an otherwise empty subdirectory named exe to avoid
   526			// naming conflicts. The only possible conflict is if we were
   527			// to create a top-level package named exe.
   528			name := "a.out"
   529			if p.Internal.ExeName != "" {
   530				name = p.Internal.ExeName
   531			} else if (cfg.Goos == "darwin" || cfg.Goos == "windows") && cfg.BuildBuildmode == "c-shared" && p.Target != "" {
   532				// On OS X, the linker output name gets recorded in the
   533				// shared library's LC_ID_DYLIB load command.
   534				// The code invoking the linker knows to pass only the final
   535				// path element. Arrange that the path element matches what
   536				// we'll install it as; otherwise the library is only loadable as "a.out".
   537				// On Windows, DLL file name is recorded in PE file
   538				// export section, so do like on OS X.
   539				_, name = filepath.Split(p.Target)
   540			}
   541			a.Target = a.Objdir + filepath.Join("exe", name) + cfg.ExeSuffix
   542			a.built = a.Target
   543			b.addTransitiveLinkDeps(a, a1, "")
   544	
   545			// Sequence the build of the main package (a1) strictly after the build
   546			// of all other dependencies that go into the link. It is likely to be after
   547			// them anyway, but just make sure. This is required by the build ID-based
   548			// shortcut in (*Builder).useCache(a1), which will call b.linkActionID(a).
   549			// In order for that linkActionID call to compute the right action ID, all the
   550			// dependencies of a (except a1) must have completed building and have
   551			// recorded their build IDs.
   552			a1.Deps = append(a1.Deps, &Action{Mode: "nop", Deps: a.Deps[1:]})
   553			return a
   554		})
   555	
   556		if mode == ModeInstall || mode == ModeBuggyInstall {
   557			a = b.installAction(a, mode)
   558		}
   559	
   560		return a
   561	}
   562	
   563	// installAction returns the action for installing the result of a1.
   564	func (b *Builder) installAction(a1 *Action, mode BuildMode) *Action {
   565		// Because we overwrite the build action with the install action below,
   566		// a1 may already be an install action fetched from the "build" cache key,
   567		// and the caller just doesn't realize.
   568		if strings.HasSuffix(a1.Mode, "-install") {
   569			if a1.buggyInstall && mode == ModeInstall {
   570				//  Congratulations! The buggy install is now a proper install.
   571				a1.buggyInstall = false
   572			}
   573			return a1
   574		}
   575	
   576		// If there's no actual action to build a1,
   577		// there's nothing to install either.
   578		// This happens if a1 corresponds to reusing an already-built object.
   579		if a1.Func == nil {
   580			return a1
   581		}
   582	
   583		p := a1.Package
   584		return b.cacheAction(a1.Mode+"-install", p, func() *Action {
   585			// The install deletes the temporary build result,
   586			// so we need all other actions, both past and future,
   587			// that attempt to depend on the build to depend instead
   588			// on the install.
   589	
   590			// Make a private copy of a1 (the build action),
   591			// no longer accessible to any other rules.
   592			buildAction := new(Action)
   593			*buildAction = *a1
   594	
   595			// Overwrite a1 with the install action.
   596			// This takes care of updating past actions that
   597			// point at a1 for the build action; now they will
   598			// point at a1 and get the install action.
   599			// We also leave a1 in the action cache as the result
   600			// for "build", so that actions not yet created that
   601			// try to depend on the build will instead depend
   602			// on the install.
   603			*a1 = Action{
   604				Mode:    buildAction.Mode + "-install",
   605				Func:    BuildInstallFunc,
   606				Package: p,
   607				Objdir:  buildAction.Objdir,
   608				Deps:    []*Action{buildAction},
   609				Target:  p.Target,
   610				built:   p.Target,
   611	
   612				buggyInstall: mode == ModeBuggyInstall,
   613			}
   614	
   615			b.addInstallHeaderAction(a1)
   616			return a1
   617		})
   618	}
   619	
   620	// addTransitiveLinkDeps adds to the link action a all packages
   621	// that are transitive dependencies of a1.Deps.
   622	// That is, if a is a link of package main, a1 is the compile of package main
   623	// and a1.Deps is the actions for building packages directly imported by
   624	// package main (what the compiler needs). The linker needs all packages
   625	// transitively imported by the whole program; addTransitiveLinkDeps
   626	// makes sure those are present in a.Deps.
   627	// If shlib is non-empty, then a corresponds to the build and installation of shlib,
   628	// so any rebuild of shlib should not be added as a dependency.
   629	func (b *Builder) addTransitiveLinkDeps(a, a1 *Action, shlib string) {
   630		// Expand Deps to include all built packages, for the linker.
   631		// Use breadth-first search to find rebuilt-for-test packages
   632		// before the standard ones.
   633		// TODO(rsc): Eliminate the standard ones from the action graph,
   634		// which will require doing a little bit more rebuilding.
   635		workq := []*Action{a1}
   636		haveDep := map[string]bool{}
   637		if a1.Package != nil {
   638			haveDep[a1.Package.ImportPath] = true
   639		}
   640		for i := 0; i < len(workq); i++ {
   641			a1 := workq[i]
   642			for _, a2 := range a1.Deps {
   643				// TODO(rsc): Find a better discriminator than the Mode strings, once the dust settles.
   644				if a2.Package == nil || (a2.Mode != "build-install" && a2.Mode != "build") || haveDep[a2.Package.ImportPath] {
   645					continue
   646				}
   647				haveDep[a2.Package.ImportPath] = true
   648				a.Deps = append(a.Deps, a2)
   649				if a2.Mode == "build-install" {
   650					a2 = a2.Deps[0] // walk children of "build" action
   651				}
   652				workq = append(workq, a2)
   653			}
   654		}
   655	
   656		// If this is go build -linkshared, then the link depends on the shared libraries
   657		// in addition to the packages themselves. (The compile steps do not.)
   658		if cfg.BuildLinkshared {
   659			haveShlib := map[string]bool{shlib: true}
   660			for _, a1 := range a.Deps {
   661				p1 := a1.Package
   662				if p1 == nil || p1.Shlib == "" || haveShlib[filepath.Base(p1.Shlib)] {
   663					continue
   664				}
   665				haveShlib[filepath.Base(p1.Shlib)] = true
   666				// TODO(rsc): The use of ModeInstall here is suspect, but if we only do ModeBuild,
   667				// we'll end up building an overall library or executable that depends at runtime
   668				// on other libraries that are out-of-date, which is clearly not good either.
   669				// We call it ModeBuggyInstall to make clear that this is not right.
   670				a.Deps = append(a.Deps, b.linkSharedAction(ModeBuggyInstall, ModeBuggyInstall, p1.Shlib, nil))
   671			}
   672		}
   673	}
   674	
   675	// addInstallHeaderAction adds an install header action to a, if needed.
   676	// The action a should be an install action as generated by either
   677	// b.CompileAction or b.LinkAction with mode=ModeInstall,
   678	// and so a.Deps[0] is the corresponding build action.
   679	func (b *Builder) addInstallHeaderAction(a *Action) {
   680		// Install header for cgo in c-archive and c-shared modes.
   681		p := a.Package
   682		if p.UsesCgo() && (cfg.BuildBuildmode == "c-archive" || cfg.BuildBuildmode == "c-shared") {
   683			hdrTarget := a.Target[:len(a.Target)-len(filepath.Ext(a.Target))] + ".h"
   684			if cfg.BuildContext.Compiler == "gccgo" && cfg.BuildO == "" {
   685				// For the header file, remove the "lib"
   686				// added by go/build, so we generate pkg.h
   687				// rather than libpkg.h.
   688				dir, file := filepath.Split(hdrTarget)
   689				file = strings.TrimPrefix(file, "lib")
   690				hdrTarget = filepath.Join(dir, file)
   691			}
   692			ah := &Action{
   693				Mode:    "install header",
   694				Package: a.Package,
   695				Deps:    []*Action{a.Deps[0]},
   696				Func:    (*Builder).installHeader,
   697				Objdir:  a.Deps[0].Objdir,
   698				Target:  hdrTarget,
   699			}
   700			a.Deps = append(a.Deps, ah)
   701		}
   702	}
   703	
   704	// buildmodeShared takes the "go build" action a1 into the building of a shared library of a1.Deps.
   705	// That is, the input a1 represents "go build pkgs" and the result represents "go build -buidmode=shared pkgs".
   706	func (b *Builder) buildmodeShared(mode, depMode BuildMode, args []string, pkgs []*load.Package, a1 *Action) *Action {
   707		name, err := libname(args, pkgs)
   708		if err != nil {
   709			base.Fatalf("%v", err)
   710		}
   711		return b.linkSharedAction(mode, depMode, name, a1)
   712	}
   713	
   714	// linkSharedAction takes a grouping action a1 corresponding to a list of built packages
   715	// and returns an action that links them together into a shared library with the name shlib.
   716	// If a1 is nil, shlib should be an absolute path to an existing shared library,
   717	// and then linkSharedAction reads that library to find out the package list.
   718	func (b *Builder) linkSharedAction(mode, depMode BuildMode, shlib string, a1 *Action) *Action {
   719		fullShlib := shlib
   720		shlib = filepath.Base(shlib)
   721		a := b.cacheAction("build-shlib "+shlib, nil, func() *Action {
   722			if a1 == nil {
   723				// TODO(rsc): Need to find some other place to store config,
   724				// not in pkg directory. See golang.org/issue/22196.
   725				pkgs := readpkglist(fullShlib)
   726				a1 = &Action{
   727					Mode: "shlib packages",
   728				}
   729				for _, p := range pkgs {
   730					a1.Deps = append(a1.Deps, b.CompileAction(mode, depMode, p))
   731				}
   732			}
   733	
   734			// Fake package to hold ldflags.
   735			// As usual shared libraries are a kludgy, abstraction-violating special case:
   736			// we let them use the flags specified for the command-line arguments.
   737			p := &load.Package{}
   738			p.Internal.CmdlinePkg = true
   739			p.Internal.Ldflags = load.BuildLdflags.For(p)
   740			p.Internal.Gccgoflags = load.BuildGccgoflags.For(p)
   741	
   742			// Add implicit dependencies to pkgs list.
   743			// Currently buildmode=shared forces external linking mode, and
   744			// external linking mode forces an import of runtime/cgo (and
   745			// math on arm). So if it was not passed on the command line and
   746			// it is not present in another shared library, add it here.
   747			// TODO(rsc): Maybe this should only happen if "runtime" is in the original package set.
   748			// TODO(rsc): This should probably be changed to use load.LinkerDeps(p).
   749			// TODO(rsc): We don't add standard library imports for gccgo
   750			// because they are all always linked in anyhow.
   751			// Maybe load.LinkerDeps should be used and updated.
   752			a := &Action{
   753				Mode:    "go build -buildmode=shared",
   754				Package: p,
   755				Objdir:  b.NewObjdir(),
   756				Func:    (*Builder).linkShared,
   757				Deps:    []*Action{a1},
   758			}
   759			a.Target = filepath.Join(a.Objdir, shlib)
   760			if cfg.BuildToolchainName != "gccgo" {
   761				add := func(a1 *Action, pkg string, force bool) {
   762					for _, a2 := range a1.Deps {
   763						if a2.Package != nil && a2.Package.ImportPath == pkg {
   764							return
   765						}
   766					}
   767					var stk load.ImportStack
   768					p := load.LoadImportWithFlags(pkg, base.Cwd, nil, &stk, nil, 0)
   769					if p.Error != nil {
   770						base.Fatalf("load %s: %v", pkg, p.Error)
   771					}
   772					// Assume that if pkg (runtime/cgo or math)
   773					// is already accounted for in a different shared library,
   774					// then that shared library also contains runtime,
   775					// so that anything we do will depend on that library,
   776					// so we don't need to include pkg in our shared library.
   777					if force || p.Shlib == "" || filepath.Base(p.Shlib) == pkg {
   778						a1.Deps = append(a1.Deps, b.CompileAction(depMode, depMode, p))
   779					}
   780				}
   781				add(a1, "runtime/cgo", false)
   782				if cfg.Goarch == "arm" {
   783					add(a1, "math", false)
   784				}
   785	
   786				// The linker step still needs all the usual linker deps.
   787				// (For example, the linker always opens runtime.a.)
   788				for _, dep := range load.LinkerDeps(nil) {
   789					add(a, dep, true)
   790				}
   791			}
   792			b.addTransitiveLinkDeps(a, a1, shlib)
   793			return a
   794		})
   795	
   796		// Install result.
   797		if (mode == ModeInstall || mode == ModeBuggyInstall) && a.Func != nil {
   798			buildAction := a
   799	
   800			a = b.cacheAction("install-shlib "+shlib, nil, func() *Action {
   801				// Determine the eventual install target.
   802				// The install target is root/pkg/shlib, where root is the source root
   803				// in which all the packages lie.
   804				// TODO(rsc): Perhaps this cross-root check should apply to the full
   805				// transitive package dependency list, not just the ones named
   806				// on the command line?
   807				pkgDir := a1.Deps[0].Package.Internal.Build.PkgTargetRoot
   808				for _, a2 := range a1.Deps {
   809					if dir := a2.Package.Internal.Build.PkgTargetRoot; dir != pkgDir {
   810						base.Fatalf("installing shared library: cannot use packages %s and %s from different roots %s and %s",
   811							a1.Deps[0].Package.ImportPath,
   812							a2.Package.ImportPath,
   813							pkgDir,
   814							dir)
   815					}
   816				}
   817				// TODO(rsc): Find out and explain here why gccgo is different.
   818				if cfg.BuildToolchainName == "gccgo" {
   819					pkgDir = filepath.Join(pkgDir, "shlibs")
   820				}
   821				target := filepath.Join(pkgDir, shlib)
   822	
   823				a := &Action{
   824					Mode:   "go install -buildmode=shared",
   825					Objdir: buildAction.Objdir,
   826					Func:   BuildInstallFunc,
   827					Deps:   []*Action{buildAction},
   828					Target: target,
   829				}
   830				for _, a2 := range buildAction.Deps[0].Deps {
   831					p := a2.Package
   832					if p.Target == "" {
   833						continue
   834					}
   835					a.Deps = append(a.Deps, &Action{
   836						Mode:    "shlibname",
   837						Package: p,
   838						Func:    (*Builder).installShlibname,
   839						Target:  strings.TrimSuffix(p.Target, ".a") + ".shlibname",
   840						Deps:    []*Action{a.Deps[0]},
   841					})
   842				}
   843				return a
   844			})
   845		}
   846	
   847		return a
   848	}
   849	

View as plain text