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:
parent
99b6e9f73b
commit
8ed026e783
@ -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")
|
||||||
|
}
|
||||||
|
@ -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,
|
||||||
|
@ -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
|
||||||
|
@ -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")
|
||||||
|
@ -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)
|
||||||
|
@ -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)
|
||||||
|
Loading…
Reference in New Issue
Block a user