Commit 2ddb672d authored by Russ Cox's avatar Russ Cox

build: on OS X 10.8 and later, use clang instead of gcc

Fixes #5822.
Will no doubt cause other problems, but Apple has forced our hand.

R=golang-dev, bradfitz, khr
CC=golang-dev
https://golang.org/cl/12350044
parent 337407d8
...@@ -646,19 +646,20 @@ func (p *Package) rewriteRef(f *File) { ...@@ -646,19 +646,20 @@ func (p *Package) rewriteRef(f *File) {
} }
} }
// gccName returns the name of the compiler to run. Use $CC if set in // gccBaseCmd returns the start of the compiler command line.
// the environment, otherwise just "gcc". // It uses $CC if set, or else $GCC, or else the compiler recorded
// during the initial build as defaultCC.
func (p *Package) gccName() string { // defaultCC is defined in zdefaultcc.go, written by cmd/dist.
func (p *Package) gccBaseCmd() []string {
// Use $CC if set, since that's what the build uses. // Use $CC if set, since that's what the build uses.
if ret := os.Getenv("CC"); ret != "" { if ret := strings.Fields(os.Getenv("CC")); len(ret) > 0 {
return ret return ret
} }
// Fall back to $GCC if set, since that's what we used to use. // Try $GCC if set, since that's what we used to use.
if ret := os.Getenv("GCC"); ret != "" { if ret := strings.Fields(os.Getenv("GCC")); len(ret) > 0 {
return ret return ret
} }
return "gcc" return strings.Fields(defaultCC)
} }
// gccMachine returns the gcc -m flag to use, either "-m32", "-m64" or "-marm". // gccMachine returns the gcc -m flag to use, either "-m32", "-m64" or "-marm".
...@@ -681,17 +682,16 @@ func gccTmp() string { ...@@ -681,17 +682,16 @@ func gccTmp() string {
// gccCmd returns the gcc command line to use for compiling // gccCmd returns the gcc command line to use for compiling
// the input. // the input.
func (p *Package) gccCmd() []string { func (p *Package) gccCmd() []string {
c := []string{ c := append(p.gccBaseCmd(),
p.gccName(),
"-Wall", // many warnings "-Wall", // many warnings
"-Werror", // warnings are errors "-Werror", // warnings are errors
"-o" + gccTmp(), // write object to tmp "-o"+gccTmp(), // write object to tmp
"-gdwarf-2", // generate DWARF v2 debugging symbols "-gdwarf-2", // generate DWARF v2 debugging symbols
"-fno-eliminate-unused-debug-types", // gets rid of e.g. untyped enum otherwise "-fno-eliminate-unused-debug-types", // gets rid of e.g. untyped enum otherwise
"-c", // do not link "-c", // do not link
"-xc", // input language is C "-xc", // input language is C
} )
if strings.Contains(p.gccName(), "clang") { if strings.Contains(c[0], "clang") {
c = append(c, c = append(c,
"-ferror-limit=0", "-ferror-limit=0",
// Apple clang version 1.7 (tags/Apple/clang-77) (based on LLVM 2.9svn) // Apple clang version 1.7 (tags/Apple/clang-77) (based on LLVM 2.9svn)
...@@ -800,7 +800,7 @@ func (p *Package) gccDebug(stdin []byte) (*dwarf.Data, binary.ByteOrder, []byte) ...@@ -800,7 +800,7 @@ func (p *Package) gccDebug(stdin []byte) (*dwarf.Data, binary.ByteOrder, []byte)
// #defines that gcc encountered while processing the input // #defines that gcc encountered while processing the input
// and its included files. // and its included files.
func (p *Package) gccDefines(stdin []byte) string { func (p *Package) gccDefines(stdin []byte) string {
base := []string{p.gccName(), "-E", "-dM", "-xc"} base := append(p.gccBaseCmd(), "-E", "-dM", "-xc")
base = append(base, p.gccMachine()...) base = append(base, p.gccMachine()...)
stdout, _ := runGcc(stdin, append(append(base, p.GccOptions...), "-")) stdout, _ := runGcc(stdin, append(append(base, p.GccOptions...), "-"))
return stdout return stdout
......
...@@ -498,7 +498,7 @@ func (p *Package) writeOutputFunc(fgcc *os.File, n *Name) { ...@@ -498,7 +498,7 @@ func (p *Package) writeOutputFunc(fgcc *os.File, n *Name) {
// Use __gcc_struct__ to work around http://gcc.gnu.org/PR52991 on x86, // Use __gcc_struct__ to work around http://gcc.gnu.org/PR52991 on x86,
// and http://golang.org/issue/5603. // and http://golang.org/issue/5603.
extraAttr := "" extraAttr := ""
if !strings.Contains(p.gccName(), "clang") && (goarch == "amd64" || goarch == "386") { if !strings.Contains(p.gccBaseCmd()[0], "clang") && (goarch == "amd64" || goarch == "386") {
extraAttr = ", __gcc_struct__" extraAttr = ", __gcc_struct__"
} }
fmt.Fprintf(fgcc, "\t%s __attribute__((__packed__%v)) *a = v;\n", ctype, extraAttr) fmt.Fprintf(fgcc, "\t%s __attribute__((__packed__%v)) *a = v;\n", ctype, extraAttr)
......
...@@ -74,10 +74,12 @@ extern char *goroot; ...@@ -74,10 +74,12 @@ extern char *goroot;
extern char *goroot_final; extern char *goroot_final;
extern char *goextlinkenabled; extern char *goextlinkenabled;
extern char *goversion; extern char *goversion;
extern char *defaultcc;
extern char *workdir; extern char *workdir;
extern char *tooldir; extern char *tooldir;
extern char *slash; extern char *slash;
extern bool rebuildall; extern bool rebuildall;
extern bool defaultclang;
int find(char*, char**, int); int find(char*, char**, int);
void init(void); void init(void);
...@@ -100,6 +102,9 @@ void mkzgoos(char*, char*); ...@@ -100,6 +102,9 @@ void mkzgoos(char*, char*);
void mkzruntimedefs(char*, char*); void mkzruntimedefs(char*, char*);
void mkzversion(char*, char*); void mkzversion(char*, char*);
// buildgo.c
void mkzdefaultcc(char*, char*);
// goc2c.c // goc2c.c
void goc2c(char*, char*); void goc2c(char*, char*);
......
...@@ -26,8 +26,9 @@ char *tooldir; ...@@ -26,8 +26,9 @@ char *tooldir;
char *gochar; char *gochar;
char *goversion; char *goversion;
char *slash; // / for unix, \ for windows char *slash; // / for unix, \ for windows
char *defaultcc;
bool rebuildall = 0; bool rebuildall;
bool defaultclang;
static bool shouldbuild(char*, char*); static bool shouldbuild(char*, char*);
static void copy(char*, char*, int); static void copy(char*, char*, int);
...@@ -146,6 +147,20 @@ init(void) ...@@ -146,6 +147,20 @@ init(void)
if(!streq(goextlinkenabled, "0") && !streq(goextlinkenabled, "1")) if(!streq(goextlinkenabled, "0") && !streq(goextlinkenabled, "1"))
fatal("unknown $GO_EXTLINK_ENABLED %s", goextlinkenabled); fatal("unknown $GO_EXTLINK_ENABLED %s", goextlinkenabled);
} }
xgetenv(&b, "CC");
if(b.len == 0) {
// 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)
bprintf(&b, "clang");
else
bprintf(&b, "gcc");
}
defaultcc = btake(&b);
xsetenv("GOROOT", goroot); xsetenv("GOROOT", goroot);
xsetenv("GOARCH", goarch); xsetenv("GOARCH", goarch);
...@@ -525,6 +540,9 @@ static struct { ...@@ -525,6 +540,9 @@ static struct {
"../ld/*", "../ld/*",
"enam.c", "enam.c",
}}, }},
{"cmd/go", {
"zdefaultcc.go",
}},
{"cmd/", { {"cmd/", {
"$GOROOT/pkg/obj/$GOOS_$GOARCH/libmach.a", "$GOROOT/pkg/obj/$GOOS_$GOARCH/libmach.a",
"$GOROOT/pkg/obj/$GOOS_$GOARCH/libbio.a", "$GOROOT/pkg/obj/$GOOS_$GOARCH/libbio.a",
...@@ -557,6 +575,7 @@ static struct { ...@@ -557,6 +575,7 @@ static struct {
{"opnames.h", gcopnames}, {"opnames.h", gcopnames},
{"enam.c", mkenam}, {"enam.c", mkenam},
{"zasm_", mkzasm}, {"zasm_", mkzasm},
{"zdefaultcc.go", mkzdefaultcc},
{"zsys_", mkzsys}, {"zsys_", mkzsys},
{"zgoarch_", mkzgoarch}, {"zgoarch_", mkzgoarch},
{"zgoos_", mkzgoos}, {"zgoos_", mkzgoos},
...@@ -616,10 +635,7 @@ install(char *dir) ...@@ -616,10 +635,7 @@ install(char *dir)
// set up gcc command line on first run. // set up gcc command line on first run.
if(gccargs.len == 0) { if(gccargs.len == 0) {
xgetenv(&b, "CC"); bprintf(&b, "%s", defaultcc);
if(b.len == 0)
bprintf(&b, "gcc");
clang = contains(bstr(&b), "clang");
splitfields(&gccargs, bstr(&b)); splitfields(&gccargs, bstr(&b));
for(i=0; i<nelem(proto_gccargs); i++) for(i=0; i<nelem(proto_gccargs); i++)
vadd(&gccargs, proto_gccargs[i]); vadd(&gccargs, proto_gccargs[i]);
...@@ -1443,6 +1459,7 @@ cmdenv(int argc, char **argv) ...@@ -1443,6 +1459,7 @@ cmdenv(int argc, char **argv)
if(argc > 0) if(argc > 0)
usage(); usage();
xprintf(format, "CC", defaultcc);
xprintf(format, "GOROOT", goroot); xprintf(format, "GOROOT", goroot);
xprintf(format, "GOBIN", gobin); xprintf(format, "GOBIN", gobin);
xprintf(format, "GOARCH", goarch); xprintf(format, "GOARCH", goarch);
......
...@@ -651,6 +651,7 @@ int ...@@ -651,6 +651,7 @@ int
main(int argc, char **argv) main(int argc, char **argv)
{ {
Buf b; Buf b;
int osx;
struct utsname u; struct utsname u;
setvbuf(stdout, nil, _IOLBF, 0); setvbuf(stdout, nil, _IOLBF, 0);
...@@ -700,17 +701,23 @@ main(int argc, char **argv) ...@@ -700,17 +701,23 @@ main(int argc, char **argv)
if(strcmp(gohostarch, "arm") == 0) if(strcmp(gohostarch, "arm") == 0)
maxnbg = 1; maxnbg = 1;
// The OS X 10.6 linker does not support external // The OS X 10.6 linker does not support external linking mode.
// linking mode; see // See golang.org/issue/5130.
// https://code.google.com/p/go/issues/detail?id=5130 . //
// The mapping from the uname release field to the OS X // OS X 10.6 does not work with clang either, but OS X 10.9 requires it.
// version number is complicated, but basically 10 or under is // It seems to work with OS X 10.8, so we default to clang for 10.8 and later.
// OS X 10.6 or earlier. // See golang.org/issue/5822.
//
// Roughly, OS X 10.N shows up as uname release (N+4),
// so OS X 10.6 is uname version 10 and OS X 10.8 is uname version 12.
if(strcmp(gohostos, "darwin") == 0) { if(strcmp(gohostos, "darwin") == 0) {
if(uname(&u) < 0) if(uname(&u) < 0)
fatal("uname: %s", strerror(errno)); fatal("uname: %s", strerror(errno));
if(u.release[1] == '.' || hasprefix(u.release, "10")) osx = atoi(u.release) - 4;
if(osx <= 6)
goextlinkenabled = "0"; goextlinkenabled = "0";
if(osx >= 8)
defaultclang = 1;
} }
init(); init();
......
...@@ -1772,8 +1772,9 @@ func (b *builder) gccld(p *Package, out string, flags []string, obj []string) er ...@@ -1772,8 +1772,9 @@ func (b *builder) gccld(p *Package, out string, flags []string, obj []string) er
} }
// gccCmd returns a gcc command line prefix // gccCmd returns a gcc command line prefix
// defaultCC is defined in zdefaultcc.go, written by cmd/dist.
func (b *builder) gccCmd(objdir string) []string { func (b *builder) gccCmd(objdir string) []string {
return b.ccompilerCmd("CC", "gcc", objdir) return b.ccompilerCmd("CC", defaultCC, objdir)
} }
// gxxCmd returns a g++ command line prefix // gxxCmd returns a g++ command line prefix
...@@ -1789,7 +1790,7 @@ func (b *builder) ccompilerCmd(envvar, defcmd, objdir string) []string { ...@@ -1789,7 +1790,7 @@ func (b *builder) ccompilerCmd(envvar, defcmd, objdir string) []string {
compiler := strings.Fields(os.Getenv(envvar)) compiler := strings.Fields(os.Getenv(envvar))
if len(compiler) == 0 { if len(compiler) == 0 {
compiler = append(compiler, defcmd) compiler = strings.Fields(defcmd)
} }
a := []string{compiler[0], "-I", objdir, "-g", "-O2"} a := []string{compiler[0], "-I", objdir, "-g", "-O2"}
a = append(a, compiler[1:]...) a = append(a, compiler[1:]...)
......
...@@ -124,7 +124,10 @@ freebsd-386 | freebsd-amd64 | linux-386 | linux-amd64 | netbsd-386 | netbsd-amd6 ...@@ -124,7 +124,10 @@ freebsd-386 | freebsd-amd64 | linux-386 | linux-amd64 | netbsd-386 | netbsd-amd6
esac esac
) || exit $? ) || exit $?
[ "$CGO_ENABLED" != 1 ] || # This tests cgo -godefs. That mode is not supported,
# so it's okay if it doesn't work on some systems.
# In particular, it works badly with clang on OS X.
[ "$CGO_ENABLED" != 1 ] || [ "$GOOS" == darwin ] ||
(xcd ../misc/cgo/testcdefs (xcd ../misc/cgo/testcdefs
./test.bash || exit 1 ./test.bash || exit 1
) || exit $? ) || exit $?
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment