]> Cypherpunks repositories - gostls13.git/commitdiff
race: build system changes
authorDmitriy Vyukov <dvyukov@google.com>
Tue, 18 Sep 2012 19:47:15 +0000 (23:47 +0400)
committerDmitriy Vyukov <dvyukov@google.com>
Tue, 18 Sep 2012 19:47:15 +0000 (23:47 +0400)
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

src/cmd/go/build.go
src/cmd/go/pkg.go
src/cmd/go/run.go
src/cmd/go/test.go
src/cmd/go/testflag.go
src/pkg/go/build/build.go

index fd11a4dcbabf6257f92304902b84ad2e9ba82b04..889ed08b3b267c971d30129ba400a4e669e343fc 100644 (file)
@@ -8,6 +8,7 @@ import (
        "bytes"
        "container/heap"
        "errors"
+       "flag"
        "fmt"
        "go/build"
        "io"
@@ -59,6 +60,9 @@ The build flags are shared by the build, install, run, and test commands:
                do not delete it when exiting.
        -x
                print the commands.
+       -race
+               enable data race detection.
+               Currently supported only on linux/amd64 and darwin/amd64.
 
        -ccflags 'arg list'
                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 buildLdflags []string    // -ldflags flag
 var buildGccgoflags []string // -gccgoflags flag
+var buildRace bool           // -race flag
 
 var buildContext = build.Default
 var buildToolchain toolchain = noToolchain{}
@@ -154,6 +159,7 @@ func addBuildFlags(cmd *Command) {
        cmd.Flag.Var((*stringsFlag)(&buildGccgoflags), "gccgoflags", "")
        cmd.Flag.Var((*stringsFlag)(&buildContext.BuildTags), "tags", "")
        cmd.Flag.Var(buildCompiler{}, "compiler", "")
+       cmd.Flag.BoolVar(&buildRace, "race", false, "")
 }
 
 func addBuildFlagsNX(cmd *Command) {
@@ -173,6 +179,7 @@ func (v *stringsFlag) String() string {
 }
 
 func runBuild(cmd *Command, args []string) {
+       raceInit()
        var b builder
        b.init()
 
@@ -217,6 +224,7 @@ See also: go build, go get, go clean.
 }
 
 func runInstall(cmd *Command, args []string) {
+       raceInit()
        pkgs := packagesForBuild(args)
 
        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
        // 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.
-       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" {
                        var stk importStack
                        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" {
                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 {
                cgoflags = append(cgoflags, "-gccgo")
                if prefix := gccgoPrefix(p); prefix != "" {
@@ -1778,3 +1790,18 @@ func (q *actionQueue) push(a *action) {
 func (q *actionQueue) pop() *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")
+}
index 602f00cba9a4eb017c34b313d229f4c9fd87f354..94f01aab056279744bf382ae3bb996c91573cf06 100644 (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.
        if !p.Standard || (p.ImportPath != "runtime" && p.ImportPath != "unsafe") {
                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,
index 6043b7e2029d8c85d2db09d6d2c640e53df41401..0f41fa61be7e9270548cec90aa8c6cc67b25448f 100644 (file)
@@ -34,6 +34,7 @@ func printStderr(args ...interface{}) (int, error) {
 }
 
 func runRun(cmd *Command, args []string) {
+       raceInit()
        var b builder
        b.init()
        b.print = printStderr
index cd9b411e9d208f98aa02165764098d6138204dc4..eab3213d29161c0bc3fea7b5aff93a28588b7826 100644 (file)
@@ -207,6 +207,7 @@ func runTest(cmd *Command, args []string) {
        var pkgArgs []string
        pkgArgs, testArgs = testFlags(args)
 
+       raceInit()
        pkgs := packagesForBuild(pkgArgs)
        if len(pkgs) == 0 {
                fatalf("no packages to test")
index ecf5bf456293fd24ce29119570e79c61201f173a..1dd27a2e4aa808159d8e6bcfa893e3ac15c1871f 100644 (file)
@@ -71,6 +71,7 @@ var testFlagDefn = []*testFlagSpec{
        {name: "gccgoflags"},
        {name: "tags"},
        {name: "compiler"},
+       {name: "race", boolVar: &buildRace},
 
        // passed to 6.out, adding a "test." prefix to the name if necessary: -v becomes -test.v.
        {name: "bench", passToTest: true},
@@ -129,7 +130,7 @@ func testFlags(args []string) (packageNames, passToTest []string) {
                }
                switch f.name {
                // bool flags.
-               case "a", "c", "i", "n", "x", "v", "work":
+               case "a", "c", "i", "n", "x", "v", "work", "race":
                        setBoolFlag(f.boolVar, value)
                case "p":
                        setIntFlag(&buildP, value)
index 43ad4531ed266f7b7a7c08d9583547673a8b9575..b8b1c13b5b8ad5f3c363d7920a866cec3beea3f8 100644 (file)
@@ -33,6 +33,7 @@ type Context struct {
        GOPATH      string   // Go path
        CgoEnabled  bool     // whether cgo can be used
        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
        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)
                pkga = "pkg/gccgo/" + dir + "lib" + elem + ".a"
        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:
                // Save error for end of function.
                pkgerr = fmt.Errorf("import %q: unknown compiler %q", path, ctxt.Compiler)