"Fossies" - the Fresh Open Source Software Archive

Member "go/src/cmd/go/internal/work/action.go" (9 Sep 2020, 28716 Bytes) of package /windows/misc/go1.14.9.windows-386.zip:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) Go source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. See also the last Fossies "Diffs" side-by-side code changes report for "action.go": 1.14.7_vs_1.15.

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