]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/go: add -compiler
authorRuss Cox <rsc@golang.org>
Tue, 6 Mar 2012 05:36:24 +0000 (00:36 -0500)
committerRuss Cox <rsc@golang.org>
Tue, 6 Mar 2012 05:36:24 +0000 (00:36 -0500)
go/build: add Context.Compiler

Fixes #3157.

R=golang-dev, r
CC=golang-dev
https://golang.org/cl/5756047

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

index cf249cdbc825fc13d7d4c6d225adb5bf6ddf0f5d..be0178c9f228efac792e97958382f64aaaf213f1 100644 (file)
@@ -12,6 +12,7 @@ import (
        "go/build"
        "io"
        "io/ioutil"
+       "log"
        "os"
        "os/exec"
        "path"
@@ -58,6 +59,8 @@ The build flags are shared by the build, install, run, and test commands:
        -x
                print the commands.
 
+       -compiler name
+               name of compiler to use, as in runtime.Compiler (gccgo or gc)
        -gccgoflags 'arg list'
                arguments to pass on each gccgo compiler/linker invocation
        -gcflags 'arg list'
@@ -97,6 +100,38 @@ var buildLdflags []string    // -ldflags flag
 var buildGccgoflags []string // -gccgoflags flag
 
 var buildContext = build.Default
+var buildToolchain toolchain = noToolchain{}
+
+// buildCompier implements flag.Var.
+// It implements Set by updating both
+// buildToolchain and buildContext.Compiler.
+type buildCompiler struct{}
+
+func (c buildCompiler) Set(value string) error {
+       switch value {
+       case "gc":
+               buildToolchain = gcToolchain{}
+       case "gccgo":
+               buildToolchain = gccgcToolchain{}
+       default:
+               return fmt.Errorf("unknown compiler %q", value)
+       }
+       buildContext.Compiler = value
+       return nil
+}
+
+func (c buildCompiler) String() string {
+       return buildContext.Compiler
+}
+
+func init() {
+       switch build.Default.Compiler {
+       case "gc":
+               buildToolchain = gcToolchain{}
+       case "gccgo":
+               buildToolchain = gccgcToolchain{}
+       }
+}
 
 // addBuildFlags adds the flags common to the build and install commands.
 func addBuildFlags(cmd *Command) {
@@ -111,6 +146,7 @@ func addBuildFlags(cmd *Command) {
        cmd.Flag.Var((*stringsFlag)(&buildLdflags), "ldflags", "")
        cmd.Flag.Var((*stringsFlag)(&buildGccgoflags), "gccgoflags", "")
        cmd.Flag.Var((*stringsFlag)(&buildContext.BuildTags), "tags", "")
+       cmd.Flag.Var(buildCompiler{}, "compiler", "")
 }
 
 type stringsFlag []string
@@ -413,7 +449,7 @@ func (b *builder) action(mode buildMode, depMode buildMode, p *Package) *action
                        return a
                }
                // gccgo standard library is "fake" too.
-               if _, ok := buildToolchain.(gccgoToolchain); ok {
+               if _, ok := buildToolchain.(gccgcToolchain); ok {
                        // the target name is needed for cgo.
                        a.target = p.target
                        return a
@@ -768,7 +804,7 @@ func (b *builder) includeArgs(flag string, all []*action) []string {
        for _, a1 := range all {
                if dir := a1.pkgdir; dir == a1.p.build.PkgRoot && !incMap[dir] {
                        incMap[dir] = true
-                       if _, ok := buildToolchain.(gccgoToolchain); ok {
+                       if _, ok := buildToolchain.(gccgcToolchain); ok {
                                dir = filepath.Join(dir, "gccgo")
                        } else {
                                dir = filepath.Join(dir, goos+"_"+goarch)
@@ -1073,32 +1109,60 @@ type toolchain interface {
        linker() string
 }
 
-type goToolchain struct{}
-type gccgoToolchain struct{}
+type noToolchain struct{}
 
-var buildToolchain toolchain
+func noCompiler() error {
+       log.Fatal("unknown compiler %q", buildContext.Compiler)
+       return nil
+}
 
-func init() {
-       // TODO(rsc): Decide how to trigger gccgo.  Issue 3157.
-       if os.Getenv("GC") == "gccgo" {
-               buildContext.Gccgo = true
-               buildToolchain = gccgoToolchain{}
-       } else {
-               buildToolchain = goToolchain{}
-       }
+func (noToolchain) compiler() string {
+       noCompiler()
+       return ""
+}
+
+func (noToolchain) linker() string {
+       noCompiler()
+       return ""
+}
+
+func (noToolchain) gc(b *builder, p *Package, obj string, importArgs []string, gofiles []string) (ofile string, err error) {
+       return "", noCompiler()
+}
+
+func (noToolchain) asm(b *builder, p *Package, obj, ofile, sfile string) error {
+       return noCompiler()
+}
+
+func (noToolchain) pkgpath(basedir string, p *Package) string {
+       noCompiler()
+       return ""
+}
+
+func (noToolchain) pack(b *builder, p *Package, objDir, afile string, ofiles []string) error {
+       return noCompiler()
+}
+
+func (noToolchain) ld(b *builder, p *Package, out string, allactions []*action, mainpkg string, ofiles []string) error {
+       return noCompiler()
+}
+
+func (noToolchain) cc(b *builder, p *Package, objdir, ofile, cfile string) error {
+       return noCompiler()
 }
 
 // The Go toolchain.
+type gcToolchain struct{}
 
-func (goToolchain) compiler() string {
+func (gcToolchain) compiler() string {
        return tool(archChar + "g")
 }
 
-func (goToolchain) linker() string {
+func (gcToolchain) linker() string {
        return tool(archChar + "l")
 }
 
-func (goToolchain) gc(b *builder, p *Package, obj string, importArgs []string, gofiles []string) (ofile string, err error) {
+func (gcToolchain) gc(b *builder, p *Package, obj string, importArgs []string, gofiles []string) (ofile string, err error) {
        out := "_go_." + archChar
        ofile = obj + out
        gcargs := []string{"-p", p.ImportPath}
@@ -1115,17 +1179,17 @@ func (goToolchain) gc(b *builder, p *Package, obj string, importArgs []string, g
        return ofile, b.run(p.Dir, p.ImportPath, args)
 }
 
-func (goToolchain) asm(b *builder, p *Package, obj, ofile, sfile string) error {
+func (gcToolchain) asm(b *builder, p *Package, obj, ofile, sfile string) error {
        sfile = mkAbs(p.Dir, sfile)
        return b.run(p.Dir, p.ImportPath, tool(archChar+"a"), "-I", obj, "-o", ofile, "-DGOOS_"+goos, "-DGOARCH_"+goarch, sfile)
 }
 
-func (goToolchain) pkgpath(basedir string, p *Package) string {
+func (gcToolchain) pkgpath(basedir string, p *Package) string {
        end := filepath.FromSlash(p.ImportPath + ".a")
        return filepath.Join(basedir, end)
 }
 
-func (goToolchain) pack(b *builder, p *Package, objDir, afile string, ofiles []string) error {
+func (gcToolchain) pack(b *builder, p *Package, objDir, afile string, ofiles []string) error {
        var absOfiles []string
        for _, f := range ofiles {
                absOfiles = append(absOfiles, mkAbs(objDir, f))
@@ -1133,12 +1197,12 @@ func (goToolchain) pack(b *builder, p *Package, objDir, afile string, ofiles []s
        return b.run(p.Dir, p.ImportPath, tool("pack"), "grc", mkAbs(objDir, afile), absOfiles)
 }
 
-func (goToolchain) ld(b *builder, p *Package, out string, allactions []*action, mainpkg string, ofiles []string) error {
+func (gcToolchain) ld(b *builder, p *Package, out string, allactions []*action, mainpkg string, ofiles []string) error {
        importArgs := b.includeArgs("-L", allactions)
        return b.run(p.Dir, p.ImportPath, tool(archChar+"l"), "-o", out, importArgs, buildLdflags, mainpkg)
 }
 
-func (goToolchain) cc(b *builder, p *Package, objdir, ofile, cfile string) error {
+func (gcToolchain) cc(b *builder, p *Package, objdir, ofile, cfile string) error {
        inc := filepath.Join(goroot, "pkg", fmt.Sprintf("%s_%s", goos, goarch))
        cfile = mkAbs(p.Dir, cfile)
        return b.run(p.Dir, p.ImportPath, tool(archChar+"c"), "-FVw",
@@ -1147,18 +1211,19 @@ func (goToolchain) cc(b *builder, p *Package, objdir, ofile, cfile string) error
 }
 
 // The Gccgo toolchain.
+type gccgcToolchain struct{}
 
 var gccgoBin, _ = exec.LookPath("gccgo")
 
-func (gccgoToolchain) compiler() string {
+func (gccgcToolchain) compiler() string {
        return gccgoBin
 }
 
-func (gccgoToolchain) linker() string {
+func (gccgcToolchain) linker() string {
        return gccgoBin
 }
 
-func (gccgoToolchain) gc(b *builder, p *Package, obj string, importArgs []string, gofiles []string) (ofile string, err error) {
+func (gccgcToolchain) gc(b *builder, p *Package, obj string, importArgs []string, gofiles []string) (ofile string, err error) {
        out := p.Name + ".o"
        ofile = obj + out
        gcargs := []string{"-g"}
@@ -1176,19 +1241,19 @@ func (gccgoToolchain) gc(b *builder, p *Package, obj string, importArgs []string
        return ofile, b.run(p.Dir, p.ImportPath, args)
 }
 
-func (gccgoToolchain) asm(b *builder, p *Package, obj, ofile, sfile string) error {
+func (gccgcToolchain) asm(b *builder, p *Package, obj, ofile, sfile string) error {
        sfile = mkAbs(p.Dir, sfile)
        return b.run(p.Dir, p.ImportPath, "gccgo", "-I", obj, "-o", ofile, "-DGOOS_"+goos, "-DGOARCH_"+goarch, sfile)
 }
 
-func (gccgoToolchain) pkgpath(basedir string, p *Package) string {
+func (gccgcToolchain) pkgpath(basedir string, p *Package) string {
        end := filepath.FromSlash(p.ImportPath + ".a")
        afile := filepath.Join(basedir, end)
        // add "lib" to the final element
        return filepath.Join(filepath.Dir(afile), "lib"+filepath.Base(afile))
 }
 
-func (gccgoToolchain) pack(b *builder, p *Package, objDir, afile string, ofiles []string) error {
+func (gccgcToolchain) pack(b *builder, p *Package, objDir, afile string, ofiles []string) error {
        var absOfiles []string
        for _, f := range ofiles {
                absOfiles = append(absOfiles, mkAbs(objDir, f))
@@ -1196,7 +1261,7 @@ func (gccgoToolchain) pack(b *builder, p *Package, objDir, afile string, ofiles
        return b.run(p.Dir, p.ImportPath, "ar", "cru", mkAbs(objDir, afile), absOfiles)
 }
 
-func (tools gccgoToolchain) ld(b *builder, p *Package, out string, allactions []*action, mainpkg string, ofiles []string) error {
+func (tools gccgcToolchain) ld(b *builder, p *Package, out string, allactions []*action, mainpkg string, ofiles []string) error {
        // gccgo needs explicit linking with all package dependencies,
        // and all LDFLAGS from cgo dependencies.
        afiles := make(map[*Package]string)
@@ -1219,7 +1284,7 @@ func (tools gccgoToolchain) ld(b *builder, p *Package, out string, allactions []
        return b.run(p.Dir, p.ImportPath, "gccgo", "-o", out, buildGccgoflags, ofiles, "-Wl,-(", ldflags, "-Wl,-)")
 }
 
-func (gccgoToolchain) cc(b *builder, p *Package, objdir, ofile, cfile string) error {
+func (gccgcToolchain) cc(b *builder, p *Package, objdir, ofile, cfile string) error {
        inc := filepath.Join(goroot, "pkg", fmt.Sprintf("%s_%s", goos, goarch))
        cfile = mkAbs(p.Dir, cfile)
        return b.run(p.Dir, p.ImportPath, "gcc", "-Wall", "-g",
@@ -1322,7 +1387,7 @@ 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 _, ok := buildToolchain.(gccgoToolchain); ok {
+       if _, ok := buildToolchain.(gccgcToolchain); ok {
                cgoflags = append(cgoflags, "-gccgo")
        }
        if err := b.run(p.Dir, p.ImportPath, cgoExe, "-objdir", obj, cgoflags, "--", cgoCFLAGS, p.CgoFiles); err != nil {
@@ -1362,7 +1427,7 @@ func (b *builder) cgo(p *Package, cgoExe, obj string, gccfiles []string) (outGo,
                return nil, nil, err
        }
 
-       if _, ok := buildToolchain.(gccgoToolchain); ok {
+       if _, ok := buildToolchain.(gccgcToolchain); ok {
                // we don't use dynimport when using gccgo.
                return outGo, outObj, nil
        }
index d0aa3a012aefbe256f618ae150ac51798dc8b46b..8c887ba7507b23b4f5d6c21ea1236fa4ff2a5f6f 100644 (file)
@@ -70,6 +70,7 @@ var testFlagDefn = []*testFlagSpec{
        {name: "ldflags"},
        {name: "gccgoflags"},
        {name: "tags"},
+       {name: "compiler"},
 
        // passed to 6.out, adding a "test." prefix to the name if necessary: -v becomes -test.v.
        {name: "bench", passToTest: true},
@@ -140,6 +141,8 @@ func testFlags(args []string) (packageNames, passToTest []string) {
                        buildGccgoflags = strings.Fields(value)
                case "tags":
                        buildContext.BuildTags = strings.Fields(value)
+               case "compiler":
+                       buildContext.Compiler = value
                case "file":
                        testFiles = append(testFiles, value)
                case "bench":
index eece7610562de836bbe4ce1a2cd0fea942151de0..d986f8039fe480c500eee69e52a97d9a59ae28eb 100644 (file)
@@ -34,7 +34,7 @@ type Context struct {
        CgoEnabled  bool     // whether cgo can be used
        BuildTags   []string // additional tags to recognize in +build lines
        UseAllFiles bool     // use files regardless of +build lines, file names
-       Gccgo       bool     // assume use of gccgo when computing object paths
+       Compiler    string   // compiler to assume when computing target paths
 
        // By default, Import uses the operating system's file system calls
        // to read directories and files.  To read from other sources,
@@ -228,6 +228,7 @@ func defaultContext() Context {
        c.GOOS = envOr("GOOS", runtime.GOOS)
        c.GOROOT = runtime.GOROOT()
        c.GOPATH = envOr("GOPATH", "")
+       c.Compiler = runtime.Compiler
 
        switch os.Getenv("CGO_ENABLED") {
        case "1":
@@ -336,11 +337,16 @@ func (ctxt *Context) Import(path string, src string, mode ImportMode) (*Package,
        }
 
        var pkga string
-       if ctxt.Gccgo {
+       var pkgerr error
+       switch ctxt.Compiler {
+       case "gccgo":
                dir, elem := pathpkg.Split(p.ImportPath)
                pkga = "pkg/gccgo/" + dir + "lib" + elem + ".a"
-       } else {
+       case "gc":
                pkga = "pkg/" + ctxt.GOOS + "_" + ctxt.GOARCH + "/" + p.ImportPath + ".a"
+       default:
+               // Save error for end of function.
+               pkgerr = fmt.Errorf("import %q: unknown compiler %q", path, ctxt.Compiler)
        }
 
        binaryOnly := false
@@ -396,7 +402,7 @@ func (ctxt *Context) Import(path string, src string, mode ImportMode) (*Package,
                if ctxt.GOROOT != "" {
                        dir := ctxt.joinPath(ctxt.GOROOT, "src", "pkg", path)
                        isDir := ctxt.isDir(dir)
-                       binaryOnly = !isDir && mode&AllowBinary != 0 && ctxt.isFile(ctxt.joinPath(ctxt.GOROOT, pkga))
+                       binaryOnly = !isDir && mode&AllowBinary != 0 && pkga != "" && ctxt.isFile(ctxt.joinPath(ctxt.GOROOT, pkga))
                        if isDir || binaryOnly {
                                p.Dir = dir
                                p.Goroot = true
@@ -407,7 +413,7 @@ func (ctxt *Context) Import(path string, src string, mode ImportMode) (*Package,
                for _, root := range ctxt.gopath() {
                        dir := ctxt.joinPath(root, "src", path)
                        isDir := ctxt.isDir(dir)
-                       binaryOnly = !isDir && mode&AllowBinary != 0 && ctxt.isFile(ctxt.joinPath(root, pkga))
+                       binaryOnly = !isDir && mode&AllowBinary != 0 && pkga != "" && ctxt.isFile(ctxt.joinPath(root, pkga))
                        if isDir || binaryOnly {
                                p.Dir = dir
                                p.Root = root
@@ -426,14 +432,16 @@ Found:
                }
                p.PkgRoot = ctxt.joinPath(p.Root, "pkg")
                p.BinDir = ctxt.joinPath(p.Root, "bin")
-               p.PkgObj = ctxt.joinPath(p.Root, pkga)
+               if pkga != "" {
+                       p.PkgObj = ctxt.joinPath(p.Root, pkga)
+               }
        }
 
        if mode&FindOnly != 0 {
-               return p, nil
+               return p, pkgerr
        }
        if binaryOnly && (mode&AllowBinary) != 0 {
-               return p, nil
+               return p, pkgerr
        }
 
        dirs, err := ctxt.readDir(p.Dir)
@@ -601,7 +609,7 @@ Found:
                sort.Strings(p.SFiles)
        }
 
-       return p, nil
+       return p, pkgerr
 }
 
 func cleanImports(m map[string][]token.Position) ([]string, map[string][]token.Position) {