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