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