mirror of
https://github.com/golang/go
synced 2024-11-19 15:44:44 -07:00
cmd/dist, cmd/cgo, cmd/go: allow per-goos/goarch default CC
Even though cmd/dist has historically distinguished "CC for gohostos/gohostarch" from "CC for target goos/goarch", it has not recorded that distinction for later use by cmd/cgo and cmd/go. Now that content-based staleness includes the CC setting in the decision about when to rebuild packages, the go command needs to know the details of which CC to use when. Otherwise lots of things look out of date and (worse) may be rebuilt with the wrong CC. A related issue is that users may want to be able to build a toolchain capable of cross-compiling for two different non-host targets, and to date we've required that CC_FOR_TARGET apply to both. This CL introduces CC_FOR_${GOOS}_${GOARCH}, so that you can (for example) set CC_FOR_linux_arm and CC_FOR_linux_arm64 separately on a linux/ppc64 host and be able to cross-compile to either arm or arm64 with the right toolchain. Fixes #8161. Half of a fix for #22509. Change-Id: I7a43769f39d859f659d31bc96980918ba102fb83 Reviewed-on: https://go-review.googlesource.com/76018 Run-TryBot: Russ Cox <rsc@golang.org> Reviewed-by: David Crawshaw <crawshaw@golang.org>
This commit is contained in:
parent
5e48d2b62a
commit
4739c0db47
@ -102,11 +102,13 @@ the use of cgo, and to 0 to disable it. The go tool will set the
|
||||
build constraint "cgo" if cgo is enabled.
|
||||
|
||||
When cross-compiling, you must specify a C cross-compiler for cgo to
|
||||
use. You can do this by setting the CC_FOR_TARGET environment
|
||||
variable when building the toolchain using make.bash, or by setting
|
||||
the CC environment variable any time you run the go tool. The
|
||||
CXX_FOR_TARGET and CXX environment variables work in a similar way for
|
||||
C++ code.
|
||||
use. You can do this by setting the generic CC_FOR_TARGET or the
|
||||
more specific CC_FOR_${GOOS}_${GOARCH} (for example, CC_FOR_linux_arm)
|
||||
environment variable when building the toolchain using make.bash,
|
||||
or you can set the CC environment variable any time you run the go tool.
|
||||
|
||||
The CXX_FOR_TARGET, CXX_FOR_${GOOS}_${GOARCH}, and CXX
|
||||
environment variables work in a similar way for C++ code.
|
||||
|
||||
Go references to C
|
||||
|
||||
|
@ -1221,7 +1221,7 @@ func (p *Package) gccBaseCmd() []string {
|
||||
if ret := strings.Fields(os.Getenv("GCC")); len(ret) > 0 {
|
||||
return ret
|
||||
}
|
||||
return strings.Fields(defaultCC)
|
||||
return strings.Fields(defaultCC(goos, goarch))
|
||||
}
|
||||
|
||||
// gccMachine returns the gcc -m flag to use, either "-m32", "-m64" or "-marm".
|
||||
|
147
src/cmd/dist/build.go
vendored
147
src/cmd/dist/build.go
vendored
@ -23,29 +23,28 @@ import (
|
||||
|
||||
// The usual variables.
|
||||
var (
|
||||
goarch string
|
||||
gobin string
|
||||
gohostarch string
|
||||
gohostos string
|
||||
goos string
|
||||
goarm string
|
||||
go386 string
|
||||
goroot string
|
||||
goroot_final string
|
||||
goextlinkenabled string
|
||||
gogcflags string // For running built compiler
|
||||
goldflags string
|
||||
workdir string
|
||||
tooldir string
|
||||
oldgoos string
|
||||
oldgoarch string
|
||||
exe string
|
||||
defaultcc string
|
||||
defaultcflags string
|
||||
defaultldflags string
|
||||
defaultcxxtarget string
|
||||
defaultcctarget string
|
||||
defaultpkgconfigtarget string
|
||||
goarch string
|
||||
gobin string
|
||||
gohostarch string
|
||||
gohostos string
|
||||
goos string
|
||||
goarm string
|
||||
go386 string
|
||||
goroot string
|
||||
goroot_final string
|
||||
goextlinkenabled string
|
||||
gogcflags string // For running built compiler
|
||||
goldflags string
|
||||
workdir string
|
||||
tooldir string
|
||||
oldgoos string
|
||||
oldgoarch string
|
||||
exe string
|
||||
defaultcc map[string]string
|
||||
defaultcxx map[string]string
|
||||
defaultcflags string
|
||||
defaultldflags string
|
||||
defaultpkgconfig string
|
||||
|
||||
rebuildall bool
|
||||
defaultclang bool
|
||||
@ -172,49 +171,21 @@ func xinit() {
|
||||
|
||||
gogcflags = os.Getenv("BOOT_GO_GCFLAGS")
|
||||
|
||||
b = os.Getenv("CC")
|
||||
if b == "" {
|
||||
// Use clang on OS X, because gcc is deprecated there.
|
||||
// Xcode for OS X 10.9 Mavericks will ship a fake "gcc" binary that
|
||||
// actually runs clang. We prepare different command
|
||||
// lines for the two binaries, so it matters what we call it.
|
||||
// See golang.org/issue/5822.
|
||||
if defaultclang {
|
||||
b = "clang"
|
||||
} else {
|
||||
b = "gcc"
|
||||
}
|
||||
cc := "gcc"
|
||||
if defaultclang {
|
||||
cc = "clang"
|
||||
}
|
||||
defaultcc = b
|
||||
defaultcc = compilerEnv("CC", cc)
|
||||
defaultcxx = compilerEnv("CXX", cc+"++")
|
||||
|
||||
defaultcflags = os.Getenv("CFLAGS")
|
||||
|
||||
defaultldflags = os.Getenv("LDFLAGS")
|
||||
|
||||
b = os.Getenv("CC_FOR_TARGET")
|
||||
if b == "" {
|
||||
b = defaultcc
|
||||
}
|
||||
defaultcctarget = b
|
||||
|
||||
b = os.Getenv("CXX_FOR_TARGET")
|
||||
if b == "" {
|
||||
b = os.Getenv("CXX")
|
||||
if b == "" {
|
||||
if defaultclang {
|
||||
b = "clang++"
|
||||
} else {
|
||||
b = "g++"
|
||||
}
|
||||
}
|
||||
}
|
||||
defaultcxxtarget = b
|
||||
|
||||
b = os.Getenv("PKG_CONFIG")
|
||||
if b == "" {
|
||||
b = "pkg-config"
|
||||
}
|
||||
defaultpkgconfigtarget = b
|
||||
defaultpkgconfig = b
|
||||
|
||||
// For tools being invoked but also for os.ExpandEnv.
|
||||
os.Setenv("GO386", go386)
|
||||
@ -244,6 +215,55 @@ func xinit() {
|
||||
tooldir = pathf("%s/pkg/tool/%s_%s", goroot, gohostos, gohostarch)
|
||||
}
|
||||
|
||||
// compilerEnv returns a map from "goos/goarch" to the
|
||||
// compiler setting to use for that platform.
|
||||
// The entry for key "" covers any goos/goarch not explicitly set in the map.
|
||||
// For example, compilerEnv("CC", "gcc") returns the C compiler settings
|
||||
// read from $CC, defaulting to gcc.
|
||||
//
|
||||
// The result is a map because additional environment variables
|
||||
// can be set to change the compiler based on goos/goarch settings.
|
||||
// The following applies to all envNames but CC is assumed to simplify
|
||||
// the presentation.
|
||||
//
|
||||
// If no environment variables are set, we use def for all goos/goarch.
|
||||
// $CC, if set, applies to all goos/goarch but is overridden by the following.
|
||||
// $CC_FOR_TARGET, if set, applies to all goos/goarch except gohostos/gohostarch,
|
||||
// but is overridden by the following.
|
||||
// If gohostos=goos and gohostarch=goarch, then $CC_FOR_TARGET applies even for gohostos/gohostarch.
|
||||
// $CC_FOR_goos_goarch, if set, applies only to goos/goarch.
|
||||
func compilerEnv(envName, def string) map[string]string {
|
||||
m := map[string]string{"": def}
|
||||
|
||||
if env := os.Getenv(envName); env != "" {
|
||||
m[""] = env
|
||||
}
|
||||
if env := os.Getenv(envName + "_FOR_TARGET"); env != "" {
|
||||
if gohostos != goos || gohostarch != goarch {
|
||||
m[gohostos+"/"+gohostarch] = m[""]
|
||||
}
|
||||
m[""] = env
|
||||
}
|
||||
|
||||
for _, goos := range okgoos {
|
||||
for _, goarch := range okgoarch {
|
||||
if env := os.Getenv(envName + "_FOR_" + goos + "_" + goarch); env != "" {
|
||||
m[goos+"/"+goarch] = env
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return m
|
||||
}
|
||||
|
||||
// compilerEnvLookup returns the compiler settings for goos/goarch in map m.
|
||||
func compilerEnvLookup(m map[string]string, goos, goarch string) string {
|
||||
if cc := m[goos+"/"+goarch]; cc != "" {
|
||||
return cc
|
||||
}
|
||||
return m[""]
|
||||
}
|
||||
|
||||
// rmworkdir deletes the work directory.
|
||||
func rmworkdir() {
|
||||
if vflag > 1 {
|
||||
@ -1009,8 +1029,6 @@ func cmdenv() {
|
||||
format = "set %s=%s\r\n"
|
||||
}
|
||||
|
||||
xprintf(format, "CC", defaultcc)
|
||||
xprintf(format, "CC_FOR_TARGET", defaultcctarget)
|
||||
xprintf(format, "GOROOT", goroot)
|
||||
xprintf(format, "GOBIN", gobin)
|
||||
xprintf(format, "GOARCH", goarch)
|
||||
@ -1171,12 +1189,7 @@ func cmdbootstrap() {
|
||||
xprintf("\n")
|
||||
}
|
||||
xprintf("Building Go toolchain2 using go_bootstrap and Go toolchain1.\n")
|
||||
os.Setenv("CC", defaultcc)
|
||||
if goos == oldgoos && goarch == oldgoarch {
|
||||
// Host and target are same, and we have historically
|
||||
// chosen $CC_FOR_TARGET in this case.
|
||||
os.Setenv("CC", defaultcctarget)
|
||||
}
|
||||
os.Setenv("CC", compilerEnvLookup(defaultcc, goos, goarch))
|
||||
goInstall(goBootstrap, append([]string{"-i"}, toolchain...)...)
|
||||
if debug {
|
||||
run("", ShowOutput|CheckExit, pathf("%s/compile", tooldir), "-V=full")
|
||||
@ -1241,7 +1254,7 @@ func cmdbootstrap() {
|
||||
goarch = oldgoarch
|
||||
os.Setenv("GOOS", goos)
|
||||
os.Setenv("GOARCH", goarch)
|
||||
os.Setenv("CC", defaultcctarget)
|
||||
os.Setenv("CC", compilerEnvLookup(defaultcc, goos, goarch))
|
||||
xprintf("Building packages and commands for target, %s/%s.\n", goos, goarch)
|
||||
}
|
||||
goInstall(goBootstrap, "std", "cmd")
|
||||
@ -1372,7 +1385,7 @@ func checkCC() {
|
||||
if !needCC() {
|
||||
return
|
||||
}
|
||||
if output, err := exec.Command(defaultcc, "--help").CombinedOutput(); err != nil {
|
||||
if output, err := exec.Command(defaultcc[""], "--help").CombinedOutput(); err != nil {
|
||||
outputHdr := ""
|
||||
if len(output) > 0 {
|
||||
outputHdr = "\nCommand output:\n\n"
|
||||
|
34
src/cmd/dist/buildgo.go
vendored
34
src/cmd/dist/buildgo.go
vendored
@ -33,9 +33,9 @@ func mkzdefaultcc(dir, file string) {
|
||||
fmt.Fprintln(&buf)
|
||||
fmt.Fprintf(&buf, "package cfg\n")
|
||||
fmt.Fprintln(&buf)
|
||||
fmt.Fprintf(&buf, "const DefaultCC = `%s`\n", defaultcctarget)
|
||||
fmt.Fprintf(&buf, "const DefaultCXX = `%s`\n", defaultcxxtarget)
|
||||
fmt.Fprintf(&buf, "const DefaultPkgConfig = `%s`\n", defaultpkgconfigtarget)
|
||||
fmt.Fprintf(&buf, "const DefaultPkgConfig = `%s`\n", defaultpkgconfig)
|
||||
buf.WriteString(defaultCCFunc("DefaultCC", defaultcc))
|
||||
buf.WriteString(defaultCCFunc("DefaultCXX", defaultcxx))
|
||||
writefile(buf.String(), file, writeSkipSame)
|
||||
return
|
||||
}
|
||||
@ -45,12 +45,34 @@ func mkzdefaultcc(dir, file string) {
|
||||
fmt.Fprintln(&buf)
|
||||
fmt.Fprintf(&buf, "package main\n")
|
||||
fmt.Fprintln(&buf)
|
||||
fmt.Fprintf(&buf, "const defaultCC = `%s`\n", defaultcctarget)
|
||||
fmt.Fprintf(&buf, "const defaultCXX = `%s`\n", defaultcxxtarget)
|
||||
fmt.Fprintf(&buf, "const defaultPkgConfig = `%s`\n", defaultpkgconfigtarget)
|
||||
fmt.Fprintf(&buf, "const defaultPkgConfig = `%s`\n", defaultpkgconfig)
|
||||
buf.WriteString(defaultCCFunc("defaultCC", defaultcc))
|
||||
buf.WriteString(defaultCCFunc("defaultCXX", defaultcxx))
|
||||
writefile(buf.String(), file, writeSkipSame)
|
||||
}
|
||||
|
||||
func defaultCCFunc(name string, defaultcc map[string]string) string {
|
||||
var buf bytes.Buffer
|
||||
|
||||
fmt.Fprintf(&buf, "func %s(goos, goarch string) string {\n", name)
|
||||
fmt.Fprintf(&buf, "\tswitch goos+`/`+goarch {\n")
|
||||
var keys []string
|
||||
for k := range defaultcc {
|
||||
if k != "" {
|
||||
keys = append(keys, k)
|
||||
}
|
||||
}
|
||||
sort.Strings(keys)
|
||||
for _, k := range keys {
|
||||
fmt.Fprintf(&buf, "\tcase %q:\n\t\treturn %q\n", k, defaultcc[k])
|
||||
}
|
||||
fmt.Fprintf(&buf, "\t}\n")
|
||||
fmt.Fprintf(&buf, "\treturn %q\n", defaultcc[""])
|
||||
fmt.Fprintf(&buf, "}\n")
|
||||
|
||||
return buf.String()
|
||||
}
|
||||
|
||||
// mkzcgo writes zosarch.go for cmd/go.
|
||||
func mkzosarch(dir, file string) {
|
||||
// sort for deterministic zosarch.go file
|
||||
|
@ -78,11 +78,11 @@ func MkEnv() []cfg.EnvVar {
|
||||
env = append(env, cfg.EnvVar{Name: "GO386", Value: cfg.GO386})
|
||||
}
|
||||
|
||||
cc := cfg.DefaultCC
|
||||
cc := cfg.DefaultCC(cfg.Goos, cfg.Goarch)
|
||||
if env := strings.Fields(os.Getenv("CC")); len(env) > 0 {
|
||||
cc = env[0]
|
||||
}
|
||||
cxx := cfg.DefaultCXX
|
||||
cxx := cfg.DefaultCXX(cfg.Goos, cfg.Goarch)
|
||||
if env := strings.Fields(os.Getenv("CXX")); len(env) > 0 {
|
||||
cxx = env[0]
|
||||
}
|
||||
|
@ -1597,12 +1597,12 @@ func (b *Builder) gfortranCmd(incdir, workdir string) []string {
|
||||
|
||||
// ccExe returns the CC compiler setting without all the extra flags we add implicitly.
|
||||
func (b *Builder) ccExe() []string {
|
||||
return b.compilerExe(origCC, cfg.DefaultCC)
|
||||
return b.compilerExe(origCC, cfg.DefaultCC(cfg.Goos, cfg.Goarch))
|
||||
}
|
||||
|
||||
// cxxExe returns the CXX compiler setting without all the extra flags we add implicitly.
|
||||
func (b *Builder) cxxExe() []string {
|
||||
return b.compilerExe(origCXX, cfg.DefaultCXX)
|
||||
return b.compilerExe(origCXX, cfg.DefaultCXX(cfg.Goos, cfg.Goarch))
|
||||
}
|
||||
|
||||
// fcExe returns the FC compiler setting without all the extra flags we add implicitly.
|
||||
|
@ -430,9 +430,9 @@ func (gcToolchain) ld(b *Builder, root *Action, out, importcfg, mainpkg string)
|
||||
// Else, use the CC environment variable and defaultCC as fallback.
|
||||
var compiler []string
|
||||
if cxx {
|
||||
compiler = envList("CXX", cfg.DefaultCXX)
|
||||
compiler = envList("CXX", cfg.DefaultCXX(cfg.Goos, cfg.Goarch))
|
||||
} else {
|
||||
compiler = envList("CC", cfg.DefaultCC)
|
||||
compiler = envList("CC", cfg.DefaultCC(cfg.Goos, cfg.Goarch))
|
||||
}
|
||||
ldflags = append(ldflags, "-buildmode="+ldBuildmode)
|
||||
if root.buildID != "" {
|
||||
@ -474,9 +474,9 @@ func (gcToolchain) ldShared(b *Builder, toplevelactions []*Action, out, importcf
|
||||
// Else, use the CC environment variable and defaultCC as fallback.
|
||||
var compiler []string
|
||||
if cxx {
|
||||
compiler = envList("CXX", cfg.DefaultCXX)
|
||||
compiler = envList("CXX", cfg.DefaultCXX(cfg.Goos, cfg.Goarch))
|
||||
} else {
|
||||
compiler = envList("CC", cfg.DefaultCC)
|
||||
compiler = envList("CC", cfg.DefaultCC(cfg.Goos, cfg.Goarch))
|
||||
}
|
||||
ldflags = setextld(ldflags, compiler)
|
||||
for _, d := range toplevelactions {
|
||||
|
@ -464,7 +464,7 @@ func (tools gccgoToolchain) cc(b *Builder, a *Action, ofile, cfile string) error
|
||||
defs = append(defs, "-fsplit-stack")
|
||||
}
|
||||
defs = tools.maybePIC(defs)
|
||||
return b.run(p.Dir, p.ImportPath, nil, envList("CC", cfg.DefaultCC), "-Wall", "-g",
|
||||
return b.run(p.Dir, p.ImportPath, nil, envList("CC", cfg.DefaultCC(cfg.Goos, cfg.Goarch)), "-Wall", "-g",
|
||||
"-I", a.Objdir, "-I", inc, "-o", ofile, defs, "-c", cfile)
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user