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.
5 // Action graph execution.
33 "cmd/go/internal/base"
34 "cmd/go/internal/cache"
36 "cmd/go/internal/fsys"
37 "cmd/go/internal/load"
38 "cmd/go/internal/modload"
40 "cmd/go/internal/trace"
45 const defaultCFlags = "-O2 -g"
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{}
52 var walk func(*Action)
53 walk = func(a *Action) {
58 for _, a1 := range a.Deps {
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+")")
73 // If we're doing real work, take time at the end to trim the cache.
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 {
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)
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)
111 b.readySema = make(chan bool, len(all))
113 // Initialize per-action execution state.
114 for _, a := range all {
115 for _, a1 := range a.Deps {
116 a1.triggers = append(a1.triggers, a)
118 a.pending = len(a.Deps)
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) {
129 a.json.TimeStart = time.Now()
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() + ")"
138 ctx, span := trace.StartSpan(ctx, desc)
140 for _, d := range a.Deps {
141 trace.Flow(ctx, d.traceSpan, a.traceSpan)
143 err = a.Func(b, ctx, a)
147 a.json.TimeDone = time.Now()
150 // The actions run in parallel but all the updates to the
151 // shared work state are serialized through b.exec.
153 defer b.exec.Unlock()
157 if a.Package.Error == nil {
158 a.Package.Error = &load.PackageError{Err: err}
161 base.Errorf("%s", err)
166 for _, a0 := range a.triggers {
170 if a0.pending--; a0.pending == 0 {
181 var wg sync.WaitGroup
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.
191 for i := 0; i < par; i++ {
194 ctx := trace.StartGoroutine(ctx)
198 case _, ok := <-b.readySema:
202 // Receiving a value from b.readySema entitles
203 // us to take from the ready queue.
208 case <-base.Interrupted:
209 base.SetExitStatus(1)
218 // Write action graph again, this time with timing information.
222 // buildActionID computes the action ID for a build action.
223 func (b *Builder) buildActionID(a *Action) cache.ActionID {
225 h := cache.NewHash("build " + p.ImportPath)
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")
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.
241 fmt.Fprintf(h, "module %s@%s\n", p.Module.Path, p.Module.Version)
244 // The Go compiler always hides the exact value of $GOROOT
245 // when building things in GOROOT.
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.)
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)
262 fmt.Fprintf(h, "go %s\n", p.Module.GoVersion)
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")
270 if p.Internal.ForceLibrary {
271 fmt.Fprintf(h, "forcelibrary\n")
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)
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.
285 if ccID, err := b.gccToolID(ccExe[0], "c"); err == nil {
286 fmt.Fprintf(h, "CC ID=%q\n", ccID)
289 if len(p.CXXFiles)+len(p.SwigCXXFiles) > 0 {
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)
296 if len(p.FFiles) > 0 {
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)
303 // TODO(rsc): Should we include the SWIG version?
305 if p.Internal.CoverMode != "" {
306 fmt.Fprintf(h, "cover %q %q\n", p.Internal.CoverMode, b.toolID("cover"))
308 if p.Internal.FuzzInstrument {
309 if fuzzFlags := fuzzInstrumentFlags(); fuzzFlags != nil {
310 fmt.Fprintf(h, "fuzz %q\n", fuzzFlags)
313 if p.Internal.BuildInfo != "" {
314 fmt.Fprintf(h, "modinfo %q\n", p.Internal.BuildInfo)
317 // Configuration specific to compiler toolchain.
318 switch cfg.BuildToolchainName {
320 base.Fatalf("buildActionID: unknown build toolchain %q", cfg.BuildToolchainName)
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)
327 // GOARM, GOMIPS, etc.
328 key, val := cfg.GetArchEnv()
329 fmt.Fprintf(h, "%s=%s\n", key, val)
331 if cfg.CleanGOEXPERIMENT != "" {
332 fmt.Fprintf(h, "GOEXPERIMENT=%q\n", cfg.CleanGOEXPERIMENT)
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.
346 for _, env := range magic {
347 if x := os.Getenv(env); x != "" {
348 fmt.Fprintf(h, "magic %s=%s\n", env, x)
351 if os.Getenv("GOSSAHASH") != "" {
353 env := fmt.Sprintf("GOSSAHASH%d", i)
358 fmt.Fprintf(h, "magic %s=%s\n", env, x)
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())
370 id, err := b.gccToolID(BuildToolchain.compiler(), "go")
372 base.Fatalf("%v", err)
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)
386 inputFiles := str.StringList(
400 for _, file := range inputFiles {
401 fmt.Fprintf(h, "file %s %s\n", file, b.fileHash(filepath.Join(p.Dir, file)))
403 for _, a1 := range a.Deps {
406 fmt.Fprintf(h, "import %s %s\n", p1.ImportPath, contentID(a1.buildID))
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" {
423 for _, t1 := range a.triggers {
424 for _, t2 := range t1.triggers {
425 if t2.Mode == "install header" {
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.
442 // Special case "1.0" means "go1", which is OK.
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 {
456 needBuild uint32 = 1 << iota
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) {
468 bit := func(x uint32, b bool) uint32 {
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)
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.
489 a.output = []byte{} // start saving output in case we miss any cache results
493 p.BuildID = a.buildID
495 if need&needCompiledGoFiles != 0 {
496 if err := b.loadCachedSrcFiles(a); err == nil {
497 need &^= needCompiledGoFiles
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
513 defer b.flushOutput(a)
518 err = fmt.Errorf("go build %s: %v", p.ImportPath, err)
520 if err != nil && b.IsCmdList && b.NeedError && p.Error == nil {
521 p.Error = &load.PackageError{Err: err}
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")
534 b.Print(p.ImportPath + "\n")
539 p.StaleReason = "binary-only packages are no longer supported"
543 return errors.New("binary-only packages are no longer supported")
546 if err := b.Mkdir(a.Objdir); err != nil {
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 {
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.
563 if err := b.loadCachedVet(a); err == nil {
571 if err := AllowInstall(a); err != nil {
575 // make target directory
576 dir, _ := filepath.Split(a.Target)
578 if err := b.Mkdir(dir); err != nil {
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
590 if p.UsesCgo() || p.UsesSwig() {
591 if pcCFLAGS, pcLDFLAGS, err = b.getPkgConfigFlags(p); err != nil {
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}
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)
610 if a.nonGoOverlay != nil {
611 for _, fs := range nonGoFileLists {
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 {
619 a.nonGoOverlay[from] = dst
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.
628 outGo, outC, outCXX, err := b.swig(a, p, objdir, pcCFLAGS)
632 cgofiles = append(cgofiles, outGo...)
633 cfiles = append(cfiles, outC...)
634 cxxfiles = append(cxxfiles, outCXX...)
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.
646 var sourceFile string
649 if base, found := strings.CutSuffix(file, ".cgo1.go"); found {
650 // cgo files have absolute paths
651 base = filepath.Base(base)
653 coverFile = objdir + base + ".cgo1.go"
656 sourceFile = filepath.Join(p.Dir, file)
657 coverFile = objdir + file
660 coverFile = strings.TrimSuffix(coverFile, ".go") + ".cover.go"
661 if cfg.Experiment.CoverageRedesign {
662 infiles = append(infiles, sourceFile)
663 outfiles = append(outfiles, coverFile)
665 cover := p.Internal.CoverVars[key]
667 continue // Not covering this file.
669 if err := b.cover(a, coverFile, sourceFile, cover.Var); err != nil {
673 if i < len(gofiles) {
674 gofiles[i] = coverFile
676 cgofiles[i-len(gofiles)] = coverFile
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
695 panic("covermode should be set at this point")
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 {
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
708 p.Internal.CoverMode = ""
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...)
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_") {
728 nongcc = append(nongcc, f)
733 sfiles, gccfiles = filter(sfiles, sfiles[:0], gccfiles)
735 for _, sfile := range sfiles {
736 data, err := os.ReadFile(filepath.Join(p.Dir, sfile))
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)
745 gccfiles = append(gccfiles, sfiles...)
749 outGo, outObj, err := b.cgo(a, base.Tool("cgo"), objdir, pcCFLAGS, pcLDFLAGS, mkAbsFiles(p.Dir, cgofiles), gccfiles, cxxfiles, p.MFiles, p.FFiles)
751 // The files in cxxfiles have now been handled by b.cgo.
757 if cfg.BuildToolchainName == "gccgo" {
758 cgoObjects = append(cgoObjects, a.Objdir+"_cgo_flags")
760 cgoObjects = append(cgoObjects, outObj...)
761 gofiles = append(gofiles, outGo...)
763 switch cfg.BuildBuildmode {
764 case "c-archive", "c-shared":
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)
776 // Running cgo generated the cgo header.
779 // Sanity check only, since Package.load already checked as well.
780 if len(gofiles) == 0 {
781 return &load.NoGoError{Package: p}
784 // Prepare Go vet config if needed.
785 if need&needVet != 0 {
786 buildVetConfig(a, srcfiles)
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)
793 need &^= needCompiledGoFiles
796 // Nothing left to do.
800 // Collect symbol ABI requirements from assembly.
801 symabis, err := BuildToolchain.symabis(b, a, sfiles)
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]
817 fmt.Fprintf(&icfg, "importmap %s=%s\n", raw, final)
820 for _, a1 := range a.Deps {
822 if p1 == nil || p1.ImportPath == "" || a1.built == "" {
825 fmt.Fprintf(&icfg, "packagefile %s=%s\n", p1.ImportPath, a1.built)
828 // Prepare Go embed config if needed.
829 // Unlike the import config, it's okay for the embed config to be empty.
831 if len(p.Internal.Embed) > 0 {
833 Patterns map[string][]string
834 Files map[string]string
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)
841 js, err := json.MarshalIndent(&embed, "", "\t")
843 return fmt.Errorf("marshal embedcfg: %v", err)
848 if p.Internal.BuildInfo != "" && cfg.ModulesEnabled {
849 prog := modload.ModInfoProg(p.Internal.BuildInfo, cfg.BuildToolchainName == "gccgo")
851 if err := b.writeFile(objdir+"_gomod_.go", prog); err != nil {
854 gofiles = append(gofiles, objdir+"_gomod_.go")
859 objpkg := objdir + "_pkg_.a"
860 ofile, out, err := BuildToolchain.gc(b, a, objpkg, icfg.Bytes(), embedcfg, symabis, len(sfiles) > 0, gofiles)
862 output := b.processOutput(out)
863 if p.Module != nil && !allowedVersion(p.Module.GoVersion) {
864 output += "note: module requires Go " + p.Module.GoVersion + "\n"
868 return errors.New(fmt.Sprint(formatOutput(b.WorkDir, p.Dir, p.Desc(), output)))
870 b.showOutput(a, p.Dir, p.Desc(), output)
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")
880 objects = append(objects, ofile)
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)
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 {
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 {
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 {
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 {
915 objects = append(objects, out)
918 // Assemble .s files.
920 ofiles, err := BuildToolchain.asm(b, a, sfiles)
924 objects = append(objects, ofiles...)
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" {
932 case "aix", "android", "dragonfly", "freebsd", "illumos", "linux", "netbsd", "openbsd", "solaris":
933 asmfile, err := b.gccgoBuildIDFile(a)
937 ofiles, err := BuildToolchain.asm(b, a, []string{asmfile})
941 objects = append(objects, ofiles...)
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...)
951 // Add system object files.
952 for _, syso := range p.SysoFiles {
953 objects = append(objects, filepath.Join(p.Dir, syso))
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 {
967 if err := b.updateBuildID(a, objpkg, true); err != nil {
975 func (b *Builder) cacheObjdirFile(a *Action, c *cache.Cache, name string) error {
976 f, err := os.Open(a.Objdir + name)
981 _, _, err = c.Put(cache.Subkey(a.actionID, name), f)
985 func (b *Builder) findCachedObjdirFile(a *Action, c *cache.Cache, name string) (string, error) {
986 file, _, err := c.GetFile(cache.Subkey(a.actionID, name))
988 return "", fmt.Errorf("loading cached file %s: %w", name, err)
993 func (b *Builder) loadCachedObjdirFile(a *Action, c *cache.Cache, name string) error {
994 cached, err := b.findCachedObjdirFile(a, c, name)
998 return b.copyFile(a.Objdir+name, cached, 0666, true)
1001 func (b *Builder) cacheCgoHdr(a *Action) {
1002 c := cache.Default()
1003 b.cacheObjdirFile(a, c, "_cgo_install.h")
1006 func (b *Builder) loadCachedCgoHdr(a *Action) error {
1007 c := cache.Default()
1008 return b.loadCachedObjdirFile(a, c, "_cgo_install.h")
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) {
1017 buf.WriteString("./")
1018 buf.WriteString(file)
1019 buf.WriteString("\n")
1022 name := file[len(a.Objdir):]
1023 buf.WriteString(name)
1024 buf.WriteString("\n")
1025 if err := b.cacheObjdirFile(a, c, name); err != nil {
1029 c.PutBytes(cache.Subkey(a.actionID, "srcfiles"), buf.Bytes())
1032 func (b *Builder) loadCachedVet(a *Action) error {
1033 c := cache.Default()
1034 list, _, err := c.GetBytes(cache.Subkey(a.actionID, "srcfiles"))
1036 return fmt.Errorf("reading srcfiles list: %w", err)
1038 var srcfiles []string
1039 for _, name := range strings.Split(string(list), "\n") {
1040 if name == "" { // end of list
1043 if strings.HasPrefix(name, "./") {
1044 srcfiles = append(srcfiles, name[2:])
1047 if err := b.loadCachedObjdirFile(a, c, name); err != nil {
1050 srcfiles = append(srcfiles, a.Objdir+name)
1052 buildVetConfig(a, srcfiles)
1056 func (b *Builder) loadCachedSrcFiles(a *Action) error {
1057 c := cache.Default()
1058 list, _, err := c.GetBytes(cache.Subkey(a.actionID, "srcfiles"))
1060 return fmt.Errorf("reading srcfiles list: %w", err)
1063 for _, name := range strings.Split(string(list), "\n") {
1064 if name == "" { // end of list
1067 if strings.HasPrefix(name, "./") {
1068 files = append(files, name[len("./"):])
1071 file, err := b.findCachedObjdirFile(a, c, name)
1073 return fmt.Errorf("finding %s: %w", name, err)
1075 files = append(files, file)
1077 a.Package.CompiledGoFiles = files
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
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
1098 SucceedOnTypecheckFailure bool // awful hack; see #18395 and below
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)
1109 nongofiles = append(nongofiles, name)
1113 ignored := str.StringList(a.Package.IgnoredGoFiles, a.Package.IgnoredOtherFiles)
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.
1120 ID: a.Package.ImportPath,
1121 Compiler: cfg.BuildToolchainName,
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),
1132 for i, raw := range a.Package.Internal.RawImports {
1133 final := a.Package.Imports[i]
1134 vcfg.ImportMap[raw] = final
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
1144 for _, a1 := range a.Deps {
1146 if p1 == nil || p1.ImportPath == "" {
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
1155 vcfg.PackageFile[p1.ImportPath] = a1.built
1158 vcfg.Standard[p1.ImportPath] = true
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.
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
1171 // VetExplicit records whether the vet flags were set explicitly on the command line.
1172 var VetExplicit bool
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.
1178 a.Failed = false // vet of dependency may have failed but we can still succeed
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.
1187 vcfg := a.Deps[0].vetCfg
1189 // Vet config should only be missing if the build failed.
1190 return fmt.Errorf("vet config not found")
1193 vcfg.VetxOnly = a.VetxOnly
1194 vcfg.VetxOutput = a.Objdir + "vet.out"
1195 vcfg.PackageVetx = make(map[string]string)
1197 h := cache.NewHash("vet " + a.Package.ImportPath)
1198 fmt.Fprintf(h, "vet %q\n", b.toolID("vet"))
1200 vetFlags := VetFlags
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.
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
1227 vetFlags = []string{"-unsafeptr=false"}
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")
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)
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
1255 key := cache.ActionID(h.Sum())
1257 if vcfg.VetxOnly && !cfg.BuildA {
1258 c := cache.Default()
1259 if file, _, err := c.GetFile(key); err == nil {
1265 js, err := json.MarshalIndent(vcfg, "", "\t")
1267 return fmt.Errorf("internal error marshaling vet config: %v", err)
1269 js = append(js, '\n')
1270 if err := b.writeFile(a.Objdir+"vet.cfg", js); err != nil {
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())
1283 tool = base.Tool("vet")
1285 runErr := b.run(a, p.Dir, p.ImportPath, env, cfg.BuildToolexec, tool, vetFlags, a.Objdir+"vet.cfg")
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)
1297 // linkActionID computes the action ID for a link action.
1298 func (b *Builder) linkActionID(a *Action) cache.ActionID {
1300 h := cache.NewHash("link " + p.ImportPath)
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")
1311 // Toolchain-dependent configuration, shared with b.linkSharedActionID.
1312 b.printLinkerConfig(h, p)
1315 for _, a1 := range a.Deps {
1318 if a1.built != "" || a1.buildID != "" {
1319 buildID := a1.buildID
1321 buildID = b.buildID(a1.built)
1323 fmt.Fprintf(h, "packagefile %s=%s\n", p1.ImportPath, contentID(buildID))
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)
1331 fmt.Fprintf(h, "packageshlib %s=%s\n", p1.ImportPath, contentID(b.buildID(p1.Shlib)))
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 {
1344 base.Fatalf("linkActionID: unknown toolchain %q", cfg.BuildToolchainName)
1347 fmt.Fprintf(h, "link %s %q %s\n", b.toolID("link"), forcedLdflags, ldBuildmode)
1349 fmt.Fprintf(h, "linkflags %q\n", p.Internal.Ldflags)
1352 // GOARM, GOMIPS, etc.
1353 key, val := cfg.GetArchEnv()
1354 fmt.Fprintf(h, "%s=%s\n", key, val)
1356 if cfg.CleanGOEXPERIMENT != "" {
1357 fmt.Fprintf(h, "GOEXPERIMENT=%q\n", cfg.CleanGOEXPERIMENT)
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
1366 fmt.Fprintf(h, "GOROOT=%s\n", gorootFinal)
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"))
1371 // TODO(rsc): Do cgo settings and flags need to be included?
1372 // Or external linker settings and flags?
1375 id, err := b.gccToolID(BuildToolchain.linker(), "go")
1377 base.Fatalf("%v", err)
1379 fmt.Fprintf(h, "link %s %s\n", id, ldBuildmode)
1380 // TODO(iant): Should probably include cgo flags here.
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 {
1390 defer b.flushOutput(a)
1392 if err := b.Mkdir(a.Objdir); err != nil {
1396 importcfg := a.Objdir + "importcfg.link"
1397 if err := b.writeLinkImportcfg(a, importcfg); err != nil {
1401 if err := AllowInstall(a); err != nil {
1405 // make target directory
1406 dir, _ := filepath.Split(a.Target)
1408 if err := b.Mkdir(dir); err != nil {
1413 if err := BuildToolchain.ld(b, a, a.Target, importcfg, a.Deps[0].built); err != nil {
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 {
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 {
1449 fmt.Fprintf(&icfg, "packagefile %s=%s\n", p1.ImportPath, a1.built)
1451 fmt.Fprintf(&icfg, "packageshlib %s=%s\n", p1.ImportPath, p1.Shlib)
1454 fmt.Fprintf(&icfg, "modinfo %q\n", modload.ModInfoData(a.Package.Internal.BuildInfo))
1455 return b.writeFile(file, icfg.Bytes())
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]
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) {
1471 flag := make([]byte, 0, len(out))
1475 for _, c := range out {
1479 case '$', '`', '"', '\\':
1481 flag = append(flag, '\\')
1483 flag = append(flag, c)
1485 flag = append(flag, c)
1488 } else if quote != 0 {
1496 flag = append(flag, c)
1499 } else if strings.IndexByte(" \t\n\v\f\r", c) < 0 {
1506 flag = append(flag, c)
1508 } else if len(flag) != 0 {
1509 flags = append(flags, string(flag))
1514 return nil, errors.New("broken character escaping in pkgconf output ")
1517 return nil, errors.New("unterminated quoted string in pkgconf output ")
1518 } else if len(flag) != 0 {
1519 flags = append(flags, string(flag))
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
1532 for _, pcarg := range pcargs {
1534 // We're going to add our own "--" argument.
1535 } else if strings.HasPrefix(pcarg, "--") {
1536 pcflags = append(pcflags, pcarg)
1538 pkgs = append(pkgs, pcarg)
1541 for _, pkg := range pkgs {
1542 if !load.SafeArg(pkg) {
1543 return nil, nil, fmt.Errorf("invalid pkg-config package name: %s", pkg)
1547 out, err = b.runOut(nil, p.Dir, nil, b.PkgconfigCmd(), "--cflags", pcflags, "--", pkgs)
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()))
1553 cflags, err = splitPkgConfigOutput(out)
1555 return nil, nil, err
1557 if err := checkCompilerFlags("CFLAGS", "pkg-config --cflags", cflags); err != nil {
1558 return nil, nil, err
1561 out, err = b.runOut(nil, p.Dir, nil, b.PkgconfigCmd(), "--libs", pcflags, "--", pkgs)
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()))
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
1579 func (b *Builder) installShlibname(ctx context.Context, a *Action) error {
1580 if err := AllowInstall(a); err != nil {
1586 err := os.WriteFile(a.Target, []byte(filepath.Base(a1.Target)+"\n"), 0666)
1591 b.Showcmd("", "echo '%s' > %s # internal", filepath.Base(a1.Target), a.Target)
1596 func (b *Builder) linkSharedActionID(a *Action) cache.ActionID {
1597 h := cache.NewHash("linkShared")
1599 // Toolchain-independent configuration.
1600 fmt.Fprintf(h, "linkShared\n")
1601 fmt.Fprintf(h, "goos %s goarch %s\n", cfg.Goos, cfg.Goarch)
1603 // Toolchain-dependent configuration, shared with b.linkActionID.
1604 b.printLinkerConfig(h, nil)
1607 for _, a1 := range a.Deps {
1613 fmt.Fprintf(h, "packagefile %s=%s\n", p1.ImportPath, contentID(b.buildID(a1.built)))
1615 fmt.Fprintf(h, "packageshlib %s=%s\n", p1.ImportPath, contentID(b.buildID(p1.Shlib)))
1619 // Files named on command line are special.
1620 for _, a1 := range a.Deps[0].Deps {
1622 fmt.Fprintf(h, "top %s=%s\n", p1.ImportPath, contentID(b.buildID(a1.built)))
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 {
1632 defer b.flushOutput(a)
1634 if err := AllowInstall(a); err != nil {
1638 if err := b.Mkdir(a.Objdir); err != nil {
1642 importcfg := a.Objdir + "importcfg.link"
1643 if err := b.writeLinkImportcfg(a, importcfg); err != nil {
1647 // TODO(rsc): There is a missing updateBuildID here,
1648 // but we have to decide where to store the build ID in these files.
1650 return BuildToolchain.ldShared(b, a, a.Deps[0].Deps, a.Target, importcfg, a.Deps)
1653 // BuildInstallFunc is the action for installing a single package or executable.
1654 func BuildInstallFunc(b *Builder, ctx context.Context, a *Action) (err error) {
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.
1661 if a.Package != nil {
1662 sep, path = " ", a.Package.ImportPath
1664 err = fmt.Errorf("go %s%s%s: %v", cfg.CmdName, sep, path, err)
1669 a.buildID = a1.buildID
1671 a.json.BuildID = a.buildID
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 {
1681 if !a.buggyInstall {
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.
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
1702 if !a.buggyInstall && !b.IsCmdList {
1704 b.Showcmd("", "touch %s", a.Target)
1705 } else if err := AllowInstall(a); err == nil {
1707 os.Chtimes(a.Target, now, now)
1713 // If we're building for go list -export,
1714 // never install anything; just keep the cache reference.
1719 if err := AllowInstall(a); err != nil {
1723 if err := b.Mkdir(a.Objdir); err != nil {
1727 perm := fs.FileMode(0666)
1728 if a1.Mode == "link" {
1729 switch cfg.BuildBuildmode {
1730 case "c-archive", "c-shared", "plugin":
1736 // make target directory
1737 dir, _ := filepath.Split(a.Target)
1739 if err := b.Mkdir(dir); err != nil {
1744 if !a.buggyInstall {
1748 return b.moveOrCopyFile(a.Target, a1.built, perm, false)
1751 // AllowInstall returns a non-nil error if this invocation of the go command is
1752 // allowed to install a.Target.
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 }
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) {
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)
1771 os.RemoveAll(a.Objdir)
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 {
1778 b.Showcmd("", "mv %s %s", src, dst)
1782 // If we can update the mode and rename to the dst, do it.
1783 // Otherwise fall back to standard copy.
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)
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)
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)
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.
1813 f, err := os.OpenFile(filepath.Clean(dst)+"-go-tmp-umask", os.O_WRONLY|os.O_CREATE|os.O_EXCL, perm)
1817 mode = fi.Mode() & 0777
1824 if err := os.Chmod(src, mode); err == nil {
1825 if err := os.Rename(src, dst); err == nil {
1827 b.Showcmd("", "mv %s %s", src, dst)
1833 return b.copyFile(dst, src, perm, force)
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)
1845 sf, err := os.Open(src)
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 {
1856 return fmt.Errorf("build output %q already exists and is a directory", dst)
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)
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 + "~")
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 + "~")
1880 df, err = os.OpenFile(dst, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, perm)
1883 return fmt.Errorf("copying %s: %w", src, err) // err should already refer to dst
1886 _, err = io.Copy(df, sf)
1889 mayberemovefile(dst)
1890 return fmt.Errorf("copying %s to %s: %v", src, dst, err)
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)
1903 return os.WriteFile(file, text, 0666)
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.
1916 b.Showcmd("", "# %s not created", src)
1921 if err := AllowInstall(a); err != nil {
1925 dir, _ := filepath.Split(a.Target)
1927 if err := b.Mkdir(dir); err != nil {
1932 return b.moveOrCopyFile(a.Target, src, 0666, true)
1935 // cover runs, in effect,
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,
1942 "-mode", a.Package.Internal.CoverMode,
1948 // cover2 runs, in effect,
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 {
1955 args := []string{base.Tool("cover"),
1959 "-outfilelist", covoutputs,
1961 args = append(args, infiles...)
1962 return b.run(a, a.Objdir, "cover "+a.Package.ImportPath, nil,
1963 cfg.BuildToolexec, args)
1966 func (b *Builder) writeCoverPkgInputs(a *Action, pconfigfile string, covoutputsfile string, outfiles []string) error {
1968 p.Internal.CoverageCfg = a.Objdir + "coveragecfg"
1969 pcfg := coverage.CoverPkgConfig{
1970 PkgPath: p.ImportPath,
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,
1979 if a.Package.Module != nil {
1980 pcfg.ModulePath = a.Package.Module.Path
1982 data, err := json.Marshal(pcfg)
1986 if err := b.writeFile(pconfigfile, data); err != nil {
1989 var sb strings.Builder
1990 for i := range outfiles {
1991 fmt.Fprintf(&sb, "%s\n", outfiles[i])
1993 return b.writeFile(covoutputsfile, []byte(sb.String()))
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
2014 func isObject(s string) bool {
2015 f, err := os.Open(s)
2020 buf := make([]byte, 64)
2022 for _, magic := range objectMagic {
2023 if bytes.HasPrefix(buf, magic) {
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() {
2040 // fmtcmd formats a command in the manner of fmt.Sprintf but also:
2042 // If dir is non-empty and the script is not in dir right now,
2043 // fmtcmd inserts "cd dir\n" before the command.
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.
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 != "/" {
2055 if dir[len(dir)-1] == filepath.Separator {
2056 dot += string(filepath.Separator)
2058 cmd = strings.ReplaceAll(" "+cmd, " "+dir, dot)[1:]
2059 if b.scriptDir != dir {
2061 cmd = "cd " + dir + "\n" + cmd
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")
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) {
2079 defer b.output.Unlock()
2080 b.Print(b.fmtcmd(dir, format, args...) + "\n")
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,
2093 // ../fmt/print.go:1090: undefined: asdf
2100 // /usr/gopher/go/src/fmt/print.go:1090: undefined: asdf
2103 // showOutput also replaces references to the work directory with $WORK.
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...)
2116 defer b.output.Unlock()
2117 b.Print(prefix, suffix)
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,
2130 // ../fmt/print.go:1090: undefined: asdf
2137 // /usr/gopher/go/src/fmt/print.go:1090: undefined: asdf
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
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)
2151 suffix = strings.ReplaceAll(suffix, " "+workDir, " $WORK")
2153 return prefix, suffix
2156 var cgoLine = lazyregexp.New(`\[[^\[\]]+\.(cgo1|cover)\.go:[0-9]+(:[0-9]+)?\]`)
2157 var cgoTypeSigRe = lazyregexp.New(`\b_C2?(type|func|var|macro)_\B`)
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...)
2166 desc = b.fmtcmd(dir, "%s", strings.Join(str.StringList(cmdargs...), " "))
2169 err = errors.New(fmt.Sprint(formatOutput(b.WorkDir, dir, desc, b.processOutput(out))))
2171 b.showOutput(a, dir, desc, b.processOutput(out))
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')
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.")
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...)
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))
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:])
2217 envcmdline += fmt.Sprintf("%s='%s'", e[:j], e[j+1:])
2222 envcmdline += joinUnambiguously(cmdline)
2223 b.Showcmd(dir, "%s", envcmdline)
2229 var buf bytes.Buffer
2230 cmd := exec.Command(cmdline[0], cmdline[1:]...)
2232 cmd.Args[0] = cmd.Path
2236 cleanup := passLongArgsInResponseFiles(cmd)
2241 cmd.Env = cmd.Environ() // Pre-allocate with correct PWD.
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())
2252 cmd.Env = append(cmd.Env, env...)
2255 if a != nil && a.json != nil {
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()
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.
2271 err = errors.New(cmdline[0] + ": " + err.Error())
2273 return buf.Bytes(), err
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 {
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 {
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"}
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 == "".
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] {
2319 b.mkdirCache[dir] = true
2321 if cfg.BuildN || cfg.BuildX {
2322 b.Showcmd("", "mkdir -p %s", dir)
2328 if err := os.MkdirAll(dir, 0777); err != nil {
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 {
2341 if cfg.BuildN || cfg.BuildX {
2342 b.Showcmd("", "ln -s %s %s", oldname, newname)
2347 return os.Symlink(oldname, newname)
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") {
2363 return filepath.Join(dir, f)
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
2392 type noToolchain struct{}
2394 func noCompiler() error {
2395 log.Fatalf("unknown compiler %q", cfg.BuildContext.Compiler)
2399 func (noToolchain) compiler() string {
2404 func (noToolchain) linker() string {
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()
2413 func (noToolchain) asm(b *Builder, a *Action, sfiles []string) ([]string, error) {
2414 return nil, noCompiler()
2417 func (noToolchain) symabis(b *Builder, a *Action, sfiles []string) (string, error) {
2418 return "", noCompiler()
2421 func (noToolchain) pack(b *Builder, a *Action, afile string, ofiles []string) error {
2425 func (noToolchain) ld(b *Builder, root *Action, out, importcfg, mainpkg string) error {
2429 func (noToolchain) ldShared(b *Builder, root *Action, toplevelactions []*Action, out, importcfg string, allactions []*Action) error {
2433 func (noToolchain) cc(b *Builder, a *Action, ofile, cfile string) error {
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))
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))
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))
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)
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
2468 var from, toPath string
2469 if m := p.Module; m != nil {
2471 toPath = m.Path + "@" + m.Version
2474 toPath = p.ImportPath
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
2480 if cfg.BuildContext.GOOS == "windows" {
2481 to = filepath.Join(`\\_\_`, toPath)
2483 to = filepath.Join("/_", toPath)
2485 flags = append(flags[:len(flags):len(flags)], "-fdebug-prefix-map="+from+"="+to)
2490 if p, ok := a.nonGoOverlay[overlayPath]; ok {
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)
2510 if len(newFlags) < len(flags) {
2511 return b.ccompile(a, p, outfile, newFlags, file, compiler)
2515 if err != nil || os.Getenv("GO_BUILDER_NAME") != "" {
2516 err = errors.New(fmt.Sprintf(formatOutput(b.WorkDir, p.Dir, desc, b.processOutput(output))))
2518 b.showOutput(a, p.Dir, desc, b.processOutput(output))
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 {
2528 if len(p.CXXFiles) > 0 || len(p.SwigCXXFiles) > 0 {
2529 cmd = b.GxxCmd(p.Dir, objdir)
2531 cmd = b.GccCmd(p.Dir, objdir)
2534 cmdargs := []any{cmd, "-o", outfile, objs, flags}
2536 out, err := b.runOut(a, base.Cwd(), b.cCompilerEnv(), cmdargs...)
2539 // Filter out useless linker warnings caused by bugs outside Go.
2540 // See also cmd/link/internal/ld's hostlink method.
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")) {
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
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")) {
2568 save = append(save, line)
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))
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)
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)
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)
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))
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))
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")
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)
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")
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 {
2626 a = append(a, "-mthreads")
2628 a = append(a, "-pthread")
2632 if cfg.Goos == "aix" {
2633 // mcmodel=large must always be enabled to allow large TOC.
2634 a = append(a, "-mcmodel=large")
2637 // disable ASCII art in clang errors, if possible
2638 if b.gccSupportsFlag(compiler, "-fno-caret-diagnostics") {
2639 a = append(a, "-fno-caret-diagnostics")
2641 // clang is too smart about command-line arguments
2642 if b.gccSupportsFlag(compiler, "-Qunused-arguments") {
2643 a = append(a, "-Qunused-arguments")
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")
2653 // disable word wrapping in error messages
2654 a = append(a, "-fmessage-length=0")
2656 // Tell gcc not to include the work directory in object files.
2657 if b.gccSupportsFlag(compiler, "-fdebug-prefix-map=a=b") {
2661 workdir = strings.TrimSuffix(workdir, string(filepath.Separator))
2662 a = append(a, "-fdebug-prefix-map="+workdir+"=/tmp/go-build")
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")
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")
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") {
2689 if b.gccSupportsFlag(linker, "-nopie") {
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}
2700 defer b.exec.Unlock()
2701 if b, ok := b.flagCache[key]; ok {
2704 if b.flagCache == nil {
2705 b.flagCache = make(map[[2]string]bool)
2710 // On the iOS builder the command
2711 // $CC -Wl,--no-gc-sections -x c - -o /dev/null < /dev/null
2713 // Unable to remove existing file: Invalid argument
2714 if runtime.GOOS == "windows" || runtime.GOOS == "ios" {
2715 f, err := os.CreateTemp(b.WorkDir, "")
2721 defer os.Remove(tmp)
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.
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".
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)
2741 cmdArgs = append(cmdArgs, ldflags...)
2742 } else { /* compiler flag, add "-c" */
2743 cflags, err := buildFlags("CFLAGS", defaultCFlags, nil, checkCompilerFlags)
2747 cmdArgs = append(cmdArgs, cflags...)
2748 cmdArgs = append(cmdArgs, "-c")
2751 cmdArgs = append(cmdArgs, "-x", "c", "-", "-o", tmp)
2753 if cfg.BuildN || cfg.BuildX {
2754 b.Showcmd(b.WorkDir, "%s || true", joinUnambiguously(cmdArgs))
2759 cmd := exec.Command(cmdArgs[0], cmdArgs[1:]...)
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
2779 // gccArchArgs returns arguments to pass to gcc based on the architecture.
2780 func (b *Builder) gccArchArgs() []string {
2783 return []string{"-m32"}
2785 if cfg.Goos == "darwin" {
2786 return []string{"-arch", "x86_64", "-m64"}
2788 return []string{"-m64"}
2790 if cfg.Goos == "darwin" {
2791 return []string{"-arch", "arm64"}
2794 return []string{"-marm"} // not thumb
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")
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")
2812 return []string{"-mabi=lp64d"}
2814 if cfg.Goos == "aix" {
2815 return []string{"-maix64"}
2821 // envList returns the value of the given environment variable broken
2822 // into fields, using the default value when the variable is empty.
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)
2832 args, err := quoted.Split(v)
2834 panic(fmt.Sprintf("could not parse environment variable %s with value %q: %v", key, v, err))
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 {
2844 if cflags, err = buildFlags("CFLAGS", defaultCFlags, p.CgoCFLAGS, checkCompilerFlags); err != nil {
2847 if cxxflags, err = buildFlags("CXXFLAGS", defaultCFlags, p.CgoCXXFLAGS, checkCompilerFlags); err != nil {
2850 if fflags, err = buildFlags("FFLAGS", defaultCFlags, p.CgoFFLAGS, checkCompilerFlags); err != nil {
2853 if ldflags, err = buildFlags("LDFLAGS", defaultCFlags, p.CgoLDFLAGS, checkLinkerFlags); err != nil {
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 {
2864 return str.StringList(envList("CGO_"+name, defaults), fromPackage), nil
2867 var cgoRe = lazyregexp.New(`[/\\:]`)
2869 func (b *Builder) cgo(a *Action, cgoExe, objdir string, pcCFLAGS, pcLDFLAGS, cgofiles, gccfiles, gxxfiles, mfiles, ffiles []string) (outGo, outObj []string, err error) {
2871 cgoCPPFLAGS, cgoCFLAGS, cgoCXXFLAGS, cgoFFLAGS, cgoLDFLAGS, err := b.CFlags(p)
2873 return nil, nil, err
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")
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
2886 if len(ffiles) > 0 {
2887 fc := cfg.Getenv("FC")
2891 if strings.Contains(fc, "gfortran") {
2892 cgoLDFLAGS = append(cgoLDFLAGS, "-lgfortran")
2897 cgoCFLAGS = append([]string{"-fsanitize=memory"}, cgoCFLAGS...)
2898 cgoLDFLAGS = append([]string{"-fsanitize=memory"}, cgoLDFLAGS...)
2901 cgoCFLAGS = append([]string{"-fsanitize=address"}, cgoCFLAGS...)
2902 cgoLDFLAGS = append([]string{"-fsanitize=address"}, cgoLDFLAGS...)
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)
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")
2919 // TODO: make cgo not depend on $GOARCH?
2921 cgoflags := []string{}
2922 if p.Standard && p.ImportPath == "runtime/cgo" {
2923 cgoflags = append(cgoflags, "-import_runtime_cgo=false")
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")
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)
2942 cgoenv = append(cgoenv, "CGO_LDFLAGS="+strings.Join(flags, " "))
2945 if cfg.BuildToolchainName == "gccgo" {
2946 if b.gccSupportsFlag([]string{BuildToolchain.compiler()}, "-fsplit-stack") {
2947 cgoCFLAGS = append(cgoCFLAGS, "-fsplit-stack")
2949 cgoflags = append(cgoflags, "-gccgo")
2950 if pkgpath := gccgoPkgpath(p); pkgpath != "" {
2951 cgoflags = append(cgoflags, "-gccgopkgpath="+pkgpath)
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
2960 cgoflags = append(cgoflags, "-exportheader="+objdir+"_cgo_install.h")
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 {
2972 trimpath = append(trimpath, opath+"=>"+path)
2975 if len(trimpath) > 0 {
2976 cgoflags = append(cgoflags, "-trimpath", strings.Join(trimpath, ";"))
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
2982 outGo = append(outGo, gofiles...)
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.
2991 nextOfile := func() string {
2993 return objdir + fmt.Sprintf("_x%03d.o", oseq)
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
3003 outObj = append(outObj, ofile)
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
3011 outObj = append(outObj, ofile)
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
3020 outObj = append(outObj, ofile)
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
3028 outObj = append(outObj, ofile)
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
3037 outObj = append(outObj, ofile)
3040 switch cfg.BuildToolchainName {
3042 importGo := objdir + "_cgo_import.go"
3043 dynOutGo, dynOutObj, err := b.dynimport(a, p, objdir, importGo, cgoExe, cflags, cgoLDFLAGS, outObj)
3045 return nil, nil, err
3048 outGo = append(outGo, dynOutGo)
3050 if dynOutObj != "" {
3051 outObj = append(outObj, dynOutObj)
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
3060 outObj = append(outObj, defunObj)
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 {
3073 for _, f := range outGo {
3074 if !strings.HasPrefix(filepath.Base(f), "_cgo_") {
3078 src, err := os.ReadFile(f)
3080 return nil, nil, err
3083 const cgoLdflag = "//go:cgo_ldflag"
3084 idx := bytes.Index(src, []byte(cgoLdflag))
3086 // We are looking at //go:cgo_ldflag.
3087 // Find start of line.
3088 start := bytes.LastIndex(src[:idx], []byte("\n"))
3093 // Find end of line.
3094 end := bytes.Index(src[idx:], []byte("\n"))
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,
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)
3118 idx = bytes.Index(src, []byte(cgoLdflag))
3122 // We expect to find the contents of cgoLDFLAGS in flags.
3123 if len(cgoLDFLAGS) > 0 {
3125 for i := range flags {
3126 for j, f := range cgoLDFLAGS {
3127 if f != flags[i+j] {
3131 flags = append(flags[:i], flags[i+len(cgoLDFLAGS):]...)
3136 if err := checkLinkerFlags("LDFLAGS", "go:cgo_ldflag", flags); err != nil {
3137 return nil, nil, err
3141 return outGo, outObj, nil
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 {
3156 // Gather .syso files from this package and all (transitive) dependencies.
3158 seen := make(map[*Action]bool)
3159 var gatherSyso func(*Action)
3160 gatherSyso = func(a1 *Action) {
3165 if p1 := a1.Package; p1 != nil {
3166 syso = append(syso, mkAbsFiles(p1.Dir, p1.SysoFiles)...)
3168 for _, a2 := range a1.Deps {
3175 linkobj := str.StringList(ofile, outObj, syso)
3176 dynobj := objdir + "_cgo_.o"
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")
3185 if str.Contains(ldflags, "-pie") && str.Contains(ldflags, "-static") {
3186 // -static -pie doesn't make sense, and causes link errors.
3188 n := make([]string, 0, len(ldflags)-1)
3189 for _, flag := range ldflags {
3190 if flag != "-static" {
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)
3209 if err := os.WriteFile(fail, nil, 0666); err != nil {
3213 return "", fail, nil
3217 var cgoflags []string
3218 if p.Standard && p.ImportPath == "runtime/cgo" {
3219 cgoflags = []string{"-dynlinker"} // record path to dynamic linker
3221 err = b.run(a, base.Cwd(), p.ImportPath, b.cCompilerEnv(), cfg.BuildToolexec, cgoExe, "-dynpackage", p.Name, "-dynimport", dynobj, "-dynout", importGo, cgoflags)
3225 return importGo, "", nil
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
3236 intgosize, err := b.swigIntSize(objdir)
3238 return nil, nil, nil, err
3241 for _, f := range p.SwigFiles {
3242 goFile, cFile, err := b.swigOne(a, p, f, objdir, pcCFLAGS, false, intgosize)
3244 return nil, nil, nil, err
3247 outGo = append(outGo, goFile)
3250 outC = append(outC, cFile)
3253 for _, f := range p.SwigCXXFiles {
3254 goFile, cxxFile, err := b.swigOne(a, p, f, objdir, pcCFLAGS, true, intgosize)
3256 return nil, nil, nil, err
3259 outGo = append(outGo, goFile)
3262 outCXX = append(outCXX, cxxFile)
3265 return outGo, outC, outCXX, nil
3268 // Make sure SWIG is new enough.
3270 swigCheckOnce sync.Once
3274 func (b *Builder) swigDoVersionCheck() error {
3275 out, err := b.runOut(nil, ".", nil, "swig", "-version")
3279 re := regexp.MustCompile(`[vV]ersion +(\d+)([.]\d+)?([.]\d+)?`)
3280 matches := re.FindSubmatch(out)
3282 // Can't find version number; hope for the best.
3286 major, err := strconv.Atoi(string(matches[1]))
3288 // Can't find version number; hope for the best.
3291 const errmsg = "must have SWIG version >= 3.0.6"
3293 return errors.New(errmsg)
3300 // We have SWIG version 3.x.
3301 if len(matches[2]) > 0 {
3302 minor, err := strconv.Atoi(string(matches[2][1:]))
3312 // We have SWIG version 3.0.x.
3313 if len(matches[3]) > 0 {
3314 patch, err := strconv.Atoi(string(matches[3][1:]))
3320 return errors.New(errmsg)
3327 func (b *Builder) swigVersionCheck() error {
3328 swigCheckOnce.Do(func() {
3329 swigCheck = b.swigDoVersionCheck()
3334 // Find the value to pass for the -intgosize option to swig.
3336 swigIntSizeOnce sync.Once
3338 swigIntSizeError error
3341 // This code fails to build if sizeof(int) <= 32
3342 const swigIntSizeCode = `
3344 const i int = 1 << 32
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) {
3351 return "$INTBITS", nil
3353 src := filepath.Join(b.WorkDir, "swig_intsize.go")
3354 if err = os.WriteFile(src, []byte(swigIntSizeCode), 0666); err != nil {
3357 srcs := []string{src}
3359 p := load.GoFilesPackage(context.TODO(), load.PackageOpts{}, srcs)
3361 if _, _, e := BuildToolchain.gc(b, &Action{Mode: "swigDoIntSize", Package: p, Objdir: objdir}, "", nil, nil, "", false, srcs); e != nil {
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)
3373 return swigIntSize, swigIntSizeError
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)
3385 cflags = str.StringList(cgoCPPFLAGS, pcCFLAGS, cgoCXXFLAGS)
3387 cflags = str.StringList(cgoCPPFLAGS, pcCFLAGS, cgoCFLAGS)
3390 n := 5 // length of ".swig"
3392 n = 8 // length of ".swigcxx"
3394 base := file[:len(file)-n]
3395 goFile := base + ".go"
3396 gccBase := base + "_wrap."
3402 gccgo := cfg.BuildToolchainName == "gccgo"
3408 "-intgosize", intgosize,
3410 "-o", objdir + gccBase + gccExt,
3414 for _, f := range cflags {
3415 if len(f) > 3 && f[:2] == "-I" {
3416 args = append(args, f)
3421 args = append(args, "-gccgo")
3422 if pkgpath := gccgoPkgpath(p); pkgpath != "" {
3423 args = append(args, "-go-pkgpath", pkgpath)
3427 args = append(args, "-c++")
3430 out, err := b.runOut(a, p.Dir, nil, "swig", args, file)
3433 if bytes.Contains(out, []byte("-intgosize")) || bytes.Contains(out, []byte("-cgo")) {
3434 return "", "", errors.New("must have SWIG version >= 3.0.6")
3437 return "", "", errors.New(fmt.Sprint(formatOutput(b.WorkDir, p.Dir, p.Desc(), b.processOutput(out))))
3442 b.showOutput(a, p.Dir, p.Desc(), b.processOutput(out)) // swig warning
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 {
3458 return newGoFile, objdir + gccBase + gccExt, nil
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 {
3473 case "android", "dragonfly", "linux", "netbsd":
3474 ldflags = append(ldflags, "-Wl,--build-id=none")
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)
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.
3499 // See issues 18468 (Windows) and 37768 (Darwin).
3500 func passLongArgsInResponseFiles(cmd *exec.Cmd) (cleanup func()) {
3501 cleanup = func() {} // no cleanup by default
3504 for _, arg := range cmd.Args {
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) {
3514 tf, err := os.CreateTemp("", "args")
3516 log.Fatalf("error writing long arguments to response file: %v", err)
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))
3523 if _, err := tf.Write(buf.Bytes()); err != nil {
3526 log.Fatalf("error writing long arguments to response file: %v", err)
3528 if err := tf.Close(); err != nil {
3530 log.Fatalf("error writing long arguments to response file: %v", err)
3532 cmd.Args = []string{cmd.Args[0], "@" + tf.Name()}
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")
3542 case "compile", "link", "cgo", "asm":
3547 if argLen > sys.ExecArgLengthLimit {
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 {
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") {
3567 var b strings.Builder
3568 for _, r := range arg {