Source file src/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  	"cmd/internal/par"
    13  	"container/heap"
    14  	"context"
    15  	"debug/elf"
    16  	"encoding/json"
    17  	"fmt"
    18  	"internal/platform"
    19  	"os"
    20  	"path/filepath"
    21  	"slices"
    22  	"strings"
    23  	"sync"
    24  	"time"
    25  
    26  	"cmd/go/internal/base"
    27  	"cmd/go/internal/cache"
    28  	"cmd/go/internal/cfg"
    29  	"cmd/go/internal/load"
    30  	"cmd/go/internal/modload"
    31  	"cmd/go/internal/str"
    32  	"cmd/go/internal/trace"
    33  	"cmd/internal/buildid"
    34  	"cmd/internal/robustio"
    35  )
    36  
    37  // A Builder holds global state about a build.
    38  // It does not hold per-package state, because we
    39  // build packages in parallel, and the builder is shared.
    40  type Builder struct {
    41  	WorkDir            string                    // the temporary work directory (ends in filepath.Separator)
    42  	getVendorDir       func() string             // TODO(jitsu): remove this after we eliminate global module state
    43  	actionCache        map[cacheKey]*Action      // a cache of already-constructed actions
    44  	flagCache          map[[2]string]bool        // a cache of supported compiler flags
    45  	gccCompilerIDCache map[string]cache.ActionID // cache for gccCompilerID
    46  
    47  	IsCmdList           bool // running as part of go list; set p.Stale and additional fields below
    48  	NeedError           bool // list needs p.Error
    49  	NeedExport          bool // list needs p.Export
    50  	NeedCompiledGoFiles bool // list needs p.CompiledGoFiles
    51  	AllowErrors         bool // errors don't immediately exit the program
    52  
    53  	objdirSeq int // counter for NewObjdir
    54  	pkgSeq    int
    55  
    56  	backgroundSh *Shell // Shell that per-Action Shells are derived from
    57  
    58  	exec      sync.Mutex
    59  	readySema chan bool
    60  	ready     actionQueue
    61  
    62  	id             sync.Mutex
    63  	toolIDCache    par.Cache[string, string] // tool name -> tool ID
    64  	gccToolIDCache map[string]string         // tool name -> tool ID
    65  	buildIDCache   map[string]string         // file name -> build ID
    66  }
    67  
    68  // NOTE: Much of Action would not need to be exported if not for test.
    69  // Maybe test functionality should move into this package too?
    70  
    71  // An Actor runs an action.
    72  type Actor interface {
    73  	Act(*Builder, context.Context, *Action) error
    74  }
    75  
    76  // An ActorFunc is an Actor that calls the function.
    77  type ActorFunc func(*Builder, context.Context, *Action) error
    78  
    79  func (f ActorFunc) Act(b *Builder, ctx context.Context, a *Action) error {
    80  	return f(b, ctx, a)
    81  }
    82  
    83  // An Action represents a single action in the action graph.
    84  type Action struct {
    85  	Mode       string        // description of action operation
    86  	Package    *load.Package // the package this action works on
    87  	Deps       []*Action     // actions that must happen before this one
    88  	Actor      Actor         // the action itself (nil = no-op)
    89  	IgnoreFail bool          // whether to run f even if dependencies fail
    90  	TestOutput *bytes.Buffer // test output buffer
    91  	Args       []string      // additional args for runProgram
    92  
    93  	Provider any // Additional information to be passed to successive actions. Similar to a Bazel provider.
    94  
    95  	triggers []*Action // inverse of deps
    96  
    97  	buggyInstall bool // is this a buggy install (see -linkshared)?
    98  
    99  	TryCache func(*Builder, *Action, *Action) bool // callback for cache bypass
   100  
   101  	CacheExecutable bool // Whether to cache executables produced by link steps
   102  
   103  	// Generated files, directories.
   104  	Objdir           string         // directory for intermediate objects
   105  	Target           string         // goal of the action: the created package or executable
   106  	built            string         // the actual created package or executable
   107  	cachedExecutable string         // the cached executable, if CacheExecutable was set
   108  	actionID         cache.ActionID // cache ID of action input
   109  	buildID          string         // build ID of action output
   110  
   111  	VetxOnly   bool       // Mode=="vet": only being called to supply info about dependencies
   112  	needVet    bool       // Mode=="build": need to fill in vet config
   113  	needBuild  bool       // Mode=="build": need to do actual build (can be false if needVet is true)
   114  	needFix    bool       // Mode=="vet": need secondary target, a .zip file containing fixes
   115  	vetCfg     *vetConfig // vet config
   116  	FixArchive string     // the created .zip file containing fixes (if needFix)
   117  	output     []byte     // output redirect buffer (nil means use b.Print)
   118  
   119  	sh *Shell // lazily created per-Action shell; see Builder.Shell
   120  
   121  	// Execution state.
   122  	pending      int               // number of deps yet to complete
   123  	priority     int               // relative execution priority
   124  	Failed       *Action           // set to root cause if the action failed
   125  	json         *actionJSON       // action graph information
   126  	nonGoOverlay map[string]string // map from non-.go source files to copied files in objdir. Nil if no overlay is used.
   127  	traceSpan    *trace.Span
   128  }
   129  
   130  // BuildActionID returns the action ID section of a's build ID.
   131  func (a *Action) BuildActionID() string { return buildActionID(a.buildID) }
   132  
   133  // BuildContentID returns the content ID section of a's build ID.
   134  func (a *Action) BuildContentID() string { return buildObjectID(a.buildID) }
   135  
   136  // BuildID returns a's build ID.
   137  func (a *Action) BuildID() string { return a.buildID }
   138  
   139  // BuiltTarget returns the actual file that was built. This differs
   140  // from Target when the result was cached.
   141  func (a *Action) BuiltTarget() string { return a.built }
   142  
   143  // CachedExecutable returns the cached executable, if CacheExecutable
   144  // was set and the executable could be cached, and "" otherwise.
   145  func (a *Action) CachedExecutable() string { return a.cachedExecutable }
   146  
   147  // An actionQueue is a priority queue of actions.
   148  type actionQueue []*Action
   149  
   150  // Implement heap.Interface
   151  func (q *actionQueue) Len() int           { return len(*q) }
   152  func (q *actionQueue) Swap(i, j int)      { (*q)[i], (*q)[j] = (*q)[j], (*q)[i] }
   153  func (q *actionQueue) Less(i, j int) bool { return (*q)[i].priority < (*q)[j].priority }
   154  func (q *actionQueue) Push(x any)         { *q = append(*q, x.(*Action)) }
   155  func (q *actionQueue) Pop() any {
   156  	n := len(*q) - 1
   157  	x := (*q)[n]
   158  	*q = (*q)[:n]
   159  	return x
   160  }
   161  
   162  func (q *actionQueue) push(a *Action) {
   163  	if a.json != nil {
   164  		a.json.TimeReady = time.Now()
   165  	}
   166  	heap.Push(q, a)
   167  }
   168  
   169  func (q *actionQueue) pop() *Action {
   170  	return heap.Pop(q).(*Action)
   171  }
   172  
   173  type actionJSON struct {
   174  	ID         int
   175  	Mode       string
   176  	Package    string
   177  	Deps       []int     `json:",omitempty"`
   178  	IgnoreFail bool      `json:",omitempty"`
   179  	Args       []string  `json:",omitempty"`
   180  	Link       bool      `json:",omitempty"`
   181  	Objdir     string    `json:",omitempty"`
   182  	Target     string    `json:",omitempty"`
   183  	Priority   int       `json:",omitempty"`
   184  	Failed     bool      `json:",omitempty"`
   185  	Built      string    `json:",omitempty"`
   186  	VetxOnly   bool      `json:",omitempty"`
   187  	NeedVet    bool      `json:",omitempty"`
   188  	NeedBuild  bool      `json:",omitempty"`
   189  	ActionID   string    `json:",omitempty"`
   190  	BuildID    string    `json:",omitempty"`
   191  	TimeReady  time.Time `json:",omitempty"`
   192  	TimeStart  time.Time `json:",omitempty"`
   193  	TimeDone   time.Time `json:",omitempty"`
   194  
   195  	Cmd     []string      // `json:",omitempty"`
   196  	CmdReal time.Duration `json:",omitempty"`
   197  	CmdUser time.Duration `json:",omitempty"`
   198  	CmdSys  time.Duration `json:",omitempty"`
   199  }
   200  
   201  // cacheKey is the key for the action cache.
   202  type cacheKey struct {
   203  	mode string
   204  	p    *load.Package
   205  }
   206  
   207  func actionGraphJSON(a *Action) string {
   208  	var workq []*Action
   209  	var inWorkq = make(map[*Action]int)
   210  
   211  	add := func(a *Action) {
   212  		if _, ok := inWorkq[a]; ok {
   213  			return
   214  		}
   215  		inWorkq[a] = len(workq)
   216  		workq = append(workq, a)
   217  	}
   218  	add(a)
   219  
   220  	for i := 0; i < len(workq); i++ {
   221  		for _, dep := range workq[i].Deps {
   222  			add(dep)
   223  		}
   224  	}
   225  
   226  	list := make([]*actionJSON, 0, len(workq))
   227  	for id, a := range workq {
   228  		if a.json == nil {
   229  			a.json = &actionJSON{
   230  				Mode:       a.Mode,
   231  				ID:         id,
   232  				IgnoreFail: a.IgnoreFail,
   233  				Args:       a.Args,
   234  				Objdir:     a.Objdir,
   235  				Target:     a.Target,
   236  				Failed:     a.Failed != nil,
   237  				Priority:   a.priority,
   238  				Built:      a.built,
   239  				VetxOnly:   a.VetxOnly,
   240  				NeedBuild:  a.needBuild,
   241  				NeedVet:    a.needVet,
   242  			}
   243  			if a.Package != nil {
   244  				// TODO(rsc): Make this a unique key for a.Package somehow.
   245  				a.json.Package = a.Package.ImportPath
   246  			}
   247  			for _, a1 := range a.Deps {
   248  				a.json.Deps = append(a.json.Deps, inWorkq[a1])
   249  			}
   250  		}
   251  		list = append(list, a.json)
   252  	}
   253  
   254  	js, err := json.MarshalIndent(list, "", "\t")
   255  	if err != nil {
   256  		fmt.Fprintf(os.Stderr, "go: writing debug action graph: %v\n", err)
   257  		return ""
   258  	}
   259  	return string(js)
   260  }
   261  
   262  // BuildMode specifies the build mode:
   263  // are we just building things or also installing the results?
   264  type BuildMode int
   265  
   266  const (
   267  	ModeBuild BuildMode = iota
   268  	ModeInstall
   269  	ModeBuggyInstall
   270  
   271  	ModeVetOnly = 1 << 8
   272  )
   273  
   274  // NewBuilder returns a new Builder ready for use.
   275  //
   276  // If workDir is the empty string, NewBuilder creates a WorkDir if needed
   277  // and arranges for it to be removed in case of an unclean exit.
   278  // The caller must Close the builder explicitly to clean up the WorkDir
   279  // before a clean exit.
   280  func NewBuilder(workDir string, getVendorDir func() string) *Builder {
   281  	b := new(Builder)
   282  	b.getVendorDir = getVendorDir
   283  
   284  	b.actionCache = make(map[cacheKey]*Action)
   285  	b.gccToolIDCache = make(map[string]string)
   286  	b.buildIDCache = make(map[string]string)
   287  
   288  	printWorkDir := false
   289  	if workDir != "" {
   290  		b.WorkDir = workDir
   291  	} else if cfg.BuildN {
   292  		b.WorkDir = "$WORK"
   293  	} else {
   294  		if !buildInitStarted {
   295  			panic("internal error: NewBuilder called before BuildInit")
   296  		}
   297  		tmp, err := os.MkdirTemp(cfg.Getenv("GOTMPDIR"), "go-build")
   298  		if err != nil {
   299  			base.Fatalf("go: creating work dir: %v", err)
   300  		}
   301  		if !filepath.IsAbs(tmp) {
   302  			abs, err := filepath.Abs(tmp)
   303  			if err != nil {
   304  				os.RemoveAll(tmp)
   305  				base.Fatalf("go: creating work dir: %v", err)
   306  			}
   307  			tmp = abs
   308  		}
   309  		b.WorkDir = tmp
   310  		builderWorkDirs.Store(b, b.WorkDir)
   311  		printWorkDir = cfg.BuildX || cfg.BuildWork
   312  	}
   313  
   314  	b.backgroundSh = NewShell(b.WorkDir, nil)
   315  
   316  	if printWorkDir {
   317  		b.BackgroundShell().Printf("WORK=%s\n", b.WorkDir)
   318  	}
   319  
   320  	if err := CheckGOOSARCHPair(cfg.Goos, cfg.Goarch); err != nil {
   321  		fmt.Fprintf(os.Stderr, "go: %v\n", err)
   322  		base.SetExitStatus(2)
   323  		base.Exit()
   324  	}
   325  
   326  	for _, tag := range cfg.BuildContext.BuildTags {
   327  		if strings.Contains(tag, ",") {
   328  			fmt.Fprintf(os.Stderr, "go: -tags space-separated list contains comma\n")
   329  			base.SetExitStatus(2)
   330  			base.Exit()
   331  		}
   332  	}
   333  
   334  	return b
   335  }
   336  
   337  var builderWorkDirs sync.Map // *Builder → WorkDir
   338  
   339  func (b *Builder) Close() error {
   340  	wd, ok := builderWorkDirs.Load(b)
   341  	if !ok {
   342  		return nil
   343  	}
   344  	defer builderWorkDirs.Delete(b)
   345  
   346  	if b.WorkDir != wd.(string) {
   347  		base.Errorf("go: internal error: Builder WorkDir unexpectedly changed from %s to %s", wd, b.WorkDir)
   348  	}
   349  
   350  	if !cfg.BuildWork {
   351  		if err := robustio.RemoveAll(b.WorkDir); err != nil {
   352  			return err
   353  		}
   354  	}
   355  	b.WorkDir = ""
   356  	return nil
   357  }
   358  
   359  func closeBuilders() {
   360  	leakedBuilders := 0
   361  	builderWorkDirs.Range(func(bi, _ any) bool {
   362  		leakedBuilders++
   363  		if err := bi.(*Builder).Close(); err != nil {
   364  			base.Error(err)
   365  		}
   366  		return true
   367  	})
   368  
   369  	if leakedBuilders > 0 && base.GetExitStatus() == 0 {
   370  		fmt.Fprintf(os.Stderr, "go: internal error: Builder leaked on successful exit\n")
   371  		base.SetExitStatus(1)
   372  	}
   373  }
   374  
   375  func CheckGOOSARCHPair(goos, goarch string) error {
   376  	if !platform.BuildModeSupported(cfg.BuildContext.Compiler, "default", goos, goarch) {
   377  		return fmt.Errorf("unsupported GOOS/GOARCH pair %s/%s", goos, goarch)
   378  	}
   379  	return nil
   380  }
   381  
   382  // NewObjdir returns the name of a fresh object directory under b.WorkDir.
   383  // It is up to the caller to call b.Mkdir on the result at an appropriate time.
   384  // The result ends in a slash, so that file names in that directory
   385  // can be constructed with direct string addition.
   386  //
   387  // NewObjdir must be called only from a single goroutine at a time,
   388  // so it is safe to call during action graph construction, but it must not
   389  // be called during action graph execution.
   390  func (b *Builder) NewObjdir() string {
   391  	b.objdirSeq++
   392  	return str.WithFilePathSeparator(filepath.Join(b.WorkDir, fmt.Sprintf("b%03d", b.objdirSeq)))
   393  }
   394  
   395  // readpkglist returns the list of packages that were built into the shared library
   396  // at shlibpath. For the native toolchain this list is stored, newline separated, in
   397  // an ELF note with name "Go\x00\x00" and type 1. For GCCGO it is extracted from the
   398  // .go_export section.
   399  func readpkglist(s *modload.Loader, shlibpath string) (pkgs []*load.Package) {
   400  	var stk load.ImportStack
   401  	if cfg.BuildToolchainName == "gccgo" {
   402  		f, err := elf.Open(shlibpath)
   403  		if err != nil {
   404  			base.Fatal(fmt.Errorf("failed to open shared library: %v", err))
   405  		}
   406  		defer f.Close()
   407  		sect := f.Section(".go_export")
   408  		if sect == nil {
   409  			base.Fatal(fmt.Errorf("%s: missing .go_export section", shlibpath))
   410  		}
   411  		data, err := sect.Data()
   412  		if err != nil {
   413  			base.Fatal(fmt.Errorf("%s: failed to read .go_export section: %v", shlibpath, err))
   414  		}
   415  		pkgpath := []byte("pkgpath ")
   416  		for _, line := range bytes.Split(data, []byte{'\n'}) {
   417  			if path, found := bytes.CutPrefix(line, pkgpath); found {
   418  				path = bytes.TrimSuffix(path, []byte{';'})
   419  				pkgs = append(pkgs, load.LoadPackageWithFlags(s, string(path), base.Cwd(), &stk, nil, 0))
   420  			}
   421  		}
   422  	} else {
   423  		pkglistbytes, err := buildid.ReadELFNote(shlibpath, "Go\x00\x00", 1)
   424  		if err != nil {
   425  			base.Fatalf("readELFNote failed: %v", err)
   426  		}
   427  		scanner := bufio.NewScanner(bytes.NewBuffer(pkglistbytes))
   428  		for scanner.Scan() {
   429  			t := scanner.Text()
   430  			pkgs = append(pkgs, load.LoadPackageWithFlags(s, t, base.Cwd(), &stk, nil, 0))
   431  		}
   432  	}
   433  	return
   434  }
   435  
   436  // cacheAction looks up {mode, p} in the cache and returns the resulting action.
   437  // If the cache has no such action, f() is recorded and returned.
   438  // TODO(rsc): Change the second key from *load.Package to interface{},
   439  // to make the caching in linkShared less awkward?
   440  func (b *Builder) cacheAction(mode string, p *load.Package, f func() *Action) *Action {
   441  	a := b.actionCache[cacheKey{mode, p}]
   442  	if a == nil {
   443  		a = f()
   444  		b.actionCache[cacheKey{mode, p}] = a
   445  	}
   446  	return a
   447  }
   448  
   449  // AutoAction returns the "right" action for go build or go install of p.
   450  func (b *Builder) AutoAction(s *modload.Loader, mode, depMode BuildMode, p *load.Package) *Action {
   451  	if p.Name == "main" {
   452  		return b.LinkAction(s, mode, depMode, p)
   453  	}
   454  	a := b.CompileAction(mode, depMode, p)
   455  	// Add the compile actions to the builder to ensure the built outputs are cached.
   456  	exportAction := b.BuildExportAction(mode, depMode, p)
   457  	b.addTransitiveCompileActions(a, exportAction)
   458  	return a
   459  }
   460  
   461  // exportProvider holds the information from the export action needed by the build action.
   462  type exportProvider struct {
   463  	exportFile string
   464  	objects    []string
   465  	cgoObjects []string
   466  	cfiles     []string
   467  	sfiles     []string
   468  	output     []byte
   469  	compile    *shellCmd
   470  }
   471  
   472  // pgoActionID computes the action ID for a preprocess PGO action.
   473  func (b *Builder) pgoActionID(input string) cache.ActionID {
   474  	h := cache.NewHash("preprocess PGO profile " + input)
   475  
   476  	fmt.Fprintf(h, "preprocess PGO profile\n")
   477  	fmt.Fprintf(h, "preprofile %s\n", b.toolID("preprofile"))
   478  	fmt.Fprintf(h, "input %q\n", b.fileHash(input))
   479  
   480  	return h.Sum()
   481  }
   482  
   483  // pgoActor implements the Actor interface for preprocessing PGO profiles.
   484  type pgoActor struct {
   485  	// input is the path to the original pprof profile.
   486  	input string
   487  }
   488  
   489  func (p *pgoActor) Act(b *Builder, ctx context.Context, a *Action) error {
   490  	if b.useCache(a, b.pgoActionID(p.input), a.Target, !b.IsCmdList) || b.IsCmdList {
   491  		return nil
   492  	}
   493  	defer b.flushOutput(a)
   494  
   495  	sh := b.Shell(a)
   496  
   497  	if err := sh.Mkdir(a.Objdir); err != nil {
   498  		return err
   499  	}
   500  
   501  	if err := sh.run(".", p.input, nil, cfg.BuildToolexec, base.Tool("preprofile"), "-o", a.Target, "-i", p.input); err != nil {
   502  		return err
   503  	}
   504  
   505  	// N.B. Builder.build looks for the out in a.built, regardless of
   506  	// whether this came from cache.
   507  	a.built = a.Target
   508  
   509  	if !cfg.BuildN {
   510  		// Cache the output.
   511  		//
   512  		// N.B. We don't use updateBuildID here, as preprocessed PGO profiles
   513  		// do not contain a build ID. updateBuildID is typically responsible
   514  		// for adding to the cache, thus we must do so ourselves instead.
   515  
   516  		r, err := os.Open(a.Target)
   517  		if err != nil {
   518  			return fmt.Errorf("error opening target for caching: %w", err)
   519  		}
   520  
   521  		c := cache.Default()
   522  		outputID, _, err := c.Put(a.actionID, r)
   523  		r.Close()
   524  		if err != nil {
   525  			return fmt.Errorf("error adding target to cache: %w", err)
   526  		}
   527  		if cfg.BuildX {
   528  			sh.ShowCmd("", "%s # internal", joinUnambiguously(str.StringList("cp", a.Target, c.OutputFile(outputID))))
   529  		}
   530  	}
   531  
   532  	return nil
   533  }
   534  
   535  type coverProvider struct {
   536  	// name of static metadata file fragment emitted by the cover
   537  	// tool as part of the package cover action, for selected
   538  	// "go test -cover" runs.
   539  	covMetaFileName string
   540  
   541  	// coverageConfig is the path to the json-serialized covcmd.CoverPkgConfig
   542  	// provided to the cover tool. The config is created by coverConfig.
   543  	coverageConfig string
   544  
   545  	goSources, cgoSources []string // The go and cgo sources generated by the cover tool, which should be used instead of the raw sources on the package.
   546  }
   547  
   548  // runCgoActor implements the Actor interface for running the cgo command for the package.
   549  type runCgoActor struct {
   550  }
   551  
   552  func (c runCgoActor) Act(b *Builder, ctx context.Context, a *Action) error {
   553  	return b.runCgo(ctx, a)
   554  }
   555  
   556  type cgoCompileActor struct {
   557  	file string
   558  
   559  	compileFunc  func(*Action, string, string, []string, string) error
   560  	getFlagsFunc func(*runCgoProvider) []string
   561  }
   562  
   563  func (c cgoCompileActor) Act(b *Builder, ctx context.Context, a *Action) error {
   564  	pr, ok := a.Deps[0].Provider.(*runCgoProvider)
   565  	if !ok {
   566  		base.Fatalf("internal error: missing runCgoProvider")
   567  	}
   568  	a.nonGoOverlay = pr.nonGoOverlay
   569  
   570  	a.actionID = b.cgoCompileActionID(a, c.file, c.getFlagsFunc(pr))
   571  	targetBase := filepath.Base(a.Target)
   572  	if err := b.loadCachedObjdirFile(a, cache.Default(), targetBase); err == nil {
   573  		a.built = a.Target
   574  		return nil
   575  	}
   576  	defer b.flushOutput(a)
   577  
   578  	if err := c.compileFunc(a, a.Objdir, a.Target, c.getFlagsFunc(pr), c.file); err != nil {
   579  		return err
   580  	}
   581  
   582  	if !cfg.BuildN {
   583  		b.cacheObjdirFile(a, cache.Default(), targetBase)
   584  	}
   585  
   586  	return nil
   587  }
   588  
   589  // BuildExportAction returns the action to start the compile for p.
   590  // The compile process is logically split between the export action
   591  // and the compile action. The export action completing signifies the
   592  // availability of the export data for dependent build actions, while
   593  // the build action completing signifies that the complete archive for
   594  // a package is ready.
   595  func (b *Builder) BuildExportAction(mode, depMode BuildMode, p *load.Package) *Action {
   596  	vetOnly := mode&ModeVetOnly != 0
   597  	mode &^= ModeVetOnly
   598  
   599  	a := b.cacheAction("build-export", p, func() *Action {
   600  		a := &Action{
   601  			Mode:    "build-export",
   602  			Package: p,
   603  			Actor:   ActorFunc((*Builder).buildExport),
   604  			Objdir:  b.NewObjdir(),
   605  		}
   606  
   607  		if p.Error == nil || !p.Error.IsImportCycle {
   608  			for _, p1 := range p.Internal.Imports {
   609  				if cfg.BuildToolchainName == "gccgo" {
   610  					// gccgo can't do early export. it wants the full object
   611  					a.Deps = append(a.Deps, b.CompileAction(depMode, depMode, p1))
   612  				} else {
   613  					a.Deps = append(a.Deps, b.BuildExportAction(depMode, depMode, p1))
   614  				}
   615  			}
   616  		}
   617  
   618  		if p.Internal.PGOProfile != "" {
   619  			pgoAction := b.cacheAction("preprocess PGO profile "+p.Internal.PGOProfile, nil, func() *Action {
   620  				a := &Action{
   621  					Mode:   "preprocess PGO profile",
   622  					Actor:  &pgoActor{input: p.Internal.PGOProfile},
   623  					Objdir: b.NewObjdir(),
   624  				}
   625  				a.Target = filepath.Join(a.Objdir, "pgo.preprofile")
   626  
   627  				return a
   628  			})
   629  			a.Deps = append(a.Deps, pgoAction)
   630  		}
   631  
   632  		if p.Standard {
   633  			switch p.ImportPath {
   634  			case "builtin", "unsafe":
   635  				// Fake packages - nothing to build.
   636  				a.Mode = "built-in package"
   637  				a.Actor = nil
   638  				return a
   639  			}
   640  
   641  			// gccgo standard library is "fake" too.
   642  			if cfg.BuildToolchainName == "gccgo" {
   643  				// the target name is needed for cgo.
   644  				a.Mode = "gccgo stdlib"
   645  				a.Target = p.Target
   646  				a.Actor = nil
   647  				return a
   648  			}
   649  		}
   650  
   651  		// Create a cover action if we need to instrument the code for coverage.
   652  		// The cover action always runs in the same go build invocation as the build,
   653  		// and is not cached separately, so it can use the same objdir.
   654  		var coverAction *Action
   655  		if p.Internal.Cover.Mode != "" {
   656  			coverAction = b.cacheAction("cover", p, func() *Action {
   657  				return &Action{
   658  					Mode:    "cover",
   659  					Package: p,
   660  					Actor:   ActorFunc((*Builder).runCover),
   661  					Objdir:  a.Objdir,
   662  				}
   663  			})
   664  			a.Deps = append(a.Deps, coverAction)
   665  		}
   666  
   667  		// Create actions to run swig and cgo if needed. These actions
   668  		// cache their outputs independently under their own action IDs.
   669  		if p.UsesCgo() || p.UsesSwig() {
   670  			var cgoDeps []*Action
   671  			if coverAction != nil {
   672  				cgoDeps = append(cgoDeps, coverAction)
   673  			}
   674  			a.Deps = append(a.Deps, b.cgoAction(p, a.Objdir, cgoDeps, coverAction != nil))
   675  		}
   676  
   677  		return a
   678  	})
   679  	a.needBuild = a.needBuild || !vetOnly
   680  	return a
   681  }
   682  
   683  // CompileAction returns the action for compiling and possibly installing
   684  // (according to mode) the given package. The resulting action is only
   685  // for building packages (archives), never for linking executables.
   686  // depMode is the action (build or install) to use when building dependencies.
   687  // To turn package main into an executable, call b.Link instead.
   688  func (b *Builder) CompileAction(mode, depMode BuildMode, p *load.Package) *Action {
   689  	if mode != ModeBuild && p.Target == "" {
   690  		// No permanent target.
   691  		mode = ModeBuild
   692  	}
   693  	if mode != ModeBuild && p.Name == "main" {
   694  		// We never install the .a file for a main package.
   695  		mode = ModeBuild
   696  	}
   697  
   698  	a := b.cacheAction("build", p, func() *Action {
   699  		exportAction := b.BuildExportAction(mode, depMode, p)
   700  		if exportAction.Actor == nil {
   701  			return exportAction
   702  		}
   703  
   704  		a := &Action{
   705  			Mode:       "build",
   706  			Package:    p,
   707  			Actor:      ActorFunc((*Builder).buildObject),
   708  			Objdir:     exportAction.Objdir,
   709  			Deps:       []*Action{exportAction},
   710  			IgnoreFail: true,
   711  		}
   712  
   713  		return a
   714  	})
   715  
   716  	// Construct install action.
   717  	if mode == ModeInstall || mode == ModeBuggyInstall {
   718  		a = b.installAction(a, mode)
   719  	}
   720  
   721  	return a
   722  }
   723  
   724  func (b *Builder) cgoAction(p *load.Package, objdir string, deps []*Action, hasCover bool) *Action {
   725  	cgoCollectAction := b.cacheAction("cgo collect", p, func() *Action {
   726  		// Run cgo
   727  		runCgo := b.cacheAction("cgo run", p, func() *Action {
   728  			return &Action{
   729  				Package: p,
   730  				Mode:    "cgo run",
   731  				Actor:   &runCgoActor{},
   732  				Objdir:  objdir,
   733  				Deps:    deps,
   734  			}
   735  		})
   736  
   737  		// Determine which files swig will produce in the cgo run action. We'll need to create
   738  		// actions to compile the C and C++ files produced by swig, as well as the C file
   739  		// produced by cgo processing swig's Go file outputs.
   740  		swigGo, swigC, swigCXX := b.swigOutputs(p, objdir)
   741  
   742  		oseq := 0
   743  		nextOfile := func() string {
   744  			oseq++
   745  			return objdir + fmt.Sprintf("_x%03d.o", oseq)
   746  		}
   747  		compileAction := func(file string, getFlagsFunc func(*runCgoProvider) []string, compileFunc func(*Action, string, string, []string, string) error) *Action {
   748  			mode := "cgo compile " + file
   749  			return b.cacheAction(mode, p, func() *Action {
   750  				return &Action{
   751  					Package: p,
   752  					Mode:    mode,
   753  					Actor:   &cgoCompileActor{file: file, getFlagsFunc: getFlagsFunc, compileFunc: compileFunc},
   754  					Deps:    []*Action{runCgo},
   755  					Objdir:  objdir,
   756  					Target:  nextOfile(),
   757  				}
   758  			})
   759  		}
   760  
   761  		var collectDeps []*Action
   762  
   763  		// Add compile actions for C files generated by cgo.
   764  		cgoFiles := p.CgoFiles
   765  		if hasCover {
   766  			cgoFiles = slices.Clone(cgoFiles)
   767  			for i := range cgoFiles {
   768  				cgoFiles[i] = strings.TrimSuffix(cgoFiles[i], ".go") + ".cover.go"
   769  			}
   770  		}
   771  		cfiles := []string{"_cgo_export.c"}
   772  		for _, fn := range slices.Concat(cgoFiles, swigGo) {
   773  			cfiles = append(cfiles, strings.TrimSuffix(filepath.Base(fn), ".go")+".cgo2.c")
   774  		}
   775  		for _, f := range cfiles {
   776  			collectDeps = append(collectDeps, compileAction(objdir+f, (*runCgoProvider).cflags, b.gcc))
   777  		}
   778  
   779  		// Add compile actions for S files.
   780  		var sfiles []string
   781  		// In a package using cgo, cgo compiles the C, C++ and assembly files with gcc.
   782  		// There is one exception: runtime/cgo's job is to bridge the
   783  		// cgo and non-cgo worlds, so it necessarily has files in both.
   784  		// In that case gcc only gets the gcc_* files.
   785  		if p.Standard && p.ImportPath == "runtime/cgo" {
   786  			for _, f := range p.SFiles {
   787  				if strings.HasPrefix(f, "gcc_") {
   788  					sfiles = append(sfiles, f)
   789  				}
   790  			}
   791  		} else {
   792  			sfiles = p.SFiles
   793  		}
   794  		for _, f := range sfiles {
   795  			collectDeps = append(collectDeps, compileAction(mkAbs(p.Dir, f), (*runCgoProvider).cflags, b.gas))
   796  		}
   797  
   798  		// Add compile actions for C files in the package and M files.
   799  		for _, f := range slices.Concat(p.CFiles, p.MFiles) {
   800  			collectDeps = append(collectDeps, compileAction(filepath.Join(p.Dir, f), (*runCgoProvider).cflags, b.gcc))
   801  		}
   802  		// Add compile actions for C files generated by swig.
   803  		for _, f := range swigC {
   804  			collectDeps = append(collectDeps, compileAction(f, (*runCgoProvider).cflags, b.gcc))
   805  		}
   806  
   807  		// Add compile actions for C++ files in the package.
   808  		for _, f := range p.CXXFiles {
   809  			collectDeps = append(collectDeps, compileAction(filepath.Join(p.Dir, f), (*runCgoProvider).cxxflags, b.gxx))
   810  		}
   811  		// Add compile actions for C++ files generated by swig.
   812  		for _, f := range swigCXX {
   813  			collectDeps = append(collectDeps, compileAction(f, (*runCgoProvider).cxxflags, b.gxx))
   814  		}
   815  
   816  		// Add compile actions for Fortran files in the package.
   817  		for _, f := range p.FFiles {
   818  			collectDeps = append(collectDeps, compileAction(filepath.Join(p.Dir, f), (*runCgoProvider).fflags, b.gfortran))
   819  		}
   820  
   821  		// Add a single convenience action that does nothing to join the previous action,
   822  		// and better separate the cgo action dependencies of the build action from the
   823  		// build actions for its package dependencies.
   824  		return &Action{
   825  			Mode: "collect cgo",
   826  			Actor: ActorFunc(func(b *Builder, ctx context.Context, a *Action) error {
   827  				// Use the cgo run action's provider as our provider output,
   828  				// so it can be easily accessed by the build action.
   829  				a.Provider = a.Deps[0].Deps[0].Provider
   830  				return nil
   831  			}),
   832  			Deps:   collectDeps,
   833  			Objdir: objdir,
   834  		}
   835  	})
   836  
   837  	return cgoCollectAction
   838  }
   839  
   840  // VetAction returns the action for running go vet on package p.
   841  // It depends on the action for compiling p.
   842  // If the caller may be causing p to be installed, it is up to the caller
   843  // to make sure that the install depends on (runs after) vet.
   844  func (b *Builder) VetAction(s *modload.Loader, mode, depMode BuildMode, needFix bool, p *load.Package) *Action {
   845  	a := b.vetAction(s, mode, depMode, p)
   846  	a.VetxOnly = false
   847  	a.needFix = needFix
   848  	return a
   849  }
   850  
   851  func (b *Builder) vetAction(s *modload.Loader, mode, depMode BuildMode, p *load.Package) *Action {
   852  	// Construct vet action.
   853  	a := b.cacheAction("vet", p, func() *Action {
   854  		a1 := b.BuildExportAction(mode|ModeVetOnly, depMode, p)
   855  
   856  		var deps []*Action
   857  		if a1.buggyInstall {
   858  			// (*Builder).vet expects deps[0] to be the package.
   859  			// If we see buggyInstall
   860  			// here then a1 is an install of a shared library,
   861  			// and the real package is a1.Deps[0].
   862  			deps = []*Action{a1.Deps[0], a1}
   863  		} else {
   864  			deps = []*Action{a1}
   865  		}
   866  		for _, p1 := range p.Internal.Imports {
   867  			deps = append(deps, b.vetAction(s, mode, depMode, p1))
   868  		}
   869  
   870  		a := &Action{
   871  			Mode:       "vet",
   872  			Package:    p,
   873  			Deps:       deps,
   874  			Objdir:     a1.Objdir,
   875  			VetxOnly:   true,
   876  			IgnoreFail: true, // it's OK if vet of dependencies "fails" (reports problems)
   877  		}
   878  		if a1.Actor == nil {
   879  			// Built-in packages like unsafe.
   880  			return a
   881  		}
   882  		deps[0].needVet = true
   883  		a.Actor = ActorFunc((*Builder).vet)
   884  		b.addTransitiveCompileActions(a, a1)
   885  		return a
   886  	})
   887  	return a
   888  }
   889  
   890  // ExportAction returns an action to export the type information of p.
   891  func (b *Builder) ExportAction(p *load.Package) *Action {
   892  	// Fake packages don't have export data.
   893  	if p.Standard && p.ImportPath == "unsafe" {
   894  		return &Action{
   895  			Mode:    "built-in package",
   896  			Package: p,
   897  		}
   898  	}
   899  
   900  	return b.cacheAction("export", p, func() *Action {
   901  		a := &Action{
   902  			Mode:    "export",
   903  			Package: p,
   904  			Deps:    make([]*Action, len(p.Internal.Imports)),
   905  			Actor:   ActorFunc((*Builder).export),
   906  			Objdir:  b.NewObjdir(),
   907  		}
   908  		a.Target = a.Objdir + "export"
   909  		for i, imp := range p.Internal.Imports {
   910  			a.Deps[i] = b.ExportAction(imp)
   911  		}
   912  		if p.UsesCgo() { // TODO(mark): What about SWIG?
   913  			// Run the cgo preprocessor; export must examine its output files.
   914  			a.Deps = append(a.Deps, b.cgoAction(p, a.Objdir, nil, false))
   915  		}
   916  		return a
   917  	})
   918  }
   919  
   920  // LinkAction returns the action for linking p into an executable
   921  // and possibly installing the result (according to mode).
   922  // depMode is the action (build or install) to use when compiling dependencies.
   923  func (b *Builder) LinkAction(s *modload.Loader, mode, depMode BuildMode, p *load.Package) *Action {
   924  	// Construct link action.
   925  	a := b.cacheAction("link", p, func() *Action {
   926  		a := &Action{
   927  			Mode:    "link",
   928  			Package: p,
   929  		}
   930  
   931  		exportAction := b.BuildExportAction(ModeBuild, depMode, p)
   932  		a1 := b.CompileAction(ModeBuild, depMode, p)
   933  		a.Actor = ActorFunc((*Builder).link)
   934  		a.Deps = []*Action{a1}
   935  		a.Objdir = a1.Objdir
   936  
   937  		// An executable file. (This is the name of a temporary file.)
   938  		// Because we run the temporary file in 'go run' and 'go test',
   939  		// the name will show up in ps listings. If the caller has specified
   940  		// a name, use that instead of a.out. The binary is generated
   941  		// in an otherwise empty subdirectory named exe to avoid
   942  		// naming conflicts. The only possible conflict is if we were
   943  		// to create a top-level package named exe.
   944  		name := "a.out"
   945  		if p.Internal.ExeName != "" {
   946  			name = p.Internal.ExeName
   947  		} else if (cfg.Goos == "darwin" || cfg.Goos == "windows") && cfg.BuildBuildmode == "c-shared" && p.Target != "" {
   948  			// On OS X, the linker output name gets recorded in the
   949  			// shared library's LC_ID_DYLIB load command.
   950  			// The code invoking the linker knows to pass only the final
   951  			// path element. Arrange that the path element matches what
   952  			// we'll install it as; otherwise the library is only loadable as "a.out".
   953  			// On Windows, DLL file name is recorded in PE file
   954  			// export section, so do like on OS X.
   955  			_, name = filepath.Split(p.Target)
   956  		}
   957  		a.Target = a.Objdir + filepath.Join("exe", name) + cfg.ExeSuffix
   958  		a.built = a.Target
   959  		b.addTransitiveLinkDeps(s, a, exportAction, "")
   960  
   961  		// Sequence the build of the main package (a1) strictly after the build
   962  		// of all other dependencies that go into the link. It is likely to be after
   963  		// them anyway, but just make sure. This is required by the build ID-based
   964  		// shortcut in (*Builder).useCache(a1), which will call b.linkActionID(a).
   965  		// In order for that linkActionID call to compute the right action ID, all the
   966  		// dependencies of a (except a1) must have completed building and have
   967  		// recorded their build IDs.
   968  		exportAction.Deps = append(exportAction.Deps, &Action{Mode: "nop", Deps: a.Deps[1:]})
   969  		return a
   970  	})
   971  
   972  	if mode == ModeInstall || mode == ModeBuggyInstall {
   973  		a = b.installAction(a, mode)
   974  	}
   975  
   976  	return a
   977  }
   978  
   979  // installAction returns the action for installing the result of a1.
   980  func (b *Builder) installAction(a1 *Action, mode BuildMode) *Action {
   981  	// Because we overwrite the build action with the install action below,
   982  	// a1 may already be an install action fetched from the "build" cache key,
   983  	// and the caller just doesn't realize.
   984  	if strings.HasSuffix(a1.Mode, "-install") {
   985  		if a1.buggyInstall && mode == ModeInstall {
   986  			//  Congratulations! The buggy install is now a proper install.
   987  			a1.buggyInstall = false
   988  		}
   989  		return a1
   990  	}
   991  
   992  	// If there's no actual action to build a1,
   993  	// there's nothing to install either.
   994  	// This happens if a1 corresponds to reusing an already-built object.
   995  	if a1.Actor == nil {
   996  		return a1
   997  	}
   998  
   999  	p := a1.Package
  1000  	return b.cacheAction(a1.Mode+"-install", p, func() *Action {
  1001  		// The install deletes the temporary build result,
  1002  		// so we need all other actions, both past and future,
  1003  		// that attempt to depend on the build to depend instead
  1004  		// on the install.
  1005  
  1006  		// Make a private copy of a1 (the build action),
  1007  		// no longer accessible to any other rules.
  1008  		buildAction := new(Action)
  1009  		*buildAction = *a1
  1010  
  1011  		// Overwrite a1 with the install action.
  1012  		// This takes care of updating past actions that
  1013  		// point at a1 for the build action; now they will
  1014  		// point at a1 and get the install action.
  1015  		// We also leave a1 in the action cache as the result
  1016  		// for "build", so that actions not yet created that
  1017  		// try to depend on the build will instead depend
  1018  		// on the install.
  1019  		*a1 = Action{
  1020  			Mode:    buildAction.Mode + "-install",
  1021  			Actor:   ActorFunc(BuildInstallFunc),
  1022  			Package: p,
  1023  			Objdir:  buildAction.Objdir,
  1024  			Deps:    []*Action{buildAction},
  1025  			Target:  p.Target,
  1026  			built:   p.Target,
  1027  
  1028  			buggyInstall: mode == ModeBuggyInstall,
  1029  		}
  1030  
  1031  		b.addInstallHeaderAction(a1)
  1032  		return a1
  1033  	})
  1034  }
  1035  
  1036  // addTransitiveCompileActions adds the compile actions for all packages
  1037  // that are transitive dependencies of root to the dependencies of action a.
  1038  func (b *Builder) addTransitiveCompileActions(a, root *Action) {
  1039  	workq := []*Action{root}
  1040  	haveDep := map[string]bool{}
  1041  	if root.Package != nil {
  1042  		haveDep[root.Package.ImportPath] = true
  1043  	}
  1044  	for i := 0; i < len(workq); i++ {
  1045  		for _, a2 := range workq[i].Deps {
  1046  			for a2.Mode == "build-install" || a2.Mode == "build" {
  1047  				a2 = a2.Deps[0]
  1048  			}
  1049  			// TODO(rsc): Find a better discriminator than the Mode strings, once the dust settles.
  1050  			if a2.Mode != "build-export" || haveDep[a2.Package.ImportPath] {
  1051  				continue
  1052  			}
  1053  			haveDep[a2.Package.ImportPath] = true
  1054  			a.Deps = append(a.Deps, b.CompileAction(ModeBuild, ModeBuild, a2.Package))
  1055  			workq = append(workq, a2)
  1056  		}
  1057  	}
  1058  }
  1059  
  1060  // addTransitiveLinkDeps adds to the link action a all packages
  1061  // that are transitive dependencies of a1.Deps.
  1062  // That is, if a is a link of package main, a1 is the compile of package main
  1063  // and a1.Deps is the actions for building packages directly imported by
  1064  // package main (what the compiler needs). The linker needs all packages
  1065  // transitively imported by the whole program; addTransitiveLinkDeps
  1066  // makes sure those are present in a.Deps.
  1067  // If shlib is non-empty, then a corresponds to the build and installation of shlib,
  1068  // so any rebuild of shlib should not be added as a dependency.
  1069  func (b *Builder) addTransitiveLinkDeps(s *modload.Loader, a, a1 *Action, shlib string) {
  1070  	// Expand Deps to include all built packages, for the linker.
  1071  	// Use breadth-first search to find rebuilt-for-test packages
  1072  	// before the standard ones.
  1073  	// TODO(rsc): Eliminate the standard ones from the action graph,
  1074  	// which will require doing a little bit more rebuilding.
  1075  	b.addTransitiveCompileActions(a, a1)
  1076  
  1077  	// If this is go build -linkshared, then the link depends on the shared libraries
  1078  	// in addition to the packages themselves. (The compile steps do not.)
  1079  	if cfg.BuildLinkshared {
  1080  		haveShlib := map[string]bool{shlib: true}
  1081  		for _, a1 := range a.Deps {
  1082  			p1 := a1.Package
  1083  			if p1 == nil || p1.Shlib == "" || haveShlib[filepath.Base(p1.Shlib)] {
  1084  				continue
  1085  			}
  1086  			haveShlib[filepath.Base(p1.Shlib)] = true
  1087  			// TODO(rsc): The use of ModeInstall here is suspect, but if we only do ModeBuild,
  1088  			// we'll end up building an overall library or executable that depends at runtime
  1089  			// on other libraries that are out-of-date, which is clearly not good either.
  1090  			// We call it ModeBuggyInstall to make clear that this is not right.
  1091  			a.Deps = append(a.Deps, b.linkSharedAction(s, ModeBuggyInstall, ModeBuggyInstall, p1.Shlib, nil))
  1092  		}
  1093  	}
  1094  }
  1095  
  1096  // addInstallHeaderAction adds an install header action to a, if needed.
  1097  // The action a should be an install action as generated by either
  1098  // b.CompileAction or b.LinkAction with mode=ModeInstall,
  1099  // and so a.Deps[0] is the corresponding build action.
  1100  func (b *Builder) addInstallHeaderAction(a *Action) {
  1101  	// Install header for cgo in c-archive and c-shared modes.
  1102  	p := a.Package
  1103  	if p.UsesCgo() && (cfg.BuildBuildmode == "c-archive" || cfg.BuildBuildmode == "c-shared") {
  1104  		hdrTarget := a.Target[:len(a.Target)-len(filepath.Ext(a.Target))] + ".h"
  1105  		if cfg.BuildContext.Compiler == "gccgo" && cfg.BuildO == "" {
  1106  			// For the header file, remove the "lib"
  1107  			// added by go/build, so we generate pkg.h
  1108  			// rather than libpkg.h.
  1109  			dir, file := filepath.Split(hdrTarget)
  1110  			file = strings.TrimPrefix(file, "lib")
  1111  			hdrTarget = filepath.Join(dir, file)
  1112  		}
  1113  		ah := &Action{
  1114  			Mode:    "install header",
  1115  			Package: a.Package,
  1116  			Deps:    []*Action{a.Deps[0]},
  1117  			Actor:   ActorFunc((*Builder).installHeader),
  1118  			Objdir:  a.Deps[0].Objdir,
  1119  			Target:  hdrTarget,
  1120  		}
  1121  		a.Deps = append(a.Deps, ah)
  1122  	}
  1123  }
  1124  
  1125  // buildmodeShared takes the "go build" action a1 into the building of a shared library of a1.Deps.
  1126  // That is, the input a1 represents "go build pkgs" and the result represents "go build -buildmode=shared pkgs".
  1127  func (b *Builder) buildmodeShared(s *modload.Loader, mode, depMode BuildMode, args []string, pkgs []*load.Package, a1 *Action) *Action {
  1128  	name, err := libname(args, pkgs)
  1129  	if err != nil {
  1130  		base.Fatalf("%v", err)
  1131  	}
  1132  	return b.linkSharedAction(s, mode, depMode, name, a1)
  1133  }
  1134  
  1135  // linkSharedAction takes a grouping action a1 corresponding to a list of built packages
  1136  // and returns an action that links them together into a shared library with the name shlib.
  1137  // If a1 is nil, shlib should be an absolute path to an existing shared library,
  1138  // and then linkSharedAction reads that library to find out the package list.
  1139  func (b *Builder) linkSharedAction(s *modload.Loader, mode, depMode BuildMode, shlib string, a1 *Action) *Action {
  1140  	fullShlib := shlib
  1141  	shlib = filepath.Base(shlib)
  1142  	a := b.cacheAction("build-shlib "+shlib, nil, func() *Action {
  1143  		if a1 == nil {
  1144  			// TODO(rsc): Need to find some other place to store config,
  1145  			// not in pkg directory. See golang.org/issue/22196.
  1146  			pkgs := readpkglist(s, fullShlib)
  1147  			a1 = &Action{
  1148  				Mode: "shlib packages",
  1149  			}
  1150  			for _, p := range pkgs {
  1151  				a1.Deps = append(a1.Deps, b.CompileAction(mode, depMode, p))
  1152  			}
  1153  		}
  1154  
  1155  		// Fake package to hold ldflags.
  1156  		// As usual shared libraries are a kludgy, abstraction-violating special case:
  1157  		// we let them use the flags specified for the command-line arguments.
  1158  		p := &load.Package{}
  1159  		p.Internal.CmdlinePkg = true
  1160  		p.Internal.Ldflags = load.BuildLdflags.For(s, p)
  1161  		p.Internal.Gccgoflags = load.BuildGccgoflags.For(s, p)
  1162  
  1163  		// Add implicit dependencies to pkgs list.
  1164  		// Currently buildmode=shared forces external linking mode, and
  1165  		// external linking mode forces an import of runtime/cgo (and
  1166  		// math on arm). So if it was not passed on the command line and
  1167  		// it is not present in another shared library, add it here.
  1168  		// TODO(rsc): Maybe this should only happen if "runtime" is in the original package set.
  1169  		// TODO(rsc): This should probably be changed to use load.LinkerDeps(p).
  1170  		// TODO(rsc): We don't add standard library imports for gccgo
  1171  		// because they are all always linked in anyhow.
  1172  		// Maybe load.LinkerDeps should be used and updated.
  1173  		a := &Action{
  1174  			Mode:    "go build -buildmode=shared",
  1175  			Package: p,
  1176  			Objdir:  b.NewObjdir(),
  1177  			Actor:   ActorFunc((*Builder).linkShared),
  1178  			Deps:    []*Action{a1},
  1179  		}
  1180  		a.Target = filepath.Join(a.Objdir, shlib)
  1181  		if cfg.BuildToolchainName != "gccgo" {
  1182  			add := func(a1 *Action, pkg string, force bool) {
  1183  				for _, a2 := range a1.Deps {
  1184  					if a2.Package != nil && a2.Package.ImportPath == pkg {
  1185  						return
  1186  					}
  1187  				}
  1188  				var stk load.ImportStack
  1189  				p := load.LoadPackageWithFlags(s, pkg, base.Cwd(), &stk, nil, 0)
  1190  				if p.Error != nil {
  1191  					base.Fatalf("load %s: %v", pkg, p.Error)
  1192  				}
  1193  				// Assume that if pkg (runtime/cgo or math)
  1194  				// is already accounted for in a different shared library,
  1195  				// then that shared library also contains runtime,
  1196  				// so that anything we do will depend on that library,
  1197  				// so we don't need to include pkg in our shared library.
  1198  				if force || p.Shlib == "" || filepath.Base(p.Shlib) == pkg {
  1199  					a1.Deps = append(a1.Deps, b.CompileAction(depMode, depMode, p))
  1200  				}
  1201  			}
  1202  			add(a1, "runtime/cgo", false)
  1203  			if cfg.Goarch == "arm" {
  1204  				add(a1, "math", false)
  1205  			}
  1206  
  1207  			// The linker step still needs all the usual linker deps.
  1208  			// (For example, the linker always opens runtime.a.)
  1209  			ldDeps, err := load.LinkerDeps(s, nil)
  1210  			if err != nil {
  1211  				base.Error(err)
  1212  			}
  1213  			for _, dep := range ldDeps {
  1214  				add(a, dep, true)
  1215  			}
  1216  		}
  1217  		b.addTransitiveLinkDeps(s, a, a1, shlib)
  1218  		return a
  1219  	})
  1220  
  1221  	// Install result.
  1222  	if (mode == ModeInstall || mode == ModeBuggyInstall) && a.Actor != nil {
  1223  		buildAction := a
  1224  
  1225  		a = b.cacheAction("install-shlib "+shlib, nil, func() *Action {
  1226  			// Determine the eventual install target.
  1227  			// The install target is root/pkg/shlib, where root is the source root
  1228  			// in which all the packages lie.
  1229  			// TODO(rsc): Perhaps this cross-root check should apply to the full
  1230  			// transitive package dependency list, not just the ones named
  1231  			// on the command line?
  1232  			pkgDir := a1.Deps[0].Package.Internal.Build.PkgTargetRoot
  1233  			for _, a2 := range a1.Deps {
  1234  				if dir := a2.Package.Internal.Build.PkgTargetRoot; dir != pkgDir {
  1235  					base.Fatalf("installing shared library: cannot use packages %s and %s from different roots %s and %s",
  1236  						a1.Deps[0].Package.ImportPath,
  1237  						a2.Package.ImportPath,
  1238  						pkgDir,
  1239  						dir)
  1240  				}
  1241  			}
  1242  			// TODO(rsc): Find out and explain here why gccgo is different.
  1243  			if cfg.BuildToolchainName == "gccgo" {
  1244  				pkgDir = filepath.Join(pkgDir, "shlibs")
  1245  			}
  1246  			target := filepath.Join(pkgDir, shlib)
  1247  
  1248  			a := &Action{
  1249  				Mode:   "go install -buildmode=shared",
  1250  				Objdir: buildAction.Objdir,
  1251  				Actor:  ActorFunc(BuildInstallFunc),
  1252  				Deps:   []*Action{buildAction},
  1253  				Target: target,
  1254  			}
  1255  			for _, a2 := range buildAction.Deps[0].Deps {
  1256  				p := a2.Package
  1257  				pkgTargetRoot := p.Internal.Build.PkgTargetRoot
  1258  				if pkgTargetRoot == "" {
  1259  					continue
  1260  				}
  1261  				a.Deps = append(a.Deps, &Action{
  1262  					Mode:    "shlibname",
  1263  					Package: p,
  1264  					Actor:   ActorFunc((*Builder).installShlibname),
  1265  					Target:  filepath.Join(pkgTargetRoot, p.ImportPath+".shlibname"),
  1266  					Deps:    []*Action{a.Deps[0]},
  1267  				})
  1268  			}
  1269  			return a
  1270  		})
  1271  	}
  1272  
  1273  	return a
  1274  }
  1275  

View as plain text