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 execution.
6
7package work
8
9import (
10	"bytes"
11	"context"
12	"encoding/json"
13	"errors"
14	"fmt"
15	"internal/buildcfg"
16	exec "internal/execabs"
17	"internal/lazyregexp"
18	"io"
19	"io/fs"
20	"log"
21	"math/rand"
22	"os"
23	"path/filepath"
24	"regexp"
25	"runtime"
26	"strconv"
27	"strings"
28	"sync"
29	"time"
30
31	"cmd/go/internal/base"
32	"cmd/go/internal/cache"
33	"cmd/go/internal/cfg"
34	"cmd/go/internal/fsys"
35	"cmd/go/internal/load"
36	"cmd/go/internal/modload"
37	"cmd/go/internal/str"
38	"cmd/go/internal/trace"
39)
40
41// actionList returns the list of actions in the dag rooted at root
42// as visited in a depth-first post-order traversal.
43func actionList(root *Action) []*Action {
44	seen := map[*Action]bool{}
45	all := []*Action{}
46	var walk func(*Action)
47	walk = func(a *Action) {
48		if seen[a] {
49			return
50		}
51		seen[a] = true
52		for _, a1 := range a.Deps {
53			walk(a1)
54		}
55		all = append(all, a)
56	}
57	walk(root)
58	return all
59}
60
61// do runs the action graph rooted at root.
62func (b *Builder) Do(ctx context.Context, root *Action) {
63	ctx, span := trace.StartSpan(ctx, "exec.Builder.Do ("+root.Mode+" "+root.Target+")")
64	defer span.Done()
65
66	if !b.IsCmdList {
67		// If we're doing real work, take time at the end to trim the cache.
68		c := cache.Default()
69		defer c.Trim()
70	}
71
72	// Build list of all actions, assigning depth-first post-order priority.
73	// The original implementation here was a true queue
74	// (using a channel) but it had the effect of getting
75	// distracted by low-level leaf actions to the detriment
76	// of completing higher-level actions. The order of
77	// work does not matter much to overall execution time,
78	// but when running "go test std" it is nice to see each test
79	// results as soon as possible. The priorities assigned
80	// ensure that, all else being equal, the execution prefers
81	// to do what it would have done first in a simple depth-first
82	// dependency order traversal.
83	all := actionList(root)
84	for i, a := range all {
85		a.priority = i
86	}
87
88	// Write action graph, without timing information, in case we fail and exit early.
89	writeActionGraph := func() {
90		if file := cfg.DebugActiongraph; file != "" {
91			if strings.HasSuffix(file, ".go") {
92				// Do not overwrite Go source code in:
93				//	go build -debug-actiongraph x.go
94				base.Fatalf("go: refusing to write action graph to %v\n", file)
95			}
96			js := actionGraphJSON(root)
97			if err := os.WriteFile(file, []byte(js), 0666); err != nil {
98				fmt.Fprintf(os.Stderr, "go: writing action graph: %v\n", err)
99				base.SetExitStatus(1)
100			}
101		}
102	}
103	writeActionGraph()
104
105	b.readySema = make(chan bool, len(all))
106
107	// Initialize per-action execution state.
108	for _, a := range all {
109		for _, a1 := range a.Deps {
110			a1.triggers = append(a1.triggers, a)
111		}
112		a.pending = len(a.Deps)
113		if a.pending == 0 {
114			b.ready.push(a)
115			b.readySema <- true
116		}
117	}
118
119	// Handle runs a single action and takes care of triggering
120	// any actions that are runnable as a result.
121	handle := func(ctx context.Context, a *Action) {
122		if a.json != nil {
123			a.json.TimeStart = time.Now()
124		}
125		var err error
126		if a.Func != nil && (!a.Failed || a.IgnoreFail) {
127			// TODO(matloob): Better action descriptions
128			desc := "Executing action "
129			if a.Package != nil {
130				desc += "(" + a.Mode + " " + a.Package.Desc() + ")"
131			}
132			ctx, span := trace.StartSpan(ctx, desc)
133			a.traceSpan = span
134			for _, d := range a.Deps {
135				trace.Flow(ctx, d.traceSpan, a.traceSpan)
136			}
137			err = a.Func(b, ctx, a)
138			span.Done()
139		}
140		if a.json != nil {
141			a.json.TimeDone = time.Now()
142		}
143
144		// The actions run in parallel but all the updates to the
145		// shared work state are serialized through b.exec.
146		b.exec.Lock()
147		defer b.exec.Unlock()
148
149		if err != nil {
150			if err == errPrintedOutput {
151				base.SetExitStatus(2)
152			} else {
153				base.Errorf("%s", err)
154			}
155			a.Failed = true
156		}
157
158		for _, a0 := range a.triggers {
159			if a.Failed {
160				a0.Failed = true
161			}
162			if a0.pending--; a0.pending == 0 {
163				b.ready.push(a0)
164				b.readySema <- true
165			}
166		}
167
168		if a == root {
169			close(b.readySema)
170		}
171	}
172
173	var wg sync.WaitGroup
174
175	// Kick off goroutines according to parallelism.
176	// If we are using the -n flag (just printing commands)
177	// drop the parallelism to 1, both to make the output
178	// deterministic and because there is no real work anyway.
179	par := cfg.BuildP
180	if cfg.BuildN {
181		par = 1
182	}
183	for i := 0; i < par; i++ {
184		wg.Add(1)
185		go func() {
186			ctx := trace.StartGoroutine(ctx)
187			defer wg.Done()
188			for {
189				select {
190				case _, ok := <-b.readySema:
191					if !ok {
192						return
193					}
194					// Receiving a value from b.readySema entitles
195					// us to take from the ready queue.
196					b.exec.Lock()
197					a := b.ready.pop()
198					b.exec.Unlock()
199					handle(ctx, a)
200				case <-base.Interrupted:
201					base.SetExitStatus(1)
202					return
203				}
204			}
205		}()
206	}
207
208	wg.Wait()
209
210	// Write action graph again, this time with timing information.
211	writeActionGraph()
212}
213
214// buildActionID computes the action ID for a build action.
215func (b *Builder) buildActionID(a *Action) cache.ActionID {
216	p := a.Package
217	h := cache.NewHash("build " + p.ImportPath)
218
219	// Configuration independent of compiler toolchain.
220	// Note: buildmode has already been accounted for in buildGcflags
221	// and should not be inserted explicitly. Most buildmodes use the
222	// same compiler settings and can reuse each other's results.
223	// If not, the reason is already recorded in buildGcflags.
224	fmt.Fprintf(h, "compile\n")
225	// Only include the package directory if it may affect the output.
226	// We trim workspace paths for all packages when -trimpath is set.
227	// The compiler hides the exact value of $GOROOT
228	// when building things in GOROOT.
229	// Assume b.WorkDir is being trimmed properly.
230	// When -trimpath is used with a package built from the module cache,
231	// use the module path and version instead of the directory.
232	if !p.Goroot && !cfg.BuildTrimpath && !strings.HasPrefix(p.Dir, b.WorkDir) {
233		fmt.Fprintf(h, "dir %s\n", p.Dir)
234	} else if cfg.BuildTrimpath && p.Module != nil {
235		fmt.Fprintf(h, "module %s@%s\n", p.Module.Path, p.Module.Version)
236	}
237	if p.Module != nil {
238		fmt.Fprintf(h, "go %s\n", p.Module.GoVersion)
239	}
240	fmt.Fprintf(h, "goos %s goarch %s\n", cfg.Goos, cfg.Goarch)
241	fmt.Fprintf(h, "import %q\n", p.ImportPath)
242	fmt.Fprintf(h, "omitdebug %v standard %v local %v prefix %q\n", p.Internal.OmitDebug, p.Standard, p.Internal.Local, p.Internal.LocalPrefix)
243	if cfg.BuildTrimpath {
244		fmt.Fprintln(h, "trimpath")
245	}
246	if p.Internal.ForceLibrary {
247		fmt.Fprintf(h, "forcelibrary\n")
248	}
249	if len(p.CgoFiles)+len(p.SwigFiles)+len(p.SwigCXXFiles) > 0 {
250		fmt.Fprintf(h, "cgo %q\n", b.toolID("cgo"))
251		cppflags, cflags, cxxflags, fflags, ldflags, _ := b.CFlags(p)
252
253		ccExe := b.ccExe()
254		fmt.Fprintf(h, "CC=%q %q %q %q\n", ccExe, cppflags, cflags, ldflags)
255		// Include the C compiler tool ID so that if the C
256		// compiler changes we rebuild the package.
257		// But don't do that for standard library packages like net,
258		// so that the prebuilt .a files from a Go binary install
259		// don't need to be rebuilt with the local compiler.
260		if !p.Standard {
261			if ccID, err := b.gccToolID(ccExe[0], "c"); err == nil {
262				fmt.Fprintf(h, "CC ID=%q\n", ccID)
263			}
264		}
265		if len(p.CXXFiles)+len(p.SwigCXXFiles) > 0 {
266			cxxExe := b.cxxExe()
267			fmt.Fprintf(h, "CXX=%q %q\n", cxxExe, cxxflags)
268			if cxxID, err := b.gccToolID(cxxExe[0], "c++"); err == nil {
269				fmt.Fprintf(h, "CXX ID=%q\n", cxxID)
270			}
271		}
272		if len(p.FFiles) > 0 {
273			fcExe := b.fcExe()
274			fmt.Fprintf(h, "FC=%q %q\n", fcExe, fflags)
275			if fcID, err := b.gccToolID(fcExe[0], "f95"); err == nil {
276				fmt.Fprintf(h, "FC ID=%q\n", fcID)
277			}
278		}
279		// TODO(rsc): Should we include the SWIG version?
280	}
281	if p.Internal.CoverMode != "" {
282		fmt.Fprintf(h, "cover %q %q\n", p.Internal.CoverMode, b.toolID("cover"))
283	}
284	fmt.Fprintf(h, "modinfo %q\n", p.Internal.BuildInfo)
285
286	// Configuration specific to compiler toolchain.
287	switch cfg.BuildToolchainName {
288	default:
289		base.Fatalf("buildActionID: unknown build toolchain %q", cfg.BuildToolchainName)
290	case "gc":
291		fmt.Fprintf(h, "compile %s %q %q\n", b.toolID("compile"), forcedGcflags, p.Internal.Gcflags)
292		if len(p.SFiles) > 0 {
293			fmt.Fprintf(h, "asm %q %q %q\n", b.toolID("asm"), forcedAsmflags, p.Internal.Asmflags)
294		}
295
296		// GOARM, GOMIPS, etc.
297		key, val := cfg.GetArchEnv()
298		fmt.Fprintf(h, "%s=%s\n", key, val)
299
300		if goexperiment := buildcfg.GOEXPERIMENT(); goexperiment != "" {
301			fmt.Fprintf(h, "GOEXPERIMENT=%q\n", goexperiment)
302		}
303
304		// TODO(rsc): Convince compiler team not to add more magic environment variables,
305		// or perhaps restrict the environment variables passed to subprocesses.
306		// Because these are clumsy, undocumented special-case hacks
307		// for debugging the compiler, they are not settable using 'go env -w',
308		// and so here we use os.Getenv, not cfg.Getenv.
309		magic := []string{
310			"GOCLOBBERDEADHASH",
311			"GOSSAFUNC",
312			"GOSSADIR",
313			"GOSSAHASH",
314		}
315		for _, env := range magic {
316			if x := os.Getenv(env); x != "" {
317				fmt.Fprintf(h, "magic %s=%s\n", env, x)
318			}
319		}
320		if os.Getenv("GOSSAHASH") != "" {
321			for i := 0; ; i++ {
322				env := fmt.Sprintf("GOSSAHASH%d", i)
323				x := os.Getenv(env)
324				if x == "" {
325					break
326				}
327				fmt.Fprintf(h, "magic %s=%s\n", env, x)
328			}
329		}
330		if os.Getenv("GSHS_LOGFILE") != "" {
331			// Clumsy hack. Compiler writes to this log file,
332			// so do not allow use of cache at all.
333			// We will still write to the cache but it will be
334			// essentially unfindable.
335			fmt.Fprintf(h, "nocache %d\n", time.Now().UnixNano())
336		}
337
338	case "gccgo":
339		id, err := b.gccToolID(BuildToolchain.compiler(), "go")
340		if err != nil {
341			base.Fatalf("%v", err)
342		}
343		fmt.Fprintf(h, "compile %s %q %q\n", id, forcedGccgoflags, p.Internal.Gccgoflags)
344		fmt.Fprintf(h, "pkgpath %s\n", gccgoPkgpath(p))
345		fmt.Fprintf(h, "ar %q\n", BuildToolchain.(gccgoToolchain).ar())
346		if len(p.SFiles) > 0 {
347			id, _ = b.gccToolID(BuildToolchain.compiler(), "assembler-with-cpp")
348			// Ignore error; different assembler versions
349			// are unlikely to make any difference anyhow.
350			fmt.Fprintf(h, "asm %q\n", id)
351		}
352	}
353
354	// Input files.
355	inputFiles := str.StringList(
356		p.GoFiles,
357		p.CgoFiles,
358		p.CFiles,
359		p.CXXFiles,
360		p.FFiles,
361		p.MFiles,
362		p.HFiles,
363		p.SFiles,
364		p.SysoFiles,
365		p.SwigFiles,
366		p.SwigCXXFiles,
367		p.EmbedFiles,
368	)
369	for _, file := range inputFiles {
370		fmt.Fprintf(h, "file %s %s\n", file, b.fileHash(filepath.Join(p.Dir, file)))
371	}
372	for _, a1 := range a.Deps {
373		p1 := a1.Package
374		if p1 != nil {
375			fmt.Fprintf(h, "import %s %s\n", p1.ImportPath, contentID(a1.buildID))
376		}
377	}
378
379	return h.Sum()
380}
381
382// needCgoHdr reports whether the actions triggered by this one
383// expect to be able to access the cgo-generated header file.
384func (b *Builder) needCgoHdr(a *Action) bool {
385	// If this build triggers a header install, run cgo to get the header.
386	if !b.IsCmdList && (a.Package.UsesCgo() || a.Package.UsesSwig()) && (cfg.BuildBuildmode == "c-archive" || cfg.BuildBuildmode == "c-shared") {
387		for _, t1 := range a.triggers {
388			if t1.Mode == "install header" {
389				return true
390			}
391		}
392		for _, t1 := range a.triggers {
393			for _, t2 := range t1.triggers {
394				if t2.Mode == "install header" {
395					return true
396				}
397			}
398		}
399	}
400	return false
401}
402
403// allowedVersion reports whether the version v is an allowed version of go
404// (one that we can compile).
405// v is known to be of the form "1.23".
406func allowedVersion(v string) bool {
407	// Special case: no requirement.
408	if v == "" {
409		return true
410	}
411	// Special case "1.0" means "go1", which is OK.
412	if v == "1.0" {
413		return true
414	}
415	// Otherwise look through release tags of form "go1.23" for one that matches.
416	for _, tag := range cfg.BuildContext.ReleaseTags {
417		if strings.HasPrefix(tag, "go") && tag[2:] == v {
418			return true
419		}
420	}
421	return false
422}
423
424const (
425	needBuild uint32 = 1 << iota
426	needCgoHdr
427	needVet
428	needCompiledGoFiles
429	needStale
430)
431
432// build is the action for building a single package.
433// Note that any new influence on this logic must be reported in b.buildActionID above as well.
434func (b *Builder) build(ctx context.Context, a *Action) (err error) {
435	p := a.Package
436
437	bit := func(x uint32, b bool) uint32 {
438		if b {
439			return x
440		}
441		return 0
442	}
443
444	cachedBuild := false
445	need := bit(needBuild, !b.IsCmdList && a.needBuild || b.NeedExport) |
446		bit(needCgoHdr, b.needCgoHdr(a)) |
447		bit(needVet, a.needVet) |
448		bit(needCompiledGoFiles, b.NeedCompiledGoFiles)
449
450	if !p.BinaryOnly {
451		if b.useCache(a, b.buildActionID(a), p.Target) {
452			// We found the main output in the cache.
453			// If we don't need any other outputs, we can stop.
454			// Otherwise, we need to write files to a.Objdir (needVet, needCgoHdr).
455			// Remember that we might have them in cache
456			// and check again after we create a.Objdir.
457			cachedBuild = true
458			a.output = []byte{} // start saving output in case we miss any cache results
459			need &^= needBuild
460			if b.NeedExport {
461				p.Export = a.built
462				p.BuildID = a.buildID
463			}
464			if need&needCompiledGoFiles != 0 {
465				if err := b.loadCachedSrcFiles(a); err == nil {
466					need &^= needCompiledGoFiles
467				}
468			}
469		}
470
471		// Source files might be cached, even if the full action is not
472		// (e.g., go list -compiled -find).
473		if !cachedBuild && need&needCompiledGoFiles != 0 {
474			if err := b.loadCachedSrcFiles(a); err == nil {
475				need &^= needCompiledGoFiles
476			}
477		}
478
479		if need == 0 {
480			return nil
481		}
482		defer b.flushOutput(a)
483	}
484
485	defer func() {
486		if err != nil && err != errPrintedOutput {
487			err = fmt.Errorf("go build %s: %v", a.Package.ImportPath, err)
488		}
489		if err != nil && b.IsCmdList && b.NeedError && p.Error == nil {
490			p.Error = &load.PackageError{Err: err}
491		}
492	}()
493	if cfg.BuildN {
494		// In -n mode, print a banner between packages.
495		// The banner is five lines so that when changes to
496		// different sections of the bootstrap script have to
497		// be merged, the banners give patch something
498		// to use to find its context.
499		b.Print("\n#\n# " + a.Package.ImportPath + "\n#\n\n")
500	}
501
502	if cfg.BuildV {
503		b.Print(a.Package.ImportPath + "\n")
504	}
505
506	if a.Package.BinaryOnly {
507		p.Stale = true
508		p.StaleReason = "binary-only packages are no longer supported"
509		if b.IsCmdList {
510			return nil
511		}
512		return errors.New("binary-only packages are no longer supported")
513	}
514
515	if err := b.Mkdir(a.Objdir); err != nil {
516		return err
517	}
518	objdir := a.Objdir
519
520	// Load cached cgo header, but only if we're skipping the main build (cachedBuild==true).
521	if cachedBuild && need&needCgoHdr != 0 {
522		if err := b.loadCachedCgoHdr(a); err == nil {
523			need &^= needCgoHdr
524		}
525	}
526
527	// Load cached vet config, but only if that's all we have left
528	// (need == needVet, not testing just the one bit).
529	// If we are going to do a full build anyway,
530	// we're going to regenerate the files below anyway.
531	if need == needVet {
532		if err := b.loadCachedVet(a); err == nil {
533			need &^= needVet
534		}
535	}
536	if need == 0 {
537		return nil
538	}
539
540	if err := allowInstall(a); err != nil {
541		return err
542	}
543
544	// make target directory
545	dir, _ := filepath.Split(a.Target)
546	if dir != "" {
547		if err := b.Mkdir(dir); err != nil {
548			return err
549		}
550	}
551
552	gofiles := str.StringList(a.Package.GoFiles)
553	cgofiles := str.StringList(a.Package.CgoFiles)
554	cfiles := str.StringList(a.Package.CFiles)
555	sfiles := str.StringList(a.Package.SFiles)
556	cxxfiles := str.StringList(a.Package.CXXFiles)
557	var objects, cgoObjects, pcCFLAGS, pcLDFLAGS []string
558
559	if a.Package.UsesCgo() || a.Package.UsesSwig() {
560		if pcCFLAGS, pcLDFLAGS, err = b.getPkgConfigFlags(a.Package); err != nil {
561			return
562		}
563	}
564
565	// Compute overlays for .c/.cc/.h/etc. and if there are any overlays
566	// put correct contents of all those files in the objdir, to ensure
567	// the correct headers are included. nonGoOverlay is the overlay that
568	// points from nongo files to the copied files in objdir.
569	nonGoFileLists := [][]string{a.Package.CFiles, a.Package.SFiles, a.Package.CXXFiles, a.Package.HFiles, a.Package.FFiles}
570OverlayLoop:
571	for _, fs := range nonGoFileLists {
572		for _, f := range fs {
573			if _, ok := fsys.OverlayPath(mkAbs(p.Dir, f)); ok {
574				a.nonGoOverlay = make(map[string]string)
575				break OverlayLoop
576			}
577		}
578	}
579	if a.nonGoOverlay != nil {
580		for _, fs := range nonGoFileLists {
581			for i := range fs {
582				from := mkAbs(p.Dir, fs[i])
583				opath, _ := fsys.OverlayPath(from)
584				dst := objdir + filepath.Base(fs[i])
585				if err := b.copyFile(dst, opath, 0666, false); err != nil {
586					return err
587				}
588				a.nonGoOverlay[from] = dst
589			}
590		}
591	}
592
593	// Run SWIG on each .swig and .swigcxx file.
594	// Each run will generate two files, a .go file and a .c or .cxx file.
595	// The .go file will use import "C" and is to be processed by cgo.
596	if a.Package.UsesSwig() {
597		outGo, outC, outCXX, err := b.swig(a, a.Package, objdir, pcCFLAGS)
598		if err != nil {
599			return err
600		}
601		cgofiles = append(cgofiles, outGo...)
602		cfiles = append(cfiles, outC...)
603		cxxfiles = append(cxxfiles, outCXX...)
604	}
605
606	// If we're doing coverage, preprocess the .go files and put them in the work directory
607	if a.Package.Internal.CoverMode != "" {
608		for i, file := range str.StringList(gofiles, cgofiles) {
609			var sourceFile string
610			var coverFile string
611			var key string
612			if strings.HasSuffix(file, ".cgo1.go") {
613				// cgo files have absolute paths
614				base := filepath.Base(file)
615				sourceFile = file
616				coverFile = objdir + base
617				key = strings.TrimSuffix(base, ".cgo1.go") + ".go"
618			} else {
619				sourceFile = filepath.Join(a.Package.Dir, file)
620				coverFile = objdir + file
621				key = file
622			}
623			coverFile = strings.TrimSuffix(coverFile, ".go") + ".cover.go"
624			cover := a.Package.Internal.CoverVars[key]
625			if cover == nil || base.IsTestFile(file) {
626				// Not covering this file.
627				continue
628			}
629			if err := b.cover(a, coverFile, sourceFile, cover.Var); err != nil {
630				return err
631			}
632			if i < len(gofiles) {
633				gofiles[i] = coverFile
634			} else {
635				cgofiles[i-len(gofiles)] = coverFile
636			}
637		}
638	}
639
640	// Run cgo.
641	if a.Package.UsesCgo() || a.Package.UsesSwig() {
642		// In a package using cgo, cgo compiles the C, C++ and assembly files with gcc.
643		// There is one exception: runtime/cgo's job is to bridge the
644		// cgo and non-cgo worlds, so it necessarily has files in both.
645		// In that case gcc only gets the gcc_* files.
646		var gccfiles []string
647		gccfiles = append(gccfiles, cfiles...)
648		cfiles = nil
649		if a.Package.Standard && a.Package.ImportPath == "runtime/cgo" {
650			filter := func(files, nongcc, gcc []string) ([]string, []string) {
651				for _, f := range files {
652					if strings.HasPrefix(f, "gcc_") {
653						gcc = append(gcc, f)
654					} else {
655						nongcc = append(nongcc, f)
656					}
657				}
658				return nongcc, gcc
659			}
660			sfiles, gccfiles = filter(sfiles, sfiles[:0], gccfiles)
661		} else {
662			for _, sfile := range sfiles {
663				data, err := os.ReadFile(filepath.Join(a.Package.Dir, sfile))
664				if err == nil {
665					if bytes.HasPrefix(data, []byte("TEXT")) || bytes.Contains(data, []byte("\nTEXT")) ||
666						bytes.HasPrefix(data, []byte("DATA")) || bytes.Contains(data, []byte("\nDATA")) ||
667						bytes.HasPrefix(data, []byte("GLOBL")) || bytes.Contains(data, []byte("\nGLOBL")) {
668						return fmt.Errorf("package using cgo has Go assembly file %s", sfile)
669					}
670				}
671			}
672			gccfiles = append(gccfiles, sfiles...)
673			sfiles = nil
674		}
675
676		outGo, outObj, err := b.cgo(a, base.Tool("cgo"), objdir, pcCFLAGS, pcLDFLAGS, mkAbsFiles(a.Package.Dir, cgofiles), gccfiles, cxxfiles, a.Package.MFiles, a.Package.FFiles)
677
678		// The files in cxxfiles have now been handled by b.cgo.
679		cxxfiles = nil
680
681		if err != nil {
682			return err
683		}
684		if cfg.BuildToolchainName == "gccgo" {
685			cgoObjects = append(cgoObjects, a.Objdir+"_cgo_flags")
686		}
687		cgoObjects = append(cgoObjects, outObj...)
688		gofiles = append(gofiles, outGo...)
689
690		switch cfg.BuildBuildmode {
691		case "c-archive", "c-shared":
692			b.cacheCgoHdr(a)
693		}
694	}
695
696	var srcfiles []string // .go and non-.go
697	srcfiles = append(srcfiles, gofiles...)
698	srcfiles = append(srcfiles, sfiles...)
699	srcfiles = append(srcfiles, cfiles...)
700	srcfiles = append(srcfiles, cxxfiles...)
701	b.cacheSrcFiles(a, srcfiles)
702
703	// Running cgo generated the cgo header.
704	need &^= needCgoHdr
705
706	// Sanity check only, since Package.load already checked as well.
707	if len(gofiles) == 0 {
708		return &load.NoGoError{Package: a.Package}
709	}
710
711	// Prepare Go vet config if needed.
712	if need&needVet != 0 {
713		buildVetConfig(a, srcfiles)
714		need &^= needVet
715	}
716	if need&needCompiledGoFiles != 0 {
717		if err := b.loadCachedSrcFiles(a); err != nil {
718			return fmt.Errorf("loading compiled Go files from cache: %w", err)
719		}
720		need &^= needCompiledGoFiles
721	}
722	if need == 0 {
723		// Nothing left to do.
724		return nil
725	}
726
727	// Collect symbol ABI requirements from assembly.
728	symabis, err := BuildToolchain.symabis(b, a, sfiles)
729	if err != nil {
730		return err
731	}
732
733	// Prepare Go import config.
734	// We start it off with a comment so it can't be empty, so icfg.Bytes() below is never nil.
735	// It should never be empty anyway, but there have been bugs in the past that resulted
736	// in empty configs, which then unfortunately turn into "no config passed to compiler",
737	// and the compiler falls back to looking in pkg itself, which mostly works,
738	// except when it doesn't.
739	var icfg bytes.Buffer
740	fmt.Fprintf(&icfg, "# import config\n")
741	for i, raw := range a.Package.Internal.RawImports {
742		final := a.Package.Imports[i]
743		if final != raw {
744			fmt.Fprintf(&icfg, "importmap %s=%s\n", raw, final)
745		}
746	}
747	for _, a1 := range a.Deps {
748		p1 := a1.Package
749		if p1 == nil || p1.ImportPath == "" {
750			continue
751		}
752		if a1.built != "" {
753			fmt.Fprintf(&icfg, "packagefile %s=%s\n", p1.ImportPath, a1.built)
754		}
755	}
756
757	// Prepare Go embed config if needed.
758	// Unlike the import config, it's okay for the embed config to be empty.
759	var embedcfg []byte
760	if len(p.Internal.Embed) > 0 {
761		var embed struct {
762			Patterns map[string][]string
763			Files    map[string]string
764		}
765		embed.Patterns = p.Internal.Embed
766		embed.Files = make(map[string]string)
767		for _, file := range p.EmbedFiles {
768			embed.Files[file] = filepath.Join(p.Dir, file)
769		}
770		js, err := json.MarshalIndent(&embed, "", "\t")
771		if err != nil {
772			return fmt.Errorf("marshal embedcfg: %v", err)
773		}
774		embedcfg = js
775	}
776
777	if p.Internal.BuildInfo != "" && cfg.ModulesEnabled {
778		if err := b.writeFile(objdir+"_gomod_.go", modload.ModInfoProg(p.Internal.BuildInfo, cfg.BuildToolchainName == "gccgo")); err != nil {
779			return err
780		}
781		gofiles = append(gofiles, objdir+"_gomod_.go")
782	}
783
784	// Compile Go.
785	objpkg := objdir + "_pkg_.a"
786	ofile, out, err := BuildToolchain.gc(b, a, objpkg, icfg.Bytes(), embedcfg, symabis, len(sfiles) > 0, gofiles)
787	if len(out) > 0 {
788		output := b.processOutput(out)
789		if p.Module != nil && !allowedVersion(p.Module.GoVersion) {
790			output += "note: module requires Go " + p.Module.GoVersion + "\n"
791		}
792		b.showOutput(a, a.Package.Dir, a.Package.Desc(), output)
793		if err != nil {
794			return errPrintedOutput
795		}
796	}
797	if err != nil {
798		if p.Module != nil && !allowedVersion(p.Module.GoVersion) {
799			b.showOutput(a, a.Package.Dir, a.Package.Desc(), "note: module requires Go "+p.Module.GoVersion+"\n")
800		}
801		return err
802	}
803	if ofile != objpkg {
804		objects = append(objects, ofile)
805	}
806
807	// Copy .h files named for goos or goarch or goos_goarch
808	// to names using GOOS and GOARCH.
809	// For example, defs_linux_amd64.h becomes defs_GOOS_GOARCH.h.
810	_goos_goarch := "_" + cfg.Goos + "_" + cfg.Goarch
811	_goos := "_" + cfg.Goos
812	_goarch := "_" + cfg.Goarch
813	for _, file := range a.Package.HFiles {
814		name, ext := fileExtSplit(file)
815		switch {
816		case strings.HasSuffix(name, _goos_goarch):
817			targ := file[:len(name)-len(_goos_goarch)] + "_GOOS_GOARCH." + ext
818			if err := b.copyFile(objdir+targ, filepath.Join(a.Package.Dir, file), 0666, true); err != nil {
819				return err
820			}
821		case strings.HasSuffix(name, _goarch):
822			targ := file[:len(name)-len(_goarch)] + "_GOARCH." + ext
823			if err := b.copyFile(objdir+targ, filepath.Join(a.Package.Dir, file), 0666, true); err != nil {
824				return err
825			}
826		case strings.HasSuffix(name, _goos):
827			targ := file[:len(name)-len(_goos)] + "_GOOS." + ext
828			if err := b.copyFile(objdir+targ, filepath.Join(a.Package.Dir, file), 0666, true); err != nil {
829				return err
830			}
831		}
832	}
833
834	for _, file := range cfiles {
835		out := file[:len(file)-len(".c")] + ".o"
836		if err := BuildToolchain.cc(b, a, objdir+out, file); err != nil {
837			return err
838		}
839		objects = append(objects, out)
840	}
841
842	// Assemble .s files.
843	if len(sfiles) > 0 {
844		ofiles, err := BuildToolchain.asm(b, a, sfiles)
845		if err != nil {
846			return err
847		}
848		objects = append(objects, ofiles...)
849	}
850
851	// For gccgo on ELF systems, we write the build ID as an assembler file.
852	// This lets us set the SHF_EXCLUDE flag.
853	// This is read by readGccgoArchive in cmd/internal/buildid/buildid.go.
854	if a.buildID != "" && cfg.BuildToolchainName == "gccgo" {
855		switch cfg.Goos {
856		case "aix", "android", "dragonfly", "freebsd", "illumos", "linux", "netbsd", "openbsd", "solaris":
857			asmfile, err := b.gccgoBuildIDFile(a)
858			if err != nil {
859				return err
860			}
861			ofiles, err := BuildToolchain.asm(b, a, []string{asmfile})
862			if err != nil {
863				return err
864			}
865			objects = append(objects, ofiles...)
866		}
867	}
868
869	// NOTE(rsc): On Windows, it is critically important that the
870	// gcc-compiled objects (cgoObjects) be listed after the ordinary
871	// objects in the archive. I do not know why this is.
872	// https://golang.org/issue/2601
873	objects = append(objects, cgoObjects...)
874
875	// Add system object files.
876	for _, syso := range a.Package.SysoFiles {
877		objects = append(objects, filepath.Join(a.Package.Dir, syso))
878	}
879
880	// Pack into archive in objdir directory.
881	// If the Go compiler wrote an archive, we only need to add the
882	// object files for non-Go sources to the archive.
883	// If the Go compiler wrote an archive and the package is entirely
884	// Go sources, there is no pack to execute at all.
885	if len(objects) > 0 {
886		if err := BuildToolchain.pack(b, a, objpkg, objects); err != nil {
887			return err
888		}
889	}
890
891	if err := b.updateBuildID(a, objpkg, true); err != nil {
892		return err
893	}
894
895	a.built = objpkg
896	return nil
897}
898
899func (b *Builder) cacheObjdirFile(a *Action, c *cache.Cache, name string) error {
900	f, err := os.Open(a.Objdir + name)
901	if err != nil {
902		return err
903	}
904	defer f.Close()
905	_, _, err = c.Put(cache.Subkey(a.actionID, name), f)
906	return err
907}
908
909func (b *Builder) findCachedObjdirFile(a *Action, c *cache.Cache, name string) (string, error) {
910	file, _, err := c.GetFile(cache.Subkey(a.actionID, name))
911	if err != nil {
912		return "", fmt.Errorf("loading cached file %s: %w", name, err)
913	}
914	return file, nil
915}
916
917func (b *Builder) loadCachedObjdirFile(a *Action, c *cache.Cache, name string) error {
918	cached, err := b.findCachedObjdirFile(a, c, name)
919	if err != nil {
920		return err
921	}
922	return b.copyFile(a.Objdir+name, cached, 0666, true)
923}
924
925func (b *Builder) cacheCgoHdr(a *Action) {
926	c := cache.Default()
927	b.cacheObjdirFile(a, c, "_cgo_install.h")
928}
929
930func (b *Builder) loadCachedCgoHdr(a *Action) error {
931	c := cache.Default()
932	return b.loadCachedObjdirFile(a, c, "_cgo_install.h")
933}
934
935func (b *Builder) cacheSrcFiles(a *Action, srcfiles []string) {
936	c := cache.Default()
937	var buf bytes.Buffer
938	for _, file := range srcfiles {
939		if !strings.HasPrefix(file, a.Objdir) {
940			// not generated
941			buf.WriteString("./")
942			buf.WriteString(file)
943			buf.WriteString("\n")
944			continue
945		}
946		name := file[len(a.Objdir):]
947		buf.WriteString(name)
948		buf.WriteString("\n")
949		if err := b.cacheObjdirFile(a, c, name); err != nil {
950			return
951		}
952	}
953	c.PutBytes(cache.Subkey(a.actionID, "srcfiles"), buf.Bytes())
954}
955
956func (b *Builder) loadCachedVet(a *Action) error {
957	c := cache.Default()
958	list, _, err := c.GetBytes(cache.Subkey(a.actionID, "srcfiles"))
959	if err != nil {
960		return fmt.Errorf("reading srcfiles list: %w", err)
961	}
962	var srcfiles []string
963	for _, name := range strings.Split(string(list), "\n") {
964		if name == "" { // end of list
965			continue
966		}
967		if strings.HasPrefix(name, "./") {
968			srcfiles = append(srcfiles, name[2:])
969			continue
970		}
971		if err := b.loadCachedObjdirFile(a, c, name); err != nil {
972			return err
973		}
974		srcfiles = append(srcfiles, a.Objdir+name)
975	}
976	buildVetConfig(a, srcfiles)
977	return nil
978}
979
980func (b *Builder) loadCachedSrcFiles(a *Action) error {
981	c := cache.Default()
982	list, _, err := c.GetBytes(cache.Subkey(a.actionID, "srcfiles"))
983	if err != nil {
984		return fmt.Errorf("reading srcfiles list: %w", err)
985	}
986	var files []string
987	for _, name := range strings.Split(string(list), "\n") {
988		if name == "" { // end of list
989			continue
990		}
991		if strings.HasPrefix(name, "./") {
992			files = append(files, name[len("./"):])
993			continue
994		}
995		file, err := b.findCachedObjdirFile(a, c, name)
996		if err != nil {
997			return fmt.Errorf("finding %s: %w", name, err)
998		}
999		files = append(files, file)
1000	}
1001	a.Package.CompiledGoFiles = files
1002	return nil
1003}
1004
1005// vetConfig is the configuration passed to vet describing a single package.
1006type vetConfig struct {
1007	ID           string   // package ID (example: "fmt [fmt.test]")
1008	Compiler     string   // compiler name (gc, gccgo)
1009	Dir          string   // directory containing package
1010	ImportPath   string   // canonical import path ("package path")
1011	GoFiles      []string // absolute paths to package source files
1012	NonGoFiles   []string // absolute paths to package non-Go files
1013	IgnoredFiles []string // absolute paths to ignored source files
1014
1015	ImportMap   map[string]string // map import path in source code to package path
1016	PackageFile map[string]string // map package path to .a file with export data
1017	Standard    map[string]bool   // map package path to whether it's in the standard library
1018	PackageVetx map[string]string // map package path to vetx data from earlier vet run
1019	VetxOnly    bool              // only compute vetx data; don't report detected problems
1020	VetxOutput  string            // write vetx data to this output file
1021
1022	SucceedOnTypecheckFailure bool // awful hack; see #18395 and below
1023}
1024
1025func buildVetConfig(a *Action, srcfiles []string) {
1026	// Classify files based on .go extension.
1027	// srcfiles does not include raw cgo files.
1028	var gofiles, nongofiles []string
1029	for _, name := range srcfiles {
1030		if strings.HasSuffix(name, ".go") {
1031			gofiles = append(gofiles, name)
1032		} else {
1033			nongofiles = append(nongofiles, name)
1034		}
1035	}
1036
1037	ignored := str.StringList(a.Package.IgnoredGoFiles, a.Package.IgnoredOtherFiles)
1038
1039	// Pass list of absolute paths to vet,
1040	// so that vet's error messages will use absolute paths,
1041	// so that we can reformat them relative to the directory
1042	// in which the go command is invoked.
1043	vcfg := &vetConfig{
1044		ID:           a.Package.ImportPath,
1045		Compiler:     cfg.BuildToolchainName,
1046		Dir:          a.Package.Dir,
1047		GoFiles:      mkAbsFiles(a.Package.Dir, gofiles),
1048		NonGoFiles:   mkAbsFiles(a.Package.Dir, nongofiles),
1049		IgnoredFiles: mkAbsFiles(a.Package.Dir, ignored),
1050		ImportPath:   a.Package.ImportPath,
1051		ImportMap:    make(map[string]string),
1052		PackageFile:  make(map[string]string),
1053		Standard:     make(map[string]bool),
1054	}
1055	a.vetCfg = vcfg
1056	for i, raw := range a.Package.Internal.RawImports {
1057		final := a.Package.Imports[i]
1058		vcfg.ImportMap[raw] = final
1059	}
1060
1061	// Compute the list of mapped imports in the vet config
1062	// so that we can add any missing mappings below.
1063	vcfgMapped := make(map[string]bool)
1064	for _, p := range vcfg.ImportMap {
1065		vcfgMapped[p] = true
1066	}
1067
1068	for _, a1 := range a.Deps {
1069		p1 := a1.Package
1070		if p1 == nil || p1.ImportPath == "" {
1071			continue
1072		}
1073		// Add import mapping if needed
1074		// (for imports like "runtime/cgo" that appear only in generated code).
1075		if !vcfgMapped[p1.ImportPath] {
1076			vcfg.ImportMap[p1.ImportPath] = p1.ImportPath
1077		}
1078		if a1.built != "" {
1079			vcfg.PackageFile[p1.ImportPath] = a1.built
1080		}
1081		if p1.Standard {
1082			vcfg.Standard[p1.ImportPath] = true
1083		}
1084	}
1085}
1086
1087// VetTool is the path to an alternate vet tool binary.
1088// The caller is expected to set it (if needed) before executing any vet actions.
1089var VetTool string
1090
1091// VetFlags are the default flags to pass to vet.
1092// The caller is expected to set them before executing any vet actions.
1093var VetFlags []string
1094
1095// VetExplicit records whether the vet flags were set explicitly on the command line.
1096var VetExplicit bool
1097
1098func (b *Builder) vet(ctx context.Context, a *Action) error {
1099	// a.Deps[0] is the build of the package being vetted.
1100	// a.Deps[1] is the build of the "fmt" package.
1101
1102	a.Failed = false // vet of dependency may have failed but we can still succeed
1103
1104	if a.Deps[0].Failed {
1105		// The build of the package has failed. Skip vet check.
1106		// Vet could return export data for non-typecheck errors,
1107		// but we ignore it because the package cannot be compiled.
1108		return nil
1109	}
1110
1111	vcfg := a.Deps[0].vetCfg
1112	if vcfg == nil {
1113		// Vet config should only be missing if the build failed.
1114		return fmt.Errorf("vet config not found")
1115	}
1116
1117	vcfg.VetxOnly = a.VetxOnly
1118	vcfg.VetxOutput = a.Objdir + "vet.out"
1119	vcfg.PackageVetx = make(map[string]string)
1120
1121	h := cache.NewHash("vet " + a.Package.ImportPath)
1122	fmt.Fprintf(h, "vet %q\n", b.toolID("vet"))
1123
1124	vetFlags := VetFlags
1125
1126	// In GOROOT, we enable all the vet tests during 'go test',
1127	// not just the high-confidence subset. This gets us extra
1128	// checking for the standard library (at some compliance cost)
1129	// and helps us gain experience about how well the checks
1130	// work, to help decide which should be turned on by default.
1131	// The command-line still wins.
1132	//
1133	// Note that this flag change applies even when running vet as
1134	// a dependency of vetting a package outside std.
1135	// (Otherwise we'd have to introduce a whole separate
1136	// space of "vet fmt as a dependency of a std top-level vet"
1137	// versus "vet fmt as a dependency of a non-std top-level vet".)
1138	// This is OK as long as the packages that are farther down the
1139	// dependency tree turn on *more* analysis, as here.
1140	// (The unsafeptr check does not write any facts for use by
1141	// later vet runs, nor does unreachable.)
1142	if a.Package.Goroot && !VetExplicit && VetTool == "" {
1143		// Turn off -unsafeptr checks.
1144		// There's too much unsafe.Pointer code
1145		// that vet doesn't like in low-level packages
1146		// like runtime, sync, and reflect.
1147		// Note that $GOROOT/src/buildall.bash
1148		// does the same for the misc-compile trybots
1149		// and should be updated if these flags are
1150		// changed here.
1151		vetFlags = []string{"-unsafeptr=false"}
1152
1153		// Also turn off -unreachable checks during go test.
1154		// During testing it is very common to make changes
1155		// like hard-coded forced returns or panics that make
1156		// code unreachable. It's unreasonable to insist on files
1157		// not having any unreachable code during "go test".
1158		// (buildall.bash still runs with -unreachable enabled
1159		// for the overall whole-tree scan.)
1160		if cfg.CmdName == "test" {
1161			vetFlags = append(vetFlags, "-unreachable=false")
1162		}
1163	}
1164
1165	// Note: We could decide that vet should compute export data for
1166	// all analyses, in which case we don't need to include the flags here.
1167	// But that would mean that if an analysis causes problems like
1168	// unexpected crashes there would be no way to turn it off.
1169	// It seems better to let the flags disable export analysis too.
1170	fmt.Fprintf(h, "vetflags %q\n", vetFlags)
1171
1172	fmt.Fprintf(h, "pkg %q\n", a.Deps[0].actionID)
1173	for _, a1 := range a.Deps {
1174		if a1.Mode == "vet" && a1.built != "" {
1175			fmt.Fprintf(h, "vetout %q %s\n", a1.Package.ImportPath, b.fileHash(a1.built))
1176			vcfg.PackageVetx[a1.Package.ImportPath] = a1.built
1177		}
1178	}
1179	key := cache.ActionID(h.Sum())
1180
1181	if vcfg.VetxOnly && !cfg.BuildA {
1182		c := cache.Default()
1183		if file, _, err := c.GetFile(key); err == nil {
1184			a.built = file
1185			return nil
1186		}
1187	}
1188
1189	js, err := json.MarshalIndent(vcfg, "", "\t")
1190	if err != nil {
1191		return fmt.Errorf("internal error marshaling vet config: %v", err)
1192	}
1193	js = append(js, '\n')
1194	if err := b.writeFile(a.Objdir+"vet.cfg", js); err != nil {
1195		return err
1196	}
1197
1198	// TODO(rsc): Why do we pass $GCCGO to go vet?
1199	env := b.cCompilerEnv()
1200	if cfg.BuildToolchainName == "gccgo" {
1201		env = append(env, "GCCGO="+BuildToolchain.compiler())
1202	}
1203
1204	p := a.Package
1205	tool := VetTool
1206	if tool == "" {
1207		tool = base.Tool("vet")
1208	}
1209	runErr := b.run(a, p.Dir, p.ImportPath, env, cfg.BuildToolexec, tool, vetFlags, a.Objdir+"vet.cfg")
1210
1211	// If vet wrote export data, save it for input to future vets.
1212	if f, err := os.Open(vcfg.VetxOutput); err == nil {
1213		a.built = vcfg.VetxOutput
1214		cache.Default().Put(key, f)
1215		f.Close()
1216	}
1217
1218	return runErr
1219}
1220
1221// linkActionID computes the action ID for a link action.
1222func (b *Builder) linkActionID(a *Action) cache.ActionID {
1223	p := a.Package
1224	h := cache.NewHash("link " + p.ImportPath)
1225
1226	// Toolchain-independent configuration.
1227	fmt.Fprintf(h, "link\n")
1228	fmt.Fprintf(h, "buildmode %s goos %s goarch %s\n", cfg.BuildBuildmode, cfg.Goos, cfg.Goarch)
1229	fmt.Fprintf(h, "import %q\n", p.ImportPath)
1230	fmt.Fprintf(h, "omitdebug %v standard %v local %v prefix %q\n", p.Internal.OmitDebug, p.Standard, p.Internal.Local, p.Internal.LocalPrefix)
1231	if cfg.BuildTrimpath {
1232		fmt.Fprintln(h, "trimpath")
1233	}
1234
1235	// Toolchain-dependent configuration, shared with b.linkSharedActionID.
1236	b.printLinkerConfig(h, p)
1237
1238	// Input files.
1239	for _, a1 := range a.Deps {
1240		p1 := a1.Package
1241		if p1 != nil {
1242			if a1.built != "" || a1.buildID != "" {
1243				buildID := a1.buildID
1244				if buildID == "" {
1245					buildID = b.buildID(a1.built)
1246				}
1247				fmt.Fprintf(h, "packagefile %s=%s\n", p1.ImportPath, contentID(buildID))
1248			}
1249			// Because we put package main's full action ID into the binary's build ID,
1250			// we must also put the full action ID into the binary's action ID hash.
1251			if p1.Name == "main" {
1252				fmt.Fprintf(h, "packagemain %s\n", a1.buildID)
1253			}
1254			if p1.Shlib != "" {
1255				fmt.Fprintf(h, "packageshlib %s=%s\n", p1.ImportPath, contentID(b.buildID(p1.Shlib)))
1256			}
1257		}
1258	}
1259
1260	return h.Sum()
1261}
1262
1263// printLinkerConfig prints the linker config into the hash h,
1264// as part of the computation of a linker-related action ID.
1265func (b *Builder) printLinkerConfig(h io.Writer, p *load.Package) {
1266	switch cfg.BuildToolchainName {
1267	default:
1268		base.Fatalf("linkActionID: unknown toolchain %q", cfg.BuildToolchainName)
1269
1270	case "gc":
1271		fmt.Fprintf(h, "link %s %q %s\n", b.toolID("link"), forcedLdflags, ldBuildmode)
1272		if p != nil {
1273			fmt.Fprintf(h, "linkflags %q\n", p.Internal.Ldflags)
1274		}
1275
1276		// GOARM, GOMIPS, etc.
1277		key, val := cfg.GetArchEnv()
1278		fmt.Fprintf(h, "%s=%s\n", key, val)
1279
1280		if goexperiment := buildcfg.GOEXPERIMENT(); goexperiment != "" {
1281			fmt.Fprintf(h, "GOEXPERIMENT=%q\n", goexperiment)
1282		}
1283
1284		// The linker writes source file paths that say GOROOT_FINAL, but
1285		// only if -trimpath is not specified (see ld() in gc.go).
1286		gorootFinal := cfg.GOROOT_FINAL
1287		if cfg.BuildTrimpath {
1288			gorootFinal = trimPathGoRootFinal
1289		}
1290		fmt.Fprintf(h, "GOROOT=%s\n", gorootFinal)
1291
1292		// GO_EXTLINK_ENABLED controls whether the external linker is used.
1293		fmt.Fprintf(h, "GO_EXTLINK_ENABLED=%s\n", cfg.Getenv("GO_EXTLINK_ENABLED"))
1294
1295		// TODO(rsc): Do cgo settings and flags need to be included?
1296		// Or external linker settings and flags?
1297
1298	case "gccgo":
1299		id, err := b.gccToolID(BuildToolchain.linker(), "go")
1300		if err != nil {
1301			base.Fatalf("%v", err)
1302		}
1303		fmt.Fprintf(h, "link %s %s\n", id, ldBuildmode)
1304		// TODO(iant): Should probably include cgo flags here.
1305	}
1306}
1307
1308// link is the action for linking a single command.
1309// Note that any new influence on this logic must be reported in b.linkActionID above as well.
1310func (b *Builder) link(ctx context.Context, a *Action) (err error) {
1311	if b.useCache(a, b.linkActionID(a), a.Package.Target) || b.IsCmdList {
1312		return nil
1313	}
1314	defer b.flushOutput(a)
1315
1316	if err := b.Mkdir(a.Objdir); err != nil {
1317		return err
1318	}
1319
1320	importcfg := a.Objdir + "importcfg.link"
1321	if err := b.writeLinkImportcfg(a, importcfg); err != nil {
1322		return err
1323	}
1324
1325	if err := allowInstall(a); err != nil {
1326		return err
1327	}
1328
1329	// make target directory
1330	dir, _ := filepath.Split(a.Target)
1331	if dir != "" {
1332		if err := b.Mkdir(dir); err != nil {
1333			return err
1334		}
1335	}
1336
1337	if err := BuildToolchain.ld(b, a, a.Target, importcfg, a.Deps[0].built); err != nil {
1338		return err
1339	}
1340
1341	// Update the binary with the final build ID.
1342	// But if OmitDebug is set, don't rewrite the binary, because we set OmitDebug
1343	// on binaries that we are going to run and then delete.
1344	// There's no point in doing work on such a binary.
1345	// Worse, opening the binary for write here makes it
1346	// essentially impossible to safely fork+exec due to a fundamental
1347	// incompatibility between ETXTBSY and threads on modern Unix systems.
1348	// See golang.org/issue/22220.
1349	// We still call updateBuildID to update a.buildID, which is important
1350	// for test result caching, but passing rewrite=false (final arg)
1351	// means we don't actually rewrite the binary, nor store the
1352	// result into the cache. That's probably a net win:
1353	// less cache space wasted on large binaries we are not likely to
1354	// need again. (On the other hand it does make repeated go test slower.)
1355	// It also makes repeated go run slower, which is a win in itself:
1356	// we don't want people to treat go run like a scripting environment.
1357	if err := b.updateBuildID(a, a.Target, !a.Package.Internal.OmitDebug); err != nil {
1358		return err
1359	}
1360
1361	a.built = a.Target
1362	return nil
1363}
1364
1365func (b *Builder) writeLinkImportcfg(a *Action, file string) error {
1366	// Prepare Go import cfg.
1367	var icfg bytes.Buffer
1368	for _, a1 := range a.Deps {
1369		p1 := a1.Package
1370		if p1 == nil {
1371			continue
1372		}
1373		fmt.Fprintf(&icfg, "packagefile %s=%s\n", p1.ImportPath, a1.built)
1374		if p1.Shlib != "" {
1375			fmt.Fprintf(&icfg, "packageshlib %s=%s\n", p1.ImportPath, p1.Shlib)
1376		}
1377	}
1378	return b.writeFile(file, icfg.Bytes())
1379}
1380
1381// PkgconfigCmd returns a pkg-config binary name
1382// defaultPkgConfig is defined in zdefaultcc.go, written by cmd/dist.
1383func (b *Builder) PkgconfigCmd() string {
1384	return envList("PKG_CONFIG", cfg.DefaultPkgConfig)[0]
1385}
1386
1387// splitPkgConfigOutput parses the pkg-config output into a slice of
1388// flags. This implements the algorithm from pkgconf/libpkgconf/argvsplit.c.
1389func splitPkgConfigOutput(out []byte) ([]string, error) {
1390	if len(out) == 0 {
1391		return nil, nil
1392	}
1393	var flags []string
1394	flag := make([]byte, 0, len(out))
1395	escaped := false
1396	quote := byte(0)
1397
1398	for _, c := range out {
1399		if escaped {
1400			if quote != 0 {
1401				switch c {
1402				case '$', '`', '"', '\\':
1403				default:
1404					flag = append(flag, '\\')
1405				}
1406				flag = append(flag, c)
1407			} else {
1408				flag = append(flag, c)
1409			}
1410			escaped = false
1411		} else if quote != 0 {
1412			if c == quote {
1413				quote = 0
1414			} else {
1415				switch c {
1416				case '\\':
1417					escaped = true
1418				default:
1419					flag = append(flag, c)
1420				}
1421			}
1422		} else if strings.IndexByte(" \t\n\v\f\r", c) < 0 {
1423			switch c {
1424			case '\\':
1425				escaped = true
1426			case '\'', '"':
1427				quote = c
1428			default:
1429				flag = append(flag, c)
1430			}
1431		} else if len(flag) != 0 {
1432			flags = append(flags, string(flag))
1433			flag = flag[:0]
1434		}
1435	}
1436	if escaped {
1437		return nil, errors.New("broken character escaping in pkgconf output ")
1438	}
1439	if quote != 0 {
1440		return nil, errors.New("unterminated quoted string in pkgconf output ")
1441	} else if len(flag) != 0 {
1442		flags = append(flags, string(flag))
1443	}
1444
1445	return flags, nil
1446}
1447
1448// Calls pkg-config if needed and returns the cflags/ldflags needed to build the package.
1449func (b *Builder) getPkgConfigFlags(p *load.Package) (cflags, ldflags []string, err error) {
1450	if pcargs := p.CgoPkgConfig; len(pcargs) > 0 {
1451		// pkg-config permits arguments to appear anywhere in
1452		// the command line. Move them all to the front, before --.
1453		var pcflags []string
1454		var pkgs []string
1455		for _, pcarg := range pcargs {
1456			if pcarg == "--" {
1457				// We're going to add our own "--" argument.
1458			} else if strings.HasPrefix(pcarg, "--") {
1459				pcflags = append(pcflags, pcarg)
1460			} else {
1461				pkgs = append(pkgs, pcarg)
1462			}
1463		}
1464		for _, pkg := range pkgs {
1465			if !load.SafeArg(pkg) {
1466				return nil, nil, fmt.Errorf("invalid pkg-config package name: %s", pkg)
1467			}
1468		}
1469		var out []byte
1470		out, err = b.runOut(nil, p.Dir, nil, b.PkgconfigCmd(), "--cflags", pcflags, "--", pkgs)
1471		if err != nil {
1472			b.showOutput(nil, p.Dir, b.PkgconfigCmd()+" --cflags "+strings.Join(pcflags, " ")+" -- "+strings.Join(pkgs, " "), string(out))
1473			b.Print(err.Error() + "\n")
1474			return nil, nil, errPrintedOutput
1475		}
1476		if len(out) > 0 {
1477			cflags, err = splitPkgConfigOutput(out)
1478			if err != nil {
1479				return nil, nil, err
1480			}
1481			if err := checkCompilerFlags("CFLAGS", "pkg-config --cflags", cflags); err != nil {
1482				return nil, nil, err
1483			}
1484		}
1485		out, err = b.runOut(nil, p.Dir, nil, b.PkgconfigCmd(), "--libs", pcflags, "--", pkgs)
1486		if err != nil {
1487			b.showOutput(nil, p.Dir, b.PkgconfigCmd()+" --libs "+strings.Join(pcflags, " ")+" -- "+strings.Join(pkgs, " "), string(out))
1488			b.Print(err.Error() + "\n")
1489			return nil, nil, errPrintedOutput
1490		}
1491		if len(out) > 0 {
1492			ldflags = strings.Fields(string(out))
1493			if err := checkLinkerFlags("LDFLAGS", "pkg-config --libs", ldflags); err != nil {
1494				return nil, nil, err
1495			}
1496		}
1497	}
1498
1499	return
1500}
1501
1502func (b *Builder) installShlibname(ctx context.Context, a *Action) error {
1503	if err := allowInstall(a); err != nil {
1504		return err
1505	}
1506
1507	// TODO: BuildN
1508	a1 := a.Deps[0]
1509	err := os.WriteFile(a.Target, []byte(filepath.Base(a1.Target)+"\n"), 0666)
1510	if err != nil {
1511		return err
1512	}
1513	if cfg.BuildX {
1514		b.Showcmd("", "echo '%s' > %s # internal", filepath.Base(a1.Target), a.Target)
1515	}
1516	return nil
1517}
1518
1519func (b *Builder) linkSharedActionID(a *Action) cache.ActionID {
1520	h := cache.NewHash("linkShared")
1521
1522	// Toolchain-independent configuration.
1523	fmt.Fprintf(h, "linkShared\n")
1524	fmt.Fprintf(h, "goos %s goarch %s\n", cfg.Goos, cfg.Goarch)
1525
1526	// Toolchain-dependent configuration, shared with b.linkActionID.
1527	b.printLinkerConfig(h, nil)
1528
1529	// Input files.
1530	for _, a1 := range a.Deps {
1531		p1 := a1.Package
1532		if a1.built == "" {
1533			continue
1534		}
1535		if p1 != nil {
1536			fmt.Fprintf(h, "packagefile %s=%s\n", p1.ImportPath, contentID(b.buildID(a1.built)))
1537			if p1.Shlib != "" {
1538				fmt.Fprintf(h, "packageshlib %s=%s\n", p1.ImportPath, contentID(b.buildID(p1.Shlib)))
1539			}
1540		}
1541	}
1542	// Files named on command line are special.
1543	for _, a1 := range a.Deps[0].Deps {
1544		p1 := a1.Package
1545		fmt.Fprintf(h, "top %s=%s\n", p1.ImportPath, contentID(b.buildID(a1.built)))
1546	}
1547
1548	return h.Sum()
1549}
1550
1551func (b *Builder) linkShared(ctx context.Context, a *Action) (err error) {
1552	if b.useCache(a, b.linkSharedActionID(a), a.Target) || b.IsCmdList {
1553		return nil
1554	}
1555	defer b.flushOutput(a)
1556
1557	if err := allowInstall(a); err != nil {
1558		return err
1559	}
1560
1561	if err := b.Mkdir(a.Objdir); err != nil {
1562		return err
1563	}
1564
1565	importcfg := a.Objdir + "importcfg.link"
1566	if err := b.writeLinkImportcfg(a, importcfg); err != nil {
1567		return err
1568	}
1569
1570	// TODO(rsc): There is a missing updateBuildID here,
1571	// but we have to decide where to store the build ID in these files.
1572	a.built = a.Target
1573	return BuildToolchain.ldShared(b, a, a.Deps[0].Deps, a.Target, importcfg, a.Deps)
1574}
1575
1576// BuildInstallFunc is the action for installing a single package or executable.
1577func BuildInstallFunc(b *Builder, ctx context.Context, a *Action) (err error) {
1578	defer func() {
1579		if err != nil && err != errPrintedOutput {
1580			// a.Package == nil is possible for the go install -buildmode=shared
1581			// action that installs libmangledname.so, which corresponds to
1582			// a list of packages, not just one.
1583			sep, path := "", ""
1584			if a.Package != nil {
1585				sep, path = " ", a.Package.ImportPath
1586			}
1587			err = fmt.Errorf("go %s%s%s: %v", cfg.CmdName, sep, path, err)
1588		}
1589	}()
1590
1591	a1 := a.Deps[0]
1592	a.buildID = a1.buildID
1593	if a.json != nil {
1594		a.json.BuildID = a.buildID
1595	}
1596
1597	// If we are using the eventual install target as an up-to-date
1598	// cached copy of the thing we built, then there's no need to
1599	// copy it into itself (and that would probably fail anyway).
1600	// In this case a1.built == a.Target because a1.built == p.Target,
1601	// so the built target is not in the a1.Objdir tree that b.cleanup(a1) removes.
1602	if a1.built == a.Target {
1603		a.built = a.Target
1604		if !a.buggyInstall {
1605			b.cleanup(a1)
1606		}
1607		// Whether we're smart enough to avoid a complete rebuild
1608		// depends on exactly what the staleness and rebuild algorithms
1609		// are, as well as potentially the state of the Go build cache.
1610		// We don't really want users to be able to infer (or worse start depending on)
1611		// those details from whether the modification time changes during
1612		// "go install", so do a best-effort update of the file times to make it
1613		// look like we rewrote a.Target even if we did not. Updating the mtime
1614		// may also help other mtime-based systems that depend on our
1615		// previous mtime updates that happened more often.
1616		// This is still not perfect - we ignore the error result, and if the file was
1617		// unwritable for some reason then pretending to have written it is also
1618		// confusing - but it's probably better than not doing the mtime update.
1619		//
1620		// But don't do that for the special case where building an executable
1621		// with -linkshared implicitly installs all its dependent libraries.
1622		// We want to hide that awful detail as much as possible, so don't
1623		// advertise it by touching the mtimes (usually the libraries are up
1624		// to date).
1625		if !a.buggyInstall && !b.IsCmdList {
1626			if cfg.BuildN {
1627				b.Showcmd("", "touch %s", a.Target)
1628			} else if err := allowInstall(a); err == nil {
1629				now := time.Now()
1630				os.Chtimes(a.Target, now, now)
1631			}
1632		}
1633		return nil
1634	}
1635
1636	// If we're building for go list -export,
1637	// never install anything; just keep the cache reference.
1638	if b.IsCmdList {
1639		a.built = a1.built
1640		return nil
1641	}
1642	if err := allowInstall(a); err != nil {
1643		return err
1644	}
1645
1646	if err := b.Mkdir(a.Objdir); err != nil {
1647		return err
1648	}
1649
1650	perm := fs.FileMode(0666)
1651	if a1.Mode == "link" {
1652		switch cfg.BuildBuildmode {
1653		case "c-archive", "c-shared", "plugin":
1654		default:
1655			perm = 0777
1656		}
1657	}
1658
1659	// make target directory
1660	dir, _ := filepath.Split(a.Target)
1661	if dir != "" {
1662		if err := b.Mkdir(dir); err != nil {
1663			return err
1664		}
1665	}
1666
1667	if !a.buggyInstall {
1668		defer b.cleanup(a1)
1669	}
1670
1671	return b.moveOrCopyFile(a.Target, a1.built, perm, false)
1672}
1673
1674// allowInstall returns a non-nil error if this invocation of the go command is
1675// allowed to install a.Target.
1676//
1677// (The build of cmd/go running under its own test is forbidden from installing
1678// to its original GOROOT.)
1679var allowInstall = func(*Action) error { return nil }
1680
1681// cleanup removes a's object dir to keep the amount of
1682// on-disk garbage down in a large build. On an operating system
1683// with aggressive buffering, cleaning incrementally like
1684// this keeps the intermediate objects from hitting the disk.
1685func (b *Builder) cleanup(a *Action) {
1686	if !cfg.BuildWork {
1687		if cfg.BuildX {
1688			// Don't say we are removing the directory if
1689			// we never created it.
1690			if _, err := os.Stat(a.Objdir); err == nil || cfg.BuildN {
1691				b.Showcmd("", "rm -r %s", a.Objdir)
1692			}
1693		}
1694		os.RemoveAll(a.Objdir)
1695	}
1696}
1697
1698// moveOrCopyFile is like 'mv src dst' or 'cp src dst'.
1699func (b *Builder) moveOrCopyFile(dst, src string, perm fs.FileMode, force bool) error {
1700	if cfg.BuildN {
1701		b.Showcmd("", "mv %s %s", src, dst)
1702		return nil
1703	}
1704
1705	// If we can update the mode and rename to the dst, do it.
1706	// Otherwise fall back to standard copy.
1707
1708	// If the source is in the build cache, we need to copy it.
1709	if strings.HasPrefix(src, cache.DefaultDir()) {
1710		return b.copyFile(dst, src, perm, force)
1711	}
1712
1713	// On Windows, always copy the file, so that we respect the NTFS
1714	// permissions of the parent folder. https://golang.org/issue/22343.
1715	// What matters here is not cfg.Goos (the system we are building
1716	// for) but runtime.GOOS (the system we are building on).
1717	if runtime.GOOS == "windows" {
1718		return b.copyFile(dst, src, perm, force)
1719	}
1720
1721	// If the destination directory has the group sticky bit set,
1722	// we have to copy the file to retain the correct permissions.
1723	// https://golang.org/issue/18878
1724	if fi, err := os.Stat(filepath.Dir(dst)); err == nil {
1725		if fi.IsDir() && (fi.Mode()&fs.ModeSetgid) != 0 {
1726			return b.copyFile(dst, src, perm, force)
1727		}
1728	}
1729
1730	// The perm argument is meant to be adjusted according to umask,
1731	// but we don't know what the umask is.
1732	// Create a dummy file to find out.
1733	// This avoids build tags and works even on systems like Plan 9
1734	// where the file mask computation incorporates other information.
1735	mode := perm
1736	f, err := os.OpenFile(filepath.Clean(dst)+"-go-tmp-umask", os.O_WRONLY|os.O_CREATE|os.O_EXCL, perm)
1737	if err == nil {
1738		fi, err := f.Stat()
1739		if err == nil {
1740			mode = fi.Mode() & 0777
1741		}
1742		name := f.Name()
1743		f.Close()
1744		os.Remove(name)
1745	}
1746
1747	if err := os.Chmod(src, mode); err == nil {
1748		if err := os.Rename(src, dst); err == nil {
1749			if cfg.BuildX {
1750				b.Showcmd("", "mv %s %s", src, dst)
1751			}
1752			return nil
1753		}
1754	}
1755
1756	return b.copyFile(dst, src, perm, force)
1757}
1758
1759// copyFile is like 'cp src dst'.
1760func (b *Builder) copyFile(dst, src string, perm fs.FileMode, force bool) error {
1761	if cfg.BuildN || cfg.BuildX {
1762		b.Showcmd("", "cp %s %s", src, dst)
1763		if cfg.BuildN {
1764			return nil
1765		}
1766	}
1767
1768	sf, err := os.Open(src)
1769	if err != nil {
1770		return err
1771	}
1772	defer sf.Close()
1773
1774	// Be careful about removing/overwriting dst.
1775	// Do not remove/overwrite if dst exists and is a directory
1776	// or a non-empty non-object file.
1777	if fi, err := os.Stat(dst); err == nil {
1778		if fi.IsDir() {
1779			return fmt.Errorf("build output %q already exists and is a directory", dst)
1780		}
1781		if !force && fi.Mode().IsRegular() && fi.Size() != 0 && !isObject(dst) {
1782			return fmt.Errorf("build output %q already exists and is not an object file", dst)
1783		}
1784	}
1785
1786	// On Windows, remove lingering ~ file from last attempt.
1787	if base.ToolIsWindows {
1788		if _, err := os.Stat(dst + "~"); err == nil {
1789			os.Remove(dst + "~")
1790		}
1791	}
1792
1793	mayberemovefile(dst)
1794	df, err := os.OpenFile(dst, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, perm)
1795	if err != nil && base.ToolIsWindows {
1796		// Windows does not allow deletion of a binary file
1797		// while it is executing. Try to move it out of the way.
1798		// If the move fails, which is likely, we'll try again the
1799		// next time we do an install of this binary.
1800		if err := os.Rename(dst, dst+"~"); err == nil {
1801			os.Remove(dst + "~")
1802		}
1803		df, err = os.OpenFile(dst, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, perm)
1804	}
1805	if err != nil {
1806		return fmt.Errorf("copying %s: %w", src, err) // err should already refer to dst
1807	}
1808
1809	_, err = io.Copy(df, sf)
1810	df.Close()
1811	if err != nil {
1812		mayberemovefile(dst)
1813		return fmt.Errorf("copying %s to %s: %v", src, dst, err)
1814	}
1815	return nil
1816}
1817
1818// writeFile writes the text to file.
1819func (b *Builder) writeFile(file string, text []byte) error {
1820	if cfg.BuildN || cfg.BuildX {
1821		b.Showcmd("", "cat >%s << 'EOF' # internal\n%sEOF", file, text)
1822	}
1823	if cfg.BuildN {
1824		return nil
1825	}
1826	return os.WriteFile(file, text, 0666)
1827}
1828
1829// Install the cgo export header file, if there is one.
1830func (b *Builder) installHeader(ctx context.Context, a *Action) error {
1831	src := a.Objdir + "_cgo_install.h"
1832	if _, err := os.Stat(src); os.IsNotExist(err) {
1833		// If the file does not exist, there are no exported
1834		// functions, and we do not install anything.
1835		// TODO(rsc): Once we know that caching is rebuilding
1836		// at the right times (not missing rebuilds), here we should
1837		// probably delete the installed header, if any.
1838		if cfg.BuildX {
1839			b.Showcmd("", "# %s not created", src)
1840		}
1841		return nil
1842	}
1843
1844	if err := allowInstall(a); err != nil {
1845		return err
1846	}
1847
1848	dir, _ := filepath.Split(a.Target)
1849	if dir != "" {
1850		if err := b.Mkdir(dir); err != nil {
1851			return err
1852		}
1853	}
1854
1855	return b.moveOrCopyFile(a.Target, src, 0666, true)
1856}
1857
1858// cover runs, in effect,
1859//	go tool cover -mode=b.coverMode -var="varName" -o dst.go src.go
1860func (b *Builder) cover(a *Action, dst, src string, varName string) error {
1861	return b.run(a, a.Objdir, "cover "+a.Package.ImportPath, nil,
1862		cfg.BuildToolexec,
1863		base.Tool("cover"),
1864		"-mode", a.Package.Internal.CoverMode,
1865		"-var", varName,
1866		"-o", dst,
1867		src)
1868}
1869
1870var objectMagic = [][]byte{
1871	{'!', '<', 'a', 'r', 'c', 'h', '>', '\n'}, // Package archive
1872	{'<', 'b', 'i', 'g', 'a', 'f', '>', '\n'}, // Package AIX big archive
1873	{'\x7F', 'E', 'L', 'F'},                   // ELF
1874	{0xFE, 0xED, 0xFA, 0xCE},                  // Mach-O big-endian 32-bit
1875	{0xFE, 0xED, 0xFA, 0xCF},                  // Mach-O big-endian 64-bit
1876	{0xCE, 0xFA, 0xED, 0xFE},                  // Mach-O little-endian 32-bit
1877	{0xCF, 0xFA, 0xED, 0xFE},                  // Mach-O little-endian 64-bit
1878	{0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00},      // PE (Windows) as generated by 6l/8l and gcc
1879	{0x4d, 0x5a, 0x78, 0x00, 0x01, 0x00},      // PE (Windows) as generated by llvm for dll
1880	{0x00, 0x00, 0x01, 0xEB},                  // Plan 9 i386
1881	{0x00, 0x00, 0x8a, 0x97},                  // Plan 9 amd64
1882	{0x00, 0x00, 0x06, 0x47},                  // Plan 9 arm
1883	{0x00, 0x61, 0x73, 0x6D},                  // WASM
1884	{0x01, 0xDF},                              // XCOFF 32bit
1885	{0x01, 0xF7},                              // XCOFF 64bit
1886}
1887
1888func isObject(s string) bool {
1889	f, err := os.Open(s)
1890	if err != nil {
1891		return false
1892	}
1893	defer f.Close()
1894	buf := make([]byte, 64)
1895	io.ReadFull(f, buf)
1896	for _, magic := range objectMagic {
1897		if bytes.HasPrefix(buf, magic) {
1898			return true
1899		}
1900	}
1901	return false
1902}
1903
1904// mayberemovefile removes a file only if it is a regular file
1905// When running as a user with sufficient privileges, we may delete
1906// even device files, for example, which is not intended.
1907func mayberemovefile(s string) {
1908	if fi, err := os.Lstat(s); err == nil && !fi.Mode().IsRegular() {
1909		return
1910	}
1911	os.Remove(s)
1912}
1913
1914// fmtcmd formats a command in the manner of fmt.Sprintf but also:
1915//
1916//	If dir is non-empty and the script is not in dir right now,
1917//	fmtcmd inserts "cd dir\n" before the command.
1918//
1919//	fmtcmd replaces the value of b.WorkDir with $WORK.
1920//	fmtcmd replaces the value of goroot with $GOROOT.
1921//	fmtcmd replaces the value of b.gobin with $GOBIN.
1922//
1923//	fmtcmd replaces the name of the current directory with dot (.)
1924//	but only when it is at the beginning of a space-separated token.
1925//
1926func (b *Builder) fmtcmd(dir string, format string, args ...interface{}) string {
1927	cmd := fmt.Sprintf(format, args...)
1928	if dir != "" && dir != "/" {
1929		dot := " ."
1930		if dir[len(dir)-1] == filepath.Separator {
1931			dot += string(filepath.Separator)
1932		}
1933		cmd = strings.ReplaceAll(" "+cmd, " "+dir, dot)[1:]
1934		if b.scriptDir != dir {
1935			b.scriptDir = dir
1936			cmd = "cd " + dir + "\n" + cmd
1937		}
1938	}
1939	if b.WorkDir != "" {
1940		cmd = strings.ReplaceAll(cmd, b.WorkDir, "$WORK")
1941		escaped := strconv.Quote(b.WorkDir)
1942		escaped = escaped[1 : len(escaped)-1] // strip quote characters
1943		if escaped != b.WorkDir {
1944			cmd = strings.ReplaceAll(cmd, escaped, "$WORK")
1945		}
1946	}
1947	return cmd
1948}
1949
1950// showcmd prints the given command to standard output
1951// for the implementation of -n or -x.
1952func (b *Builder) Showcmd(dir string, format string, args ...interface{}) {
1953	b.output.Lock()
1954	defer b.output.Unlock()
1955	b.Print(b.fmtcmd(dir, format, args...) + "\n")
1956}
1957
1958// showOutput prints "# desc" followed by the given output.
1959// The output is expected to contain references to 'dir', usually
1960// the source directory for the package that has failed to build.
1961// showOutput rewrites mentions of dir with a relative path to dir
1962// when the relative path is shorter. This is usually more pleasant.
1963// For example, if fmt doesn't compile and we are in src/html,
1964// the output is
1965//
1966//	$ go build
1967//	# fmt
1968//	../fmt/print.go:1090: undefined: asdf
1969//	$
1970//
1971// instead of
1972//
1973//	$ go build
1974//	# fmt
1975//	/usr/gopher/go/src/fmt/print.go:1090: undefined: asdf
1976//	$
1977//
1978// showOutput also replaces references to the work directory with $WORK.
1979//
1980// If a is not nil and a.output is not nil, showOutput appends to that slice instead of
1981// printing to b.Print.
1982//
1983func (b *Builder) showOutput(a *Action, dir, desc, out string) {
1984	prefix := "# " + desc
1985	suffix := "\n" + out
1986	if reldir := base.ShortPath(dir); reldir != dir {
1987		suffix = strings.ReplaceAll(suffix, " "+dir, " "+reldir)
1988		suffix = strings.ReplaceAll(suffix, "\n"+dir, "\n"+reldir)
1989	}
1990	suffix = strings.ReplaceAll(suffix, " "+b.WorkDir, " $WORK")
1991
1992	if a != nil && a.output != nil {
1993		a.output = append(a.output, prefix...)
1994		a.output = append(a.output, suffix...)
1995		return
1996	}
1997
1998	b.output.Lock()
1999	defer b.output.Unlock()
2000	b.Print(prefix, suffix)
2001}
2002
2003// errPrintedOutput is a special error indicating that a command failed
2004// but that it generated output as well, and that output has already
2005// been printed, so there's no point showing 'exit status 1' or whatever
2006// the wait status was. The main executor, builder.do, knows not to
2007// print this error.
2008var errPrintedOutput = errors.New("already printed output - no need to show error")
2009
2010var cgoLine = lazyregexp.New(`\[[^\[\]]+\.(cgo1|cover)\.go:[0-9]+(:[0-9]+)?\]`)
2011var cgoTypeSigRe = lazyregexp.New(`\b_C2?(type|func|var|macro)_\B`)
2012
2013// run runs the command given by cmdline in the directory dir.
2014// If the command fails, run prints information about the failure
2015// and returns a non-nil error.
2016func (b *Builder) run(a *Action, dir string, desc string, env []string, cmdargs ...interface{}) error {
2017	out, err := b.runOut(a, dir, env, cmdargs...)
2018	if len(out) > 0 {
2019		if desc == "" {
2020			desc = b.fmtcmd(dir, "%s", strings.Join(str.StringList(cmdargs...), " "))
2021		}
2022		b.showOutput(a, dir, desc, b.processOutput(out))
2023		if err != nil {
2024			err = errPrintedOutput
2025		}
2026	}
2027	return err
2028}
2029
2030// processOutput prepares the output of runOut to be output to the console.
2031func (b *Builder) processOutput(out []byte) string {
2032	if out[len(out)-1] != '\n' {
2033		out = append(out, '\n')
2034	}
2035	messages := string(out)
2036	// Fix up output referring to cgo-generated code to be more readable.
2037	// Replace x.go:19[/tmp/.../x.cgo1.go:18] with x.go:19.
2038	// Replace *[100]_Ctype_foo with *[100]C.foo.
2039	// If we're using -x, assume we're debugging and want the full dump, so disable the rewrite.
2040	if !cfg.BuildX && cgoLine.MatchString(messages) {
2041		messages = cgoLine.ReplaceAllString(messages, "")
2042		messages = cgoTypeSigRe.ReplaceAllString(messages, "C.")
2043	}
2044	return messages
2045}
2046
2047// runOut runs the command given by cmdline in the directory dir.
2048// It returns the command output and any errors that occurred.
2049// It accumulates execution time in a.
2050func (b *Builder) runOut(a *Action, dir string, env []string, cmdargs ...interface{}) ([]byte, error) {
2051	cmdline := str.StringList(cmdargs...)
2052
2053	for _, arg := range cmdline {
2054		// GNU binutils commands, including gcc and gccgo, interpret an argument
2055		// @foo anywhere in the command line (even following --) as meaning
2056		// "read and insert arguments from the file named foo."
2057		// Don't say anything that might be misinterpreted that way.
2058		if strings.HasPrefix(arg, "@") {
2059			return nil, fmt.Errorf("invalid command-line argument %s in command: %s", arg, joinUnambiguously(cmdline))
2060		}
2061	}
2062
2063	if cfg.BuildN || cfg.BuildX {
2064		var envcmdline string
2065		for _, e := range env {
2066			if j := strings.IndexByte(e, '='); j != -1 {
2067				if strings.ContainsRune(e[j+1:], '\'') {
2068					envcmdline += fmt.Sprintf("%s=%q", e[:j], e[j+1:])
2069				} else {
2070					envcmdline += fmt.Sprintf("%s='%s'", e[:j], e[j+1:])
2071				}
2072				envcmdline += " "
2073			}
2074		}
2075		envcmdline += joinUnambiguously(cmdline)
2076		b.Showcmd(dir, "%s", envcmdline)
2077		if cfg.BuildN {
2078			return nil, nil
2079		}
2080	}
2081
2082	var buf bytes.Buffer
2083	cmd := exec.Command(cmdline[0], cmdline[1:]...)
2084	if cmd.Path != "" {
2085		cmd.Args[0] = cmd.Path
2086	}
2087	cmd.Stdout = &buf
2088	cmd.Stderr = &buf
2089	cleanup := passLongArgsInResponseFiles(cmd)
2090	defer cleanup()
2091	cmd.Dir = dir
2092	cmd.Env = base.AppendPWD(os.Environ(), cmd.Dir)
2093
2094	// Add the TOOLEXEC_IMPORTPATH environment variable for -toolexec tools.
2095	// It doesn't really matter if -toolexec isn't being used.
2096	// Note that a.Package.Desc is not really an import path,
2097	// but this is consistent with 'go list -f {{.ImportPath}}'.
2098	// Plus, it is useful to uniquely identify packages in 'go list -json'.
2099	if a != nil && a.Package != nil {
2100		cmd.Env = append(cmd.Env, "TOOLEXEC_IMPORTPATH="+a.Package.Desc())
2101	}
2102
2103	cmd.Env = append(cmd.Env, env...)
2104	start := time.Now()
2105	err := cmd.Run()
2106	if a != nil && a.json != nil {
2107		aj := a.json
2108		aj.Cmd = append(aj.Cmd, joinUnambiguously(cmdline))
2109		aj.CmdReal += time.Since(start)
2110		if ps := cmd.ProcessState; ps != nil {
2111			aj.CmdUser += ps.UserTime()
2112			aj.CmdSys += ps.SystemTime()
2113		}
2114	}
2115
2116	// err can be something like 'exit status 1'.
2117	// Add information about what program was running.
2118	// Note that if buf.Bytes() is non-empty, the caller usually
2119	// shows buf.Bytes() and does not print err at all, so the
2120	// prefix here does not make most output any more verbose.
2121	if err != nil {
2122		err = errors.New(cmdline[0] + ": " + err.Error())
2123	}
2124	return buf.Bytes(), err
2125}
2126
2127// joinUnambiguously prints the slice, quoting where necessary to make the
2128// output unambiguous.
2129// TODO: See issue 5279. The printing of commands needs a complete redo.
2130func joinUnambiguously(a []string) string {
2131	var buf bytes.Buffer
2132	for i, s := range a {
2133		if i > 0 {
2134			buf.WriteByte(' ')
2135		}
2136		q := strconv.Quote(s)
2137		// A gccgo command line can contain -( and -).
2138		// Make sure we quote them since they are special to the shell.
2139		// The trimpath argument can also contain > (part of =>) and ;. Quote those too.
2140		if s == "" || strings.ContainsAny(s, " ()>;") || len(q) > len(s)+2 {
2141			buf.WriteString(q)
2142		} else {
2143			buf.WriteString(s)
2144		}
2145	}
2146	return buf.String()
2147}
2148
2149// cCompilerEnv returns environment variables to set when running the
2150// C compiler. This is needed to disable escape codes in clang error
2151// messages that confuse tools like cgo.
2152func (b *Builder) cCompilerEnv() []string {
2153	return []string{"TERM=dumb"}
2154}
2155
2156// mkdir makes the named directory.
2157func (b *Builder) Mkdir(dir string) error {
2158	// Make Mkdir(a.Objdir) a no-op instead of an error when a.Objdir == "".
2159	if dir == "" {
2160		return nil
2161	}
2162
2163	b.exec.Lock()
2164	defer b.exec.Unlock()
2165	// We can be a little aggressive about being
2166	// sure directories exist. Skip repeated calls.
2167	if b.mkdirCache[dir] {
2168		return nil
2169	}
2170	b.mkdirCache[dir] = true
2171
2172	if cfg.BuildN || cfg.BuildX {
2173		b.Showcmd("", "mkdir -p %s", dir)
2174		if cfg.BuildN {
2175			return nil
2176		}
2177	}
2178
2179	if err := os.MkdirAll(dir, 0777); err != nil {
2180		return err
2181	}
2182	return nil
2183}
2184
2185// symlink creates a symlink newname -> oldname.
2186func (b *Builder) Symlink(oldname, newname string) error {
2187	// It's not an error to try to recreate an existing symlink.
2188	if link, err := os.Readlink(newname); err == nil && link == oldname {
2189		return nil
2190	}
2191
2192	if cfg.BuildN || cfg.BuildX {
2193		b.Showcmd("", "ln -s %s %s", oldname, newname)
2194		if cfg.BuildN {
2195			return nil
2196		}
2197	}
2198	return os.Symlink(oldname, newname)
2199}
2200
2201// mkAbs returns an absolute path corresponding to
2202// evaluating f in the directory dir.
2203// We always pass absolute paths of source files so that
2204// the error messages will include the full path to a file
2205// in need of attention.
2206func mkAbs(dir, f string) string {
2207	// Leave absolute paths alone.
2208	// Also, during -n mode we use the pseudo-directory $WORK
2209	// instead of creating an actual work directory that won't be used.
2210	// Leave paths beginning with $WORK alone too.
2211	if filepath.IsAbs(f) || strings.HasPrefix(f, "$WORK") {
2212		return f
2213	}
2214	return filepath.Join(dir, f)
2215}
2216
2217type toolchain interface {
2218	// gc runs the compiler in a specific directory on a set of files
2219	// and returns the name of the generated output file.
2220	gc(b *Builder, a *Action, archive string, importcfg, embedcfg []byte, symabis string, asmhdr bool, gofiles []string) (ofile string, out []byte, err error)
2221	// cc runs the toolchain's C compiler in a directory on a C file
2222	// to produce an output file.
2223	cc(b *Builder, a *Action, ofile, cfile string) error
2224	// asm runs the assembler in a specific directory on specific files
2225	// and returns a list of named output files.
2226	asm(b *Builder, a *Action, sfiles []string) ([]string, error)
2227	// symabis scans the symbol ABIs from sfiles and returns the
2228	// path to the output symbol ABIs file, or "" if none.
2229	symabis(b *Builder, a *Action, sfiles []string) (string, error)
2230	// pack runs the archive packer in a specific directory to create
2231	// an archive from a set of object files.
2232	// typically it is run in the object directory.
2233	pack(b *Builder, a *Action, afile string, ofiles []string) error
2234	// ld runs the linker to create an executable starting at mainpkg.
2235	ld(b *Builder, root *Action, out, importcfg, mainpkg string) error
2236	// ldShared runs the linker to create a shared library containing the pkgs built by toplevelactions
2237	ldShared(b *Builder, root *Action, toplevelactions []*Action, out, importcfg string, allactions []*Action) error
2238
2239	compiler() string
2240	linker() string
2241}
2242
2243type noToolchain struct{}
2244
2245func noCompiler() error {
2246	log.Fatalf("unknown compiler %q", cfg.BuildContext.Compiler)
2247	return nil
2248}
2249
2250func (noToolchain) compiler() string {
2251	noCompiler()
2252	return ""
2253}
2254
2255func (noToolchain) linker() string {
2256	noCompiler()
2257	return ""
2258}
2259
2260func (noToolchain) gc(b *Builder, a *Action, archive string, importcfg, embedcfg []byte, symabis string, asmhdr bool, gofiles []string) (ofile string, out []byte, err error) {
2261	return "", nil, noCompiler()
2262}
2263
2264func (noToolchain) asm(b *Builder, a *Action, sfiles []string) ([]string, error) {
2265	return nil, noCompiler()
2266}
2267
2268func (noToolchain) symabis(b *Builder, a *Action, sfiles []string) (string, error) {
2269	return "", noCompiler()
2270}
2271
2272func (noToolchain) pack(b *Builder, a *Action, afile string, ofiles []string) error {
2273	return noCompiler()
2274}
2275
2276func (noToolchain) ld(b *Builder, root *Action, out, importcfg, mainpkg string) error {
2277	return noCompiler()
2278}
2279
2280func (noToolchain) ldShared(b *Builder, root *Action, toplevelactions []*Action, out, importcfg string, allactions []*Action) error {
2281	return noCompiler()
2282}
2283
2284func (noToolchain) cc(b *Builder, a *Action, ofile, cfile string) error {
2285	return noCompiler()
2286}
2287
2288// gcc runs the gcc C compiler to create an object from a single C file.
2289func (b *Builder) gcc(a *Action, p *load.Package, workdir, out string, flags []string, cfile string) error {
2290	return b.ccompile(a, p, out, flags, cfile, b.GccCmd(p.Dir, workdir))
2291}
2292
2293// gxx runs the g++ C++ compiler to create an object from a single C++ file.
2294func (b *Builder) gxx(a *Action, p *load.Package, workdir, out string, flags []string, cxxfile string) error {
2295	return b.ccompile(a, p, out, flags, cxxfile, b.GxxCmd(p.Dir, workdir))
2296}
2297
2298// gfortran runs the gfortran Fortran compiler to create an object from a single Fortran file.
2299func (b *Builder) gfortran(a *Action, p *load.Package, workdir, out string, flags []string, ffile string) error {
2300	return b.ccompile(a, p, out, flags, ffile, b.gfortranCmd(p.Dir, workdir))
2301}
2302
2303// ccompile runs the given C or C++ compiler and creates an object from a single source file.
2304func (b *Builder) ccompile(a *Action, p *load.Package, outfile string, flags []string, file string, compiler []string) error {
2305	file = mkAbs(p.Dir, file)
2306	desc := p.ImportPath
2307	outfile = mkAbs(p.Dir, outfile)
2308
2309	// Elide source directory paths if -trimpath or GOROOT_FINAL is set.
2310	// This is needed for source files (e.g., a .c file in a package directory).
2311	// TODO(golang.org/issue/36072): cgo also generates files with #line
2312	// directives pointing to the source directory. It should not generate those
2313	// when -trimpath is enabled.
2314	if b.gccSupportsFlag(compiler, "-fdebug-prefix-map=a=b") {
2315		if cfg.BuildTrimpath {
2316			// Keep in sync with Action.trimpath.
2317			// The trimmed paths are a little different, but we need to trim in the
2318			// same situations.
2319			var from, toPath string
2320			if m := p.Module; m != nil {
2321				from = m.Dir
2322				toPath = m.Path + "@" + m.Version
2323			} else {
2324				from = p.Dir
2325				toPath = p.ImportPath
2326			}
2327			// -fdebug-prefix-map requires an absolute "to" path (or it joins the path
2328			// with the working directory). Pick something that makes sense for the
2329			// target platform.
2330			var to string
2331			if cfg.BuildContext.GOOS == "windows" {
2332				to = filepath.Join(`\\_\_`, toPath)
2333			} else {
2334				to = filepath.Join("/_", toPath)
2335			}
2336			flags = append(flags[:len(flags):len(flags)], "-fdebug-prefix-map="+from+"="+to)
2337		} else if p.Goroot && cfg.GOROOT_FINAL != cfg.GOROOT {
2338			flags = append(flags[:len(flags):len(flags)], "-fdebug-prefix-map="+cfg.GOROOT+"="+cfg.GOROOT_FINAL)
2339		}
2340	}
2341
2342	overlayPath := file
2343	if p, ok := a.nonGoOverlay[overlayPath]; ok {
2344		overlayPath = p
2345	}
2346	output, err := b.runOut(a, filepath.Dir(overlayPath), b.cCompilerEnv(), compiler, flags, "-o", outfile, "-c", filepath.Base(overlayPath))
2347	if len(output) > 0 {
2348		// On FreeBSD 11, when we pass -g to clang 3.8 it
2349		// invokes its internal assembler with -dwarf-version=2.
2350		// When it sees .section .note.GNU-stack, it warns
2351		// "DWARF2 only supports one section per compilation unit".
2352		// This warning makes no sense, since the section is empty,
2353		// but it confuses people.
2354		// We work around the problem by detecting the warning
2355		// and dropping -g and trying again.
2356		if bytes.Contains(output, []byte("DWARF2 only supports one section per compilation unit")) {
2357			newFlags := make([]string, 0, len(flags))
2358			for _, f := range flags {
2359				if !strings.HasPrefix(f, "-g") {
2360					newFlags = append(newFlags, f)
2361				}
2362			}
2363			if len(newFlags) < len(flags) {
2364				return b.ccompile(a, p, outfile, newFlags, file, compiler)
2365			}
2366		}
2367
2368		b.showOutput(a, p.Dir, desc, b.processOutput(output))
2369		if err != nil {
2370			err = errPrintedOutput
2371		} else if os.Getenv("GO_BUILDER_NAME") != "" {
2372			return errors.New("C compiler warning promoted to error on Go builders")
2373		}
2374	}
2375	return err
2376}
2377
2378// gccld runs the gcc linker to create an executable from a set of object files.
2379func (b *Builder) gccld(a *Action, p *load.Package, objdir, outfile string, flags []string, objs []string) error {
2380	var cmd []string
2381	if len(p.CXXFiles) > 0 || len(p.SwigCXXFiles) > 0 {
2382		cmd = b.GxxCmd(p.Dir, objdir)
2383	} else {
2384		cmd = b.GccCmd(p.Dir, objdir)
2385	}
2386
2387	cmdargs := []interface{}{cmd, "-o", outfile, objs, flags}
2388	dir := p.Dir
2389	out, err := b.runOut(a, base.Cwd(), b.cCompilerEnv(), cmdargs...)
2390
2391	if len(out) > 0 {
2392		// Filter out useless linker warnings caused by bugs outside Go.
2393		// See also cmd/link/internal/ld's hostlink method.
2394		var save [][]byte
2395		var skipLines int
2396		for _, line := range bytes.SplitAfter(out, []byte("\n")) {
2397			// golang.org/issue/26073 - Apple Xcode bug
2398			if bytes.Contains(line, []byte("ld: warning: text-based stub file")) {
2399				continue
2400			}
2401
2402			if skipLines > 0 {
2403				skipLines--
2404				continue
2405			}
2406
2407			// Remove duplicate main symbol with runtime/cgo on AIX.
2408			// With runtime/cgo, two main are available:
2409			// One is generated by cgo tool with {return 0;}.
2410			// The other one is the main calling runtime.rt0_go
2411			// in runtime/cgo.
2412			// The second can't be used by cgo programs because
2413			// runtime.rt0_go is unknown to them.
2414			// Therefore, we let ld remove this main version
2415			// and used the cgo generated one.
2416			if p.ImportPath == "runtime/cgo" && bytes.Contains(line, []byte("ld: 0711-224 WARNING: Duplicate symbol: .main")) {
2417				skipLines = 1
2418				continue
2419			}
2420
2421			save = append(save, line)
2422		}
2423		out = bytes.Join(save, nil)
2424		if len(out) > 0 {
2425			b.showOutput(nil, dir, p.ImportPath, b.processOutput(out))
2426			if err != nil {
2427				err = errPrintedOutput
2428			}
2429		}
2430	}
2431	return err
2432}
2433
2434// Grab these before main helpfully overwrites them.
2435var (
2436	origCC  = cfg.Getenv("CC")
2437	origCXX = cfg.Getenv("CXX")
2438)
2439
2440// gccCmd returns a gcc command line prefix
2441// defaultCC is defined in zdefaultcc.go, written by cmd/dist.
2442func (b *Builder) GccCmd(incdir, workdir string) []string {
2443	return b.compilerCmd(b.ccExe(), incdir, workdir)
2444}
2445
2446// gxxCmd returns a g++ command line prefix
2447// defaultCXX is defined in zdefaultcc.go, written by cmd/dist.
2448func (b *Builder) GxxCmd(incdir, workdir string) []string {
2449	return b.compilerCmd(b.cxxExe(), incdir, workdir)
2450}
2451
2452// gfortranCmd returns a gfortran command line prefix.
2453func (b *Builder) gfortranCmd(incdir, workdir string) []string {
2454	return b.compilerCmd(b.fcExe(), incdir, workdir)
2455}
2456
2457// ccExe returns the CC compiler setting without all the extra flags we add implicitly.
2458func (b *Builder) ccExe() []string {
2459	return b.compilerExe(origCC, cfg.DefaultCC(cfg.Goos, cfg.Goarch))
2460}
2461
2462// cxxExe returns the CXX compiler setting without all the extra flags we add implicitly.
2463func (b *Builder) cxxExe() []string {
2464	return b.compilerExe(origCXX, cfg.DefaultCXX(cfg.Goos, cfg.Goarch))
2465}
2466
2467// fcExe returns the FC compiler setting without all the extra flags we add implicitly.
2468func (b *Builder) fcExe() []string {
2469	return b.compilerExe(cfg.Getenv("FC"), "gfortran")
2470}
2471
2472// compilerExe returns the compiler to use given an
2473// environment variable setting (the value not the name)
2474// and a default. The resulting slice is usually just the name
2475// of the compiler but can have additional arguments if they
2476// were present in the environment value.
2477// For example if CC="gcc -DGOPHER" then the result is ["gcc", "-DGOPHER"].
2478func (b *Builder) compilerExe(envValue string, def string) []string {
2479	compiler := strings.Fields(envValue)
2480	if len(compiler) == 0 {
2481		compiler = strings.Fields(def)
2482	}
2483	return compiler
2484}
2485
2486// compilerCmd returns a command line prefix for the given environment
2487// variable and using the default command when the variable is empty.
2488func (b *Builder) compilerCmd(compiler []string, incdir, workdir string) []string {
2489	// NOTE: env.go's mkEnv knows that the first three
2490	// strings returned are "gcc", "-I", incdir (and cuts them off).
2491	a := []string{compiler[0], "-I", incdir}
2492	a = append(a, compiler[1:]...)
2493
2494	// Definitely want -fPIC but on Windows gcc complains
2495	// "-fPIC ignored for target (all code is position independent)"
2496	if cfg.Goos != "windows" {
2497		a = append(a, "-fPIC")
2498	}
2499	a = append(a, b.gccArchArgs()...)
2500	// gcc-4.5 and beyond require explicit "-pthread" flag
2501	// for multithreading with pthread library.
2502	if cfg.BuildContext.CgoEnabled {
2503		switch cfg.Goos {
2504		case "windows":
2505			a = append(a, "-mthreads")
2506		default:
2507			a = append(a, "-pthread")
2508		}
2509	}
2510
2511	if cfg.Goos == "aix" {
2512		// mcmodel=large must always be enabled to allow large TOC.
2513		a = append(a, "-mcmodel=large")
2514	}
2515
2516	// disable ASCII art in clang errors, if possible
2517	if b.gccSupportsFlag(compiler, "-fno-caret-diagnostics") {
2518		a = append(a, "-fno-caret-diagnostics")
2519	}
2520	// clang is too smart about command-line arguments
2521	if b.gccSupportsFlag(compiler, "-Qunused-arguments") {
2522		a = append(a, "-Qunused-arguments")
2523	}
2524
2525	// disable word wrapping in error messages
2526	a = append(a, "-fmessage-length=0")
2527
2528	// Tell gcc not to include the work directory in object files.
2529	if b.gccSupportsFlag(compiler, "-fdebug-prefix-map=a=b") {
2530		if workdir == "" {
2531			workdir = b.WorkDir
2532		}
2533		workdir = strings.TrimSuffix(workdir, string(filepath.Separator))
2534		a = append(a, "-fdebug-prefix-map="+workdir+"=/tmp/go-build")
2535	}
2536
2537	// Tell gcc not to include flags in object files, which defeats the
2538	// point of -fdebug-prefix-map above.
2539	if b.gccSupportsFlag(compiler, "-gno-record-gcc-switches") {
2540		a = append(a, "-gno-record-gcc-switches")
2541	}
2542
2543	// On OS X, some of the compilers behave as if -fno-common
2544	// is always set, and the Mach-O linker in 6l/8l assumes this.
2545	// See https://golang.org/issue/3253.
2546	if cfg.Goos == "darwin" || cfg.Goos == "ios" {
2547		a = append(a, "-fno-common")
2548	}
2549
2550	// gccgo uses the language-independent exception mechanism to
2551	// handle panics, so it always needs unwind tables.
2552	if cfg.BuildToolchainName == "gccgo" {
2553		a = append(a, "-funwind-tables")
2554	}
2555
2556	return a
2557}
2558
2559// gccNoPie returns the flag to use to request non-PIE. On systems
2560// with PIE (position independent executables) enabled by default,
2561// -no-pie must be passed when doing a partial link with -Wl,-r.
2562// But -no-pie is not supported by all compilers, and clang spells it -nopie.
2563func (b *Builder) gccNoPie(linker []string) string {
2564	if b.gccSupportsFlag(linker, "-no-pie") {
2565		return "-no-pie"
2566	}
2567	if b.gccSupportsFlag(linker, "-nopie") {
2568		return "-nopie"
2569	}
2570	return ""
2571}
2572
2573// gccSupportsFlag checks to see if the compiler supports a flag.
2574func (b *Builder) gccSupportsFlag(compiler []string, flag string) bool {
2575	key := [2]string{compiler[0], flag}
2576
2577	b.exec.Lock()
2578	defer b.exec.Unlock()
2579	if b, ok := b.flagCache[key]; ok {
2580		return b
2581	}
2582	if b.flagCache == nil {
2583		b.flagCache = make(map[[2]string]bool)
2584	}
2585
2586	tmp := os.DevNull
2587	if runtime.GOOS == "windows" {
2588		f, err := os.CreateTemp(b.WorkDir, "")
2589		if err != nil {
2590			return false
2591		}
2592		f.Close()
2593		tmp = f.Name()
2594		defer os.Remove(tmp)
2595	}
2596
2597	// We used to write an empty C file, but that gets complicated with
2598	// go build -n. We tried using a file that does not exist, but that
2599	// fails on systems with GCC version 4.2.1; that is the last GPLv2
2600	// version of GCC, so some systems have frozen on it.
2601	// Now we pass an empty file on stdin, which should work at least for
2602	// GCC and clang.
2603	cmdArgs := str.StringList(compiler, flag, "-c", "-x", "c", "-", "-o", tmp)
2604	if cfg.BuildN || cfg.BuildX {
2605		b.Showcmd(b.WorkDir, "%s || true", joinUnambiguously(cmdArgs))
2606		if cfg.BuildN {
2607			return false
2608		}
2609	}
2610	cmd := exec.Command(cmdArgs[0], cmdArgs[1:]...)
2611	cmd.Dir = b.WorkDir
2612	cmd.Env = base.AppendPWD(os.Environ(), cmd.Dir)
2613	cmd.Env = append(cmd.Env, "LC_ALL=C")
2614	out, _ := cmd.CombinedOutput()
2615	// GCC says "unrecognized command line option".
2616	// clang says "unknown argument".
2617	// Older versions of GCC say "unrecognised debug output level".
2618	// For -fsplit-stack GCC says "'-fsplit-stack' is not supported".
2619	supported := !bytes.Contains(out, []byte("unrecognized")) &&
2620		!bytes.Contains(out, []byte("unknown")) &&
2621		!bytes.Contains(out, []byte("unrecognised")) &&
2622		!bytes.Contains(out, []byte("is not supported"))
2623	b.flagCache[key] = supported
2624	return supported
2625}
2626
2627// gccArchArgs returns arguments to pass to gcc based on the architecture.
2628func (b *Builder) gccArchArgs() []string {
2629	switch cfg.Goarch {
2630	case "386":
2631		return []string{"-m32"}
2632	case "amd64":
2633		if cfg.Goos == "darwin" {
2634			return []string{"-arch", "x86_64", "-m64"}
2635		}
2636		return []string{"-m64"}
2637	case "arm64":
2638		if cfg.Goos == "darwin" {
2639			return []string{"-arch", "arm64"}
2640		}
2641	case "arm":
2642		return []string{"-marm"} // not thumb
2643	case "s390x":
2644		return []string{"-m64", "-march=z196"}
2645	case "mips64", "mips64le":
2646		args := []string{"-mabi=64"}
2647		if cfg.GOMIPS64 == "hardfloat" {
2648			return append(args, "-mhard-float")
2649		} else if cfg.GOMIPS64 == "softfloat" {
2650			return append(args, "-msoft-float")
2651		}
2652	case "mips", "mipsle":
2653		args := []string{"-mabi=32", "-march=mips32"}
2654		if cfg.GOMIPS == "hardfloat" {
2655			return append(args, "-mhard-float", "-mfp32", "-mno-odd-spreg")
2656		} else if cfg.GOMIPS == "softfloat" {
2657			return append(args, "-msoft-float")
2658		}
2659	case "ppc64":
2660		if cfg.Goos == "aix" {
2661			return []string{"-maix64"}
2662		}
2663	case "ppc":
2664		if cfg.Goos == "aix" {
2665			return []string{"-maix32"}
2666		}
2667	}
2668	return nil
2669}
2670
2671// envList returns the value of the given environment variable broken
2672// into fields, using the default value when the variable is empty.
2673func envList(key, def string) []string {
2674	v := cfg.Getenv(key)
2675	if v == "" {
2676		v = def
2677	}
2678	return strings.Fields(v)
2679}
2680
2681// CFlags returns the flags to use when invoking the C, C++ or Fortran compilers, or cgo.
2682func (b *Builder) CFlags(p *load.Package) (cppflags, cflags, cxxflags, fflags, ldflags []string, err error) {
2683	defaults := "-g -O2"
2684
2685	if cppflags, err = buildFlags("CPPFLAGS", "", p.CgoCPPFLAGS, checkCompilerFlags); err != nil {
2686		return
2687	}
2688	if cflags, err = buildFlags("CFLAGS", defaults, p.CgoCFLAGS, checkCompilerFlags); err != nil {
2689		return
2690	}
2691	if cxxflags, err = buildFlags("CXXFLAGS", defaults, p.CgoCXXFLAGS, checkCompilerFlags); err != nil {
2692		return
2693	}
2694	if fflags, err = buildFlags("FFLAGS", defaults, p.CgoFFLAGS, checkCompilerFlags); err != nil {
2695		return
2696	}
2697	if ldflags, err = buildFlags("LDFLAGS", defaults, p.CgoLDFLAGS, checkLinkerFlags); err != nil {
2698		return
2699	}
2700
2701	return
2702}
2703
2704func buildFlags(name, defaults string, fromPackage []string, check func(string, string, []string) error) ([]string, error) {
2705	if err := check(name, "#cgo "+name, fromPackage); err != nil {
2706		return nil, err
2707	}
2708	return str.StringList(envList("CGO_"+name, defaults), fromPackage), nil
2709}
2710
2711var cgoRe = lazyregexp.New(`[/\\:]`)
2712
2713func (b *Builder) cgo(a *Action, cgoExe, objdir string, pcCFLAGS, pcLDFLAGS, cgofiles, gccfiles, gxxfiles, mfiles, ffiles []string) (outGo, outObj []string, err error) {
2714	p := a.Package
2715	cgoCPPFLAGS, cgoCFLAGS, cgoCXXFLAGS, cgoFFLAGS, cgoLDFLAGS, err := b.CFlags(p)
2716	if err != nil {
2717		return nil, nil, err
2718	}
2719
2720	cgoCPPFLAGS = append(cgoCPPFLAGS, pcCFLAGS...)
2721	cgoLDFLAGS = append(cgoLDFLAGS, pcLDFLAGS...)
2722	// If we are compiling Objective-C code, then we need to link against libobjc
2723	if len(mfiles) > 0 {
2724		cgoLDFLAGS = append(cgoLDFLAGS, "-lobjc")
2725	}
2726
2727	// Likewise for Fortran, except there are many Fortran compilers.
2728	// Support gfortran out of the box and let others pass the correct link options
2729	// via CGO_LDFLAGS
2730	if len(ffiles) > 0 {
2731		fc := cfg.Getenv("FC")
2732		if fc == "" {
2733			fc = "gfortran"
2734		}
2735		if strings.Contains(fc, "gfortran") {
2736			cgoLDFLAGS = append(cgoLDFLAGS, "-lgfortran")
2737		}
2738	}
2739
2740	if cfg.BuildMSan {
2741		cgoCFLAGS = append([]string{"-fsanitize=memory"}, cgoCFLAGS...)
2742		cgoLDFLAGS = append([]string{"-fsanitize=memory"}, cgoLDFLAGS...)
2743	}
2744
2745	// Allows including _cgo_export.h, as well as the user's .h files,
2746	// from .[ch] files in the package.
2747	cgoCPPFLAGS = append(cgoCPPFLAGS, "-I", objdir)
2748
2749	// cgo
2750	// TODO: CGO_FLAGS?
2751	gofiles := []string{objdir + "_cgo_gotypes.go"}
2752	cfiles := []string{"_cgo_export.c"}
2753	for _, fn := range cgofiles {
2754		f := strings.TrimSuffix(filepath.Base(fn), ".go")
2755		gofiles = append(gofiles, objdir+f+".cgo1.go")
2756		cfiles = append(cfiles, f+".cgo2.c")
2757	}
2758
2759	// TODO: make cgo not depend on $GOARCH?
2760
2761	cgoflags := []string{}
2762	if p.Standard && p.ImportPath == "runtime/cgo" {
2763		cgoflags = append(cgoflags, "-import_runtime_cgo=false")
2764	}
2765	if p.Standard && (p.ImportPath == "runtime/race" || p.ImportPath == "runtime/msan" || p.ImportPath == "runtime/cgo") {
2766		cgoflags = append(cgoflags, "-import_syscall=false")
2767	}
2768
2769	// Update $CGO_LDFLAGS with p.CgoLDFLAGS.
2770	// These flags are recorded in the generated _cgo_gotypes.go file
2771	// using //go:cgo_ldflag directives, the compiler records them in the
2772	// object file for the package, and then the Go linker passes them
2773	// along to the host linker. At this point in the code, cgoLDFLAGS
2774	// consists of the original $CGO_LDFLAGS (unchecked) and all the
2775	// flags put together from source code (checked).
2776	cgoenv := b.cCompilerEnv()
2777	if len(cgoLDFLAGS) > 0 {
2778		flags := make([]string, len(cgoLDFLAGS))
2779		for i, f := range cgoLDFLAGS {
2780			flags[i] = strconv.Quote(f)
2781		}
2782		cgoenv = append(cgoenv, "CGO_LDFLAGS="+strings.Join(flags, " "))
2783	}
2784
2785	if cfg.BuildToolchainName == "gccgo" {
2786		if b.gccSupportsFlag([]string{BuildToolchain.compiler()}, "-fsplit-stack") {
2787			cgoCFLAGS = append(cgoCFLAGS, "-fsplit-stack")
2788		}
2789		cgoflags = append(cgoflags, "-gccgo")
2790		if pkgpath := gccgoPkgpath(p); pkgpath != "" {
2791			cgoflags = append(cgoflags, "-gccgopkgpath="+pkgpath)
2792		}
2793	}
2794
2795	switch cfg.BuildBuildmode {
2796	case "c-archive", "c-shared":
2797		// Tell cgo that if there are any exported functions
2798		// it should generate a header file that C code can
2799		// #include.
2800		cgoflags = append(cgoflags, "-exportheader="+objdir+"_cgo_install.h")
2801	}
2802
2803	execdir := p.Dir
2804
2805	// Rewrite overlaid paths in cgo files.
2806	// cgo adds //line and #line pragmas in generated files with these paths.
2807	var trimpath []string
2808	for i := range cgofiles {
2809		path := mkAbs(p.Dir, cgofiles[i])
2810		if opath, ok := fsys.OverlayPath(path); ok {
2811			cgofiles[i] = opath
2812			trimpath = append(trimpath, opath+"=>"+path)
2813		}
2814	}
2815	if len(trimpath) > 0 {
2816		cgoflags = append(cgoflags, "-trimpath", strings.Join(trimpath, ";"))
2817	}
2818
2819	if err := b.run(a, execdir, p.ImportPath, cgoenv, cfg.BuildToolexec, cgoExe, "-objdir", objdir, "-importpath", p.ImportPath, cgoflags, "--", cgoCPPFLAGS, cgoCFLAGS, cgofiles); err != nil {
2820		return nil, nil, err
2821	}
2822	outGo = append(outGo, gofiles...)
2823
2824	// Use sequential object file names to keep them distinct
2825	// and short enough to fit in the .a header file name slots.
2826	// We no longer collect them all into _all.o, and we'd like
2827	// tools to see both the .o suffix and unique names, so
2828	// we need to make them short enough not to be truncated
2829	// in the final archive.
2830	oseq := 0
2831	nextOfile := func() string {
2832		oseq++
2833		return objdir + fmt.Sprintf("_x%03d.o", oseq)
2834	}
2835
2836	// gcc
2837	cflags := str.StringList(cgoCPPFLAGS, cgoCFLAGS)
2838	for _, cfile := range cfiles {
2839		ofile := nextOfile()
2840		if err := b.gcc(a, p, a.Objdir, ofile, cflags, objdir+cfile); err != nil {
2841			return nil, nil, err
2842		}
2843		outObj = append(outObj, ofile)
2844	}
2845
2846	for _, file := range gccfiles {
2847		ofile := nextOfile()
2848		if err := b.gcc(a, p, a.Objdir, ofile, cflags, file); err != nil {
2849			return nil, nil, err
2850		}
2851		outObj = append(outObj, ofile)
2852	}
2853
2854	cxxflags := str.StringList(cgoCPPFLAGS, cgoCXXFLAGS)
2855	for _, file := range gxxfiles {
2856		ofile := nextOfile()
2857		if err := b.gxx(a, p, a.Objdir, ofile, cxxflags, file); err != nil {
2858			return nil, nil, err
2859		}
2860		outObj = append(outObj, ofile)
2861	}
2862
2863	for _, file := range mfiles {
2864		ofile := nextOfile()
2865		if err := b.gcc(a, p, a.Objdir, ofile, cflags, file); err != nil {
2866			return nil, nil, err
2867		}
2868		outObj = append(outObj, ofile)
2869	}
2870
2871	fflags := str.StringList(cgoCPPFLAGS, cgoFFLAGS)
2872	for _, file := range ffiles {
2873		ofile := nextOfile()
2874		if err := b.gfortran(a, p, a.Objdir, ofile, fflags, file); err != nil {
2875			return nil, nil, err
2876		}
2877		outObj = append(outObj, ofile)
2878	}
2879
2880	switch cfg.BuildToolchainName {
2881	case "gc":
2882		importGo := objdir + "_cgo_import.go"
2883		if err := b.dynimport(a, p, objdir, importGo, cgoExe, cflags, cgoLDFLAGS, outObj); err != nil {
2884			return nil, nil, err
2885		}
2886		outGo = append(outGo, importGo)
2887
2888	case "gccgo":
2889		defunC := objdir + "_cgo_defun.c"
2890		defunObj := objdir + "_cgo_defun.o"
2891		if err := BuildToolchain.cc(b, a, defunObj, defunC); err != nil {
2892			return nil, nil, err
2893		}
2894		outObj = append(outObj, defunObj)
2895
2896	default:
2897		noCompiler()
2898	}
2899
2900	// Double check the //go:cgo_ldflag comments in the generated files.
2901	// The compiler only permits such comments in files whose base name
2902	// starts with "_cgo_". Make sure that the comments in those files
2903	// are safe. This is a backstop against people somehow smuggling
2904	// such a comment into a file generated by cgo.
2905	if cfg.BuildToolchainName == "gc" && !cfg.BuildN {
2906		var flags []string
2907		for _, f := range outGo {
2908			if !strings.HasPrefix(filepath.Base(f), "_cgo_") {
2909				continue
2910			}
2911
2912			src, err := os.ReadFile(f)
2913			if err != nil {
2914				return nil, nil, err
2915			}
2916
2917			const cgoLdflag = "//go:cgo_ldflag"
2918			idx := bytes.Index(src, []byte(cgoLdflag))
2919			for idx >= 0 {
2920				// We are looking at //go:cgo_ldflag.
2921				// Find start of line.
2922				start := bytes.LastIndex(src[:idx], []byte("\n"))
2923				if start == -1 {
2924					start = 0
2925				}
2926
2927				// Find end of line.
2928				end := bytes.Index(src[idx:], []byte("\n"))
2929				if end == -1 {
2930					end = len(src)
2931				} else {
2932					end += idx
2933				}
2934
2935				// Check for first line comment in line.
2936				// We don't worry about /* */ comments,
2937				// which normally won't appear in files
2938				// generated by cgo.
2939				commentStart := bytes.Index(src[start:], []byte("//"))
2940				commentStart += start
2941				// If that line comment is //go:cgo_ldflag,
2942				// it's a match.
2943				if bytes.HasPrefix(src[commentStart:], []byte(cgoLdflag)) {
2944					// Pull out the flag, and unquote it.
2945					// This is what the compiler does.
2946					flag := string(src[idx+len(cgoLdflag) : end])
2947					flag = strings.TrimSpace(flag)
2948					flag = strings.Trim(flag, `"`)
2949					flags = append(flags, flag)
2950				}
2951				src = src[end:]
2952				idx = bytes.Index(src, []byte(cgoLdflag))
2953			}
2954		}
2955
2956		// We expect to find the contents of cgoLDFLAGS in flags.
2957		if len(cgoLDFLAGS) > 0 {
2958		outer:
2959			for i := range flags {
2960				for j, f := range cgoLDFLAGS {
2961					if f != flags[i+j] {
2962						continue outer
2963					}
2964				}
2965				flags = append(flags[:i], flags[i+len(cgoLDFLAGS):]...)
2966				break
2967			}
2968		}
2969
2970		if err := checkLinkerFlags("LDFLAGS", "go:cgo_ldflag", flags); err != nil {
2971			return nil, nil, err
2972		}
2973	}
2974
2975	return outGo, outObj, nil
2976}
2977
2978// dynimport creates a Go source file named importGo containing
2979// //go:cgo_import_dynamic directives for each symbol or library
2980// dynamically imported by the object files outObj.
2981func (b *Builder) dynimport(a *Action, p *load.Package, objdir, importGo, cgoExe string, cflags, cgoLDFLAGS, outObj []string) error {
2982	cfile := objdir + "_cgo_main.c"
2983	ofile := objdir + "_cgo_main.o"
2984	if err := b.gcc(a, p, objdir, ofile, cflags, cfile); err != nil {
2985		return err
2986	}
2987
2988	linkobj := str.StringList(ofile, outObj, mkAbsFiles(p.Dir, p.SysoFiles))
2989	dynobj := objdir + "_cgo_.o"
2990
2991	// we need to use -pie for Linux/ARM to get accurate imported sym
2992	ldflags := cgoLDFLAGS
2993	if (cfg.Goarch == "arm" && cfg.Goos == "linux") || cfg.Goos == "android" {
2994		// -static -pie doesn't make sense, and causes link errors.
2995		// Issue 26197.
2996		n := make([]string, 0, len(ldflags))
2997		for _, flag := range ldflags {
2998			if flag != "-static" {
2999				n = append(n, flag)
3000			}
3001		}
3002		ldflags = append(n, "-pie")
3003	}
3004	if err := b.gccld(a, p, objdir, dynobj, ldflags, linkobj); err != nil {
3005		return err
3006	}
3007
3008	// cgo -dynimport
3009	var cgoflags []string
3010	if p.Standard && p.ImportPath == "runtime/cgo" {
3011		cgoflags = []string{"-dynlinker"} // record path to dynamic linker
3012	}
3013	return b.run(a, base.Cwd(), p.ImportPath, b.cCompilerEnv(), cfg.BuildToolexec, cgoExe, "-dynpackage", p.Name, "-dynimport", dynobj, "-dynout", importGo, cgoflags)
3014}
3015
3016// Run SWIG on all SWIG input files.
3017// TODO: Don't build a shared library, once SWIG emits the necessary
3018// pragmas for external linking.
3019func (b *Builder) swig(a *Action, p *load.Package, objdir string, pcCFLAGS []string) (outGo, outC, outCXX []string, err error) {
3020	if err := b.swigVersionCheck(); err != nil {
3021		return nil, nil, nil, err
3022	}
3023
3024	intgosize, err := b.swigIntSize(objdir)
3025	if err != nil {
3026		return nil, nil, nil, err
3027	}
3028
3029	for _, f := range p.SwigFiles {
3030		goFile, cFile, err := b.swigOne(a, p, f, objdir, pcCFLAGS, false, intgosize)
3031		if err != nil {
3032			return nil, nil, nil, err
3033		}
3034		if goFile != "" {
3035			outGo = append(outGo, goFile)
3036		}
3037		if cFile != "" {
3038			outC = append(outC, cFile)
3039		}
3040	}
3041	for _, f := range p.SwigCXXFiles {
3042		goFile, cxxFile, err := b.swigOne(a, p, f, objdir, pcCFLAGS, true, intgosize)
3043		if err != nil {
3044			return nil, nil, nil, err
3045		}
3046		if goFile != "" {
3047			outGo = append(outGo, goFile)
3048		}
3049		if cxxFile != "" {
3050			outCXX = append(outCXX, cxxFile)
3051		}
3052	}
3053	return outGo, outC, outCXX, nil
3054}
3055
3056// Make sure SWIG is new enough.
3057var (
3058	swigCheckOnce sync.Once
3059	swigCheck     error
3060)
3061
3062func (b *Builder) swigDoVersionCheck() error {
3063	out, err := b.runOut(nil, "", nil, "swig", "-version")
3064	if err != nil {
3065		return err
3066	}
3067	re := regexp.MustCompile(`[vV]ersion +([\d]+)([.][\d]+)?([.][\d]+)?`)
3068	matches := re.FindSubmatch(out)
3069	if matches == nil {
3070		// Can't find version number; hope for the best.
3071		return nil
3072	}
3073
3074	major, err := strconv.Atoi(string(matches[1]))
3075	if err != nil {
3076		// Can't find version number; hope for the best.
3077		return nil
3078	}
3079	const errmsg = "must have SWIG version >= 3.0.6"
3080	if major < 3 {
3081		return errors.New(errmsg)
3082	}
3083	if major > 3 {
3084		// 4.0 or later
3085		return nil
3086	}
3087
3088	// We have SWIG version 3.x.
3089	if len(matches[2]) > 0 {
3090		minor, err := strconv.Atoi(string(matches[2][1:]))
3091		if err != nil {
3092			return nil
3093		}
3094		if minor > 0 {
3095			// 3.1 or later
3096			return nil
3097		}
3098	}
3099
3100	// We have SWIG version 3.0.x.
3101	if len(matches[3]) > 0 {
3102		patch, err := strconv.Atoi(string(matches[3][1:]))
3103		if err != nil {
3104			return nil
3105		}
3106		if patch < 6 {
3107			// Before 3.0.6.
3108			return errors.New(errmsg)
3109		}
3110	}
3111
3112	return nil
3113}
3114
3115func (b *Builder) swigVersionCheck() error {
3116	swigCheckOnce.Do(func() {
3117		swigCheck = b.swigDoVersionCheck()
3118	})
3119	return swigCheck
3120}
3121
3122// Find the value to pass for the -intgosize option to swig.
3123var (
3124	swigIntSizeOnce  sync.Once
3125	swigIntSize      string
3126	swigIntSizeError error
3127)
3128
3129// This code fails to build if sizeof(int) <= 32
3130const swigIntSizeCode = `
3131package main
3132const i int = 1 << 32
3133`
3134
3135// Determine the size of int on the target system for the -intgosize option
3136// of swig >= 2.0.9. Run only once.
3137func (b *Builder) swigDoIntSize(objdir string) (intsize string, err error) {
3138	if cfg.BuildN {
3139		return "$INTBITS", nil
3140	}
3141	src := filepath.Join(b.WorkDir, "swig_intsize.go")
3142	if err = os.WriteFile(src, []byte(swigIntSizeCode), 0666); err != nil {
3143		return
3144	}
3145	srcs := []string{src}
3146
3147	p := load.GoFilesPackage(context.TODO(), load.PackageOpts{}, srcs)
3148
3149	if _, _, e := BuildToolchain.gc(b, &Action{Mode: "swigDoIntSize", Package: p, Objdir: objdir}, "", nil, nil, "", false, srcs); e != nil {
3150		return "32", nil
3151	}
3152	return "64", nil
3153}
3154
3155// Determine the size of int on the target system for the -intgosize option
3156// of swig >= 2.0.9.
3157func (b *Builder) swigIntSize(objdir string) (intsize string, err error) {
3158	swigIntSizeOnce.Do(func() {
3159		swigIntSize, swigIntSizeError = b.swigDoIntSize(objdir)
3160	})
3161	return swigIntSize, swigIntSizeError
3162}
3163
3164// Run SWIG on one SWIG input file.
3165func (b *Builder) swigOne(a *Action, p *load.Package, file, objdir string, pcCFLAGS []string, cxx bool, intgosize string) (outGo, outC string, err error) {
3166	cgoCPPFLAGS, cgoCFLAGS, cgoCXXFLAGS, _, _, err := b.CFlags(p)
3167	if err != nil {
3168		return "", "", err
3169	}
3170
3171	var cflags []string
3172	if cxx {
3173		cflags = str.StringList(cgoCPPFLAGS, pcCFLAGS, cgoCXXFLAGS)
3174	} else {
3175		cflags = str.StringList(cgoCPPFLAGS, pcCFLAGS, cgoCFLAGS)
3176	}
3177
3178	n := 5 // length of ".swig"
3179	if cxx {
3180		n = 8 // length of ".swigcxx"
3181	}
3182	base := file[:len(file)-n]
3183	goFile := base + ".go"
3184	gccBase := base + "_wrap."
3185	gccExt := "c"
3186	if cxx {
3187		gccExt = "cxx"
3188	}
3189
3190	gccgo := cfg.BuildToolchainName == "gccgo"
3191
3192	// swig
3193	args := []string{
3194		"-go",
3195		"-cgo",
3196		"-intgosize", intgosize,
3197		"-module", base,
3198		"-o", objdir + gccBase + gccExt,
3199		"-outdir", objdir,
3200	}
3201
3202	for _, f := range cflags {
3203		if len(f) > 3 && f[:2] == "-I" {
3204			args = append(args, f)
3205		}
3206	}
3207
3208	if gccgo {
3209		args = append(args, "-gccgo")
3210		if pkgpath := gccgoPkgpath(p); pkgpath != "" {
3211			args = append(args, "-go-pkgpath", pkgpath)
3212		}
3213	}
3214	if cxx {
3215		args = append(args, "-c++")
3216	}
3217
3218	out, err := b.runOut(a, p.Dir, nil, "swig", args, file)
3219	if err != nil {
3220		if len(out) > 0 {
3221			if bytes.Contains(out, []byte("-intgosize")) || bytes.Contains(out, []byte("-cgo")) {
3222				return "", "", errors.New("must have SWIG version >= 3.0.6")
3223			}
3224			b.showOutput(a, p.Dir, p.Desc(), b.processOutput(out)) // swig error
3225			return "", "", errPrintedOutput
3226		}
3227		return "", "", err
3228	}
3229	if len(out) > 0 {
3230		b.showOutput(a, p.Dir, p.Desc(), b.processOutput(out)) // swig warning
3231	}
3232
3233	// If the input was x.swig, the output is x.go in the objdir.
3234	// But there might be an x.go in the original dir too, and if it
3235	// uses cgo as well, cgo will be processing both and will
3236	// translate both into x.cgo1.go in the objdir, overwriting one.
3237	// Rename x.go to _x_swig.go to avoid this problem.
3238	// We ignore files in the original dir that begin with underscore
3239	// so _x_swig.go cannot conflict with an original file we were
3240	// going to compile.
3241	goFile = objdir + goFile
3242	newGoFile := objdir + "_" + base + "_swig.go"
3243	if err := os.Rename(goFile, newGoFile); err != nil {
3244		return "", "", err
3245	}
3246	return newGoFile, objdir + gccBase + gccExt, nil
3247}
3248
3249// disableBuildID adjusts a linker command line to avoid creating a
3250// build ID when creating an object file rather than an executable or
3251// shared library. Some systems, such as Ubuntu, always add
3252// --build-id to every link, but we don't want a build ID when we are
3253// producing an object file. On some of those system a plain -r (not
3254// -Wl,-r) will turn off --build-id, but clang 3.0 doesn't support a
3255// plain -r. I don't know how to turn off --build-id when using clang
3256// other than passing a trailing --build-id=none. So that is what we
3257// do, but only on systems likely to support it, which is to say,
3258// systems that normally use gold or the GNU linker.
3259func (b *Builder) disableBuildID(ldflags []string) []string {
3260	switch cfg.Goos {
3261	case "android", "dragonfly", "linux", "netbsd":
3262		ldflags = append(ldflags, "-Wl,--build-id=none")
3263	}
3264	return ldflags
3265}
3266
3267// mkAbsFiles converts files into a list of absolute files,
3268// assuming they were originally relative to dir,
3269// and returns that new list.
3270func mkAbsFiles(dir string, files []string) []string {
3271	abs := make([]string, len(files))
3272	for i, f := range files {
3273		if !filepath.IsAbs(f) {
3274			f = filepath.Join(dir, f)
3275		}
3276		abs[i] = f
3277	}
3278	return abs
3279}
3280
3281// passLongArgsInResponseFiles modifies cmd such that, for
3282// certain programs, long arguments are passed in "response files", a
3283// file on disk with the arguments, with one arg per line. An actual
3284// argument starting with '@' means that the rest of the argument is
3285// a filename of arguments to expand.
3286//
3287// See issues 18468 (Windows) and 37768 (Darwin).
3288func passLongArgsInResponseFiles(cmd *exec.Cmd) (cleanup func()) {
3289	cleanup = func() {} // no cleanup by default
3290
3291	var argLen int
3292	for _, arg := range cmd.Args {
3293		argLen += len(arg)
3294	}
3295
3296	// If we're not approaching 32KB of args, just pass args normally.
3297	// (use 30KB instead to be conservative; not sure how accounting is done)
3298	if !useResponseFile(cmd.Path, argLen) {
3299		return
3300	}
3301
3302	tf, err := os.CreateTemp("", "args")
3303	if err != nil {
3304		log.Fatalf("error writing long arguments to response file: %v", err)
3305	}
3306	cleanup = func() { os.Remove(tf.Name()) }
3307	var buf bytes.Buffer
3308	for _, arg := range cmd.Args[1:] {
3309		fmt.Fprintf(&buf, "%s\n", encodeArg(arg))
3310	}
3311	if _, err := tf.Write(buf.Bytes()); err != nil {
3312		tf.Close()
3313		cleanup()
3314		log.Fatalf("error writing long arguments to response file: %v", err)
3315	}
3316	if err := tf.Close(); err != nil {
3317		cleanup()
3318		log.Fatalf("error writing long arguments to response file: %v", err)
3319	}
3320	cmd.Args = []string{cmd.Args[0], "@" + tf.Name()}
3321	return cleanup
3322}
3323
3324// Windows has a limit of 32 KB arguments. To be conservative and not worry
3325// about whether that includes spaces or not, just use 30 KB. Darwin's limit is
3326// less clear. The OS claims 256KB, but we've seen failures with arglen as
3327// small as 50KB.
3328const ArgLengthForResponseFile = (30 << 10)
3329
3330func useResponseFile(path string, argLen int) bool {
3331	// Unless the program uses objabi.Flagparse, which understands
3332	// response files, don't use response files.
3333	// TODO: do we need more commands? asm? cgo? For now, no.
3334	prog := strings.TrimSuffix(filepath.Base(path), ".exe")
3335	switch prog {
3336	case "compile", "link":
3337	default:
3338		return false
3339	}
3340
3341	if argLen > ArgLengthForResponseFile {
3342		return true
3343	}
3344
3345	// On the Go build system, use response files about 10% of the
3346	// time, just to exercise this codepath.
3347	isBuilder := os.Getenv("GO_BUILDER_NAME") != ""
3348	if isBuilder && rand.Intn(10) == 0 {
3349		return true
3350	}
3351
3352	return false
3353}
3354
3355// encodeArg encodes an argument for response file writing.
3356func encodeArg(arg string) string {
3357	// If there aren't any characters we need to reencode, fastpath out.
3358	if !strings.ContainsAny(arg, "\\\n") {
3359		return arg
3360	}
3361	var b strings.Builder
3362	for _, r := range arg {
3363		switch r {
3364		case '\\':
3365			b.WriteByte('\\')
3366			b.WriteByte('\\')
3367		case '\n':
3368			b.WriteByte('\\')
3369			b.WriteByte('n')
3370		default:
3371			b.WriteRune(r)
3372		}
3373	}
3374	return b.String()
3375}
3376