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