libgo: update to Go 1.11
[official-gcc.git] / libgo / go / cmd / go / internal / work / buildid.go
blobfb57e9128026baa3d38ff4f0e3c87ca1bdc135ed
1 // Copyright 2017 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.
5 package work
7 import (
8 "bytes"
9 "fmt"
10 "io/ioutil"
11 "os"
12 "os/exec"
13 "strings"
15 "cmd/go/internal/base"
16 "cmd/go/internal/cache"
17 "cmd/go/internal/cfg"
18 "cmd/go/internal/load"
19 "cmd/go/internal/str"
20 "cmd/internal/buildid"
21 "cmd/internal/objabi"
24 // Build IDs
26 // Go packages and binaries are stamped with build IDs that record both
27 // the action ID, which is a hash of the inputs to the action that produced
28 // the packages or binary, and the content ID, which is a hash of the action
29 // output, namely the archive or binary itself. The hash is the same one
30 // used by the build artifact cache (see cmd/go/internal/cache), but
31 // truncated when stored in packages and binaries, as the full length is not
32 // needed and is a bit unwieldy. The precise form is
34 // actionID/[.../]contentID
36 // where the actionID and contentID are prepared by hashToString below.
37 // and are found by looking for the first or last slash.
38 // Usually the buildID is simply actionID/contentID, but see below for an
39 // exception.
41 // The build ID serves two primary purposes.
43 // 1. The action ID half allows installed packages and binaries to serve as
44 // one-element cache entries. If we intend to build math.a with a given
45 // set of inputs summarized in the action ID, and the installed math.a already
46 // has that action ID, we can reuse the installed math.a instead of rebuilding it.
48 // 2. The content ID half allows the easy preparation of action IDs for steps
49 // that consume a particular package or binary. The content hash of every
50 // input file for a given action must be included in the action ID hash.
51 // Storing the content ID in the build ID lets us read it from the file with
52 // minimal I/O, instead of reading and hashing the entire file.
53 // This is especially effective since packages and binaries are typically
54 // the largest inputs to an action.
56 // Separating action ID from content ID is important for reproducible builds.
57 // The compiler is compiled with itself. If an output were represented by its
58 // own action ID (instead of content ID) when computing the action ID of
59 // the next step in the build process, then the compiler could never have its
60 // own input action ID as its output action ID (short of a miraculous hash collision).
61 // Instead we use the content IDs to compute the next action ID, and because
62 // the content IDs converge, so too do the action IDs and therefore the
63 // build IDs and the overall compiler binary. See cmd/dist's cmdbootstrap
64 // for the actual convergence sequence.
66 // The “one-element cache” purpose is a bit more complex for installed
67 // binaries. For a binary, like cmd/gofmt, there are two steps: compile
68 // cmd/gofmt/*.go into main.a, and then link main.a into the gofmt binary.
69 // We do not install gofmt's main.a, only the gofmt binary. Being able to
70 // decide that the gofmt binary is up-to-date means computing the action ID
71 // for the final link of the gofmt binary and comparing it against the
72 // already-installed gofmt binary. But computing the action ID for the link
73 // means knowing the content ID of main.a, which we did not keep.
74 // To sidestep this problem, each binary actually stores an expanded build ID:
76 // actionID(binary)/actionID(main.a)/contentID(main.a)/contentID(binary)
78 // (Note that this can be viewed equivalently as:
80 // actionID(binary)/buildID(main.a)/contentID(binary)
82 // Storing the buildID(main.a) in the middle lets the computations that care
83 // about the prefix or suffix halves ignore the middle and preserves the
84 // original build ID as a contiguous string.)
86 // During the build, when it's time to build main.a, the gofmt binary has the
87 // information needed to decide whether the eventual link would produce
88 // the same binary: if the action ID for main.a's inputs matches and then
89 // the action ID for the link step matches when assuming the given main.a
90 // content ID, then the binary as a whole is up-to-date and need not be rebuilt.
92 // This is all a bit complex and may be simplified once we can rely on the
93 // main cache, but at least at the start we will be using the content-based
94 // staleness determination without a cache beyond the usual installed
95 // package and binary locations.
97 const buildIDSeparator = "/"
99 // actionID returns the action ID half of a build ID.
100 func actionID(buildID string) string {
101 i := strings.Index(buildID, buildIDSeparator)
102 if i < 0 {
103 return buildID
105 return buildID[:i]
108 // contentID returns the content ID half of a build ID.
109 func contentID(buildID string) string {
110 return buildID[strings.LastIndex(buildID, buildIDSeparator)+1:]
113 // hashToString converts the hash h to a string to be recorded
114 // in package archives and binaries as part of the build ID.
115 // We use the first 96 bits of the hash and encode it in base64,
116 // resulting in a 16-byte string. Because this is only used for
117 // detecting the need to rebuild installed files (not for lookups
118 // in the object file cache), 96 bits are sufficient to drive the
119 // probability of a false "do not need to rebuild" decision to effectively zero.
120 // We embed two different hashes in archives and four in binaries,
121 // so cutting to 16 bytes is a significant savings when build IDs are displayed.
122 // (16*4+3 = 67 bytes compared to 64*4+3 = 259 bytes for the
123 // more straightforward option of printing the entire h in hex).
124 func hashToString(h [cache.HashSize]byte) string {
125 const b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"
126 const chunks = 5
127 var dst [chunks * 4]byte
128 for i := 0; i < chunks; i++ {
129 v := uint32(h[3*i])<<16 | uint32(h[3*i+1])<<8 | uint32(h[3*i+2])
130 dst[4*i+0] = b64[(v>>18)&0x3F]
131 dst[4*i+1] = b64[(v>>12)&0x3F]
132 dst[4*i+2] = b64[(v>>6)&0x3F]
133 dst[4*i+3] = b64[v&0x3F]
135 return string(dst[:])
138 // toolID returns the unique ID to use for the current copy of the
139 // named tool (asm, compile, cover, link).
141 // It is important that if the tool changes (for example a compiler bug is fixed
142 // and the compiler reinstalled), toolID returns a different string, so that old
143 // package archives look stale and are rebuilt (with the fixed compiler).
144 // This suggests using a content hash of the tool binary, as stored in the build ID.
146 // Unfortunately, we can't just open the tool binary, because the tool might be
147 // invoked via a wrapper program specified by -toolexec and we don't know
148 // what the wrapper program does. In particular, we want "-toolexec toolstash"
149 // to continue working: it does no good if "-toolexec toolstash" is executing a
150 // stashed copy of the compiler but the go command is acting as if it will run
151 // the standard copy of the compiler. The solution is to ask the tool binary to tell
152 // us its own build ID using the "-V=full" flag now supported by all tools.
153 // Then we know we're getting the build ID of the compiler that will actually run
154 // during the build. (How does the compiler binary know its own content hash?
155 // We store it there using updateBuildID after the standard link step.)
157 // A final twist is that we'd prefer to have reproducible builds for release toolchains.
158 // It should be possible to cross-compile for Windows from either Linux or Mac
159 // or Windows itself and produce the same binaries, bit for bit. If the tool ID,
160 // which influences the action ID half of the build ID, is based on the content ID,
161 // then the Linux compiler binary and Mac compiler binary will have different tool IDs
162 // and therefore produce executables with different action IDs.
163 // To avoids this problem, for releases we use the release version string instead
164 // of the compiler binary's content hash. This assumes that all compilers built
165 // on all different systems are semantically equivalent, which is of course only true
166 // modulo bugs. (Producing the exact same executables also requires that the different
167 // build setups agree on details like $GOROOT and file name paths, but at least the
168 // tool IDs do not make it impossible.)
169 func (b *Builder) toolID(name string) string {
170 b.id.Lock()
171 id := b.toolIDCache[name]
172 b.id.Unlock()
174 if id != "" {
175 return id
178 path := base.Tool(name)
179 desc := "go tool " + name
181 // Special case: undocumented -vettool overrides usual vet, for testing vet.
182 if name == "vet" && VetTool != "" {
183 path = VetTool
184 desc = VetTool
187 cmdline := str.StringList(cfg.BuildToolexec, path, "-V=full")
188 cmd := exec.Command(cmdline[0], cmdline[1:]...)
189 cmd.Env = base.EnvForDir(cmd.Dir, os.Environ())
190 var stdout, stderr bytes.Buffer
191 cmd.Stdout = &stdout
192 cmd.Stderr = &stderr
193 if err := cmd.Run(); err != nil {
194 base.Fatalf("%s: %v\n%s%s", desc, err, stdout.Bytes(), stderr.Bytes())
197 line := stdout.String()
198 f := strings.Fields(line)
199 if len(f) < 3 || f[0] != name && path != VetTool || f[1] != "version" || f[2] == "devel" && !strings.HasPrefix(f[len(f)-1], "buildID=") {
200 base.Fatalf("%s -V=full: unexpected output:\n\t%s", desc, line)
202 if f[2] == "devel" {
203 // On the development branch, use the content ID part of the build ID.
204 id = contentID(f[len(f)-1])
205 } else {
206 // For a release, the output is like: "compile version go1.9.1". Use the whole line.
207 id = f[2]
210 // For the compiler, add any experiments.
211 if name == "compile" {
212 id += " " + objabi.Expstring()
215 b.id.Lock()
216 b.toolIDCache[name] = id
217 b.id.Unlock()
219 return id
222 // gccToolID returns the unique ID to use for a tool that is invoked
223 // by the GCC driver. This is in particular gccgo, but this can also
224 // be used for gcc, g++, gfortran, etc.; those tools all use the GCC
225 // driver under different names. The approach used here should also
226 // work for sufficiently new versions of clang. Unlike toolID, the
227 // name argument is the program to run. The language argument is the
228 // type of input file as passed to the GCC driver's -x option.
230 // For these tools we have no -V=full option to dump the build ID,
231 // but we can run the tool with -v -### to reliably get the compiler proper
232 // and hash that. That will work in the presence of -toolexec.
234 // In order to get reproducible builds for released compilers, we
235 // detect a released compiler by the absence of "experimental" in the
236 // --version output, and in that case we just use the version string.
237 func (b *Builder) gccgoToolID(name, language string) (string, error) {
238 key := name + "." + language
239 b.id.Lock()
240 id := b.toolIDCache[key]
241 b.id.Unlock()
243 if id != "" {
244 return id, nil
247 // Invoke the driver with -### to see the subcommands and the
248 // version strings. Use -x to set the language. Pretend to
249 // compile an empty file on standard input.
250 cmdline := str.StringList(cfg.BuildToolexec, name, "-###", "-x", language, "-c", "-")
251 cmd := exec.Command(cmdline[0], cmdline[1:]...)
252 cmd.Env = base.EnvForDir(cmd.Dir, os.Environ())
253 // Force untranslated output so that we see the string "version".
254 cmd.Env = append(cmd.Env, "LC_ALL=C")
255 out, err := cmd.CombinedOutput()
256 if err != nil {
257 return "", fmt.Errorf("%s: %v; output: %q", name, err, out)
260 version := ""
261 lines := strings.Split(string(out), "\n")
262 for _, line := range lines {
263 if fields := strings.Fields(line); len(fields) > 1 && fields[1] == "version" {
264 version = line
265 break
268 if version == "" {
269 return "", fmt.Errorf("%s: can not find version number in %q", name, out)
272 if !strings.Contains(version, "experimental") {
273 // This is a release. Use this line as the tool ID.
274 id = version
275 } else {
276 // This is a development version. The first line with
277 // a leading space is the compiler proper.
278 compiler := ""
279 for _, line := range lines {
280 if len(line) > 1 && line[0] == ' ' {
281 compiler = line
282 break
285 if compiler == "" {
286 return "", fmt.Errorf("%s: can not find compilation command in %q", name, out)
289 fields := strings.Fields(compiler)
290 if len(fields) == 0 {
291 return "", fmt.Errorf("%s: compilation command confusion %q", name, out)
293 exe := fields[0]
294 if !strings.ContainsAny(exe, `/\`) {
295 if lp, err := exec.LookPath(exe); err == nil {
296 exe = lp
299 if _, err := os.Stat(exe); err != nil {
300 return "", fmt.Errorf("%s: can not find compiler %q: %v; output %q", name, exe, err, out)
302 id = b.fileHash(exe)
305 b.id.Lock()
306 b.toolIDCache[name] = id
307 b.id.Unlock()
309 return id, nil
312 // Check if assembler used by gccgo is GNU as.
313 func assemblerIsGas() bool {
314 cmd := exec.Command(BuildToolchain.compiler(), "-print-prog-name=as")
315 assembler, err := cmd.Output()
316 if err == nil {
317 cmd := exec.Command(strings.TrimSpace(string(assembler)), "--version")
318 out, err := cmd.Output()
319 return err == nil && strings.Contains(string(out), "GNU")
320 } else {
321 return false
325 // gccgoBuildIDELFFile creates an assembler file that records the
326 // action's build ID in an SHF_EXCLUDE section.
327 func (b *Builder) gccgoBuildIDELFFile(a *Action) (string, error) {
328 sfile := a.Objdir + "_buildid.s"
330 var buf bytes.Buffer
331 if cfg.Goos != "solaris" || assemblerIsGas() {
332 fmt.Fprintf(&buf, "\t"+`.section .go.buildid,"e"`+"\n")
333 } else if cfg.Goarch == "sparc" || cfg.Goarch == "sparc64" {
334 fmt.Fprintf(&buf, "\t"+`.section ".go.buildid",#exclude`+"\n")
335 } else { // cfg.Goarch == "386" || cfg.Goarch == "amd64"
336 fmt.Fprintf(&buf, "\t"+`.section .go.buildid,#exclude`+"\n")
338 fmt.Fprintf(&buf, "\t.byte ")
339 for i := 0; i < len(a.buildID); i++ {
340 if i > 0 {
341 if i%8 == 0 {
342 fmt.Fprintf(&buf, "\n\t.byte ")
343 } else {
344 fmt.Fprintf(&buf, ",")
347 fmt.Fprintf(&buf, "%#02x", a.buildID[i])
349 fmt.Fprintf(&buf, "\n")
350 if cfg.Goos != "solaris" {
351 secType := "@progbits"
352 if cfg.Goarch == "arm" {
353 secType = "%progbits"
355 fmt.Fprintf(&buf, "\t"+`.section .note.GNU-stack,"",%s`+"\n", secType)
356 fmt.Fprintf(&buf, "\t"+`.section .note.GNU-split-stack,"",%s`+"\n", secType)
359 if cfg.BuildN || cfg.BuildX {
360 for _, line := range bytes.Split(buf.Bytes(), []byte("\n")) {
361 b.Showcmd("", "echo '%s' >> %s", line, sfile)
363 if cfg.BuildN {
364 return sfile, nil
368 if err := ioutil.WriteFile(sfile, buf.Bytes(), 0666); err != nil {
369 return "", err
372 return sfile, nil
375 // gccgoBuildIDXCOFFFile creates an assembler file that records the
376 // action's build ID in a CSECT (AIX linker deletes CSECTs that are
377 // not referenced in the output file).
378 func (b *Builder) gccgoBuildIDXCOFFFile(a *Action) (string, error) {
379 sfile := a.Objdir + "_buildid.s"
381 var buf bytes.Buffer
382 fmt.Fprintf(&buf, "\t.csect .go.buildid[XO]\n")
383 fmt.Fprintf(&buf, "\t.byte ")
384 for i := 0; i < len(a.buildID); i++ {
385 if i > 0 {
386 if i%8 == 0 {
387 fmt.Fprintf(&buf, "\n\t.byte ")
388 } else {
389 fmt.Fprintf(&buf, ",")
392 fmt.Fprintf(&buf, "%#02x", a.buildID[i])
394 fmt.Fprintf(&buf, "\n")
396 if cfg.BuildN || cfg.BuildX {
397 for _, line := range bytes.Split(buf.Bytes(), []byte("\n")) {
398 b.Showcmd("", "echo '%s' >> %s", line, sfile)
400 if cfg.BuildN {
401 return sfile, nil
405 if err := ioutil.WriteFile(sfile, buf.Bytes(), 0666); err != nil {
406 return "", err
409 return sfile, nil
412 // buildID returns the build ID found in the given file.
413 // If no build ID is found, buildID returns the content hash of the file.
414 func (b *Builder) buildID(file string) string {
415 b.id.Lock()
416 id := b.buildIDCache[file]
417 b.id.Unlock()
419 if id != "" {
420 return id
423 id, err := buildid.ReadFile(file)
424 if err != nil {
425 id = b.fileHash(file)
428 b.id.Lock()
429 b.buildIDCache[file] = id
430 b.id.Unlock()
432 return id
435 // fileHash returns the content hash of the named file.
436 func (b *Builder) fileHash(file string) string {
437 sum, err := cache.FileHash(file)
438 if err != nil {
439 return ""
441 return hashToString(sum)
444 // useCache tries to satisfy the action a, which has action ID actionHash,
445 // by using a cached result from an earlier build. At the moment, the only
446 // cached result is the installed package or binary at target.
447 // If useCache decides that the cache can be used, it sets a.buildID
448 // and a.built for use by parent actions and then returns true.
449 // Otherwise it sets a.buildID to a temporary build ID for use in the build
450 // and returns false. When useCache returns false the expectation is that
451 // the caller will build the target and then call updateBuildID to finish the
452 // build ID computation.
453 // When useCache returns false, it may have initiated buffering of output
454 // during a's work. The caller should defer b.flushOutput(a), to make sure
455 // that flushOutput is eventually called regardless of whether the action
456 // succeeds. The flushOutput call must happen after updateBuildID.
457 func (b *Builder) useCache(a *Action, p *load.Package, actionHash cache.ActionID, target string) bool {
458 // The second half of the build ID here is a placeholder for the content hash.
459 // It's important that the overall buildID be unlikely verging on impossible
460 // to appear in the output by chance, but that should be taken care of by
461 // the actionID half; if it also appeared in the input that would be like an
462 // engineered 96-bit partial SHA256 collision.
463 a.actionID = actionHash
464 actionID := hashToString(actionHash)
465 contentID := actionID // temporary placeholder, likely unique
466 a.buildID = actionID + buildIDSeparator + contentID
468 // Executable binaries also record the main build ID in the middle.
469 // See "Build IDs" comment above.
470 if a.Mode == "link" {
471 mainpkg := a.Deps[0]
472 a.buildID = actionID + buildIDSeparator + mainpkg.buildID + buildIDSeparator + contentID
475 // Check to see if target exists and matches the expected action ID.
476 // If so, it's up to date and we can reuse it instead of rebuilding it.
477 var buildID string
478 if target != "" && !cfg.BuildA {
479 buildID, _ = buildid.ReadFile(target)
480 if strings.HasPrefix(buildID, actionID+buildIDSeparator) {
481 a.buildID = buildID
482 a.built = target
483 // Poison a.Target to catch uses later in the build.
484 a.Target = "DO NOT USE - " + a.Mode
485 return true
489 // Special case for building a main package: if the only thing we
490 // want the package for is to link a binary, and the binary is
491 // already up-to-date, then to avoid a rebuild, report the package
492 // as up-to-date as well. See "Build IDs" comment above.
493 // TODO(rsc): Rewrite this code to use a TryCache func on the link action.
494 if target != "" && !cfg.BuildA && !b.NeedExport && a.Mode == "build" && len(a.triggers) == 1 && a.triggers[0].Mode == "link" {
495 buildID, err := buildid.ReadFile(target)
496 if err == nil {
497 id := strings.Split(buildID, buildIDSeparator)
498 if len(id) == 4 && id[1] == actionID {
499 // Temporarily assume a.buildID is the package build ID
500 // stored in the installed binary, and see if that makes
501 // the upcoming link action ID a match. If so, report that
502 // we built the package, safe in the knowledge that the
503 // link step will not ask us for the actual package file.
504 // Note that (*Builder).LinkAction arranged that all of
505 // a.triggers[0]'s dependencies other than a are also
506 // dependencies of a, so that we can be sure that,
507 // other than a.buildID, b.linkActionID is only accessing
508 // build IDs of completed actions.
509 oldBuildID := a.buildID
510 a.buildID = id[1] + buildIDSeparator + id[2]
511 linkID := hashToString(b.linkActionID(a.triggers[0]))
512 if id[0] == linkID {
513 // Best effort attempt to display output from the compile and link steps.
514 // If it doesn't work, it doesn't work: reusing the cached binary is more
515 // important than reprinting diagnostic information.
516 if c := cache.Default(); c != nil {
517 showStdout(b, c, a.actionID, "stdout") // compile output
518 showStdout(b, c, a.actionID, "link-stdout") // link output
521 // Poison a.Target to catch uses later in the build.
522 a.Target = "DO NOT USE - main build pseudo-cache Target"
523 a.built = "DO NOT USE - main build pseudo-cache built"
524 return true
526 // Otherwise restore old build ID for main build.
527 a.buildID = oldBuildID
532 // Special case for linking a test binary: if the only thing we
533 // want the binary for is to run the test, and the test result is cached,
534 // then to avoid the link step, report the link as up-to-date.
535 // We avoid the nested build ID problem in the previous special case
536 // by recording the test results in the cache under the action ID half.
537 if !cfg.BuildA && len(a.triggers) == 1 && a.triggers[0].TryCache != nil && a.triggers[0].TryCache(b, a.triggers[0]) {
538 // Best effort attempt to display output from the compile and link steps.
539 // If it doesn't work, it doesn't work: reusing the test result is more
540 // important than reprinting diagnostic information.
541 if c := cache.Default(); c != nil {
542 showStdout(b, c, a.Deps[0].actionID, "stdout") // compile output
543 showStdout(b, c, a.Deps[0].actionID, "link-stdout") // link output
546 // Poison a.Target to catch uses later in the build.
547 a.Target = "DO NOT USE - pseudo-cache Target"
548 a.built = "DO NOT USE - pseudo-cache built"
549 return true
552 if b.IsCmdList {
553 // Invoked during go list to compute and record staleness.
554 if p := a.Package; p != nil && !p.Stale {
555 p.Stale = true
556 if cfg.BuildA {
557 p.StaleReason = "build -a flag in use"
558 } else {
559 p.StaleReason = "build ID mismatch"
560 for _, p1 := range p.Internal.Imports {
561 if p1.Stale && p1.StaleReason != "" {
562 if strings.HasPrefix(p1.StaleReason, "stale dependency: ") {
563 p.StaleReason = p1.StaleReason
564 break
566 if strings.HasPrefix(p.StaleReason, "build ID mismatch") {
567 p.StaleReason = "stale dependency: " + p1.ImportPath
574 // Fall through to update a.buildID from the build artifact cache,
575 // which will affect the computation of buildIDs for targets
576 // higher up in the dependency graph.
579 // Check the build artifact cache.
580 // We treat hits in this cache as being "stale" for the purposes of go list
581 // (in effect, "stale" means whether p.Target is up-to-date),
582 // but we're still happy to use results from the build artifact cache.
583 if c := cache.Default(); c != nil {
584 if !cfg.BuildA {
585 if file, _, err := c.GetFile(actionHash); err == nil {
586 if buildID, err := buildid.ReadFile(file); err == nil {
587 if err := showStdout(b, c, a.actionID, "stdout"); err == nil {
588 a.built = file
589 a.Target = "DO NOT USE - using cache"
590 a.buildID = buildID
591 if p := a.Package; p != nil {
592 // Clearer than explaining that something else is stale.
593 p.StaleReason = "not installed but available in build cache"
595 return true
601 // Begin saving output for later writing to cache.
602 a.output = []byte{}
605 return false
608 func showStdout(b *Builder, c *cache.Cache, actionID cache.ActionID, key string) error {
609 stdout, stdoutEntry, err := c.GetBytes(cache.Subkey(actionID, key))
610 if err != nil {
611 return err
614 if len(stdout) > 0 {
615 if cfg.BuildX || cfg.BuildN {
616 b.Showcmd("", "%s # internal", joinUnambiguously(str.StringList("cat", c.OutputFile(stdoutEntry.OutputID))))
618 if !cfg.BuildN {
619 b.Print(string(stdout))
622 return nil
625 // flushOutput flushes the output being queued in a.
626 func (b *Builder) flushOutput(a *Action) {
627 b.Print(string(a.output))
628 a.output = nil
631 // updateBuildID updates the build ID in the target written by action a.
632 // It requires that useCache was called for action a and returned false,
633 // and that the build was then carried out and given the temporary
634 // a.buildID to record as the build ID in the resulting package or binary.
635 // updateBuildID computes the final content ID and updates the build IDs
636 // in the binary.
638 // Keep in sync with src/cmd/buildid/buildid.go
639 func (b *Builder) updateBuildID(a *Action, target string, rewrite bool) error {
640 if cfg.BuildX || cfg.BuildN {
641 if rewrite {
642 b.Showcmd("", "%s # internal", joinUnambiguously(str.StringList(base.Tool("buildid"), "-w", target)))
644 if cfg.BuildN {
645 return nil
649 // Cache output from compile/link, even if we don't do the rest.
650 if c := cache.Default(); c != nil {
651 switch a.Mode {
652 case "build":
653 c.PutBytes(cache.Subkey(a.actionID, "stdout"), a.output)
654 case "link":
655 // Even though we don't cache the binary, cache the linker text output.
656 // We might notice that an installed binary is up-to-date but still
657 // want to pretend to have run the linker.
658 // Store it under the main package's action ID
659 // to make it easier to find when that's all we have.
660 for _, a1 := range a.Deps {
661 if p1 := a1.Package; p1 != nil && p1.Name == "main" {
662 c.PutBytes(cache.Subkey(a1.actionID, "link-stdout"), a.output)
663 break
669 // Find occurrences of old ID and compute new content-based ID.
670 r, err := os.Open(target)
671 if err != nil {
672 return err
674 matches, hash, err := buildid.FindAndHash(r, a.buildID, 0)
675 r.Close()
676 if err != nil {
677 return err
679 newID := a.buildID[:strings.LastIndex(a.buildID, buildIDSeparator)] + buildIDSeparator + hashToString(hash)
680 if len(newID) != len(a.buildID) {
681 return fmt.Errorf("internal error: build ID length mismatch %q vs %q", a.buildID, newID)
684 // Replace with new content-based ID.
685 a.buildID = newID
686 if len(matches) == 0 {
687 // Assume the user specified -buildid= to override what we were going to choose.
688 return nil
691 if rewrite {
692 w, err := os.OpenFile(target, os.O_WRONLY, 0)
693 if err != nil {
694 return err
696 err = buildid.Rewrite(w, matches, newID)
697 if err != nil {
698 w.Close()
699 return err
701 if err := w.Close(); err != nil {
702 return err
706 // Cache package builds, but not binaries (link steps).
707 // The expectation is that binaries are not reused
708 // nearly as often as individual packages, and they're
709 // much larger, so the cache-footprint-to-utility ratio
710 // of binaries is much lower for binaries.
711 // Not caching the link step also makes sure that repeated "go run" at least
712 // always rerun the linker, so that they don't get too fast.
713 // (We don't want people thinking go is a scripting language.)
714 // Note also that if we start caching binaries, then we will
715 // copy the binaries out of the cache to run them, and then
716 // that will mean the go process is itself writing a binary
717 // and then executing it, so we will need to defend against
718 // ETXTBSY problems as discussed in exec.go and golang.org/issue/22220.
719 if c := cache.Default(); c != nil && a.Mode == "build" {
720 r, err := os.Open(target)
721 if err == nil {
722 if a.output == nil {
723 panic("internal error: a.output not set")
725 outputID, _, err := c.Put(a.actionID, r)
726 r.Close()
727 if err == nil && cfg.BuildX {
728 b.Showcmd("", "%s # internal", joinUnambiguously(str.StringList("cp", target, c.OutputFile(outputID))))
730 if b.NeedExport {
731 if err != nil {
732 return err
734 a.Package.Export = c.OutputFile(outputID)
739 return nil