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.
16 exec
"internal/execabs"
31 "cmd/go/internal/base"
32 "cmd/go/internal/cache"
34 "cmd/go/internal/fsys"
35 "cmd/go/internal/load"
36 "cmd/go/internal/modload"
38 "cmd/go/internal/trace"
43 // actionList returns the list of actions in the dag rooted at root
44 // as visited in a depth-first post-order traversal.
45 func actionList(root
*Action
) []*Action
{
46 seen
:= map[*Action
]bool{}
48 var walk
func(*Action
)
49 walk
= func(a
*Action
) {
54 for _
, a1
:= range a
.Deps
{
63 // do runs the action graph rooted at root.
64 func (b
*Builder
) Do(ctx context
.Context
, root
*Action
) {
65 ctx
, span
:= trace
.StartSpan(ctx
, "exec.Builder.Do ("+root
.Mode
+" "+root
.Target
+")")
69 // If we're doing real work, take time at the end to trim the cache.
74 // Build list of all actions, assigning depth-first post-order priority.
75 // The original implementation here was a true queue
76 // (using a channel) but it had the effect of getting
77 // distracted by low-level leaf actions to the detriment
78 // of completing higher-level actions. The order of
79 // work does not matter much to overall execution time,
80 // but when running "go test std" it is nice to see each test
81 // results as soon as possible. The priorities assigned
82 // ensure that, all else being equal, the execution prefers
83 // to do what it would have done first in a simple depth-first
84 // dependency order traversal.
85 all
:= actionList(root
)
86 for i
, a
:= range all
{
90 // Write action graph, without timing information, in case we fail and exit early.
91 writeActionGraph
:= func() {
92 if file
:= cfg
.DebugActiongraph
; file
!= "" {
93 if strings
.HasSuffix(file
, ".go") {
94 // Do not overwrite Go source code in:
95 // go build -debug-actiongraph x.go
96 base
.Fatalf("go: refusing to write action graph to %v\n", file
)
98 js
:= actionGraphJSON(root
)
99 if err
:= os
.WriteFile(file
, []byte(js
), 0666); err
!= nil {
100 fmt
.Fprintf(os
.Stderr
, "go: writing action graph: %v\n", err
)
101 base
.SetExitStatus(1)
107 b
.readySema
= make(chan bool, len(all
))
109 // Initialize per-action execution state.
110 for _
, a
:= range all
{
111 for _
, a1
:= range a
.Deps
{
112 a1
.triggers
= append(a1
.triggers
, a
)
114 a
.pending
= len(a
.Deps
)
121 // Handle runs a single action and takes care of triggering
122 // any actions that are runnable as a result.
123 handle
:= func(ctx context
.Context
, a
*Action
) {
125 a
.json
.TimeStart
= time
.Now()
128 if a
.Func
!= nil && (!a
.Failed || a
.IgnoreFail
) {
129 // TODO(matloob): Better action descriptions
130 desc
:= "Executing action "
131 if a
.Package
!= nil {
132 desc
+= "(" + a
.Mode
+ " " + a
.Package
.Desc() + ")"
134 ctx
, span
:= trace
.StartSpan(ctx
, desc
)
136 for _
, d
:= range a
.Deps
{
137 trace
.Flow(ctx
, d
.traceSpan
, a
.traceSpan
)
139 err
= a
.Func(b
, ctx
, a
)
143 a
.json
.TimeDone
= time
.Now()
146 // The actions run in parallel but all the updates to the
147 // shared work state are serialized through b.exec.
149 defer b
.exec
.Unlock()
152 if err
== errPrintedOutput
{
153 base
.SetExitStatus(2)
155 base
.Errorf("%s", err
)
160 for _
, a0
:= range a
.triggers
{
164 if a0
.pending
--; a0
.pending
== 0 {
175 var wg sync
.WaitGroup
177 // Kick off goroutines according to parallelism.
178 // If we are using the -n flag (just printing commands)
179 // drop the parallelism to 1, both to make the output
180 // deterministic and because there is no real work anyway.
185 for i
:= 0; i
< par
; i
++ {
188 ctx
:= trace
.StartGoroutine(ctx
)
192 case _
, ok
:= <-b
.readySema
:
196 // Receiving a value from b.readySema entitles
197 // us to take from the ready queue.
202 case <-base
.Interrupted
:
203 base
.SetExitStatus(1)
212 // Write action graph again, this time with timing information.
216 // buildActionID computes the action ID for a build action.
217 func (b
*Builder
) buildActionID(a
*Action
) cache
.ActionID
{
219 h
:= cache
.NewHash("build " + p
.ImportPath
)
221 // Configuration independent of compiler toolchain.
222 // Note: buildmode has already been accounted for in buildGcflags
223 // and should not be inserted explicitly. Most buildmodes use the
224 // same compiler settings and can reuse each other's results.
225 // If not, the reason is already recorded in buildGcflags.
226 fmt
.Fprintf(h
, "compile\n")
228 // Include information about the origin of the package that
229 // may be embedded in the debug info for the object file.
230 if cfg
.BuildTrimpath
{
231 // When -trimpath is used with a package built from the module cache,
232 // its debug information refers to the module path and version
233 // instead of the directory.
235 fmt
.Fprintf(h
, "module %s@%s\n", p
.Module
.Path
, p
.Module
.Version
)
238 // The Go compiler always hides the exact value of $GOROOT
239 // when building things in GOROOT.
241 // The C compiler does not, but for packages in GOROOT we rewrite the path
242 // as though -trimpath were set, so that we don't invalidate the build cache
243 // (and especially any precompiled C archive files) when changing
244 // GOROOT_FINAL. (See https://go.dev/issue/50183.)
246 // b.WorkDir is always either trimmed or rewritten to
247 // the literal string "/tmp/go-build".
248 } else if !strings
.HasPrefix(p
.Dir
, b
.WorkDir
) {
249 // -trimpath is not set and no other rewrite rules apply,
250 // so the object file may refer to the absolute directory
251 // containing the package.
252 fmt
.Fprintf(h
, "dir %s\n", p
.Dir
)
256 fmt
.Fprintf(h
, "go %s\n", p
.Module
.GoVersion
)
258 fmt
.Fprintf(h
, "goos %s goarch %s\n", cfg
.Goos
, cfg
.Goarch
)
259 fmt
.Fprintf(h
, "import %q\n", p
.ImportPath
)
260 fmt
.Fprintf(h
, "omitdebug %v standard %v local %v prefix %q\n", p
.Internal
.OmitDebug
, p
.Standard
, p
.Internal
.Local
, p
.Internal
.LocalPrefix
)
261 if cfg
.BuildTrimpath
{
262 fmt
.Fprintln(h
, "trimpath")
264 if p
.Internal
.ForceLibrary
{
265 fmt
.Fprintf(h
, "forcelibrary\n")
267 if len(p
.CgoFiles
)+len(p
.SwigFiles
)+len(p
.SwigCXXFiles
) > 0 {
268 fmt
.Fprintf(h
, "cgo %q\n", b
.toolID("cgo"))
269 cppflags
, cflags
, cxxflags
, fflags
, ldflags
, _
:= b
.CFlags(p
)
272 fmt
.Fprintf(h
, "CC=%q %q %q %q\n", ccExe
, cppflags
, cflags
, ldflags
)
273 // Include the C compiler tool ID so that if the C
274 // compiler changes we rebuild the package.
275 // But don't do that for standard library packages like net,
276 // so that the prebuilt .a files from a Go binary install
277 // don't need to be rebuilt with the local compiler.
279 if ccID
, err
:= b
.gccToolID(ccExe
[0], "c"); err
== nil {
280 fmt
.Fprintf(h
, "CC ID=%q\n", ccID
)
283 if len(p
.CXXFiles
)+len(p
.SwigCXXFiles
) > 0 {
285 fmt
.Fprintf(h
, "CXX=%q %q\n", cxxExe
, cxxflags
)
286 if cxxID
, err
:= b
.gccToolID(cxxExe
[0], "c++"); err
== nil {
287 fmt
.Fprintf(h
, "CXX ID=%q\n", cxxID
)
290 if len(p
.FFiles
) > 0 {
292 fmt
.Fprintf(h
, "FC=%q %q\n", fcExe
, fflags
)
293 if fcID
, err
:= b
.gccToolID(fcExe
[0], "f95"); err
== nil {
294 fmt
.Fprintf(h
, "FC ID=%q\n", fcID
)
297 // TODO(rsc): Should we include the SWIG version?
299 if p
.Internal
.CoverMode
!= "" {
300 fmt
.Fprintf(h
, "cover %q %q\n", p
.Internal
.CoverMode
, b
.toolID("cover"))
302 if p
.Internal
.FuzzInstrument
{
303 if fuzzFlags
:= fuzzInstrumentFlags(); fuzzFlags
!= nil {
304 fmt
.Fprintf(h
, "fuzz %q\n", fuzzFlags
)
307 fmt
.Fprintf(h
, "modinfo %q\n", p
.Internal
.BuildInfo
)
309 // Configuration specific to compiler toolchain.
310 switch cfg
.BuildToolchainName
{
312 base
.Fatalf("buildActionID: unknown build toolchain %q", cfg
.BuildToolchainName
)
314 fmt
.Fprintf(h
, "compile %s %q %q\n", b
.toolID("compile"), forcedGcflags
, p
.Internal
.Gcflags
)
315 if len(p
.SFiles
) > 0 {
316 fmt
.Fprintf(h
, "asm %q %q %q\n", b
.toolID("asm"), forcedAsmflags
, p
.Internal
.Asmflags
)
319 // GOARM, GOMIPS, etc.
320 key
, val
:= cfg
.GetArchEnv()
321 fmt
.Fprintf(h
, "%s=%s\n", key
, val
)
323 if goexperiment
:= buildcfg
.GOEXPERIMENT(); goexperiment
!= "" {
324 fmt
.Fprintf(h
, "GOEXPERIMENT=%q\n", goexperiment
)
327 // TODO(rsc): Convince compiler team not to add more magic environment variables,
328 // or perhaps restrict the environment variables passed to subprocesses.
329 // Because these are clumsy, undocumented special-case hacks
330 // for debugging the compiler, they are not settable using 'go env -w',
331 // and so here we use os.Getenv, not cfg.Getenv.
338 for _
, env
:= range magic
{
339 if x
:= os
.Getenv(env
); x
!= "" {
340 fmt
.Fprintf(h
, "magic %s=%s\n", env
, x
)
343 if os
.Getenv("GOSSAHASH") != "" {
345 env
:= fmt
.Sprintf("GOSSAHASH%d", i
)
350 fmt
.Fprintf(h
, "magic %s=%s\n", env
, x
)
353 if os
.Getenv("GSHS_LOGFILE") != "" {
354 // Clumsy hack. Compiler writes to this log file,
355 // so do not allow use of cache at all.
356 // We will still write to the cache but it will be
357 // essentially unfindable.
358 fmt
.Fprintf(h
, "nocache %d\n", time
.Now().UnixNano())
362 id
, err
:= b
.gccToolID(BuildToolchain
.compiler(), "go")
364 base
.Fatalf("%v", err
)
366 fmt
.Fprintf(h
, "compile %s %q %q\n", id
, forcedGccgoflags
, p
.Internal
.Gccgoflags
)
367 fmt
.Fprintf(h
, "pkgpath %s\n", gccgoPkgpath(p
))
368 fmt
.Fprintf(h
, "ar %q\n", BuildToolchain
.(gccgoToolchain
).ar())
369 if len(p
.SFiles
) > 0 {
370 id
, _
= b
.gccToolID(BuildToolchain
.compiler(), "assembler-with-cpp")
371 // Ignore error; different assembler versions
372 // are unlikely to make any difference anyhow.
373 fmt
.Fprintf(h
, "asm %q\n", id
)
378 inputFiles
:= str
.StringList(
392 for _
, file
:= range inputFiles
{
393 fmt
.Fprintf(h
, "file %s %s\n", file
, b
.fileHash(filepath
.Join(p
.Dir
, file
)))
395 for _
, a1
:= range a
.Deps
{
398 fmt
.Fprintf(h
, "import %s %s\n", p1
.ImportPath
, contentID(a1
.buildID
))
405 // needCgoHdr reports whether the actions triggered by this one
406 // expect to be able to access the cgo-generated header file.
407 func (b
*Builder
) needCgoHdr(a
*Action
) bool {
408 // If this build triggers a header install, run cgo to get the header.
409 if !b
.IsCmdList
&& (a
.Package
.UsesCgo() || a
.Package
.UsesSwig()) && (cfg
.BuildBuildmode
== "c-archive" || cfg
.BuildBuildmode
== "c-shared") {
410 for _
, t1
:= range a
.triggers
{
411 if t1
.Mode
== "install header" {
415 for _
, t1
:= range a
.triggers
{
416 for _
, t2
:= range t1
.triggers
{
417 if t2
.Mode
== "install header" {
426 // allowedVersion reports whether the version v is an allowed version of go
427 // (one that we can compile).
428 // v is known to be of the form "1.23".
429 func allowedVersion(v
string) bool {
430 // Special case: no requirement.
434 // Special case "1.0" means "go1", which is OK.
438 // Otherwise look through release tags of form "go1.23" for one that matches.
439 for _
, tag
:= range cfg
.BuildContext
.ReleaseTags
{
440 if strings
.HasPrefix(tag
, "go") && tag
[2:] == v
{
448 needBuild
uint32 = 1 << iota
455 // build is the action for building a single package.
456 // Note that any new influence on this logic must be reported in b.buildActionID above as well.
457 func (b
*Builder
) build(ctx context
.Context
, a
*Action
) (err error
) {
460 bit
:= func(x
uint32, b
bool) uint32 {
468 need
:= bit(needBuild
, !b
.IsCmdList
&& a
.needBuild || b
.NeedExport
) |
469 bit(needCgoHdr
, b
.needCgoHdr(a
)) |
470 bit(needVet
, a
.needVet
) |
471 bit(needCompiledGoFiles
, b
.NeedCompiledGoFiles
)
474 if b
.useCache(a
, b
.buildActionID(a
), p
.Target
) {
475 // We found the main output in the cache.
476 // If we don't need any other outputs, we can stop.
477 // Otherwise, we need to write files to a.Objdir (needVet, needCgoHdr).
478 // Remember that we might have them in cache
479 // and check again after we create a.Objdir.
481 a
.output
= []byte{} // start saving output in case we miss any cache results
485 p
.BuildID
= a
.buildID
487 if need
&needCompiledGoFiles
!= 0 {
488 if err
:= b
.loadCachedSrcFiles(a
); err
== nil {
489 need
&^= needCompiledGoFiles
494 // Source files might be cached, even if the full action is not
495 // (e.g., go list -compiled -find).
496 if !cachedBuild
&& need
&needCompiledGoFiles
!= 0 {
497 if err
:= b
.loadCachedSrcFiles(a
); err
== nil {
498 need
&^= needCompiledGoFiles
505 defer b
.flushOutput(a
)
509 if err
!= nil && err
!= errPrintedOutput
{
510 err
= fmt
.Errorf("go build %s: %v", a
.Package
.ImportPath
, err
)
512 if err
!= nil && b
.IsCmdList
&& b
.NeedError
&& p
.Error
== nil {
513 p
.Error
= &load
.PackageError
{Err
: err
}
517 // In -n mode, print a banner between packages.
518 // The banner is five lines so that when changes to
519 // different sections of the bootstrap script have to
520 // be merged, the banners give patch something
521 // to use to find its context.
522 b
.Print("\n#\n# " + a
.Package
.ImportPath
+ "\n#\n\n")
526 b
.Print(a
.Package
.ImportPath
+ "\n")
529 if a
.Package
.BinaryOnly
{
531 p
.StaleReason
= "binary-only packages are no longer supported"
535 return errors
.New("binary-only packages are no longer supported")
538 if err
:= b
.Mkdir(a
.Objdir
); err
!= nil {
543 // Load cached cgo header, but only if we're skipping the main build (cachedBuild==true).
544 if cachedBuild
&& need
&needCgoHdr
!= 0 {
545 if err
:= b
.loadCachedCgoHdr(a
); err
== nil {
550 // Load cached vet config, but only if that's all we have left
551 // (need == needVet, not testing just the one bit).
552 // If we are going to do a full build anyway,
553 // we're going to regenerate the files below anyway.
555 if err
:= b
.loadCachedVet(a
); err
== nil {
563 if err
:= allowInstall(a
); err
!= nil {
567 // make target directory
568 dir
, _
:= filepath
.Split(a
.Target
)
570 if err
:= b
.Mkdir(dir
); err
!= nil {
575 gofiles
:= str
.StringList(a
.Package
.GoFiles
)
576 cgofiles
:= str
.StringList(a
.Package
.CgoFiles
)
577 cfiles
:= str
.StringList(a
.Package
.CFiles
)
578 sfiles
:= str
.StringList(a
.Package
.SFiles
)
579 cxxfiles
:= str
.StringList(a
.Package
.CXXFiles
)
580 var objects
, cgoObjects
, pcCFLAGS
, pcLDFLAGS
[]string
582 if a
.Package
.UsesCgo() || a
.Package
.UsesSwig() {
583 if pcCFLAGS
, pcLDFLAGS
, err
= b
.getPkgConfigFlags(a
.Package
); err
!= nil {
588 // Compute overlays for .c/.cc/.h/etc. and if there are any overlays
589 // put correct contents of all those files in the objdir, to ensure
590 // the correct headers are included. nonGoOverlay is the overlay that
591 // points from nongo files to the copied files in objdir.
592 nonGoFileLists
:= [][]string{a
.Package
.CFiles
, a
.Package
.SFiles
, a
.Package
.CXXFiles
, a
.Package
.HFiles
, a
.Package
.FFiles
}
594 for _
, fs
:= range nonGoFileLists
{
595 for _
, f
:= range fs
{
596 if _
, ok
:= fsys
.OverlayPath(mkAbs(p
.Dir
, f
)); ok
{
597 a
.nonGoOverlay
= make(map[string]string)
602 if a
.nonGoOverlay
!= nil {
603 for _
, fs
:= range nonGoFileLists
{
605 from
:= mkAbs(p
.Dir
, fs
[i
])
606 opath
, _
:= fsys
.OverlayPath(from
)
607 dst
:= objdir
+ filepath
.Base(fs
[i
])
608 if err
:= b
.copyFile(dst
, opath
, 0666, false); err
!= nil {
611 a
.nonGoOverlay
[from
] = dst
616 // Run SWIG on each .swig and .swigcxx file.
617 // Each run will generate two files, a .go file and a .c or .cxx file.
618 // The .go file will use import "C" and is to be processed by cgo.
619 if a
.Package
.UsesSwig() {
620 outGo
, outC
, outCXX
, err
:= b
.swig(a
, a
.Package
, objdir
, pcCFLAGS
)
624 cgofiles
= append(cgofiles
, outGo
...)
625 cfiles
= append(cfiles
, outC
...)
626 cxxfiles
= append(cxxfiles
, outCXX
...)
629 // If we're doing coverage, preprocess the .go files and put them in the work directory
630 if a
.Package
.Internal
.CoverMode
!= "" {
631 for i
, file
:= range str
.StringList(gofiles
, cgofiles
) {
632 var sourceFile
string
635 if strings
.HasSuffix(file
, ".cgo1.go") {
636 // cgo files have absolute paths
637 base
:= filepath
.Base(file
)
639 coverFile
= objdir
+ base
640 key
= strings
.TrimSuffix(base
, ".cgo1.go") + ".go"
642 sourceFile
= filepath
.Join(a
.Package
.Dir
, file
)
643 coverFile
= objdir
+ file
646 coverFile
= strings
.TrimSuffix(coverFile
, ".go") + ".cover.go"
647 cover
:= a
.Package
.Internal
.CoverVars
[key
]
648 if cover
== nil || base
.IsTestFile(file
) {
649 // Not covering this file.
652 if err
:= b
.cover(a
, coverFile
, sourceFile
, cover
.Var
); err
!= nil {
655 if i
< len(gofiles
) {
656 gofiles
[i
] = coverFile
658 cgofiles
[i
-len(gofiles
)] = coverFile
664 if a
.Package
.UsesCgo() || a
.Package
.UsesSwig() {
665 // In a package using cgo, cgo compiles the C, C++ and assembly files with gcc.
666 // There is one exception: runtime/cgo's job is to bridge the
667 // cgo and non-cgo worlds, so it necessarily has files in both.
668 // In that case gcc only gets the gcc_* files.
669 var gccfiles
[]string
670 gccfiles
= append(gccfiles
, cfiles
...)
672 if a
.Package
.Standard
&& a
.Package
.ImportPath
== "runtime/cgo" {
673 filter
:= func(files
, nongcc
, gcc
[]string) ([]string, []string) {
674 for _
, f
:= range files
{
675 if strings
.HasPrefix(f
, "gcc_") {
678 nongcc
= append(nongcc
, f
)
683 sfiles
, gccfiles
= filter(sfiles
, sfiles
[:0], gccfiles
)
685 for _
, sfile
:= range sfiles
{
686 data
, err
:= os
.ReadFile(filepath
.Join(a
.Package
.Dir
, sfile
))
688 if bytes
.HasPrefix(data
, []byte("TEXT")) || bytes
.Contains(data
, []byte("\nTEXT")) ||
689 bytes
.HasPrefix(data
, []byte("DATA")) || bytes
.Contains(data
, []byte("\nDATA")) ||
690 bytes
.HasPrefix(data
, []byte("GLOBL")) || bytes
.Contains(data
, []byte("\nGLOBL")) {
691 return fmt
.Errorf("package using cgo has Go assembly file %s", sfile
)
695 gccfiles
= append(gccfiles
, sfiles
...)
699 outGo
, outObj
, err
:= b
.cgo(a
, base
.Tool("cgo"), objdir
, pcCFLAGS
, pcLDFLAGS
, mkAbsFiles(a
.Package
.Dir
, cgofiles
), gccfiles
, cxxfiles
, a
.Package
.MFiles
, a
.Package
.FFiles
)
701 // The files in cxxfiles have now been handled by b.cgo.
707 if cfg
.BuildToolchainName
== "gccgo" {
708 cgoObjects
= append(cgoObjects
, a
.Objdir
+"_cgo_flags")
710 cgoObjects
= append(cgoObjects
, outObj
...)
711 gofiles
= append(gofiles
, outGo
...)
713 switch cfg
.BuildBuildmode
{
714 case "c-archive", "c-shared":
719 var srcfiles
[]string // .go and non-.go
720 srcfiles
= append(srcfiles
, gofiles
...)
721 srcfiles
= append(srcfiles
, sfiles
...)
722 srcfiles
= append(srcfiles
, cfiles
...)
723 srcfiles
= append(srcfiles
, cxxfiles
...)
724 b
.cacheSrcFiles(a
, srcfiles
)
726 // Running cgo generated the cgo header.
729 // Sanity check only, since Package.load already checked as well.
730 if len(gofiles
) == 0 {
731 return &load
.NoGoError
{Package
: a
.Package
}
734 // Prepare Go vet config if needed.
735 if need
&needVet
!= 0 {
736 buildVetConfig(a
, srcfiles
)
739 if need
&needCompiledGoFiles
!= 0 {
740 if err
:= b
.loadCachedSrcFiles(a
); err
!= nil {
741 return fmt
.Errorf("loading compiled Go files from cache: %w", err
)
743 need
&^= needCompiledGoFiles
746 // Nothing left to do.
750 // Collect symbol ABI requirements from assembly.
751 symabis
, err
:= BuildToolchain
.symabis(b
, a
, sfiles
)
756 // Prepare Go import config.
757 // We start it off with a comment so it can't be empty, so icfg.Bytes() below is never nil.
758 // It should never be empty anyway, but there have been bugs in the past that resulted
759 // in empty configs, which then unfortunately turn into "no config passed to compiler",
760 // and the compiler falls back to looking in pkg itself, which mostly works,
761 // except when it doesn't.
762 var icfg bytes
.Buffer
763 fmt
.Fprintf(&icfg
, "# import config\n")
764 for i
, raw
:= range a
.Package
.Internal
.RawImports
{
765 final
:= a
.Package
.Imports
[i
]
767 fmt
.Fprintf(&icfg
, "importmap %s=%s\n", raw
, final
)
770 for _
, a1
:= range a
.Deps
{
772 if p1
== nil || p1
.ImportPath
== "" {
776 fmt
.Fprintf(&icfg
, "packagefile %s=%s\n", p1
.ImportPath
, a1
.built
)
780 // Prepare Go embed config if needed.
781 // Unlike the import config, it's okay for the embed config to be empty.
783 if len(p
.Internal
.Embed
) > 0 {
785 Patterns
map[string][]string
786 Files
map[string]string
788 embed
.Patterns
= p
.Internal
.Embed
789 embed
.Files
= make(map[string]string)
790 for _
, file
:= range p
.EmbedFiles
{
791 embed
.Files
[file
] = filepath
.Join(p
.Dir
, file
)
793 js
, err
:= json
.MarshalIndent(&embed
, "", "\t")
795 return fmt
.Errorf("marshal embedcfg: %v", err
)
800 if p
.Internal
.BuildInfo
!= "" && cfg
.ModulesEnabled
{
801 prog
:= modload
.ModInfoProg(p
.Internal
.BuildInfo
, cfg
.BuildToolchainName
== "gccgo")
803 if err
:= b
.writeFile(objdir
+"_gomod_.go", prog
); err
!= nil {
806 gofiles
= append(gofiles
, objdir
+"_gomod_.go")
811 objpkg
:= objdir
+ "_pkg_.a"
812 ofile
, out
, err
:= BuildToolchain
.gc(b
, a
, objpkg
, icfg
.Bytes(), embedcfg
, symabis
, len(sfiles
) > 0, gofiles
)
814 output
:= b
.processOutput(out
)
815 if p
.Module
!= nil && !allowedVersion(p
.Module
.GoVersion
) {
816 output
+= "note: module requires Go " + p
.Module
.GoVersion
+ "\n"
818 b
.showOutput(a
, a
.Package
.Dir
, a
.Package
.Desc(), output
)
820 return errPrintedOutput
824 if p
.Module
!= nil && !allowedVersion(p
.Module
.GoVersion
) {
825 b
.showOutput(a
, a
.Package
.Dir
, a
.Package
.Desc(), "note: module requires Go "+p
.Module
.GoVersion
+"\n")
830 objects
= append(objects
, ofile
)
833 // Copy .h files named for goos or goarch or goos_goarch
834 // to names using GOOS and GOARCH.
835 // For example, defs_linux_amd64.h becomes defs_GOOS_GOARCH.h.
836 _goos_goarch
:= "_" + cfg
.Goos
+ "_" + cfg
.Goarch
837 _goos
:= "_" + cfg
.Goos
838 _goarch
:= "_" + cfg
.Goarch
839 for _
, file
:= range a
.Package
.HFiles
{
840 name
, ext
:= fileExtSplit(file
)
842 case strings
.HasSuffix(name
, _goos_goarch
):
843 targ
:= file
[:len(name
)-len(_goos_goarch
)] + "_GOOS_GOARCH." + ext
844 if err
:= b
.copyFile(objdir
+targ
, filepath
.Join(a
.Package
.Dir
, file
), 0666, true); err
!= nil {
847 case strings
.HasSuffix(name
, _goarch
):
848 targ
:= file
[:len(name
)-len(_goarch
)] + "_GOARCH." + ext
849 if err
:= b
.copyFile(objdir
+targ
, filepath
.Join(a
.Package
.Dir
, file
), 0666, true); err
!= nil {
852 case strings
.HasSuffix(name
, _goos
):
853 targ
:= file
[:len(name
)-len(_goos
)] + "_GOOS." + ext
854 if err
:= b
.copyFile(objdir
+targ
, filepath
.Join(a
.Package
.Dir
, file
), 0666, true); err
!= nil {
860 for _
, file
:= range cfiles
{
861 out
:= file
[:len(file
)-len(".c")] + ".o"
862 if err
:= BuildToolchain
.cc(b
, a
, objdir
+out
, file
); err
!= nil {
865 objects
= append(objects
, out
)
868 // Assemble .s files.
870 ofiles
, err
:= BuildToolchain
.asm(b
, a
, sfiles
)
874 objects
= append(objects
, ofiles
...)
877 // For gccgo on ELF systems, we write the build ID as an assembler file.
878 // This lets us set the SHF_EXCLUDE flag.
879 // This is read by readGccgoArchive in cmd/internal/buildid/buildid.go.
880 if a
.buildID
!= "" && cfg
.BuildToolchainName
== "gccgo" {
882 case "aix", "android", "dragonfly", "freebsd", "illumos", "linux", "netbsd", "openbsd", "solaris":
883 asmfile
, err
:= b
.gccgoBuildIDFile(a
)
887 ofiles
, err
:= BuildToolchain
.asm(b
, a
, []string{asmfile
})
891 objects
= append(objects
, ofiles
...)
895 // NOTE(rsc): On Windows, it is critically important that the
896 // gcc-compiled objects (cgoObjects) be listed after the ordinary
897 // objects in the archive. I do not know why this is.
898 // https://golang.org/issue/2601
899 objects
= append(objects
, cgoObjects
...)
901 // Add system object files.
902 for _
, syso
:= range a
.Package
.SysoFiles
{
903 objects
= append(objects
, filepath
.Join(a
.Package
.Dir
, syso
))
906 // Pack into archive in objdir directory.
907 // If the Go compiler wrote an archive, we only need to add the
908 // object files for non-Go sources to the archive.
909 // If the Go compiler wrote an archive and the package is entirely
910 // Go sources, there is no pack to execute at all.
911 if len(objects
) > 0 {
912 if err
:= BuildToolchain
.pack(b
, a
, objpkg
, objects
); err
!= nil {
917 if err
:= b
.updateBuildID(a
, objpkg
, true); err
!= nil {
925 func (b
*Builder
) cacheObjdirFile(a
*Action
, c
*cache
.Cache
, name
string) error
{
926 f
, err
:= os
.Open(a
.Objdir
+ name
)
931 _
, _
, err
= c
.Put(cache
.Subkey(a
.actionID
, name
), f
)
935 func (b
*Builder
) findCachedObjdirFile(a
*Action
, c
*cache
.Cache
, name
string) (string, error
) {
936 file
, _
, err
:= c
.GetFile(cache
.Subkey(a
.actionID
, name
))
938 return "", fmt
.Errorf("loading cached file %s: %w", name
, err
)
943 func (b
*Builder
) loadCachedObjdirFile(a
*Action
, c
*cache
.Cache
, name
string) error
{
944 cached
, err
:= b
.findCachedObjdirFile(a
, c
, name
)
948 return b
.copyFile(a
.Objdir
+name
, cached
, 0666, true)
951 func (b
*Builder
) cacheCgoHdr(a
*Action
) {
953 b
.cacheObjdirFile(a
, c
, "_cgo_install.h")
956 func (b
*Builder
) loadCachedCgoHdr(a
*Action
) error
{
958 return b
.loadCachedObjdirFile(a
, c
, "_cgo_install.h")
961 func (b
*Builder
) cacheSrcFiles(a
*Action
, srcfiles
[]string) {
964 for _
, file
:= range srcfiles
{
965 if !strings
.HasPrefix(file
, a
.Objdir
) {
967 buf
.WriteString("./")
968 buf
.WriteString(file
)
969 buf
.WriteString("\n")
972 name
:= file
[len(a
.Objdir
):]
973 buf
.WriteString(name
)
974 buf
.WriteString("\n")
975 if err
:= b
.cacheObjdirFile(a
, c
, name
); err
!= nil {
979 c
.PutBytes(cache
.Subkey(a
.actionID
, "srcfiles"), buf
.Bytes())
982 func (b
*Builder
) loadCachedVet(a
*Action
) error
{
984 list
, _
, err
:= c
.GetBytes(cache
.Subkey(a
.actionID
, "srcfiles"))
986 return fmt
.Errorf("reading srcfiles list: %w", err
)
988 var srcfiles
[]string
989 for _
, name
:= range strings
.Split(string(list
), "\n") {
990 if name
== "" { // end of list
993 if strings
.HasPrefix(name
, "./") {
994 srcfiles
= append(srcfiles
, name
[2:])
997 if err
:= b
.loadCachedObjdirFile(a
, c
, name
); err
!= nil {
1000 srcfiles
= append(srcfiles
, a
.Objdir
+name
)
1002 buildVetConfig(a
, srcfiles
)
1006 func (b
*Builder
) loadCachedSrcFiles(a
*Action
) error
{
1007 c
:= cache
.Default()
1008 list
, _
, err
:= c
.GetBytes(cache
.Subkey(a
.actionID
, "srcfiles"))
1010 return fmt
.Errorf("reading srcfiles list: %w", err
)
1013 for _
, name
:= range strings
.Split(string(list
), "\n") {
1014 if name
== "" { // end of list
1017 if strings
.HasPrefix(name
, "./") {
1018 files
= append(files
, name
[len("./"):])
1021 file
, err
:= b
.findCachedObjdirFile(a
, c
, name
)
1023 return fmt
.Errorf("finding %s: %w", name
, err
)
1025 files
= append(files
, file
)
1027 a
.Package
.CompiledGoFiles
= files
1031 // vetConfig is the configuration passed to vet describing a single package.
1032 type vetConfig
struct {
1033 ID
string // package ID (example: "fmt [fmt.test]")
1034 Compiler
string // compiler name (gc, gccgo)
1035 Dir
string // directory containing package
1036 ImportPath
string // canonical import path ("package path")
1037 GoFiles
[]string // absolute paths to package source files
1038 NonGoFiles
[]string // absolute paths to package non-Go files
1039 IgnoredFiles
[]string // absolute paths to ignored source files
1041 ImportMap
map[string]string // map import path in source code to package path
1042 PackageFile
map[string]string // map package path to .a file with export data
1043 Standard
map[string]bool // map package path to whether it's in the standard library
1044 PackageVetx
map[string]string // map package path to vetx data from earlier vet run
1045 VetxOnly
bool // only compute vetx data; don't report detected problems
1046 VetxOutput
string // write vetx data to this output file
1048 SucceedOnTypecheckFailure
bool // awful hack; see #18395 and below
1051 func buildVetConfig(a
*Action
, srcfiles
[]string) {
1052 // Classify files based on .go extension.
1053 // srcfiles does not include raw cgo files.
1054 var gofiles
, nongofiles
[]string
1055 for _
, name
:= range srcfiles
{
1056 if strings
.HasSuffix(name
, ".go") {
1057 gofiles
= append(gofiles
, name
)
1059 nongofiles
= append(nongofiles
, name
)
1063 ignored
:= str
.StringList(a
.Package
.IgnoredGoFiles
, a
.Package
.IgnoredOtherFiles
)
1065 // Pass list of absolute paths to vet,
1066 // so that vet's error messages will use absolute paths,
1067 // so that we can reformat them relative to the directory
1068 // in which the go command is invoked.
1070 ID
: a
.Package
.ImportPath
,
1071 Compiler
: cfg
.BuildToolchainName
,
1073 GoFiles
: mkAbsFiles(a
.Package
.Dir
, gofiles
),
1074 NonGoFiles
: mkAbsFiles(a
.Package
.Dir
, nongofiles
),
1075 IgnoredFiles
: mkAbsFiles(a
.Package
.Dir
, ignored
),
1076 ImportPath
: a
.Package
.ImportPath
,
1077 ImportMap
: make(map[string]string),
1078 PackageFile
: make(map[string]string),
1079 Standard
: make(map[string]bool),
1082 for i
, raw
:= range a
.Package
.Internal
.RawImports
{
1083 final
:= a
.Package
.Imports
[i
]
1084 vcfg
.ImportMap
[raw
] = final
1087 // Compute the list of mapped imports in the vet config
1088 // so that we can add any missing mappings below.
1089 vcfgMapped
:= make(map[string]bool)
1090 for _
, p
:= range vcfg
.ImportMap
{
1091 vcfgMapped
[p
] = true
1094 for _
, a1
:= range a
.Deps
{
1096 if p1
== nil || p1
.ImportPath
== "" {
1099 // Add import mapping if needed
1100 // (for imports like "runtime/cgo" that appear only in generated code).
1101 if !vcfgMapped
[p1
.ImportPath
] {
1102 vcfg
.ImportMap
[p1
.ImportPath
] = p1
.ImportPath
1105 vcfg
.PackageFile
[p1
.ImportPath
] = a1
.built
1108 vcfg
.Standard
[p1
.ImportPath
] = true
1113 // VetTool is the path to an alternate vet tool binary.
1114 // The caller is expected to set it (if needed) before executing any vet actions.
1117 // VetFlags are the default flags to pass to vet.
1118 // The caller is expected to set them before executing any vet actions.
1119 var VetFlags
[]string
1121 // VetExplicit records whether the vet flags were set explicitly on the command line.
1122 var VetExplicit
bool
1124 func (b
*Builder
) vet(ctx context
.Context
, a
*Action
) error
{
1125 // a.Deps[0] is the build of the package being vetted.
1126 // a.Deps[1] is the build of the "fmt" package.
1128 a
.Failed
= false // vet of dependency may have failed but we can still succeed
1130 if a
.Deps
[0].Failed
{
1131 // The build of the package has failed. Skip vet check.
1132 // Vet could return export data for non-typecheck errors,
1133 // but we ignore it because the package cannot be compiled.
1137 vcfg
:= a
.Deps
[0].vetCfg
1139 // Vet config should only be missing if the build failed.
1140 return fmt
.Errorf("vet config not found")
1143 vcfg
.VetxOnly
= a
.VetxOnly
1144 vcfg
.VetxOutput
= a
.Objdir
+ "vet.out"
1145 vcfg
.PackageVetx
= make(map[string]string)
1147 h
:= cache
.NewHash("vet " + a
.Package
.ImportPath
)
1148 fmt
.Fprintf(h
, "vet %q\n", b
.toolID("vet"))
1150 vetFlags
:= VetFlags
1152 // In GOROOT, we enable all the vet tests during 'go test',
1153 // not just the high-confidence subset. This gets us extra
1154 // checking for the standard library (at some compliance cost)
1155 // and helps us gain experience about how well the checks
1156 // work, to help decide which should be turned on by default.
1157 // The command-line still wins.
1159 // Note that this flag change applies even when running vet as
1160 // a dependency of vetting a package outside std.
1161 // (Otherwise we'd have to introduce a whole separate
1162 // space of "vet fmt as a dependency of a std top-level vet"
1163 // versus "vet fmt as a dependency of a non-std top-level vet".)
1164 // This is OK as long as the packages that are farther down the
1165 // dependency tree turn on *more* analysis, as here.
1166 // (The unsafeptr check does not write any facts for use by
1167 // later vet runs, nor does unreachable.)
1168 if a
.Package
.Goroot
&& !VetExplicit
&& VetTool
== "" {
1169 // Turn off -unsafeptr checks.
1170 // There's too much unsafe.Pointer code
1171 // that vet doesn't like in low-level packages
1172 // like runtime, sync, and reflect.
1173 // Note that $GOROOT/src/buildall.bash
1174 // does the same for the misc-compile trybots
1175 // and should be updated if these flags are
1177 vetFlags
= []string{"-unsafeptr=false"}
1179 // Also turn off -unreachable checks during go test.
1180 // During testing it is very common to make changes
1181 // like hard-coded forced returns or panics that make
1182 // code unreachable. It's unreasonable to insist on files
1183 // not having any unreachable code during "go test".
1184 // (buildall.bash still runs with -unreachable enabled
1185 // for the overall whole-tree scan.)
1186 if cfg
.CmdName
== "test" {
1187 vetFlags
= append(vetFlags
, "-unreachable=false")
1191 // Note: We could decide that vet should compute export data for
1192 // all analyses, in which case we don't need to include the flags here.
1193 // But that would mean that if an analysis causes problems like
1194 // unexpected crashes there would be no way to turn it off.
1195 // It seems better to let the flags disable export analysis too.
1196 fmt
.Fprintf(h
, "vetflags %q\n", vetFlags
)
1198 fmt
.Fprintf(h
, "pkg %q\n", a
.Deps
[0].actionID
)
1199 for _
, a1
:= range a
.Deps
{
1200 if a1
.Mode
== "vet" && a1
.built
!= "" {
1201 fmt
.Fprintf(h
, "vetout %q %s\n", a1
.Package
.ImportPath
, b
.fileHash(a1
.built
))
1202 vcfg
.PackageVetx
[a1
.Package
.ImportPath
] = a1
.built
1205 key
:= cache
.ActionID(h
.Sum())
1207 if vcfg
.VetxOnly
&& !cfg
.BuildA
{
1208 c
:= cache
.Default()
1209 if file
, _
, err
:= c
.GetFile(key
); err
== nil {
1215 js
, err
:= json
.MarshalIndent(vcfg
, "", "\t")
1217 return fmt
.Errorf("internal error marshaling vet config: %v", err
)
1219 js
= append(js
, '\n')
1220 if err
:= b
.writeFile(a
.Objdir
+"vet.cfg", js
); err
!= nil {
1224 // TODO(rsc): Why do we pass $GCCGO to go vet?
1225 env
:= b
.cCompilerEnv()
1226 if cfg
.BuildToolchainName
== "gccgo" {
1227 env
= append(env
, "GCCGO="+BuildToolchain
.compiler())
1233 tool
= base
.Tool("vet")
1235 runErr
:= b
.run(a
, p
.Dir
, p
.ImportPath
, env
, cfg
.BuildToolexec
, tool
, vetFlags
, a
.Objdir
+"vet.cfg")
1237 // If vet wrote export data, save it for input to future vets.
1238 if f
, err
:= os
.Open(vcfg
.VetxOutput
); err
== nil {
1239 a
.built
= vcfg
.VetxOutput
1240 cache
.Default().Put(key
, f
)
1247 // linkActionID computes the action ID for a link action.
1248 func (b
*Builder
) linkActionID(a
*Action
) cache
.ActionID
{
1250 h
:= cache
.NewHash("link " + p
.ImportPath
)
1252 // Toolchain-independent configuration.
1253 fmt
.Fprintf(h
, "link\n")
1254 fmt
.Fprintf(h
, "buildmode %s goos %s goarch %s\n", cfg
.BuildBuildmode
, cfg
.Goos
, cfg
.Goarch
)
1255 fmt
.Fprintf(h
, "import %q\n", p
.ImportPath
)
1256 fmt
.Fprintf(h
, "omitdebug %v standard %v local %v prefix %q\n", p
.Internal
.OmitDebug
, p
.Standard
, p
.Internal
.Local
, p
.Internal
.LocalPrefix
)
1257 if cfg
.BuildTrimpath
{
1258 fmt
.Fprintln(h
, "trimpath")
1261 // Toolchain-dependent configuration, shared with b.linkSharedActionID.
1262 b
.printLinkerConfig(h
, p
)
1265 for _
, a1
:= range a
.Deps
{
1268 if a1
.built
!= "" || a1
.buildID
!= "" {
1269 buildID
:= a1
.buildID
1271 buildID
= b
.buildID(a1
.built
)
1273 fmt
.Fprintf(h
, "packagefile %s=%s\n", p1
.ImportPath
, contentID(buildID
))
1275 // Because we put package main's full action ID into the binary's build ID,
1276 // we must also put the full action ID into the binary's action ID hash.
1277 if p1
.Name
== "main" {
1278 fmt
.Fprintf(h
, "packagemain %s\n", a1
.buildID
)
1281 fmt
.Fprintf(h
, "packageshlib %s=%s\n", p1
.ImportPath
, contentID(b
.buildID(p1
.Shlib
)))
1289 // printLinkerConfig prints the linker config into the hash h,
1290 // as part of the computation of a linker-related action ID.
1291 func (b
*Builder
) printLinkerConfig(h io
.Writer
, p
*load
.Package
) {
1292 switch cfg
.BuildToolchainName
{
1294 base
.Fatalf("linkActionID: unknown toolchain %q", cfg
.BuildToolchainName
)
1297 fmt
.Fprintf(h
, "link %s %q %s\n", b
.toolID("link"), forcedLdflags
, ldBuildmode
)
1299 fmt
.Fprintf(h
, "linkflags %q\n", p
.Internal
.Ldflags
)
1302 // GOARM, GOMIPS, etc.
1303 key
, val
:= cfg
.GetArchEnv()
1304 fmt
.Fprintf(h
, "%s=%s\n", key
, val
)
1306 if goexperiment
:= buildcfg
.GOEXPERIMENT(); goexperiment
!= "" {
1307 fmt
.Fprintf(h
, "GOEXPERIMENT=%q\n", goexperiment
)
1310 // The linker writes source file paths that say GOROOT_FINAL, but
1311 // only if -trimpath is not specified (see ld() in gc.go).
1312 gorootFinal
:= cfg
.GOROOT_FINAL
1313 if cfg
.BuildTrimpath
{
1314 gorootFinal
= trimPathGoRootFinal
1316 fmt
.Fprintf(h
, "GOROOT=%s\n", gorootFinal
)
1318 // GO_EXTLINK_ENABLED controls whether the external linker is used.
1319 fmt
.Fprintf(h
, "GO_EXTLINK_ENABLED=%s\n", cfg
.Getenv("GO_EXTLINK_ENABLED"))
1321 // TODO(rsc): Do cgo settings and flags need to be included?
1322 // Or external linker settings and flags?
1325 id
, err
:= b
.gccToolID(BuildToolchain
.linker(), "go")
1327 base
.Fatalf("%v", err
)
1329 fmt
.Fprintf(h
, "link %s %s\n", id
, ldBuildmode
)
1330 // TODO(iant): Should probably include cgo flags here.
1334 // link is the action for linking a single command.
1335 // Note that any new influence on this logic must be reported in b.linkActionID above as well.
1336 func (b
*Builder
) link(ctx context
.Context
, a
*Action
) (err error
) {
1337 if b
.useCache(a
, b
.linkActionID(a
), a
.Package
.Target
) || b
.IsCmdList
{
1340 defer b
.flushOutput(a
)
1342 if err
:= b
.Mkdir(a
.Objdir
); err
!= nil {
1346 importcfg
:= a
.Objdir
+ "importcfg.link"
1347 if err
:= b
.writeLinkImportcfg(a
, importcfg
); err
!= nil {
1351 if err
:= allowInstall(a
); err
!= nil {
1355 // make target directory
1356 dir
, _
:= filepath
.Split(a
.Target
)
1358 if err
:= b
.Mkdir(dir
); err
!= nil {
1363 if err
:= BuildToolchain
.ld(b
, a
, a
.Target
, importcfg
, a
.Deps
[0].built
); err
!= nil {
1367 // Update the binary with the final build ID.
1368 // But if OmitDebug is set, don't rewrite the binary, because we set OmitDebug
1369 // on binaries that we are going to run and then delete.
1370 // There's no point in doing work on such a binary.
1371 // Worse, opening the binary for write here makes it
1372 // essentially impossible to safely fork+exec due to a fundamental
1373 // incompatibility between ETXTBSY and threads on modern Unix systems.
1374 // See golang.org/issue/22220.
1375 // We still call updateBuildID to update a.buildID, which is important
1376 // for test result caching, but passing rewrite=false (final arg)
1377 // means we don't actually rewrite the binary, nor store the
1378 // result into the cache. That's probably a net win:
1379 // less cache space wasted on large binaries we are not likely to
1380 // need again. (On the other hand it does make repeated go test slower.)
1381 // It also makes repeated go run slower, which is a win in itself:
1382 // we don't want people to treat go run like a scripting environment.
1383 if err
:= b
.updateBuildID(a
, a
.Target
, !a
.Package
.Internal
.OmitDebug
); err
!= nil {
1391 func (b
*Builder
) writeLinkImportcfg(a
*Action
, file
string) error
{
1392 // Prepare Go import cfg.
1393 var icfg bytes
.Buffer
1394 for _
, a1
:= range a
.Deps
{
1399 fmt
.Fprintf(&icfg
, "packagefile %s=%s\n", p1
.ImportPath
, a1
.built
)
1401 fmt
.Fprintf(&icfg
, "packageshlib %s=%s\n", p1
.ImportPath
, p1
.Shlib
)
1404 fmt
.Fprintf(&icfg
, "modinfo %q\n", modload
.ModInfoData(a
.Package
.Internal
.BuildInfo
))
1405 return b
.writeFile(file
, icfg
.Bytes())
1408 // PkgconfigCmd returns a pkg-config binary name
1409 // defaultPkgConfig is defined in zdefaultcc.go, written by cmd/dist.
1410 func (b
*Builder
) PkgconfigCmd() string {
1411 return envList("PKG_CONFIG", cfg
.DefaultPkgConfig
)[0]
1414 // splitPkgConfigOutput parses the pkg-config output into a slice of
1415 // flags. This implements the algorithm from pkgconf/libpkgconf/argvsplit.c.
1416 func splitPkgConfigOutput(out
[]byte) ([]string, error
) {
1421 flag
:= make([]byte, 0, len(out
))
1425 for _
, c
:= range out
{
1429 case '$', '`', '"', '\\':
1431 flag
= append(flag
, '\\')
1433 flag
= append(flag
, c
)
1435 flag
= append(flag
, c
)
1438 } else if quote
!= 0 {
1446 flag
= append(flag
, c
)
1449 } else if strings
.IndexByte(" \t\n\v\f\r", c
) < 0 {
1456 flag
= append(flag
, c
)
1458 } else if len(flag
) != 0 {
1459 flags
= append(flags
, string(flag
))
1464 return nil, errors
.New("broken character escaping in pkgconf output ")
1467 return nil, errors
.New("unterminated quoted string in pkgconf output ")
1468 } else if len(flag
) != 0 {
1469 flags
= append(flags
, string(flag
))
1475 // Calls pkg-config if needed and returns the cflags/ldflags needed to build the package.
1476 func (b
*Builder
) getPkgConfigFlags(p
*load
.Package
) (cflags
, ldflags
[]string, err error
) {
1477 if pcargs
:= p
.CgoPkgConfig
; len(pcargs
) > 0 {
1478 // pkg-config permits arguments to appear anywhere in
1479 // the command line. Move them all to the front, before --.
1480 var pcflags
[]string
1482 for _
, pcarg
:= range pcargs
{
1484 // We're going to add our own "--" argument.
1485 } else if strings
.HasPrefix(pcarg
, "--") {
1486 pcflags
= append(pcflags
, pcarg
)
1488 pkgs
= append(pkgs
, pcarg
)
1491 for _
, pkg
:= range pkgs
{
1492 if !load
.SafeArg(pkg
) {
1493 return nil, nil, fmt
.Errorf("invalid pkg-config package name: %s", pkg
)
1497 out
, err
= b
.runOut(nil, p
.Dir
, nil, b
.PkgconfigCmd(), "--cflags", pcflags
, "--", pkgs
)
1499 b
.showOutput(nil, p
.Dir
, b
.PkgconfigCmd()+" --cflags "+strings
.Join(pcflags
, " ")+" -- "+strings
.Join(pkgs
, " "), string(out
))
1500 b
.Print(err
.Error() + "\n")
1501 return nil, nil, errPrintedOutput
1504 cflags
, err
= splitPkgConfigOutput(out
)
1506 return nil, nil, err
1508 if err
:= checkCompilerFlags("CFLAGS", "pkg-config --cflags", cflags
); err
!= nil {
1509 return nil, nil, err
1512 out
, err
= b
.runOut(nil, p
.Dir
, nil, b
.PkgconfigCmd(), "--libs", pcflags
, "--", pkgs
)
1514 b
.showOutput(nil, p
.Dir
, b
.PkgconfigCmd()+" --libs "+strings
.Join(pcflags
, " ")+" -- "+strings
.Join(pkgs
, " "), string(out
))
1515 b
.Print(err
.Error() + "\n")
1516 return nil, nil, errPrintedOutput
1519 // NOTE: we don't attempt to parse quotes and unescapes here. pkg-config
1520 // is typically used within shell backticks, which treats quotes literally.
1521 ldflags
= strings
.Fields(string(out
))
1522 if err
:= checkLinkerFlags("LDFLAGS", "pkg-config --libs", ldflags
); err
!= nil {
1523 return nil, nil, err
1531 func (b
*Builder
) installShlibname(ctx context
.Context
, a
*Action
) error
{
1532 if err
:= allowInstall(a
); err
!= nil {
1538 err
:= os
.WriteFile(a
.Target
, []byte(filepath
.Base(a1
.Target
)+"\n"), 0666)
1543 b
.Showcmd("", "echo '%s' > %s # internal", filepath
.Base(a1
.Target
), a
.Target
)
1548 func (b
*Builder
) linkSharedActionID(a
*Action
) cache
.ActionID
{
1549 h
:= cache
.NewHash("linkShared")
1551 // Toolchain-independent configuration.
1552 fmt
.Fprintf(h
, "linkShared\n")
1553 fmt
.Fprintf(h
, "goos %s goarch %s\n", cfg
.Goos
, cfg
.Goarch
)
1555 // Toolchain-dependent configuration, shared with b.linkActionID.
1556 b
.printLinkerConfig(h
, nil)
1559 for _
, a1
:= range a
.Deps
{
1565 fmt
.Fprintf(h
, "packagefile %s=%s\n", p1
.ImportPath
, contentID(b
.buildID(a1
.built
)))
1567 fmt
.Fprintf(h
, "packageshlib %s=%s\n", p1
.ImportPath
, contentID(b
.buildID(p1
.Shlib
)))
1571 // Files named on command line are special.
1572 for _
, a1
:= range a
.Deps
[0].Deps
{
1574 fmt
.Fprintf(h
, "top %s=%s\n", p1
.ImportPath
, contentID(b
.buildID(a1
.built
)))
1580 func (b
*Builder
) linkShared(ctx context
.Context
, a
*Action
) (err error
) {
1581 if b
.useCache(a
, b
.linkSharedActionID(a
), a
.Target
) || b
.IsCmdList
{
1584 defer b
.flushOutput(a
)
1586 if err
:= allowInstall(a
); err
!= nil {
1590 if err
:= b
.Mkdir(a
.Objdir
); err
!= nil {
1594 importcfg
:= a
.Objdir
+ "importcfg.link"
1595 if err
:= b
.writeLinkImportcfg(a
, importcfg
); err
!= nil {
1599 // TODO(rsc): There is a missing updateBuildID here,
1600 // but we have to decide where to store the build ID in these files.
1602 return BuildToolchain
.ldShared(b
, a
, a
.Deps
[0].Deps
, a
.Target
, importcfg
, a
.Deps
)
1605 // BuildInstallFunc is the action for installing a single package or executable.
1606 func BuildInstallFunc(b
*Builder
, ctx context
.Context
, a
*Action
) (err error
) {
1608 if err
!= nil && err
!= errPrintedOutput
{
1609 // a.Package == nil is possible for the go install -buildmode=shared
1610 // action that installs libmangledname.so, which corresponds to
1611 // a list of packages, not just one.
1613 if a
.Package
!= nil {
1614 sep
, path
= " ", a
.Package
.ImportPath
1616 err
= fmt
.Errorf("go %s%s%s: %v", cfg
.CmdName
, sep
, path
, err
)
1621 a
.buildID
= a1
.buildID
1623 a
.json
.BuildID
= a
.buildID
1626 // If we are using the eventual install target as an up-to-date
1627 // cached copy of the thing we built, then there's no need to
1628 // copy it into itself (and that would probably fail anyway).
1629 // In this case a1.built == a.Target because a1.built == p.Target,
1630 // so the built target is not in the a1.Objdir tree that b.cleanup(a1) removes.
1631 if a1
.built
== a
.Target
{
1633 if !a
.buggyInstall
{
1636 // Whether we're smart enough to avoid a complete rebuild
1637 // depends on exactly what the staleness and rebuild algorithms
1638 // are, as well as potentially the state of the Go build cache.
1639 // We don't really want users to be able to infer (or worse start depending on)
1640 // those details from whether the modification time changes during
1641 // "go install", so do a best-effort update of the file times to make it
1642 // look like we rewrote a.Target even if we did not. Updating the mtime
1643 // may also help other mtime-based systems that depend on our
1644 // previous mtime updates that happened more often.
1645 // This is still not perfect - we ignore the error result, and if the file was
1646 // unwritable for some reason then pretending to have written it is also
1647 // confusing - but it's probably better than not doing the mtime update.
1649 // But don't do that for the special case where building an executable
1650 // with -linkshared implicitly installs all its dependent libraries.
1651 // We want to hide that awful detail as much as possible, so don't
1652 // advertise it by touching the mtimes (usually the libraries are up
1654 if !a
.buggyInstall
&& !b
.IsCmdList
{
1656 b
.Showcmd("", "touch %s", a
.Target
)
1657 } else if err
:= allowInstall(a
); err
== nil {
1659 os
.Chtimes(a
.Target
, now
, now
)
1665 // If we're building for go list -export,
1666 // never install anything; just keep the cache reference.
1671 if err
:= allowInstall(a
); err
!= nil {
1675 if err
:= b
.Mkdir(a
.Objdir
); err
!= nil {
1679 perm
:= fs
.FileMode(0666)
1680 if a1
.Mode
== "link" {
1681 switch cfg
.BuildBuildmode
{
1682 case "c-archive", "c-shared", "plugin":
1688 // make target directory
1689 dir
, _
:= filepath
.Split(a
.Target
)
1691 if err
:= b
.Mkdir(dir
); err
!= nil {
1696 if !a
.buggyInstall
{
1700 return b
.moveOrCopyFile(a
.Target
, a1
.built
, perm
, false)
1703 // allowInstall returns a non-nil error if this invocation of the go command is
1704 // allowed to install a.Target.
1706 // (The build of cmd/go running under its own test is forbidden from installing
1707 // to its original GOROOT.)
1708 var allowInstall
= func(*Action
) error
{ return nil }
1710 // cleanup removes a's object dir to keep the amount of
1711 // on-disk garbage down in a large build. On an operating system
1712 // with aggressive buffering, cleaning incrementally like
1713 // this keeps the intermediate objects from hitting the disk.
1714 func (b
*Builder
) cleanup(a
*Action
) {
1717 // Don't say we are removing the directory if
1718 // we never created it.
1719 if _
, err
:= os
.Stat(a
.Objdir
); err
== nil || cfg
.BuildN
{
1720 b
.Showcmd("", "rm -r %s", a
.Objdir
)
1723 os
.RemoveAll(a
.Objdir
)
1727 // moveOrCopyFile is like 'mv src dst' or 'cp src dst'.
1728 func (b
*Builder
) moveOrCopyFile(dst
, src
string, perm fs
.FileMode
, force
bool) error
{
1730 b
.Showcmd("", "mv %s %s", src
, dst
)
1734 // If we can update the mode and rename to the dst, do it.
1735 // Otherwise fall back to standard copy.
1737 // If the source is in the build cache, we need to copy it.
1738 if strings
.HasPrefix(src
, cache
.DefaultDir()) {
1739 return b
.copyFile(dst
, src
, perm
, force
)
1742 // On Windows, always copy the file, so that we respect the NTFS
1743 // permissions of the parent folder. https://golang.org/issue/22343.
1744 // What matters here is not cfg.Goos (the system we are building
1745 // for) but runtime.GOOS (the system we are building on).
1746 if runtime
.GOOS
== "windows" {
1747 return b
.copyFile(dst
, src
, perm
, force
)
1750 // If the destination directory has the group sticky bit set,
1751 // we have to copy the file to retain the correct permissions.
1752 // https://golang.org/issue/18878
1753 if fi
, err
:= os
.Stat(filepath
.Dir(dst
)); err
== nil {
1754 if fi
.IsDir() && (fi
.Mode()&fs
.ModeSetgid
) != 0 {
1755 return b
.copyFile(dst
, src
, perm
, force
)
1759 // The perm argument is meant to be adjusted according to umask,
1760 // but we don't know what the umask is.
1761 // Create a dummy file to find out.
1762 // This avoids build tags and works even on systems like Plan 9
1763 // where the file mask computation incorporates other information.
1765 f
, err
:= os
.OpenFile(filepath
.Clean(dst
)+"-go-tmp-umask", os
.O_WRONLY|os
.O_CREATE|os
.O_EXCL
, perm
)
1769 mode
= fi
.Mode() & 0777
1776 if err
:= os
.Chmod(src
, mode
); err
== nil {
1777 if err
:= os
.Rename(src
, dst
); err
== nil {
1779 b
.Showcmd("", "mv %s %s", src
, dst
)
1785 return b
.copyFile(dst
, src
, perm
, force
)
1788 // copyFile is like 'cp src dst'.
1789 func (b
*Builder
) copyFile(dst
, src
string, perm fs
.FileMode
, force
bool) error
{
1790 if cfg
.BuildN || cfg
.BuildX
{
1791 b
.Showcmd("", "cp %s %s", src
, dst
)
1797 sf
, err
:= os
.Open(src
)
1803 // Be careful about removing/overwriting dst.
1804 // Do not remove/overwrite if dst exists and is a directory
1805 // or a non-empty non-object file.
1806 if fi
, err
:= os
.Stat(dst
); err
== nil {
1808 return fmt
.Errorf("build output %q already exists and is a directory", dst
)
1810 if !force
&& fi
.Mode().IsRegular() && fi
.Size() != 0 && !isObject(dst
) {
1811 return fmt
.Errorf("build output %q already exists and is not an object file", dst
)
1815 // On Windows, remove lingering ~ file from last attempt.
1816 if base
.ToolIsWindows
{
1817 if _
, err
:= os
.Stat(dst
+ "~"); err
== nil {
1818 os
.Remove(dst
+ "~")
1822 mayberemovefile(dst
)
1823 df
, err
:= os
.OpenFile(dst
, os
.O_WRONLY|os
.O_CREATE|os
.O_TRUNC
, perm
)
1824 if err
!= nil && base
.ToolIsWindows
{
1825 // Windows does not allow deletion of a binary file
1826 // while it is executing. Try to move it out of the way.
1827 // If the move fails, which is likely, we'll try again the
1828 // next time we do an install of this binary.
1829 if err
:= os
.Rename(dst
, dst
+"~"); err
== nil {
1830 os
.Remove(dst
+ "~")
1832 df
, err
= os
.OpenFile(dst
, os
.O_WRONLY|os
.O_CREATE|os
.O_TRUNC
, perm
)
1835 return fmt
.Errorf("copying %s: %w", src
, err
) // err should already refer to dst
1838 _
, err
= io
.Copy(df
, sf
)
1841 mayberemovefile(dst
)
1842 return fmt
.Errorf("copying %s to %s: %v", src
, dst
, err
)
1847 // writeFile writes the text to file.
1848 func (b
*Builder
) writeFile(file
string, text
[]byte) error
{
1849 if cfg
.BuildN || cfg
.BuildX
{
1850 b
.Showcmd("", "cat >%s << 'EOF' # internal\n%sEOF", file
, text
)
1855 return os
.WriteFile(file
, text
, 0666)
1858 // Install the cgo export header file, if there is one.
1859 func (b
*Builder
) installHeader(ctx context
.Context
, a
*Action
) error
{
1860 src
:= a
.Objdir
+ "_cgo_install.h"
1861 if _
, err
:= os
.Stat(src
); os
.IsNotExist(err
) {
1862 // If the file does not exist, there are no exported
1863 // functions, and we do not install anything.
1864 // TODO(rsc): Once we know that caching is rebuilding
1865 // at the right times (not missing rebuilds), here we should
1866 // probably delete the installed header, if any.
1868 b
.Showcmd("", "# %s not created", src
)
1873 if err
:= allowInstall(a
); err
!= nil {
1877 dir
, _
:= filepath
.Split(a
.Target
)
1879 if err
:= b
.Mkdir(dir
); err
!= nil {
1884 return b
.moveOrCopyFile(a
.Target
, src
, 0666, true)
1887 // cover runs, in effect,
1888 // go tool cover -mode=b.coverMode -var="varName" -o dst.go src.go
1889 func (b
*Builder
) cover(a
*Action
, dst
, src
string, varName
string) error
{
1890 return b
.run(a
, a
.Objdir
, "cover "+a
.Package
.ImportPath
, nil,
1893 "-mode", a
.Package
.Internal
.CoverMode
,
1899 var objectMagic
= [][]byte{
1900 {'!', '<', 'a', 'r', 'c', 'h', '>', '\n'}, // Package archive
1901 {'<', 'b', 'i', 'g', 'a', 'f', '>', '\n'}, // Package AIX big archive
1902 {'\x7F', 'E', 'L', 'F'}, // ELF
1903 {0xFE, 0xED, 0xFA, 0xCE}, // Mach-O big-endian 32-bit
1904 {0xFE, 0xED, 0xFA, 0xCF}, // Mach-O big-endian 64-bit
1905 {0xCE, 0xFA, 0xED, 0xFE}, // Mach-O little-endian 32-bit
1906 {0xCF, 0xFA, 0xED, 0xFE}, // Mach-O little-endian 64-bit
1907 {0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00}, // PE (Windows) as generated by 6l/8l and gcc
1908 {0x4d, 0x5a, 0x78, 0x00, 0x01, 0x00}, // PE (Windows) as generated by llvm for dll
1909 {0x00, 0x00, 0x01, 0xEB}, // Plan 9 i386
1910 {0x00, 0x00, 0x8a, 0x97}, // Plan 9 amd64
1911 {0x00, 0x00, 0x06, 0x47}, // Plan 9 arm
1912 {0x00, 0x61, 0x73, 0x6D}, // WASM
1913 {0x01, 0xDF}, // XCOFF 32bit
1914 {0x01, 0xF7}, // XCOFF 64bit
1917 func isObject(s
string) bool {
1918 f
, err
:= os
.Open(s
)
1923 buf
:= make([]byte, 64)
1925 for _
, magic
:= range objectMagic
{
1926 if bytes
.HasPrefix(buf
, magic
) {
1933 // mayberemovefile removes a file only if it is a regular file
1934 // When running as a user with sufficient privileges, we may delete
1935 // even device files, for example, which is not intended.
1936 func mayberemovefile(s
string) {
1937 if fi
, err
:= os
.Lstat(s
); err
== nil && !fi
.Mode().IsRegular() {
1943 // fmtcmd formats a command in the manner of fmt.Sprintf but also:
1945 // If dir is non-empty and the script is not in dir right now,
1946 // fmtcmd inserts "cd dir\n" before the command.
1948 // fmtcmd replaces the value of b.WorkDir with $WORK.
1949 // fmtcmd replaces the value of goroot with $GOROOT.
1950 // fmtcmd replaces the value of b.gobin with $GOBIN.
1952 // fmtcmd replaces the name of the current directory with dot (.)
1953 // but only when it is at the beginning of a space-separated token.
1955 func (b
*Builder
) fmtcmd(dir
string, format
string, args
...any
) string {
1956 cmd
:= fmt
.Sprintf(format
, args
...)
1957 if dir
!= "" && dir
!= "/" {
1959 if dir
[len(dir
)-1] == filepath
.Separator
{
1960 dot
+= string(filepath
.Separator
)
1962 cmd
= strings
.ReplaceAll(" "+cmd
, " "+dir
, dot
)[1:]
1963 if b
.scriptDir
!= dir
{
1965 cmd
= "cd " + dir
+ "\n" + cmd
1968 if b
.WorkDir
!= "" {
1969 cmd
= strings
.ReplaceAll(cmd
, b
.WorkDir
, "$WORK")
1970 escaped
:= strconv
.Quote(b
.WorkDir
)
1971 escaped
= escaped
[1 : len(escaped
)-1] // strip quote characters
1972 if escaped
!= b
.WorkDir
{
1973 cmd
= strings
.ReplaceAll(cmd
, escaped
, "$WORK")
1979 // showcmd prints the given command to standard output
1980 // for the implementation of -n or -x.
1981 func (b
*Builder
) Showcmd(dir
string, format
string, args
...any
) {
1983 defer b
.output
.Unlock()
1984 b
.Print(b
.fmtcmd(dir
, format
, args
...) + "\n")
1987 // showOutput prints "# desc" followed by the given output.
1988 // The output is expected to contain references to 'dir', usually
1989 // the source directory for the package that has failed to build.
1990 // showOutput rewrites mentions of dir with a relative path to dir
1991 // when the relative path is shorter. This is usually more pleasant.
1992 // For example, if fmt doesn't compile and we are in src/html,
1997 // ../fmt/print.go:1090: undefined: asdf
2004 // /usr/gopher/go/src/fmt/print.go:1090: undefined: asdf
2007 // showOutput also replaces references to the work directory with $WORK.
2009 // If a is not nil and a.output is not nil, showOutput appends to that slice instead of
2010 // printing to b.Print.
2012 func (b
*Builder
) showOutput(a
*Action
, dir
, desc
, out
string) {
2013 prefix
:= "# " + desc
2014 suffix
:= "\n" + out
2015 if reldir
:= base
.ShortPath(dir
); reldir
!= dir
{
2016 suffix
= strings
.ReplaceAll(suffix
, " "+dir
, " "+reldir
)
2017 suffix
= strings
.ReplaceAll(suffix
, "\n"+dir
, "\n"+reldir
)
2018 suffix
= strings
.ReplaceAll(suffix
, "\n\t"+dir
, "\n\t"+reldir
)
2020 suffix
= strings
.ReplaceAll(suffix
, " "+b
.WorkDir
, " $WORK")
2022 if a
!= nil && a
.output
!= nil {
2023 a
.output
= append(a
.output
, prefix
...)
2024 a
.output
= append(a
.output
, suffix
...)
2029 defer b
.output
.Unlock()
2030 b
.Print(prefix
, suffix
)
2033 // errPrintedOutput is a special error indicating that a command failed
2034 // but that it generated output as well, and that output has already
2035 // been printed, so there's no point showing 'exit status 1' or whatever
2036 // the wait status was. The main executor, builder.do, knows not to
2037 // print this error.
2038 var errPrintedOutput
= errors
.New("already printed output - no need to show error")
2040 var cgoLine
= lazyregexp
.New(`\[[^\[\]]+\.(cgo1|cover)\.go:[0-9]+(:[0-9]+)?\]`)
2041 var cgoTypeSigRe
= lazyregexp
.New(`\b_C2?(type|func|var|macro)_\B`)
2043 // run runs the command given by cmdline in the directory dir.
2044 // If the command fails, run prints information about the failure
2045 // and returns a non-nil error.
2046 func (b
*Builder
) run(a
*Action
, dir
string, desc
string, env
[]string, cmdargs
...any
) error
{
2047 out
, err
:= b
.runOut(a
, dir
, env
, cmdargs
...)
2050 desc
= b
.fmtcmd(dir
, "%s", strings
.Join(str
.StringList(cmdargs
...), " "))
2052 b
.showOutput(a
, dir
, desc
, b
.processOutput(out
))
2054 err
= errPrintedOutput
2060 // processOutput prepares the output of runOut to be output to the console.
2061 func (b
*Builder
) processOutput(out
[]byte) string {
2062 if out
[len(out
)-1] != '\n' {
2063 out
= append(out
, '\n')
2065 messages
:= string(out
)
2066 // Fix up output referring to cgo-generated code to be more readable.
2067 // Replace x.go:19[/tmp/.../x.cgo1.go:18] with x.go:19.
2068 // Replace *[100]_Ctype_foo with *[100]C.foo.
2069 // If we're using -x, assume we're debugging and want the full dump, so disable the rewrite.
2070 if !cfg
.BuildX
&& cgoLine
.MatchString(messages
) {
2071 messages
= cgoLine
.ReplaceAllString(messages
, "")
2072 messages
= cgoTypeSigRe
.ReplaceAllString(messages
, "C.")
2077 // runOut runs the command given by cmdline in the directory dir.
2078 // It returns the command output and any errors that occurred.
2079 // It accumulates execution time in a.
2080 func (b
*Builder
) runOut(a
*Action
, dir
string, env
[]string, cmdargs
...any
) ([]byte, error
) {
2081 cmdline
:= str
.StringList(cmdargs
...)
2083 for _
, arg
:= range cmdline
{
2084 // GNU binutils commands, including gcc and gccgo, interpret an argument
2085 // @foo anywhere in the command line (even following --) as meaning
2086 // "read and insert arguments from the file named foo."
2087 // Don't say anything that might be misinterpreted that way.
2088 if strings
.HasPrefix(arg
, "@") {
2089 return nil, fmt
.Errorf("invalid command-line argument %s in command: %s", arg
, joinUnambiguously(cmdline
))
2093 if cfg
.BuildN || cfg
.BuildX
{
2094 var envcmdline
string
2095 for _
, e
:= range env
{
2096 if j
:= strings
.IndexByte(e
, '='); j
!= -1 {
2097 if strings
.ContainsRune(e
[j
+1:], '\'') {
2098 envcmdline
+= fmt
.Sprintf("%s=%q", e
[:j
], e
[j
+1:])
2100 envcmdline
+= fmt
.Sprintf("%s='%s'", e
[:j
], e
[j
+1:])
2105 envcmdline
+= joinUnambiguously(cmdline
)
2106 b
.Showcmd(dir
, "%s", envcmdline
)
2112 var buf bytes
.Buffer
2113 cmd
:= exec
.Command(cmdline
[0], cmdline
[1:]...)
2115 cmd
.Args
[0] = cmd
.Path
2119 cleanup
:= passLongArgsInResponseFiles(cmd
)
2122 cmd
.Env
= base
.AppendPWD(os
.Environ(), cmd
.Dir
)
2124 // Add the TOOLEXEC_IMPORTPATH environment variable for -toolexec tools.
2125 // It doesn't really matter if -toolexec isn't being used.
2126 // Note that a.Package.Desc is not really an import path,
2127 // but this is consistent with 'go list -f {{.ImportPath}}'.
2128 // Plus, it is useful to uniquely identify packages in 'go list -json'.
2129 if a
!= nil && a
.Package
!= nil {
2130 cmd
.Env
= append(cmd
.Env
, "TOOLEXEC_IMPORTPATH="+a
.Package
.Desc())
2133 cmd
.Env
= append(cmd
.Env
, env
...)
2136 if a
!= nil && a
.json
!= nil {
2138 aj
.Cmd
= append(aj
.Cmd
, joinUnambiguously(cmdline
))
2139 aj
.CmdReal
+= time
.Since(start
)
2140 if ps
:= cmd
.ProcessState
; ps
!= nil {
2141 aj
.CmdUser
+= ps
.UserTime()
2142 aj
.CmdSys
+= ps
.SystemTime()
2146 // err can be something like 'exit status 1'.
2147 // Add information about what program was running.
2148 // Note that if buf.Bytes() is non-empty, the caller usually
2149 // shows buf.Bytes() and does not print err at all, so the
2150 // prefix here does not make most output any more verbose.
2152 err
= errors
.New(cmdline
[0] + ": " + err
.Error())
2154 return buf
.Bytes(), err
2157 // joinUnambiguously prints the slice, quoting where necessary to make the
2158 // output unambiguous.
2159 // TODO: See issue 5279. The printing of commands needs a complete redo.
2160 func joinUnambiguously(a
[]string) string {
2161 var buf bytes
.Buffer
2162 for i
, s
:= range a
{
2166 q
:= strconv
.Quote(s
)
2167 // A gccgo command line can contain -( and -).
2168 // Make sure we quote them since they are special to the shell.
2169 // The trimpath argument can also contain > (part of =>) and ;. Quote those too.
2170 if s
== "" || strings
.ContainsAny(s
, " ()>;") ||
len(q
) > len(s
)+2 {
2179 // cCompilerEnv returns environment variables to set when running the
2180 // C compiler. This is needed to disable escape codes in clang error
2181 // messages that confuse tools like cgo.
2182 func (b
*Builder
) cCompilerEnv() []string {
2183 return []string{"TERM=dumb"}
2186 // mkdir makes the named directory.
2187 func (b
*Builder
) Mkdir(dir
string) error
{
2188 // Make Mkdir(a.Objdir) a no-op instead of an error when a.Objdir == "".
2194 defer b
.exec
.Unlock()
2195 // We can be a little aggressive about being
2196 // sure directories exist. Skip repeated calls.
2197 if b
.mkdirCache
[dir
] {
2200 b
.mkdirCache
[dir
] = true
2202 if cfg
.BuildN || cfg
.BuildX
{
2203 b
.Showcmd("", "mkdir -p %s", dir
)
2209 if err
:= os
.MkdirAll(dir
, 0777); err
!= nil {
2215 // symlink creates a symlink newname -> oldname.
2216 func (b
*Builder
) Symlink(oldname
, newname
string) error
{
2217 // It's not an error to try to recreate an existing symlink.
2218 if link
, err
:= os
.Readlink(newname
); err
== nil && link
== oldname
{
2222 if cfg
.BuildN || cfg
.BuildX
{
2223 b
.Showcmd("", "ln -s %s %s", oldname
, newname
)
2228 return os
.Symlink(oldname
, newname
)
2231 // mkAbs returns an absolute path corresponding to
2232 // evaluating f in the directory dir.
2233 // We always pass absolute paths of source files so that
2234 // the error messages will include the full path to a file
2235 // in need of attention.
2236 func mkAbs(dir
, f
string) string {
2237 // Leave absolute paths alone.
2238 // Also, during -n mode we use the pseudo-directory $WORK
2239 // instead of creating an actual work directory that won't be used.
2240 // Leave paths beginning with $WORK alone too.
2241 if filepath
.IsAbs(f
) || strings
.HasPrefix(f
, "$WORK") {
2244 return filepath
.Join(dir
, f
)
2247 type toolchain
interface {
2248 // gc runs the compiler in a specific directory on a set of files
2249 // and returns the name of the generated output file.
2250 gc(b
*Builder
, a
*Action
, archive
string, importcfg
, embedcfg
[]byte, symabis
string, asmhdr
bool, gofiles
[]string) (ofile
string, out
[]byte, err error
)
2251 // cc runs the toolchain's C compiler in a directory on a C file
2252 // to produce an output file.
2253 cc(b
*Builder
, a
*Action
, ofile
, cfile
string) error
2254 // asm runs the assembler in a specific directory on specific files
2255 // and returns a list of named output files.
2256 asm(b
*Builder
, a
*Action
, sfiles
[]string) ([]string, error
)
2257 // symabis scans the symbol ABIs from sfiles and returns the
2258 // path to the output symbol ABIs file, or "" if none.
2259 symabis(b
*Builder
, a
*Action
, sfiles
[]string) (string, error
)
2260 // pack runs the archive packer in a specific directory to create
2261 // an archive from a set of object files.
2262 // typically it is run in the object directory.
2263 pack(b
*Builder
, a
*Action
, afile
string, ofiles
[]string) error
2264 // ld runs the linker to create an executable starting at mainpkg.
2265 ld(b
*Builder
, root
*Action
, out
, importcfg
, mainpkg
string) error
2266 // ldShared runs the linker to create a shared library containing the pkgs built by toplevelactions
2267 ldShared(b
*Builder
, root
*Action
, toplevelactions
[]*Action
, out
, importcfg
string, allactions
[]*Action
) error
2273 type noToolchain
struct{}
2275 func noCompiler() error
{
2276 log
.Fatalf("unknown compiler %q", cfg
.BuildContext
.Compiler
)
2280 func (noToolchain
) compiler() string {
2285 func (noToolchain
) linker() string {
2290 func (noToolchain
) gc(b
*Builder
, a
*Action
, archive
string, importcfg
, embedcfg
[]byte, symabis
string, asmhdr
bool, gofiles
[]string) (ofile
string, out
[]byte, err error
) {
2291 return "", nil, noCompiler()
2294 func (noToolchain
) asm(b
*Builder
, a
*Action
, sfiles
[]string) ([]string, error
) {
2295 return nil, noCompiler()
2298 func (noToolchain
) symabis(b
*Builder
, a
*Action
, sfiles
[]string) (string, error
) {
2299 return "", noCompiler()
2302 func (noToolchain
) pack(b
*Builder
, a
*Action
, afile
string, ofiles
[]string) error
{
2306 func (noToolchain
) ld(b
*Builder
, root
*Action
, out
, importcfg
, mainpkg
string) error
{
2310 func (noToolchain
) ldShared(b
*Builder
, root
*Action
, toplevelactions
[]*Action
, out
, importcfg
string, allactions
[]*Action
) error
{
2314 func (noToolchain
) cc(b
*Builder
, a
*Action
, ofile
, cfile
string) error
{
2318 // gcc runs the gcc C compiler to create an object from a single C file.
2319 func (b
*Builder
) gcc(a
*Action
, p
*load
.Package
, workdir
, out
string, flags
[]string, cfile
string) error
{
2320 return b
.ccompile(a
, p
, out
, flags
, cfile
, b
.GccCmd(p
.Dir
, workdir
))
2323 // gxx runs the g++ C++ compiler to create an object from a single C++ file.
2324 func (b
*Builder
) gxx(a
*Action
, p
*load
.Package
, workdir
, out
string, flags
[]string, cxxfile
string) error
{
2325 return b
.ccompile(a
, p
, out
, flags
, cxxfile
, b
.GxxCmd(p
.Dir
, workdir
))
2328 // gfortran runs the gfortran Fortran compiler to create an object from a single Fortran file.
2329 func (b
*Builder
) gfortran(a
*Action
, p
*load
.Package
, workdir
, out
string, flags
[]string, ffile
string) error
{
2330 return b
.ccompile(a
, p
, out
, flags
, ffile
, b
.gfortranCmd(p
.Dir
, workdir
))
2333 // ccompile runs the given C or C++ compiler and creates an object from a single source file.
2334 func (b
*Builder
) ccompile(a
*Action
, p
*load
.Package
, outfile
string, flags
[]string, file
string, compiler
[]string) error
{
2335 file
= mkAbs(p
.Dir
, file
)
2336 desc
:= p
.ImportPath
2337 outfile
= mkAbs(p
.Dir
, outfile
)
2339 // Elide source directory paths if -trimpath or GOROOT_FINAL is set.
2340 // This is needed for source files (e.g., a .c file in a package directory).
2341 // TODO(golang.org/issue/36072): cgo also generates files with #line
2342 // directives pointing to the source directory. It should not generate those
2343 // when -trimpath is enabled.
2344 if b
.gccSupportsFlag(compiler
, "-fdebug-prefix-map=a=b") {
2345 if cfg
.BuildTrimpath || p
.Goroot
{
2346 // Keep in sync with Action.trimpath.
2347 // The trimmed paths are a little different, but we need to trim in the
2349 var from
, toPath
string
2350 if m
:= p
.Module
; m
!= nil {
2352 toPath
= m
.Path
+ "@" + m
.Version
2355 toPath
= p
.ImportPath
2357 // -fdebug-prefix-map requires an absolute "to" path (or it joins the path
2358 // with the working directory). Pick something that makes sense for the
2361 if cfg
.BuildContext
.GOOS
== "windows" {
2362 to
= filepath
.Join(`\\_\_`, toPath
)
2364 to
= filepath
.Join("/_", toPath
)
2366 flags
= append(flags
[:len(flags
):len(flags
)], "-fdebug-prefix-map="+from
+"="+to
)
2371 if p
, ok
:= a
.nonGoOverlay
[overlayPath
]; ok
{
2374 output
, err
:= b
.runOut(a
, filepath
.Dir(overlayPath
), b
.cCompilerEnv(), compiler
, flags
, "-o", outfile
, "-c", filepath
.Base(overlayPath
))
2375 if len(output
) > 0 {
2376 // On FreeBSD 11, when we pass -g to clang 3.8 it
2377 // invokes its internal assembler with -dwarf-version=2.
2378 // When it sees .section .note.GNU-stack, it warns
2379 // "DWARF2 only supports one section per compilation unit".
2380 // This warning makes no sense, since the section is empty,
2381 // but it confuses people.
2382 // We work around the problem by detecting the warning
2383 // and dropping -g and trying again.
2384 if bytes
.Contains(output
, []byte("DWARF2 only supports one section per compilation unit")) {
2385 newFlags
:= make([]string, 0, len(flags
))
2386 for _
, f
:= range flags
{
2387 if !strings
.HasPrefix(f
, "-g") {
2388 newFlags
= append(newFlags
, f
)
2391 if len(newFlags
) < len(flags
) {
2392 return b
.ccompile(a
, p
, outfile
, newFlags
, file
, compiler
)
2396 b
.showOutput(a
, p
.Dir
, desc
, b
.processOutput(output
))
2398 err
= errPrintedOutput
2399 } else if os
.Getenv("GO_BUILDER_NAME") != "" {
2400 return errors
.New("C compiler warning promoted to error on Go builders")
2406 // gccld runs the gcc linker to create an executable from a set of object files.
2407 func (b
*Builder
) gccld(a
*Action
, p
*load
.Package
, objdir
, outfile
string, flags
[]string, objs
[]string) error
{
2409 if len(p
.CXXFiles
) > 0 ||
len(p
.SwigCXXFiles
) > 0 {
2410 cmd
= b
.GxxCmd(p
.Dir
, objdir
)
2412 cmd
= b
.GccCmd(p
.Dir
, objdir
)
2415 cmdargs
:= []any
{cmd
, "-o", outfile
, objs
, flags
}
2417 out
, err
:= b
.runOut(a
, base
.Cwd(), b
.cCompilerEnv(), cmdargs
...)
2420 // Filter out useless linker warnings caused by bugs outside Go.
2421 // See also cmd/link/internal/ld's hostlink method.
2424 for _
, line
:= range bytes
.SplitAfter(out
, []byte("\n")) {
2425 // golang.org/issue/26073 - Apple Xcode bug
2426 if bytes
.Contains(line
, []byte("ld: warning: text-based stub file")) {
2435 // Remove duplicate main symbol with runtime/cgo on AIX.
2436 // With runtime/cgo, two main are available:
2437 // One is generated by cgo tool with {return 0;}.
2438 // The other one is the main calling runtime.rt0_go
2440 // The second can't be used by cgo programs because
2441 // runtime.rt0_go is unknown to them.
2442 // Therefore, we let ld remove this main version
2443 // and used the cgo generated one.
2444 if p
.ImportPath
== "runtime/cgo" && bytes
.Contains(line
, []byte("ld: 0711-224 WARNING: Duplicate symbol: .main")) {
2449 save
= append(save
, line
)
2451 out
= bytes
.Join(save
, nil)
2453 b
.showOutput(nil, dir
, p
.ImportPath
, b
.processOutput(out
))
2455 err
= errPrintedOutput
2462 // gccCmd returns a gcc command line prefix
2463 // defaultCC is defined in zdefaultcc.go, written by cmd/dist.
2464 func (b
*Builder
) GccCmd(incdir
, workdir
string) []string {
2465 return b
.compilerCmd(b
.ccExe(), incdir
, workdir
)
2468 // gxxCmd returns a g++ command line prefix
2469 // defaultCXX is defined in zdefaultcc.go, written by cmd/dist.
2470 func (b
*Builder
) GxxCmd(incdir
, workdir
string) []string {
2471 return b
.compilerCmd(b
.cxxExe(), incdir
, workdir
)
2474 // gfortranCmd returns a gfortran command line prefix.
2475 func (b
*Builder
) gfortranCmd(incdir
, workdir
string) []string {
2476 return b
.compilerCmd(b
.fcExe(), incdir
, workdir
)
2479 // ccExe returns the CC compiler setting without all the extra flags we add implicitly.
2480 func (b
*Builder
) ccExe() []string {
2481 return envList("CC", cfg
.DefaultCC(cfg
.Goos
, cfg
.Goarch
))
2484 // cxxExe returns the CXX compiler setting without all the extra flags we add implicitly.
2485 func (b
*Builder
) cxxExe() []string {
2486 return envList("CXX", cfg
.DefaultCXX(cfg
.Goos
, cfg
.Goarch
))
2489 // fcExe returns the FC compiler setting without all the extra flags we add implicitly.
2490 func (b
*Builder
) fcExe() []string {
2491 return envList("FC", "gfortran")
2494 // compilerCmd returns a command line prefix for the given environment
2495 // variable and using the default command when the variable is empty.
2496 func (b
*Builder
) compilerCmd(compiler
[]string, incdir
, workdir
string) []string {
2497 a
:= append(compiler
, "-I", incdir
)
2499 // Definitely want -fPIC but on Windows gcc complains
2500 // "-fPIC ignored for target (all code is position independent)"
2501 if cfg
.Goos
!= "windows" {
2502 a
= append(a
, "-fPIC")
2504 a
= append(a
, b
.gccArchArgs()...)
2505 // gcc-4.5 and beyond require explicit "-pthread" flag
2506 // for multithreading with pthread library.
2507 if cfg
.BuildContext
.CgoEnabled
{
2510 a
= append(a
, "-mthreads")
2512 a
= append(a
, "-pthread")
2516 if cfg
.Goos
== "aix" {
2517 // mcmodel=large must always be enabled to allow large TOC.
2518 a
= append(a
, "-mcmodel=large")
2521 // disable ASCII art in clang errors, if possible
2522 if b
.gccSupportsFlag(compiler
, "-fno-caret-diagnostics") {
2523 a
= append(a
, "-fno-caret-diagnostics")
2525 // clang is too smart about command-line arguments
2526 if b
.gccSupportsFlag(compiler
, "-Qunused-arguments") {
2527 a
= append(a
, "-Qunused-arguments")
2530 // disable word wrapping in error messages
2531 a
= append(a
, "-fmessage-length=0")
2533 // Tell gcc not to include the work directory in object files.
2534 if b
.gccSupportsFlag(compiler
, "-fdebug-prefix-map=a=b") {
2538 workdir
= strings
.TrimSuffix(workdir
, string(filepath
.Separator
))
2539 a
= append(a
, "-fdebug-prefix-map="+workdir
+"=/tmp/go-build")
2542 // Tell gcc not to include flags in object files, which defeats the
2543 // point of -fdebug-prefix-map above.
2544 if b
.gccSupportsFlag(compiler
, "-gno-record-gcc-switches") {
2545 a
= append(a
, "-gno-record-gcc-switches")
2548 // On OS X, some of the compilers behave as if -fno-common
2549 // is always set, and the Mach-O linker in 6l/8l assumes this.
2550 // See https://golang.org/issue/3253.
2551 if cfg
.Goos
== "darwin" || cfg
.Goos
== "ios" {
2552 a
= append(a
, "-fno-common")
2555 // gccgo uses the language-independent exception mechanism to
2556 // handle panics, so it always needs unwind tables.
2557 if cfg
.BuildToolchainName
== "gccgo" {
2558 a
= append(a
, "-funwind-tables")
2564 // gccNoPie returns the flag to use to request non-PIE. On systems
2565 // with PIE (position independent executables) enabled by default,
2566 // -no-pie must be passed when doing a partial link with -Wl,-r.
2567 // But -no-pie is not supported by all compilers, and clang spells it -nopie.
2568 func (b
*Builder
) gccNoPie(linker
[]string) string {
2569 if b
.gccSupportsFlag(linker
, "-no-pie") {
2572 if b
.gccSupportsFlag(linker
, "-nopie") {
2578 // gccSupportsFlag checks to see if the compiler supports a flag.
2579 func (b
*Builder
) gccSupportsFlag(compiler
[]string, flag
string) bool {
2580 key
:= [2]string{compiler
[0], flag
}
2583 defer b
.exec
.Unlock()
2584 if b
, ok
:= b
.flagCache
[key
]; ok
{
2587 if b
.flagCache
== nil {
2588 b
.flagCache
= make(map[[2]string]bool)
2592 if runtime
.GOOS
== "windows" {
2593 f
, err
:= os
.CreateTemp(b
.WorkDir
, "")
2599 defer os
.Remove(tmp
)
2602 // We used to write an empty C file, but that gets complicated with
2603 // go build -n. We tried using a file that does not exist, but that
2604 // fails on systems with GCC version 4.2.1; that is the last GPLv2
2605 // version of GCC, so some systems have frozen on it.
2606 // Now we pass an empty file on stdin, which should work at least for
2608 cmdArgs
:= str
.StringList(compiler
, flag
, "-c", "-x", "c", "-", "-o", tmp
)
2609 if cfg
.BuildN || cfg
.BuildX
{
2610 b
.Showcmd(b
.WorkDir
, "%s || true", joinUnambiguously(cmdArgs
))
2615 cmd
:= exec
.Command(cmdArgs
[0], cmdArgs
[1:]...)
2617 cmd
.Env
= base
.AppendPWD(os
.Environ(), cmd
.Dir
)
2618 cmd
.Env
= append(cmd
.Env
, "LC_ALL=C")
2619 out
, _
:= cmd
.CombinedOutput()
2620 // GCC says "unrecognized command line option".
2621 // clang says "unknown argument".
2622 // Older versions of GCC say "unrecognised debug output level".
2623 // For -fsplit-stack GCC says "'-fsplit-stack' is not supported".
2624 supported
:= !bytes
.Contains(out
, []byte("unrecognized")) &&
2625 !bytes
.Contains(out
, []byte("unknown")) &&
2626 !bytes
.Contains(out
, []byte("unrecognised")) &&
2627 !bytes
.Contains(out
, []byte("is not supported"))
2628 b
.flagCache
[key
] = supported
2632 // gccArchArgs returns arguments to pass to gcc based on the architecture.
2633 func (b
*Builder
) gccArchArgs() []string {
2636 return []string{"-m32"}
2638 if cfg
.Goos
== "darwin" {
2639 return []string{"-arch", "x86_64", "-m64"}
2641 return []string{"-m64"}
2643 if cfg
.Goos
== "darwin" {
2644 return []string{"-arch", "arm64"}
2647 return []string{"-marm"} // not thumb
2649 return []string{"-m64", "-march=z196"}
2650 case "mips64", "mips64le":
2651 args
:= []string{"-mabi=64"}
2652 if cfg
.GOMIPS64
== "hardfloat" {
2653 return append(args
, "-mhard-float")
2654 } else if cfg
.GOMIPS64
== "softfloat" {
2655 return append(args
, "-msoft-float")
2657 case "mips", "mipsle":
2658 args
:= []string{"-mabi=32", "-march=mips32"}
2659 if cfg
.GOMIPS
== "hardfloat" {
2660 return append(args
, "-mhard-float", "-mfp32", "-mno-odd-spreg")
2661 } else if cfg
.GOMIPS
== "softfloat" {
2662 return append(args
, "-msoft-float")
2665 if cfg
.Goos
== "aix" {
2666 return []string{"-maix64"}
2669 if cfg
.Goos
== "aix" {
2670 return []string{"-maix32"}
2676 // envList returns the value of the given environment variable broken
2677 // into fields, using the default value when the variable is empty.
2679 // The environment variable must be quoted correctly for
2680 // str.SplitQuotedFields. This should be done before building
2681 // anything, for example, in BuildInit.
2682 func envList(key
, def
string) []string {
2683 v
:= cfg
.Getenv(key
)
2687 args
, err
:= quoted
.Split(v
)
2689 panic(fmt
.Sprintf("could not parse environment variable %s with value %q: %v", key
, v
, err
))
2694 // CFlags returns the flags to use when invoking the C, C++ or Fortran compilers, or cgo.
2695 func (b
*Builder
) CFlags(p
*load
.Package
) (cppflags
, cflags
, cxxflags
, fflags
, ldflags
[]string, err error
) {
2696 defaults
:= "-g -O2"
2698 if cppflags
, err
= buildFlags("CPPFLAGS", "", p
.CgoCPPFLAGS
, checkCompilerFlags
); err
!= nil {
2701 if cflags
, err
= buildFlags("CFLAGS", defaults
, p
.CgoCFLAGS
, checkCompilerFlags
); err
!= nil {
2704 if cxxflags
, err
= buildFlags("CXXFLAGS", defaults
, p
.CgoCXXFLAGS
, checkCompilerFlags
); err
!= nil {
2707 if fflags
, err
= buildFlags("FFLAGS", defaults
, p
.CgoFFLAGS
, checkCompilerFlags
); err
!= nil {
2710 if ldflags
, err
= buildFlags("LDFLAGS", defaults
, p
.CgoLDFLAGS
, checkLinkerFlags
); err
!= nil {
2717 func buildFlags(name
, defaults
string, fromPackage
[]string, check
func(string, string, []string) error
) ([]string, error
) {
2718 if err
:= check(name
, "#cgo "+name
, fromPackage
); err
!= nil {
2721 return str
.StringList(envList("CGO_"+name
, defaults
), fromPackage
), nil
2724 var cgoRe
= lazyregexp
.New(`[/\\:]`)
2726 func (b
*Builder
) cgo(a
*Action
, cgoExe
, objdir
string, pcCFLAGS
, pcLDFLAGS
, cgofiles
, gccfiles
, gxxfiles
, mfiles
, ffiles
[]string) (outGo
, outObj
[]string, err error
) {
2728 cgoCPPFLAGS
, cgoCFLAGS
, cgoCXXFLAGS
, cgoFFLAGS
, cgoLDFLAGS
, err
:= b
.CFlags(p
)
2730 return nil, nil, err
2733 cgoCPPFLAGS
= append(cgoCPPFLAGS
, pcCFLAGS
...)
2734 cgoLDFLAGS
= append(cgoLDFLAGS
, pcLDFLAGS
...)
2735 // If we are compiling Objective-C code, then we need to link against libobjc
2736 if len(mfiles
) > 0 {
2737 cgoLDFLAGS
= append(cgoLDFLAGS
, "-lobjc")
2740 // Likewise for Fortran, except there are many Fortran compilers.
2741 // Support gfortran out of the box and let others pass the correct link options
2743 if len(ffiles
) > 0 {
2744 fc
:= cfg
.Getenv("FC")
2748 if strings
.Contains(fc
, "gfortran") {
2749 cgoLDFLAGS
= append(cgoLDFLAGS
, "-lgfortran")
2754 cgoCFLAGS
= append([]string{"-fsanitize=memory"}, cgoCFLAGS
...)
2755 cgoLDFLAGS
= append([]string{"-fsanitize=memory"}, cgoLDFLAGS
...)
2758 cgoCFLAGS
= append([]string{"-fsanitize=address"}, cgoCFLAGS
...)
2759 cgoLDFLAGS
= append([]string{"-fsanitize=address"}, cgoLDFLAGS
...)
2762 // Allows including _cgo_export.h, as well as the user's .h files,
2763 // from .[ch] files in the package.
2764 cgoCPPFLAGS
= append(cgoCPPFLAGS
, "-I", objdir
)
2768 gofiles
:= []string{objdir
+ "_cgo_gotypes.go"}
2769 cfiles
:= []string{"_cgo_export.c"}
2770 for _
, fn
:= range cgofiles
{
2771 f
:= strings
.TrimSuffix(filepath
.Base(fn
), ".go")
2772 gofiles
= append(gofiles
, objdir
+f
+".cgo1.go")
2773 cfiles
= append(cfiles
, f
+".cgo2.c")
2776 // TODO: make cgo not depend on $GOARCH?
2778 cgoflags
:= []string{}
2779 if p
.Standard
&& p
.ImportPath
== "runtime/cgo" {
2780 cgoflags
= append(cgoflags
, "-import_runtime_cgo=false")
2782 if p
.Standard
&& (p
.ImportPath
== "runtime/race" || p
.ImportPath
== "runtime/msan" || p
.ImportPath
== "runtime/cgo" || p
.ImportPath
== "runtime/asan") {
2783 cgoflags
= append(cgoflags
, "-import_syscall=false")
2786 // Update $CGO_LDFLAGS with p.CgoLDFLAGS.
2787 // These flags are recorded in the generated _cgo_gotypes.go file
2788 // using //go:cgo_ldflag directives, the compiler records them in the
2789 // object file for the package, and then the Go linker passes them
2790 // along to the host linker. At this point in the code, cgoLDFLAGS
2791 // consists of the original $CGO_LDFLAGS (unchecked) and all the
2792 // flags put together from source code (checked).
2793 cgoenv
:= b
.cCompilerEnv()
2794 if len(cgoLDFLAGS
) > 0 {
2795 flags
:= make([]string, len(cgoLDFLAGS
))
2796 for i
, f
:= range cgoLDFLAGS
{
2797 flags
[i
] = strconv
.Quote(f
)
2799 cgoenv
= append(cgoenv
, "CGO_LDFLAGS="+strings
.Join(flags
, " "))
2802 if cfg
.BuildToolchainName
== "gccgo" {
2803 if b
.gccSupportsFlag([]string{BuildToolchain
.compiler()}, "-fsplit-stack") {
2804 cgoCFLAGS
= append(cgoCFLAGS
, "-fsplit-stack")
2806 cgoflags
= append(cgoflags
, "-gccgo")
2807 if pkgpath
:= gccgoPkgpath(p
); pkgpath
!= "" {
2808 cgoflags
= append(cgoflags
, "-gccgopkgpath="+pkgpath
)
2812 switch cfg
.BuildBuildmode
{
2813 case "c-archive", "c-shared":
2814 // Tell cgo that if there are any exported functions
2815 // it should generate a header file that C code can
2817 cgoflags
= append(cgoflags
, "-exportheader="+objdir
+"_cgo_install.h")
2822 // Rewrite overlaid paths in cgo files.
2823 // cgo adds //line and #line pragmas in generated files with these paths.
2824 var trimpath
[]string
2825 for i
:= range cgofiles
{
2826 path
:= mkAbs(p
.Dir
, cgofiles
[i
])
2827 if opath
, ok
:= fsys
.OverlayPath(path
); ok
{
2829 trimpath
= append(trimpath
, opath
+"=>"+path
)
2832 if len(trimpath
) > 0 {
2833 cgoflags
= append(cgoflags
, "-trimpath", strings
.Join(trimpath
, ";"))
2836 if err
:= b
.run(a
, execdir
, p
.ImportPath
, cgoenv
, cfg
.BuildToolexec
, cgoExe
, "-objdir", objdir
, "-importpath", p
.ImportPath
, cgoflags
, "--", cgoCPPFLAGS
, cgoCFLAGS
, cgofiles
); err
!= nil {
2837 return nil, nil, err
2839 outGo
= append(outGo
, gofiles
...)
2841 // Use sequential object file names to keep them distinct
2842 // and short enough to fit in the .a header file name slots.
2843 // We no longer collect them all into _all.o, and we'd like
2844 // tools to see both the .o suffix and unique names, so
2845 // we need to make them short enough not to be truncated
2846 // in the final archive.
2848 nextOfile
:= func() string {
2850 return objdir
+ fmt
.Sprintf("_x%03d.o", oseq
)
2854 cflags
:= str
.StringList(cgoCPPFLAGS
, cgoCFLAGS
)
2855 for _
, cfile
:= range cfiles
{
2856 ofile
:= nextOfile()
2857 if err
:= b
.gcc(a
, p
, a
.Objdir
, ofile
, cflags
, objdir
+cfile
); err
!= nil {
2858 return nil, nil, err
2860 outObj
= append(outObj
, ofile
)
2863 for _
, file
:= range gccfiles
{
2864 ofile
:= nextOfile()
2865 if err
:= b
.gcc(a
, p
, a
.Objdir
, ofile
, cflags
, file
); err
!= nil {
2866 return nil, nil, err
2868 outObj
= append(outObj
, ofile
)
2871 cxxflags
:= str
.StringList(cgoCPPFLAGS
, cgoCXXFLAGS
)
2872 for _
, file
:= range gxxfiles
{
2873 ofile
:= nextOfile()
2874 if err
:= b
.gxx(a
, p
, a
.Objdir
, ofile
, cxxflags
, file
); err
!= nil {
2875 return nil, nil, err
2877 outObj
= append(outObj
, ofile
)
2880 for _
, file
:= range mfiles
{
2881 ofile
:= nextOfile()
2882 if err
:= b
.gcc(a
, p
, a
.Objdir
, ofile
, cflags
, file
); err
!= nil {
2883 return nil, nil, err
2885 outObj
= append(outObj
, ofile
)
2888 fflags
:= str
.StringList(cgoCPPFLAGS
, cgoFFLAGS
)
2889 for _
, file
:= range ffiles
{
2890 ofile
:= nextOfile()
2891 if err
:= b
.gfortran(a
, p
, a
.Objdir
, ofile
, fflags
, file
); err
!= nil {
2892 return nil, nil, err
2894 outObj
= append(outObj
, ofile
)
2897 switch cfg
.BuildToolchainName
{
2899 importGo
:= objdir
+ "_cgo_import.go"
2900 if err
:= b
.dynimport(a
, p
, objdir
, importGo
, cgoExe
, cflags
, cgoLDFLAGS
, outObj
); err
!= nil {
2901 return nil, nil, err
2903 outGo
= append(outGo
, importGo
)
2906 defunC
:= objdir
+ "_cgo_defun.c"
2907 defunObj
:= objdir
+ "_cgo_defun.o"
2908 if err
:= BuildToolchain
.cc(b
, a
, defunObj
, defunC
); err
!= nil {
2909 return nil, nil, err
2911 outObj
= append(outObj
, defunObj
)
2917 // Double check the //go:cgo_ldflag comments in the generated files.
2918 // The compiler only permits such comments in files whose base name
2919 // starts with "_cgo_". Make sure that the comments in those files
2920 // are safe. This is a backstop against people somehow smuggling
2921 // such a comment into a file generated by cgo.
2922 if cfg
.BuildToolchainName
== "gc" && !cfg
.BuildN
{
2924 for _
, f
:= range outGo
{
2925 if !strings
.HasPrefix(filepath
.Base(f
), "_cgo_") {
2929 src
, err
:= os
.ReadFile(f
)
2931 return nil, nil, err
2934 const cgoLdflag
= "//go:cgo_ldflag"
2935 idx
:= bytes
.Index(src
, []byte(cgoLdflag
))
2937 // We are looking at //go:cgo_ldflag.
2938 // Find start of line.
2939 start
:= bytes
.LastIndex(src
[:idx
], []byte("\n"))
2944 // Find end of line.
2945 end
:= bytes
.Index(src
[idx
:], []byte("\n"))
2952 // Check for first line comment in line.
2953 // We don't worry about /* */ comments,
2954 // which normally won't appear in files
2955 // generated by cgo.
2956 commentStart
:= bytes
.Index(src
[start
:], []byte("//"))
2957 commentStart
+= start
2958 // If that line comment is //go:cgo_ldflag,
2960 if bytes
.HasPrefix(src
[commentStart
:], []byte(cgoLdflag
)) {
2961 // Pull out the flag, and unquote it.
2962 // This is what the compiler does.
2963 flag
:= string(src
[idx
+len(cgoLdflag
) : end
])
2964 flag
= strings
.TrimSpace(flag
)
2965 flag
= strings
.Trim(flag
, `"`)
2966 flags
= append(flags
, flag
)
2969 idx
= bytes
.Index(src
, []byte(cgoLdflag
))
2973 // We expect to find the contents of cgoLDFLAGS in flags.
2974 if len(cgoLDFLAGS
) > 0 {
2976 for i
:= range flags
{
2977 for j
, f
:= range cgoLDFLAGS
{
2978 if f
!= flags
[i
+j
] {
2982 flags
= append(flags
[:i
], flags
[i
+len(cgoLDFLAGS
):]...)
2987 if err
:= checkLinkerFlags("LDFLAGS", "go:cgo_ldflag", flags
); err
!= nil {
2988 return nil, nil, err
2992 return outGo
, outObj
, nil
2995 // dynimport creates a Go source file named importGo containing
2996 // //go:cgo_import_dynamic directives for each symbol or library
2997 // dynamically imported by the object files outObj.
2998 func (b
*Builder
) dynimport(a
*Action
, p
*load
.Package
, objdir
, importGo
, cgoExe
string, cflags
, cgoLDFLAGS
, outObj
[]string) error
{
2999 cfile
:= objdir
+ "_cgo_main.c"
3000 ofile
:= objdir
+ "_cgo_main.o"
3001 if err
:= b
.gcc(a
, p
, objdir
, ofile
, cflags
, cfile
); err
!= nil {
3005 linkobj
:= str
.StringList(ofile
, outObj
, mkAbsFiles(p
.Dir
, p
.SysoFiles
))
3006 dynobj
:= objdir
+ "_cgo_.o"
3008 ldflags
:= cgoLDFLAGS
3009 if (cfg
.Goarch
== "arm" && cfg
.Goos
== "linux") || cfg
.Goos
== "android" {
3010 if !str
.Contains(ldflags
, "-no-pie") {
3011 // we need to use -pie for Linux/ARM to get accurate imported sym (added in https://golang.org/cl/5989058)
3012 // this seems to be outdated, but we don't want to break existing builds depending on this (Issue 45940)
3013 ldflags
= append(ldflags
, "-pie")
3015 if str
.Contains(ldflags
, "-pie") && str
.Contains(ldflags
, "-static") {
3016 // -static -pie doesn't make sense, and causes link errors.
3018 n
:= make([]string, 0, len(ldflags
)-1)
3019 for _
, flag
:= range ldflags
{
3020 if flag
!= "-static" {
3027 if err
:= b
.gccld(a
, p
, objdir
, dynobj
, ldflags
, linkobj
); err
!= nil {
3032 var cgoflags
[]string
3033 if p
.Standard
&& p
.ImportPath
== "runtime/cgo" {
3034 cgoflags
= []string{"-dynlinker"} // record path to dynamic linker
3036 return b
.run(a
, base
.Cwd(), p
.ImportPath
, b
.cCompilerEnv(), cfg
.BuildToolexec
, cgoExe
, "-dynpackage", p
.Name
, "-dynimport", dynobj
, "-dynout", importGo
, cgoflags
)
3039 // Run SWIG on all SWIG input files.
3040 // TODO: Don't build a shared library, once SWIG emits the necessary
3041 // pragmas for external linking.
3042 func (b
*Builder
) swig(a
*Action
, p
*load
.Package
, objdir
string, pcCFLAGS
[]string) (outGo
, outC
, outCXX
[]string, err error
) {
3043 if err
:= b
.swigVersionCheck(); err
!= nil {
3044 return nil, nil, nil, err
3047 intgosize
, err
:= b
.swigIntSize(objdir
)
3049 return nil, nil, nil, err
3052 for _
, f
:= range p
.SwigFiles
{
3053 goFile
, cFile
, err
:= b
.swigOne(a
, p
, f
, objdir
, pcCFLAGS
, false, intgosize
)
3055 return nil, nil, nil, err
3058 outGo
= append(outGo
, goFile
)
3061 outC
= append(outC
, cFile
)
3064 for _
, f
:= range p
.SwigCXXFiles
{
3065 goFile
, cxxFile
, err
:= b
.swigOne(a
, p
, f
, objdir
, pcCFLAGS
, true, intgosize
)
3067 return nil, nil, nil, err
3070 outGo
= append(outGo
, goFile
)
3073 outCXX
= append(outCXX
, cxxFile
)
3076 return outGo
, outC
, outCXX
, nil
3079 // Make sure SWIG is new enough.
3081 swigCheckOnce sync
.Once
3085 func (b
*Builder
) swigDoVersionCheck() error
{
3086 out
, err
:= b
.runOut(nil, "", nil, "swig", "-version")
3090 re
:= regexp
.MustCompile(`[vV]ersion +([\d]+)([.][\d]+)?([.][\d]+)?`)
3091 matches
:= re
.FindSubmatch(out
)
3093 // Can't find version number; hope for the best.
3097 major
, err
:= strconv
.Atoi(string(matches
[1]))
3099 // Can't find version number; hope for the best.
3102 const errmsg
= "must have SWIG version >= 3.0.6"
3104 return errors
.New(errmsg
)
3111 // We have SWIG version 3.x.
3112 if len(matches
[2]) > 0 {
3113 minor
, err
:= strconv
.Atoi(string(matches
[2][1:]))
3123 // We have SWIG version 3.0.x.
3124 if len(matches
[3]) > 0 {
3125 patch
, err
:= strconv
.Atoi(string(matches
[3][1:]))
3131 return errors
.New(errmsg
)
3138 func (b
*Builder
) swigVersionCheck() error
{
3139 swigCheckOnce
.Do(func() {
3140 swigCheck
= b
.swigDoVersionCheck()
3145 // Find the value to pass for the -intgosize option to swig.
3147 swigIntSizeOnce sync
.Once
3149 swigIntSizeError error
3152 // This code fails to build if sizeof(int) <= 32
3153 const swigIntSizeCode
= `
3155 const i int = 1 << 32
3158 // Determine the size of int on the target system for the -intgosize option
3159 // of swig >= 2.0.9. Run only once.
3160 func (b
*Builder
) swigDoIntSize(objdir
string) (intsize
string, err error
) {
3162 return "$INTBITS", nil
3164 src
:= filepath
.Join(b
.WorkDir
, "swig_intsize.go")
3165 if err
= os
.WriteFile(src
, []byte(swigIntSizeCode
), 0666); err
!= nil {
3168 srcs
:= []string{src
}
3170 p
:= load
.GoFilesPackage(context
.TODO(), load
.PackageOpts
{}, srcs
)
3172 if _
, _
, e
:= BuildToolchain
.gc(b
, &Action
{Mode
: "swigDoIntSize", Package
: p
, Objdir
: objdir
}, "", nil, nil, "", false, srcs
); e
!= nil {
3178 // Determine the size of int on the target system for the -intgosize option
3179 // of swig >= 2.0.9.
3180 func (b
*Builder
) swigIntSize(objdir
string) (intsize
string, err error
) {
3181 swigIntSizeOnce
.Do(func() {
3182 swigIntSize
, swigIntSizeError
= b
.swigDoIntSize(objdir
)
3184 return swigIntSize
, swigIntSizeError
3187 // Run SWIG on one SWIG input file.
3188 func (b
*Builder
) swigOne(a
*Action
, p
*load
.Package
, file
, objdir
string, pcCFLAGS
[]string, cxx
bool, intgosize
string) (outGo
, outC
string, err error
) {
3189 cgoCPPFLAGS
, cgoCFLAGS
, cgoCXXFLAGS
, _
, _
, err
:= b
.CFlags(p
)
3196 cflags
= str
.StringList(cgoCPPFLAGS
, pcCFLAGS
, cgoCXXFLAGS
)
3198 cflags
= str
.StringList(cgoCPPFLAGS
, pcCFLAGS
, cgoCFLAGS
)
3201 n
:= 5 // length of ".swig"
3203 n
= 8 // length of ".swigcxx"
3205 base
:= file
[:len(file
)-n
]
3206 goFile
:= base
+ ".go"
3207 gccBase
:= base
+ "_wrap."
3213 gccgo
:= cfg
.BuildToolchainName
== "gccgo"
3219 "-intgosize", intgosize
,
3221 "-o", objdir
+ gccBase
+ gccExt
,
3225 for _
, f
:= range cflags
{
3226 if len(f
) > 3 && f
[:2] == "-I" {
3227 args
= append(args
, f
)
3232 args
= append(args
, "-gccgo")
3233 if pkgpath
:= gccgoPkgpath(p
); pkgpath
!= "" {
3234 args
= append(args
, "-go-pkgpath", pkgpath
)
3238 args
= append(args
, "-c++")
3241 out
, err
:= b
.runOut(a
, p
.Dir
, nil, "swig", args
, file
)
3244 if bytes
.Contains(out
, []byte("-intgosize")) || bytes
.Contains(out
, []byte("-cgo")) {
3245 return "", "", errors
.New("must have SWIG version >= 3.0.6")
3247 b
.showOutput(a
, p
.Dir
, p
.Desc(), b
.processOutput(out
)) // swig error
3248 return "", "", errPrintedOutput
3253 b
.showOutput(a
, p
.Dir
, p
.Desc(), b
.processOutput(out
)) // swig warning
3256 // If the input was x.swig, the output is x.go in the objdir.
3257 // But there might be an x.go in the original dir too, and if it
3258 // uses cgo as well, cgo will be processing both and will
3259 // translate both into x.cgo1.go in the objdir, overwriting one.
3260 // Rename x.go to _x_swig.go to avoid this problem.
3261 // We ignore files in the original dir that begin with underscore
3262 // so _x_swig.go cannot conflict with an original file we were
3263 // going to compile.
3264 goFile
= objdir
+ goFile
3265 newGoFile
:= objdir
+ "_" + base
+ "_swig.go"
3266 if err
:= os
.Rename(goFile
, newGoFile
); err
!= nil {
3269 return newGoFile
, objdir
+ gccBase
+ gccExt
, nil
3272 // disableBuildID adjusts a linker command line to avoid creating a
3273 // build ID when creating an object file rather than an executable or
3274 // shared library. Some systems, such as Ubuntu, always add
3275 // --build-id to every link, but we don't want a build ID when we are
3276 // producing an object file. On some of those system a plain -r (not
3277 // -Wl,-r) will turn off --build-id, but clang 3.0 doesn't support a
3278 // plain -r. I don't know how to turn off --build-id when using clang
3279 // other than passing a trailing --build-id=none. So that is what we
3280 // do, but only on systems likely to support it, which is to say,
3281 // systems that normally use gold or the GNU linker.
3282 func (b
*Builder
) disableBuildID(ldflags
[]string) []string {
3284 case "android", "dragonfly", "linux", "netbsd":
3285 ldflags
= append(ldflags
, "-Wl,--build-id=none")
3290 // mkAbsFiles converts files into a list of absolute files,
3291 // assuming they were originally relative to dir,
3292 // and returns that new list.
3293 func mkAbsFiles(dir
string, files
[]string) []string {
3294 abs
:= make([]string, len(files
))
3295 for i
, f
:= range files
{
3296 if !filepath
.IsAbs(f
) {
3297 f
= filepath
.Join(dir
, f
)
3304 // passLongArgsInResponseFiles modifies cmd such that, for
3305 // certain programs, long arguments are passed in "response files", a
3306 // file on disk with the arguments, with one arg per line. An actual
3307 // argument starting with '@' means that the rest of the argument is
3308 // a filename of arguments to expand.
3310 // See issues 18468 (Windows) and 37768 (Darwin).
3311 func passLongArgsInResponseFiles(cmd
*exec
.Cmd
) (cleanup
func()) {
3312 cleanup
= func() {} // no cleanup by default
3315 for _
, arg
:= range cmd
.Args
{
3319 // If we're not approaching 32KB of args, just pass args normally.
3320 // (use 30KB instead to be conservative; not sure how accounting is done)
3321 if !useResponseFile(cmd
.Path
, argLen
) {
3325 tf
, err
:= os
.CreateTemp("", "args")
3327 log
.Fatalf("error writing long arguments to response file: %v", err
)
3329 cleanup
= func() { os
.Remove(tf
.Name()) }
3330 var buf bytes
.Buffer
3331 for _
, arg
:= range cmd
.Args
[1:] {
3332 fmt
.Fprintf(&buf
, "%s\n", encodeArg(arg
))
3334 if _
, err
:= tf
.Write(buf
.Bytes()); err
!= nil {
3337 log
.Fatalf("error writing long arguments to response file: %v", err
)
3339 if err
:= tf
.Close(); err
!= nil {
3341 log
.Fatalf("error writing long arguments to response file: %v", err
)
3343 cmd
.Args
= []string{cmd
.Args
[0], "@" + tf
.Name()}
3347 func useResponseFile(path
string, argLen
int) bool {
3348 // Unless the program uses objabi.Flagparse, which understands
3349 // response files, don't use response files.
3350 // TODO: do we need more commands? asm? cgo? For now, no.
3351 prog
:= strings
.TrimSuffix(filepath
.Base(path
), ".exe")
3353 case "compile", "link":
3358 if argLen
> sys
.ExecArgLengthLimit
{
3362 // On the Go build system, use response files about 10% of the
3363 // time, just to exercise this codepath.
3364 isBuilder
:= os
.Getenv("GO_BUILDER_NAME") != ""
3365 if isBuilder
&& rand
.Intn(10) == 0 {
3372 // encodeArg encodes an argument for response file writing.
3373 func encodeArg(arg
string) string {
3374 // If there aren't any characters we need to reencode, fastpath out.
3375 if !strings
.ContainsAny(arg
, "\\\n") {
3378 var b strings
.Builder
3379 for _
, r
:= range arg
{