1
0
mirror of https://github.com/golang/go synced 2024-11-25 05:57:57 -07:00

race: build system changes

This is the first part of a bigger change that adds data race detection feature:
https://golang.org/cl/6456044
Adds -race flag to go command.
API change:
+pkg go/build, type Context struct, InstallTag string

R=rsc
CC=golang-dev
https://golang.org/cl/6488075
This commit is contained in:
Dmitriy Vyukov 2012-09-18 23:47:15 +04:00
parent 99b6e9f73b
commit 8ed026e783
6 changed files with 43 additions and 3 deletions

View File

@ -8,6 +8,7 @@ import (
"bytes" "bytes"
"container/heap" "container/heap"
"errors" "errors"
"flag"
"fmt" "fmt"
"go/build" "go/build"
"io" "io"
@ -59,6 +60,9 @@ The build flags are shared by the build, install, run, and test commands:
do not delete it when exiting. do not delete it when exiting.
-x -x
print the commands. print the commands.
-race
enable data race detection.
Currently supported only on linux/amd64 and darwin/amd64.
-ccflags 'arg list' -ccflags 'arg list'
arguments to pass on each 5c, 6c, or 8c compiler invocation arguments to pass on each 5c, 6c, or 8c compiler invocation
@ -104,6 +108,7 @@ var buildGcflags []string // -gcflags flag
var buildCcflags []string // -ccflags flag var buildCcflags []string // -ccflags flag
var buildLdflags []string // -ldflags flag var buildLdflags []string // -ldflags flag
var buildGccgoflags []string // -gccgoflags flag var buildGccgoflags []string // -gccgoflags flag
var buildRace bool // -race flag
var buildContext = build.Default var buildContext = build.Default
var buildToolchain toolchain = noToolchain{} var buildToolchain toolchain = noToolchain{}
@ -154,6 +159,7 @@ func addBuildFlags(cmd *Command) {
cmd.Flag.Var((*stringsFlag)(&buildGccgoflags), "gccgoflags", "") cmd.Flag.Var((*stringsFlag)(&buildGccgoflags), "gccgoflags", "")
cmd.Flag.Var((*stringsFlag)(&buildContext.BuildTags), "tags", "") cmd.Flag.Var((*stringsFlag)(&buildContext.BuildTags), "tags", "")
cmd.Flag.Var(buildCompiler{}, "compiler", "") cmd.Flag.Var(buildCompiler{}, "compiler", "")
cmd.Flag.BoolVar(&buildRace, "race", false, "")
} }
func addBuildFlagsNX(cmd *Command) { func addBuildFlagsNX(cmd *Command) {
@ -173,6 +179,7 @@ func (v *stringsFlag) String() string {
} }
func runBuild(cmd *Command, args []string) { func runBuild(cmd *Command, args []string) {
raceInit()
var b builder var b builder
b.init() b.init()
@ -217,6 +224,7 @@ See also: go build, go get, go clean.
} }
func runInstall(cmd *Command, args []string) { func runInstall(cmd *Command, args []string) {
raceInit()
pkgs := packagesForBuild(args) pkgs := packagesForBuild(args)
for _, p := range pkgs { for _, p := range pkgs {
@ -441,7 +449,7 @@ func (b *builder) action(mode buildMode, depMode buildMode, p *Package) *action
// using cgo, to make sure we do not overwrite the binary while // using cgo, to make sure we do not overwrite the binary while
// a package is using it. If this is a cross-build, then the cgo we // a package is using it. If this is a cross-build, then the cgo we
// are writing is not the cgo we need to use. // are writing is not the cgo we need to use.
if goos == runtime.GOOS && goarch == runtime.GOARCH { if goos == runtime.GOOS && goarch == runtime.GOARCH && !buildRace {
if len(p.CgoFiles) > 0 || p.Standard && p.ImportPath == "runtime/cgo" { if len(p.CgoFiles) > 0 || p.Standard && p.ImportPath == "runtime/cgo" {
var stk importStack var stk importStack
p1 := loadPackage("cmd/cgo", &stk) p1 := loadPackage("cmd/cgo", &stk)
@ -1547,6 +1555,10 @@ func (b *builder) cgo(p *Package, cgoExe, obj string, gccfiles []string) (outGo,
if p.Standard && p.ImportPath == "runtime/cgo" { if p.Standard && p.ImportPath == "runtime/cgo" {
cgoflags = append(cgoflags, "-import_runtime_cgo=false") cgoflags = append(cgoflags, "-import_runtime_cgo=false")
} }
if p.Standard && (p.ImportPath == "runtime/race" || p.ImportPath == "runtime/cgo") {
cgoflags = append(cgoflags, "-import_syscall=false")
}
if _, ok := buildToolchain.(gccgcToolchain); ok { if _, ok := buildToolchain.(gccgcToolchain); ok {
cgoflags = append(cgoflags, "-gccgo") cgoflags = append(cgoflags, "-gccgo")
if prefix := gccgoPrefix(p); prefix != "" { if prefix := gccgoPrefix(p); prefix != "" {
@ -1778,3 +1790,18 @@ func (q *actionQueue) push(a *action) {
func (q *actionQueue) pop() *action { func (q *actionQueue) pop() *action {
return heap.Pop(q).(*action) return heap.Pop(q).(*action)
} }
func raceInit() {
if !buildRace {
return
}
if goarch != "amd64" || goos != "linux" && goos != "darwin" {
fmt.Fprintf(os.Stderr, "go %s: -race is only supported on linux/amd64 and darwin/amd64\n", flag.Args()[0])
os.Exit(2)
}
buildGcflags = append(buildGcflags, "-b")
buildLdflags = append(buildLdflags, "-b")
buildCcflags = append(buildCcflags, "-DRACE")
buildContext.InstallTag = "race"
buildContext.BuildTags = append(buildContext.BuildTags, "race")
}

View File

@ -342,6 +342,11 @@ func (p *Package) load(stk *importStack, bp *build.Package, err error) *Package
// Everything depends on runtime, except runtime and unsafe. // Everything depends on runtime, except runtime and unsafe.
if !p.Standard || (p.ImportPath != "runtime" && p.ImportPath != "unsafe") { if !p.Standard || (p.ImportPath != "runtime" && p.ImportPath != "unsafe") {
importPaths = append(importPaths, "runtime") importPaths = append(importPaths, "runtime")
// When race detection enabled everything depends on runtime/race.
// Exclude runtime/cgo and cmd/cgo to avoid circular dependencies.
if buildRace && (!p.Standard || (p.ImportPath != "runtime/race" && p.ImportPath != "runtime/cgo" && p.ImportPath != "cmd/cgo")) {
importPaths = append(importPaths, "runtime/race")
}
} }
// Build list of full paths to all Go files in the package, // Build list of full paths to all Go files in the package,

View File

@ -34,6 +34,7 @@ func printStderr(args ...interface{}) (int, error) {
} }
func runRun(cmd *Command, args []string) { func runRun(cmd *Command, args []string) {
raceInit()
var b builder var b builder
b.init() b.init()
b.print = printStderr b.print = printStderr

View File

@ -207,6 +207,7 @@ func runTest(cmd *Command, args []string) {
var pkgArgs []string var pkgArgs []string
pkgArgs, testArgs = testFlags(args) pkgArgs, testArgs = testFlags(args)
raceInit()
pkgs := packagesForBuild(pkgArgs) pkgs := packagesForBuild(pkgArgs)
if len(pkgs) == 0 { if len(pkgs) == 0 {
fatalf("no packages to test") fatalf("no packages to test")

View File

@ -71,6 +71,7 @@ var testFlagDefn = []*testFlagSpec{
{name: "gccgoflags"}, {name: "gccgoflags"},
{name: "tags"}, {name: "tags"},
{name: "compiler"}, {name: "compiler"},
{name: "race", boolVar: &buildRace},
// passed to 6.out, adding a "test." prefix to the name if necessary: -v becomes -test.v. // passed to 6.out, adding a "test." prefix to the name if necessary: -v becomes -test.v.
{name: "bench", passToTest: true}, {name: "bench", passToTest: true},
@ -129,7 +130,7 @@ func testFlags(args []string) (packageNames, passToTest []string) {
} }
switch f.name { switch f.name {
// bool flags. // bool flags.
case "a", "c", "i", "n", "x", "v", "work": case "a", "c", "i", "n", "x", "v", "work", "race":
setBoolFlag(f.boolVar, value) setBoolFlag(f.boolVar, value)
case "p": case "p":
setIntFlag(&buildP, value) setIntFlag(&buildP, value)

View File

@ -33,6 +33,7 @@ type Context struct {
GOPATH string // Go path GOPATH string // Go path
CgoEnabled bool // whether cgo can be used CgoEnabled bool // whether cgo can be used
BuildTags []string // additional tags to recognize in +build lines BuildTags []string // additional tags to recognize in +build lines
InstallTag string // package install directory suffix
UseAllFiles bool // use files regardless of +build lines, file names UseAllFiles bool // use files regardless of +build lines, file names
Compiler string // compiler to assume when computing target paths Compiler string // compiler to assume when computing target paths
@ -362,7 +363,11 @@ func (ctxt *Context) Import(path string, srcDir string, mode ImportMode) (*Packa
dir, elem := pathpkg.Split(p.ImportPath) dir, elem := pathpkg.Split(p.ImportPath)
pkga = "pkg/gccgo/" + dir + "lib" + elem + ".a" pkga = "pkg/gccgo/" + dir + "lib" + elem + ".a"
case "gc": case "gc":
pkga = "pkg/" + ctxt.GOOS + "_" + ctxt.GOARCH + "/" + p.ImportPath + ".a" tag := ""
if ctxt.InstallTag != "" {
tag = "_" + ctxt.InstallTag
}
pkga = "pkg/" + ctxt.GOOS + "_" + ctxt.GOARCH + tag + "/" + p.ImportPath + ".a"
default: default:
// Save error for end of function. // Save error for end of function.
pkgerr = fmt.Errorf("import %q: unknown compiler %q", path, ctxt.Compiler) pkgerr = fmt.Errorf("import %q: unknown compiler %q", path, ctxt.Compiler)