cmd/dist, cmd/ld: GO_EXTLINK_ENABLED=0 defaults to -linkmode=internal

Change build system to set GO_EXTLINK_ENABLED=0 by default for
OS X 10.6, since the system linker has a bug and can not
handle the object files generated by 6l.

Fixes #5130.

R=golang-dev, r
CC=golang-dev
https://golang.org/cl/8183043
diff --git a/include/libc.h b/include/libc.h
index fab1532..e10dde3 100644
--- a/include/libc.h
+++ b/include/libc.h
@@ -291,6 +291,7 @@
 extern	char*	getgoversion(void);
 extern	char*	getgoarm(void);
 extern	char*	getgo386(void);
+extern	char*	getgoextlinkenabled(void);
 
 extern	char*	mktempdir(void);
 extern	void	removeall(char*);
diff --git a/src/cmd/5l/obj.c b/src/cmd/5l/obj.c
index f5128c6..72bb1fb 100644
--- a/src/cmd/5l/obj.c
+++ b/src/cmd/5l/obj.c
@@ -136,6 +136,11 @@
 	if(argc != 1)
 		usage();
 
+	// getgoextlinkenabled is based on GO_EXTLINK_ENABLED when
+	// Go was built; see ../../make.bash.
+	if(linkmode == LinkAuto && strcmp(getgoextlinkenabled(), "0") == 0)
+		linkmode = LinkInternal;
+
 	if(linkmode == LinkExternal) {
 		diag("only -linkmode=internal is supported");
 		errorexit();
diff --git a/src/cmd/6l/obj.c b/src/cmd/6l/obj.c
index 738a2a0..4e69a8d 100644
--- a/src/cmd/6l/obj.c
+++ b/src/cmd/6l/obj.c
@@ -133,11 +133,16 @@
 	if(HEADTYPE == -1)
 		HEADTYPE = headtype(goos);
 
+	// getgoextlinkenabled is based on GO_EXTLINK_ENABLED when
+	// Go was built; see ../../make.bash.
+	if(linkmode == LinkAuto && strcmp(getgoextlinkenabled(), "0") == 0)
+		linkmode = LinkInternal;
+
 	switch(HEADTYPE) {
 	default:
 		if(linkmode == LinkAuto)
 			linkmode = LinkInternal;
-		if(linkmode == LinkExternal)
+		if(linkmode == LinkExternal && strcmp(getgoextlinkenabled(), "1") != 0)
 			sysfatal("cannot use -linkmode=external with -H %s", headstr(HEADTYPE));
 		break;
 	case Hdarwin:
diff --git a/src/cmd/8l/obj.c b/src/cmd/8l/obj.c
index 35a65ed..d624a99 100644
--- a/src/cmd/8l/obj.c
+++ b/src/cmd/8l/obj.c
@@ -139,11 +139,16 @@
 	if(HEADTYPE == -1)
 		HEADTYPE = headtype(goos);
 
+	// getgoextlinkenabled is based on GO_EXTLINK_ENABLED when
+	// Go was built; see ../../make.bash.
+	if(linkmode == LinkAuto && strcmp(getgoextlinkenabled(), "0") == 0)
+		linkmode = LinkInternal;
+
 	switch(HEADTYPE) {
 	default:
 		if(linkmode == LinkAuto)
 			linkmode = LinkInternal;
-		if(linkmode == LinkExternal)
+		if(linkmode == LinkExternal && strcmp(getgoextlinkenabled(), "1") != 0)
 			sysfatal("cannot use -linkmode=external with -H %s", headstr(HEADTYPE));
 		break;
 	case Hdarwin:
diff --git a/src/cmd/dist/a.h b/src/cmd/dist/a.h
index fcd81cc..73c1264 100644
--- a/src/cmd/dist/a.h
+++ b/src/cmd/dist/a.h
@@ -72,6 +72,7 @@
 extern char *goos;
 extern char *goroot;
 extern char *goroot_final;
+extern char *goextlinkenabled;
 extern char *goversion;
 extern char *workdir;
 extern char *tooldir;
diff --git a/src/cmd/dist/build.c b/src/cmd/dist/build.c
index fd6a329..e948623 100644
--- a/src/cmd/dist/build.c
+++ b/src/cmd/dist/build.c
@@ -20,6 +20,7 @@
 char *go386;
 char *goroot = GOROOT_FINAL;
 char *goroot_final = GOROOT_FINAL;
+char *goextlinkenabled = "";
 char *workdir;
 char *tooldir;
 char *gochar;
@@ -139,6 +140,13 @@
 	bprintf(&b, "%c", gochars[i]);
 	gochar = btake(&b);
 
+	xgetenv(&b, "GO_EXTLINK_ENABLED");
+	if(b.len > 0) {
+		goextlinkenabled = btake(&b);
+		if(!streq(goextlinkenabled, "0") && !streq(goextlinkenabled, "1"))
+			fatal("unknown $GO_EXTLINK_ENABLED %s", goextlinkenabled);
+	}
+
 	xsetenv("GOROOT", goroot);
 	xsetenv("GOARCH", goarch);
 	xsetenv("GOOS", goos);
@@ -922,6 +930,8 @@
 				vadd(&compile, bprintf(&b, "GOARM=\"%s\"", goarm));
 				vadd(&compile, "-D");
 				vadd(&compile, bprintf(&b, "GO386=\"%s\"", go386));
+				vadd(&compile, "-D");
+				vadd(&compile, bprintf(&b, "GO_EXTLINK_ENABLED=\"%s\"", goextlinkenabled));
 			}
 
 			// gc/lex.c records the GOEXPERIMENT setting used during the build.
diff --git a/src/cmd/dist/unix.c b/src/cmd/dist/unix.c
index e4e2dcc..f2ea489 100644
--- a/src/cmd/dist/unix.c
+++ b/src/cmd/dist/unix.c
@@ -698,6 +698,19 @@
 	if(strcmp(gohostarch, "arm") == 0)
 		maxnbg = 1;
 
+	// The OS X 10.6 linker does not support external
+	// linking mode; see
+	// https://code.google.com/p/go/issues/detail?id=5130 .
+	// The mapping from the uname release field to the OS X
+	// version number is complicated, but basically 10 or under is
+	// OS X 10.6 or earlier.
+	if(strcmp(gohostos, "darwin") == 0) {
+		if(uname(&u) < 0)
+			fatal("uname: %s", strerror(errno));
+		if(u.release[1] == '.' || hasprefix(u.release, "10"))
+			goextlinkenabled = "0";
+	}
+
 	init();
 	xmain(argc, argv);
 	bfree(&b);
diff --git a/src/lib9/goos.c b/src/lib9/goos.c
index 3b00271..2d4a800 100644
--- a/src/lib9/goos.c
+++ b/src/lib9/goos.c
@@ -51,3 +51,9 @@
 {
 	return defgetenv("GO386", GO386);
 }
+
+char *
+getgoextlinkenabled(void)
+{
+	return GO_EXTLINK_ENABLED;
+}
diff --git a/src/make.bash b/src/make.bash
index 2d83b6f..8d0f6eb 100755
--- a/src/make.bash
+++ b/src/make.bash
@@ -30,6 +30,11 @@
 # to include all cgo related files, .c and .go file with "cgo"
 # build directive, in the build. Set it to 0 to ignore them.
 #
+# GO_EXTLINK_ENABLED: Set to 1 to invoke the host linker when building
+# packages that use cgo.  Set to 0 to do all linking internally.  This
+# controls the default behavior of the linker's -linkmode option.  The
+# default value depends on the system.
+#
 # CC: Command line to run to get at host C compiler.
 # Default is "gcc". Also supported: "clang".
 
diff --git a/src/run.bash b/src/run.bash
index df5b95b..b197844 100755
--- a/src/run.bash
+++ b/src/run.bash
@@ -83,10 +83,18 @@
 go test -ldflags '-linkmode=auto'
 go test -ldflags '-linkmode=internal'
 case "$GOHOSTOS-$GOARCH" in
-darwin-386 | darwin-amd64 | openbsd-386 | openbsd-amd64)
+openbsd-386 | openbsd-amd64)
 	# test linkmode=external, but __thread not supported, so skip testtls.
 	go test -ldflags '-linkmode=external'
 	;;
+darwin-386 | darwin-amd64)
+	# linkmode=external fails on OS X 10.6 and earlier == Darwin
+	# 10.8 and earlier.
+	case $(uname -r) in
+	[0-9].* | 10.*) ;;
+	*) go test -ldflags '-linkmode=external' ;;
+	esac
+	;;
 freebsd-386 | freebsd-amd64 | linux-386 | linux-amd64 | netbsd-386 | netbsd-amd64)
 	go test -ldflags '-linkmode=external'
 	go test -ldflags '-linkmode=auto' ../testtls