summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorRuss Cox <rsc@golang.org>2012-02-13 22:31:51 -0500
committerRuss Cox <rsc@golang.org>2012-02-13 22:31:51 -0500
commit56435395989fa49773b9f83dcf3a4344447035e8 (patch)
tree406b0e9686a3e8a0379b937e1ab81bc1025d0e39 /src
parent49b3d319d5fac1b92c9114d13d703984263eb4bb (diff)
downloadgo-56435395989fa49773b9f83dcf3a4344447035e8.tar.gz
cmd/dist: cross-compiling fixes
This CL makes it possible to run make.bash with GOOS and GOARCH set to something other than the native host GOOS and GOARCH. As part of the CL, the tool directory moves from bin/tool/ to pkg/tool/goos_goarch where goos and goarch are the values for the host system (running the build), not the target. pkg/ is not technically appropriate, but C objects are there now tool (pkg/obj/) so this puts all the generated binaries in one place (rm -rf $GOROOT/pkg cleans everything). Including goos_goarch in the name allows different systems to share a single $GOROOT on a shared file system. Fixes issue 2920. R=golang-dev, r CC=golang-dev http://codereview.appspot.com/5645093
Diffstat (limited to 'src')
-rwxr-xr-xsrc/all.bash4
-rw-r--r--src/cmd/dist/a.h2
-rw-r--r--src/cmd/dist/build.c194
-rw-r--r--src/cmd/dist/buildruntime.c4
-rw-r--r--src/cmd/dist/goc2c.c22
-rw-r--r--src/cmd/dist/unix.c7
-rw-r--r--src/cmd/go/build.go27
-rw-r--r--src/cmd/go/pkg.go11
-rw-r--r--src/cmd/go/tool.go3
-rwxr-xr-xsrc/make.bash28
-rw-r--r--src/make.bat36
-rw-r--r--src/pkg/exp/types/gcimporter_test.go11
-rw-r--r--src/pkg/go/build/path.go3
-rwxr-xr-xsrc/run.bash2
14 files changed, 253 insertions, 101 deletions
diff --git a/src/all.bash b/src/all.bash
index d80a09d11..932b65dc0 100755
--- a/src/all.bash
+++ b/src/all.bash
@@ -9,5 +9,5 @@ if [ ! -f make.bash ]; then
exit 1
fi
. ./make.bash --no-banner
-bash run.bash --no-rebuild
-../bin/tool/dist banner # print build info
+bash run.bash --no-rebuild --banner
+$GOTOOLDIR/dist banner # print build info
diff --git a/src/cmd/dist/a.h b/src/cmd/dist/a.h
index e90f7fe65..3fbace3f6 100644
--- a/src/cmd/dist/a.h
+++ b/src/cmd/dist/a.h
@@ -72,7 +72,9 @@ extern char *goroot;
extern char *goroot_final;
extern char *goversion;
extern char *workdir;
+extern char *tooldir;
extern char *slash;
+extern bool rebuildall;
int find(char*, char**, int);
void init(void);
diff --git a/src/cmd/dist/build.c b/src/cmd/dist/build.c
index c8984300b..72097230a 100644
--- a/src/cmd/dist/build.c
+++ b/src/cmd/dist/build.c
@@ -13,15 +13,19 @@
char *goarch;
char *gobin;
char *gohostarch;
+char *gohostchar;
char *gohostos;
char *goos;
char *goroot = GOROOT_FINAL;
char *goroot_final = GOROOT_FINAL;
char *workdir;
+char *tooldir;
char *gochar;
char *goversion;
char *slash; // / for unix, \ for windows
+bool rebuildall = 0;
+
static bool shouldbuild(char*, char*);
static void copy(char*, char*);
static char *findgoversion(void);
@@ -99,14 +103,18 @@ init(void)
if(b.len > 0)
gohostarch = btake(&b);
- if(find(gohostarch, okgoarch, nelem(okgoarch)) < 0)
+ i = find(gohostarch, okgoarch, nelem(okgoarch));
+ if(i < 0)
fatal("unknown $GOHOSTARCH %s", gohostarch);
+ bprintf(&b, "%c", gochars[i]);
+ gohostchar = btake(&b);
xgetenv(&b, "GOARCH");
if(b.len == 0)
bwritestr(&b, gohostarch);
goarch = btake(&b);
- if((i=find(goarch, okgoarch, nelem(okgoarch))) < 0)
+ i = find(goarch, okgoarch, nelem(okgoarch));
+ if(i < 0)
fatal("unknown $GOARCH %s", goarch);
bprintf(&b, "%c", gochars[i]);
gochar = btake(&b);
@@ -124,6 +132,9 @@ init(void)
workdir = xworkdir();
xatexit(rmworkdir);
+ bpathf(&b, "%s/pkg/tool/%s_%s", goroot, gohostos, gohostarch);
+ tooldir = btake(&b);
+
bfree(&b);
}
@@ -256,6 +267,7 @@ static char *oldtool[] = {
"8a", "8c", "8g", "8l",
"6cov",
"6nm",
+ "6prof",
"cgo",
"ebnflint",
"goapi",
@@ -281,33 +293,51 @@ setup(void)
binit(&b);
- // Create tool directory.
+ // Create bin directory.
p = bpathf(&b, "%s/bin", goroot);
if(!isdir(p))
xmkdir(p);
- p = bpathf(&b, "%s/bin/tool", goroot);
- if(!isdir(p))
- xmkdir(p);
// Create package directory.
p = bpathf(&b, "%s/pkg", goroot);
if(!isdir(p))
xmkdir(p);
- p = bpathf(&b, "%s/pkg/%s_%s", goroot, goos, goarch);
- xremoveall(p);
+ p = bpathf(&b, "%s/pkg/%s_%s", goroot, gohostos, gohostarch);
+ if(rebuildall)
+ xremoveall(p);
xmkdir(p);
-
+ if(!streq(goos, gohostos) || !streq(goarch, gohostarch)) {
+ p = bpathf(&b, "%s/pkg/%s_%s", goroot, goos, goarch);
+ if(rebuildall)
+ xremoveall(p);
+ xmkdir(p);
+ }
+
// Create object directory.
// We keep it in pkg/ so that all the generated binaries
- // are in one tree.
- p = bpathf(&b, "%s/pkg/obj", goroot);
- xremoveall(p);
- xmkdir(p);
+ // are in one tree. If pkg/obj/libgc.a exists, it is a dreg from
+ // before we used subdirectories of obj. Delete all of obj
+ // to clean up.
+ bpathf(&b, "%s/pkg/obj/libgc.a", goroot);
+ if(isfile(bstr(&b)))
+ xremoveall(bpathf(&b, "%s/pkg/obj", goroot));
+ p = bpathf(&b, "%s/pkg/obj/%s_%s", goroot, gohostos, gohostarch);
+ if(rebuildall)
+ xremoveall(p);
+ xmkdirall(p);
+
+ // Create tool directory.
+ // We keep it in pkg/, just like the object directory above.
+ xremoveall(tooldir);
+ xmkdirall(tooldir);
+
+ // Remove tool binaries from before the tool/gohostos_gohostarch
+ xremoveall(bpathf(&b, "%s/bin/tool", goroot));
// Remove old pre-tool binaries.
for(i=0; i<nelem(oldtool); i++)
- xremove(bprintf(&b, "%s%s%s%s%s", goroot, slash, "bin", slash, oldtool[i]));
-
+ xremove(bpathf(&b, "%s/bin/%s", goroot, oldtool[i]));
+
// If $GOBIN is set and has a Go compiler, it must be cleaned.
for(i=0; gochars[i]; i++) {
if(isfile(bprintf(&b, "%s%s%c%s", gobin, slash, gochars[i], "g"))) {
@@ -390,37 +420,37 @@ static struct {
"../cc/pgen.c",
"../cc/pswt.c",
"../5l/enam.c",
- "$GOROOT/pkg/obj/libcc.a",
+ "$GOROOT/pkg/obj/$GOOS_$GOARCH/libcc.a",
}},
{"cmd/6c", {
"../cc/pgen.c",
"../cc/pswt.c",
"../6l/enam.c",
- "$GOROOT/pkg/obj/libcc.a",
+ "$GOROOT/pkg/obj/$GOOS_$GOARCH/libcc.a",
}},
{"cmd/8c", {
"../cc/pgen.c",
"../cc/pswt.c",
"../8l/enam.c",
- "$GOROOT/pkg/obj/libcc.a",
+ "$GOROOT/pkg/obj/$GOOS_$GOARCH/libcc.a",
}},
{"cmd/5g", {
"../gc/cplx.c",
"../gc/pgen.c",
"../5l/enam.c",
- "$GOROOT/pkg/obj/libgc.a",
+ "$GOROOT/pkg/obj/$GOOS_$GOARCH/libgc.a",
}},
{"cmd/6g", {
"../gc/cplx.c",
"../gc/pgen.c",
"../6l/enam.c",
- "$GOROOT/pkg/obj/libgc.a",
+ "$GOROOT/pkg/obj/$GOOS_$GOARCH/libgc.a",
}},
{"cmd/8g", {
"../gc/cplx.c",
"../gc/pgen.c",
"../8l/enam.c",
- "$GOROOT/pkg/obj/libgc.a",
+ "$GOROOT/pkg/obj/$GOOS_$GOARCH/libgc.a",
}},
{"cmd/5l", {
"../ld/data.c",
@@ -442,9 +472,9 @@ static struct {
"enam.c",
}},
{"cmd/", {
- "$GOROOT/pkg/obj/libmach.a",
- "$GOROOT/pkg/obj/libbio.a",
- "$GOROOT/pkg/obj/lib9.a",
+ "$GOROOT/pkg/obj/$GOOS_$GOARCH/libmach.a",
+ "$GOROOT/pkg/obj/$GOOS_$GOARCH/libbio.a",
+ "$GOROOT/pkg/obj/$GOOS_$GOARCH/lib9.a",
}},
{"pkg/runtime", {
"zasm_$GOOS_$GOARCH.h",
@@ -490,8 +520,12 @@ install(char *dir)
Time ttarg, t;
int i, j, k, n, doclean;
- if(vflag)
- xprintf("%s\n", dir);
+ if(vflag) {
+ if(!streq(goos, gohostos) || !streq(goarch, gohostarch))
+ xprintf("%s (%s/%s)\n", dir, goos, goarch);
+ else
+ xprintf("%s\n", dir);
+ }
binit(&b);
binit(&b1);
@@ -521,7 +555,7 @@ install(char *dir)
islib = hasprefix(dir, "lib") || streq(dir, "cmd/cc") || streq(dir, "cmd/gc");
ispkg = hasprefix(dir, "pkg");
- isgo = ispkg || streq(dir, "cmd/go");
+ isgo = ispkg || streq(dir, "cmd/go") || streq(dir, "cmd/cgo");
exe = "";
if(streq(gohostos, "windows"))
@@ -536,27 +570,30 @@ install(char *dir)
prefix = "";
if(!hasprefix(name, "lib"))
prefix = "lib";
- vadd(&link, bpathf(&b, "%s/pkg/obj/%s%s.a", goroot, prefix, name));
+ vadd(&link, bpathf(&b, "%s/pkg/obj/%s_%s/%s%s.a", goroot, gohostos, gohostarch, prefix, name));
} else if(ispkg) {
// Go library (package).
- vadd(&link, bpathf(&b, "%s/bin/tool/pack", goroot));
+ vadd(&link, bpathf(&b, "%s/pack", tooldir));
vadd(&link, "grc");
- p = bprintf(&b, "%s/pkg/%s_%s/%s", goroot, goos, goarch, dir+4);
+ p = bprintf(&b, "%s/pkg/%s_%s/%s", goroot, gohostos, gohostarch, dir+4);
*xstrrchr(p, '/') = '\0';
xmkdirall(p);
- vadd(&link, bpathf(&b, "%s/pkg/%s_%s/%s.a", goroot, goos, goarch, dir+4));
- } else if(streq(dir, "cmd/go")) {
+ vadd(&link, bpathf(&b, "%s/pkg/%s_%s/%s.a", goroot, gohostos, gohostarch, dir+4));
+ } else if(streq(dir, "cmd/go") || streq(dir, "cmd/cgo")) {
// Go command.
- vadd(&link, bpathf(&b, "%s/bin/tool/%sl", goroot, gochar));
+ vadd(&link, bpathf(&b, "%s/%sl", tooldir, gochar));
vadd(&link, "-o");
- vadd(&link, bpathf(&b, "%s/bin/tool/go_bootstrap%s", goroot, exe));
+ elem = name;
+ if(streq(elem, "go"))
+ elem = "go_bootstrap";
+ vadd(&link, bpathf(&b, "%s/%s%s", tooldir, elem, exe));
} else {
// C command.
// Use gccargs, but ensure that link.p[2] is output file,
// as noted above.
vadd(&link, gccargs.p[0]);
vadd(&link, "-o");
- vadd(&link, bpathf(&b, "%s/bin/tool/%s%s", goroot, name, exe));
+ vadd(&link, bpathf(&b, "%s/%s%s", tooldir, name, exe));
vcopy(&link, gccargs.p+1, gccargs.len-1);
if(streq(gohostarch, "amd64"))
vadd(&link, "-m64");
@@ -636,7 +673,7 @@ install(char *dir)
}
// Is the target up-to-date?
- stale = 1; // TODO: Decide when 0 is okay.
+ stale = rebuildall;
n = 0;
for(i=0; i<files.len; i++) {
p = files.p[i];
@@ -682,12 +719,6 @@ install(char *dir)
copy(bpathf(&b, "%s/signals_GOOS.h", workdir),
bpathf(&b1, "%s/signals_%s.h", bstr(&path), goos));
}
-
- // For cmd/prof, copy pprof into the tool directory.
- if(streq(dir, "cmd/prof")) {
- copy(bpathf(&b, "%s/bin/tool/pprof", goroot),
- bpathf(&b1, "%s/src/cmd/prof/pprof", goroot));
- }
// Generate any missing files; regenerate existing ones.
for(i=0; i<files.len; i++) {
@@ -737,6 +768,13 @@ install(char *dir)
}
vuniq(&files);
}
+
+ if(!streq(goos, gohostos) || !streq(goarch, gohostarch)) {
+ // We've generated the right files; the go command can do the build.
+ if(vflag > 1)
+ xprintf("skip build for cross-compile %s\n", dir);
+ goto nobuild;
+ }
// Compile the files.
for(i=0; i<files.len; i++) {
@@ -762,7 +800,7 @@ install(char *dir)
vadd(&compile, "-I");
vadd(&compile, bstr(&path));
- // runtime/goos.c gets the default constants hard-coded.
+ // lib9/goos.c gets the default constants hard-coded.
if(streq(name, "goos.c")) {
vadd(&compile, bprintf(&b, "-DGOOS=\"%s\"", goos));
vadd(&compile, bprintf(&b, "-DGOARCH=\"%s\"", goarch));
@@ -780,9 +818,9 @@ install(char *dir)
} else {
// Supporting files for a Go package.
if(hassuffix(files.p[i], ".s"))
- vadd(&compile, bpathf(&b, "%s/bin/tool/%sa", goroot, gochar));
+ vadd(&compile, bpathf(&b, "%s/%sa", tooldir, gochar));
else {
- vadd(&compile, bpathf(&b, "%s/bin/tool/%sc", goroot, gochar));
+ vadd(&compile, bpathf(&b, "%s/%sc", tooldir, gochar));
vadd(&compile, "-FVw");
}
vadd(&compile, "-I");
@@ -820,7 +858,7 @@ install(char *dir)
// The last loop was compiling individual files.
// Hand the Go files to the compiler en masse.
vreset(&compile);
- vadd(&compile, bpathf(&b, "%s/bin/tool/%sg", goroot, gochar));
+ vadd(&compile, bpathf(&b, "%s/%sg", tooldir, gochar));
bpathf(&b, "%s/_go_.%s", workdir, gochar);
vadd(&compile, "-o");
@@ -853,6 +891,7 @@ install(char *dir)
runv(nil, nil, CheckExit, &link);
+nobuild:
// In package runtime, we install runtime.h and cgocall.h too,
// for use by cgo compilation.
if(streq(dir, "pkg/runtime")) {
@@ -921,6 +960,8 @@ shouldbuild(char *file, char *dir)
// so special case that file.
if(hassuffix(file, "cmd/go/doc.go") || hassuffix(file, "cmd\\go\\doc.go"))
return 0;
+ if(hassuffix(file, "cmd/cgo/doc.go") || hassuffix(file, "cmd\\cgo\\doc.go"))
+ return 0;
// Check file contents for // +build lines.
binit(&b);
@@ -940,7 +981,7 @@ shouldbuild(char *file, char *dir)
ret = 0;
goto out;
}
- if(contains(p, "package main") && !streq(dir, "cmd/go")) {
+ if(contains(p, "package main") && !streq(dir, "cmd/go") && !streq(dir, "cmd/cgo")) {
ret = 0;
goto out;
}
@@ -1044,7 +1085,6 @@ static char *buildorder[] = {
"pkg/net/url",
"pkg/text/template/parse",
"pkg/text/template",
-
"cmd/go",
};
@@ -1140,15 +1180,18 @@ clean(void)
xremove(bpathf(&b, "%s/%s", bstr(&path), cleantab[i]+4));
}
- // Remove object tree.
- xremoveall(bpathf(&b, "%s/pkg/obj", goroot));
+ if(rebuildall) {
+ // Remove object tree.
+ xremoveall(bpathf(&b, "%s/pkg/obj/%s_%s", goroot, gohostos, gohostarch));
- // Remove installed packages and tools.
- xremoveall(bpathf(&b, "%s/pkg/%s_%s", goroot, goos, goarch));
- xremove(bpathf(&b, "%s/bin/tool", goroot));
-
- // Remove cached version info.
- xremove(bpathf(&b, "%s/VERSION.cache", goroot));
+ // Remove installed packages and tools.
+ xremoveall(bpathf(&b, "%s/pkg/%s_%s", goroot, gohostos, gohostarch));
+ xremoveall(bpathf(&b, "%s/pkg/%s_%s", goroot, goos, goarch));
+ xremoveall(tooldir);
+
+ // Remove cached version info.
+ xremove(bpathf(&b, "%s/VERSION.cache", goroot));
+ }
bfree(&b);
bfree(&path);
@@ -1212,7 +1255,11 @@ cmdenv(int argc, char **argv)
xprintf(format, "GOBIN", gobin);
xprintf(format, "GOARCH", goarch);
xprintf(format, "GOOS", goos);
+ xprintf(format, "GOHOSTARCH", gohostarch);
+ xprintf(format, "GOHOSTOS", gohostos);
+ xprintf(format, "GOTOOLDIR", tooldir);
xprintf(format, "GOCHAR", gochar);
+
if(pflag) {
sep = ":";
if(streq(gohostos, "windows"))
@@ -1233,8 +1280,14 @@ cmdbootstrap(int argc, char **argv)
{
int i;
Buf b;
+ char *oldgoos, *oldgoarch, *oldgochar;
+
+ binit(&b);
ARGBEGIN{
+ case 'a':
+ rebuildall = 1;
+ break;
case 'v':
vflag++;
break;
@@ -1249,9 +1302,32 @@ cmdbootstrap(int argc, char **argv)
goversion = findgoversion();
setup();
- binit(&b);
- for(i=0; i<nelem(buildorder); i++)
- install(bprintf(&b, buildorder[i], gochar));
+ // For the main bootstrap, building for host os/arch.
+ oldgoos = goos;
+ oldgoarch = goarch;
+ oldgochar = gochar;
+ goos = gohostos;
+ goarch = gohostarch;
+ gochar = gohostchar;
+ xsetenv("GOARCH", goarch);
+ xsetenv("GOOS", goos);
+
+ for(i=0; i<nelem(buildorder); i++) {
+ install(bprintf(&b, buildorder[i], gohostchar));
+ if(!streq(oldgochar, gohostchar) && xstrstr(buildorder[i], "%s"))
+ install(bprintf(&b, buildorder[i], oldgochar));
+ }
+
+ goos = oldgoos;
+ goarch = oldgoarch;
+ gochar = oldgochar;
+ xsetenv("GOARCH", goarch);
+ xsetenv("GOOS", goos);
+
+ // Build pkg/runtime for actual goos/goarch too.
+ if(!streq(goos, gohostos) || !streq(goarch, gohostarch))
+ install("pkg/runtime");
+
bfree(&b);
}
diff --git a/src/cmd/dist/buildruntime.c b/src/cmd/dist/buildruntime.c
index dfecc2be0..03ebd345f 100644
--- a/src/cmd/dist/buildruntime.c
+++ b/src/cmd/dist/buildruntime.c
@@ -191,7 +191,7 @@ ok:
// Run 6c -DGOOS_goos -DGOARCH_goarch -Iworkdir -a proc.c
// to get acid [sic] output.
vreset(&argv);
- vadd(&argv, bpathf(&b, "%s/bin/tool/%sc", goroot, gochar));
+ vadd(&argv, bpathf(&b, "%s/%sc", tooldir, gochar));
vadd(&argv, bprintf(&b, "-DGOOS_%s", goos));
vadd(&argv, bprintf(&b, "-DGOARCH_%s", goarch));
vadd(&argv, bprintf(&b, "-I%s", workdir));
@@ -287,7 +287,7 @@ mkzruntimedefs(char *dir, char *file)
// Run 6c -DGOOS_goos -DGOARCH_goarch -Iworkdir -q
// on each of the runtimedefs C files.
- vadd(&argv, bpathf(&b, "%s/bin/tool/%sc", goroot, gochar));
+ vadd(&argv, bpathf(&b, "%s/%sc", tooldir, gochar));
vadd(&argv, bprintf(&b, "-DGOOS_%s", goos));
vadd(&argv, bprintf(&b, "-DGOARCH_%s", goarch));
vadd(&argv, bprintf(&b, "-I%s", workdir));
diff --git a/src/cmd/dist/goc2c.c b/src/cmd/dist/goc2c.c
index 6829dedc7..2443c30b1 100644
--- a/src/cmd/dist/goc2c.c
+++ b/src/cmd/dist/goc2c.c
@@ -709,15 +709,23 @@ goc2c(char *goc, char *c)
// TODO: set gcc=1 when using gcc
- if(!gcc && streq(goarch, "amd64")) {
- type_table[Uintptr].size = 8;
- type_table[String].size = 16;
- type_table[Slice].size = 8+4+4;
- type_table[Eface].size = 8+8;
- structround = 8;
+ if(!gcc) {
+ if(streq(goarch, "amd64")) {
+ type_table[Uintptr].size = 8;
+ type_table[String].size = 16;
+ type_table[Slice].size = 8+4+4;
+ type_table[Eface].size = 8+8;
+ structround = 8;
+ } else {
+ type_table[Uintptr].size = 4;
+ type_table[String].size = 8;
+ type_table[Slice].size = 16;
+ type_table[Eface].size = 4+4;
+ structround = 4;
+ }
}
- bprintf(&out, "// auto generated by go tool dist\n\n");
+ bprintf(&out, "// auto generated by go tool dist\n// goos=%s goarch=%s\n\n", goos, goarch);
input = bstr(&in);
output = &out;
diff --git a/src/cmd/dist/unix.c b/src/cmd/dist/unix.c
index 632ebbcdb..5aedbed18 100644
--- a/src/cmd/dist/unix.c
+++ b/src/cmd/dist/unix.c
@@ -145,6 +145,7 @@ static struct {
int pid;
int mode;
char *cmd;
+ Buf *b;
} bg[MAXBG];
static int nbg;
static int maxnbg = nelem(bg);
@@ -219,6 +220,7 @@ genrun(Buf *b, char *dir, int mode, Vec *argv, int wait)
bg[nbg].pid = pid;
bg[nbg].mode = mode;
bg[nbg].cmd = btake(&cmd);
+ bg[nbg].b = b;
nbg++;
if(wait)
@@ -233,6 +235,7 @@ bgwait1(void)
{
int i, pid, status, mode;
char *cmd;
+ Buf *b;
errno = 0;
while((pid = wait(&status)) < 0) {
@@ -248,9 +251,13 @@ ok:
cmd = bg[i].cmd;
mode = bg[i].mode;
bg[i].pid = 0;
+ b = bg[i].b;
+ bg[i].b = nil;
bg[i] = bg[--nbg];
if(mode == CheckExit && (!WIFEXITED(status) || WEXITSTATUS(status) != 0)) {
+ if(b != nil)
+ xprintf("%s\n", bstr(b));
fatal("FAILED: %s", cmd);
}
xfree(cmd);
diff --git a/src/cmd/go/build.go b/src/cmd/go/build.go
index da046eedb..b8af30e37 100644
--- a/src/cmd/go/build.go
+++ b/src/cmd/go/build.go
@@ -347,14 +347,21 @@ func (b *builder) action(mode buildMode, depMode buildMode, p *Package) *action
a.deps = append(a.deps, b.action(depMode, depMode, p1))
}
- if len(p.CgoFiles) > 0 {
- var stk importStack
- p1 := loadPackage("cmd/cgo", &stk)
- if p1.Error != nil {
- fatalf("load cmd/cgo: %v", p1.Error)
+ // If we are not doing a cross-build, then record the binary we'll
+ // generate for cgo as a dependency of the build of any package
+ // 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
+ // are writing is not the cgo we need to use.
+ if b.goos == runtime.GOOS && b.goarch == runtime.GOARCH {
+ if len(p.CgoFiles) > 0 || p.Standard && p.ImportPath == "runtime/cgo" {
+ var stk importStack
+ p1 := loadPackage("cmd/cgo", &stk)
+ if p1.Error != nil {
+ fatalf("load cmd/cgo: %v", p1.Error)
+ }
+ a.cgo = b.action(depMode, depMode, p1)
+ a.deps = append(a.deps, a.cgo)
}
- a.cgo = b.action(depMode, depMode, p1)
- a.deps = append(a.deps, a.cgo)
}
if p.Standard {
@@ -567,7 +574,11 @@ func (b *builder) build(a *action) error {
sfiles = nil
}
- outGo, outObj, err := b.cgo(a.p, a.cgo.target, obj, gccfiles)
+ cgoExe := tool("cgo")
+ if a.cgo != nil {
+ cgoExe = a.cgo.target
+ }
+ outGo, outObj, err := b.cgo(a.p, cgoExe, obj, gccfiles)
if err != nil {
return err
}
diff --git a/src/cmd/go/pkg.go b/src/cmd/go/pkg.go
index e9fe845c5..00c5d30b5 100644
--- a/src/cmd/go/pkg.go
+++ b/src/cmd/go/pkg.go
@@ -295,13 +295,14 @@ func scanPackage(ctxt *build.Context, t *build.Tree, arg, importPath, dir string
if info.Package == "main" {
_, elem := filepath.Split(importPath)
- if ctxt.GOOS != toolGOOS || ctxt.GOARCH != toolGOARCH {
- // Install cross-compiled binaries to subdirectories of bin.
- elem = ctxt.GOOS + "_" + ctxt.GOARCH + "/" + elem
- }
+ full := ctxt.GOOS + "_" + ctxt.GOARCH + "/" + elem
if t.Goroot && isGoTool[p.ImportPath] {
- p.target = filepath.Join(t.Path, "bin/tool", elem)
+ p.target = filepath.Join(t.Path, "pkg/tool", full)
} else {
+ if ctxt.GOOS != toolGOOS || ctxt.GOARCH != toolGOARCH {
+ // Install cross-compiled binaries to subdirectories of bin.
+ elem = full
+ }
p.target = filepath.Join(t.BinDir(), elem)
}
if ctxt.GOOS == "windows" {
diff --git a/src/cmd/go/tool.go b/src/cmd/go/tool.go
index 0ec5cf6a7..19b0d37dc 100644
--- a/src/cmd/go/tool.go
+++ b/src/cmd/go/tool.go
@@ -31,7 +31,7 @@ var (
toolGOOS = runtime.GOOS
toolGOARCH = runtime.GOARCH
toolIsWindows = toolGOOS == "windows"
- toolDir = filepath.Join(build.Path[0].Path, "bin", "tool")
+ toolDir = build.ToolDir
)
const toolWindowsExtension = ".exe"
@@ -97,6 +97,7 @@ func listTools() {
setExitStatus(2)
return
}
+
sort.Strings(names)
for _, name := range names {
// Unify presentation by going to lower case.
diff --git a/src/make.bash b/src/make.bash
index 81ceeb729..e30743b68 100755
--- a/src/make.bash
+++ b/src/make.bash
@@ -61,24 +61,36 @@ mkdir -p ../bin/tool
export GOROOT="$(cd .. && pwd)"
GOROOT_FINAL="${GOROOT_FINAL:-$GOROOT}"
DEFGOROOT='-DGOROOT_FINAL="'"$GOROOT_FINAL"'"'
-gcc -O2 -Wall -Werror -o ../bin/tool/dist -Icmd/dist "$DEFGOROOT" cmd/dist/*.c
+gcc -O2 -Wall -Werror -ggdb -o cmd/dist/dist -Icmd/dist "$DEFGOROOT" cmd/dist/*.c
+eval $(./cmd/dist/dist env)
echo
if [ "$1" = "--dist-tool" ]; then
# Stop after building dist tool.
+ mv cmd/dist/dist $GOTOOLDIR/dist
exit 0
fi
-echo '# Building compilers and Go bootstrap tool.'
-../bin/tool/dist bootstrap -v # builds go_bootstrap
+echo "# Building compilers and Go bootstrap tool for host, $GOHOSTOS/$GOHOSTARCH."
+./cmd/dist/dist bootstrap -a -v # builds go_bootstrap
+# Delay move of dist tool to now, because bootstrap cleared tool directory.
+mv cmd/dist/dist $GOTOOLDIR/dist
+$GOTOOLDIR/go_bootstrap clean -i std
echo
-echo '# Building packages and commands.'
-../bin/tool/go_bootstrap clean std
-../bin/tool/go_bootstrap install -a -v std
-rm -f ../bin/tool/go_bootstrap
+if [ "$GOHOSTARCH" != "$GOARCH" -o "$GOHOSTOS" != "$GOOS" ]; then
+ echo "# Building packages and commands for host, $GOHOSTOS/$GOHOSTARCH."
+ GOOS=$GOHOSTOS GOARCH=$GOHOSTARCH \
+ $GOTOOLDIR/go_bootstrap install -v std
+ echo
+fi
+
+echo "# Building packages and commands for $GOOS/$GOARCH."
+$GOTOOLDIR/go_bootstrap install -v std
echo
+rm -f $GOTOOLDIR/go_bootstrap
+
if [ "$1" != "--no-banner" ]; then
- ../bin/tool/dist banner
+ $GOTOOLDIR/dist banner
fi
diff --git a/src/make.bat b/src/make.bat
index 010e418c0..6618bc4ed 100644
--- a/src/make.bat
+++ b/src/make.bat
@@ -25,26 +25,48 @@ echo # Building C bootstrap tool.
echo cmd/dist
if not exist ..\bin\tool mkdir ..\bin\tool
:: Windows has no glob expansion, so spell out cmd/dist/*.c.
-gcc -O2 -Wall -Werror -o ../bin/tool/dist.exe -Icmd/dist %DEFGOROOT% cmd/dist/buf.c cmd/dist/build.c cmd/dist/buildgc.c cmd/dist/buildruntime.c cmd/dist/goc2c.c cmd/dist/main.c cmd/dist/windows.c
+gcc -O2 -Wall -Werror -o cmd/dist/dist.exe -Icmd/dist %DEFGOROOT% cmd/dist/buf.c cmd/dist/build.c cmd/dist/buildgc.c cmd/dist/buildruntime.c cmd/dist/goc2c.c cmd/dist/main.c cmd/dist/windows.c
if errorlevel 1 goto fail
+.\cmd\dist\dist env -wp >env.bat
+if errorlevel 1 goto fail
+call env.bat
+del env.bat
:: Echo with no arguments prints whether echo is turned on, so echo dot.
echo .
echo # Building compilers and Go bootstrap tool.
-..\bin\tool\dist bootstrap -v
+.\cmd\dist\dist bootstrap -a -v
if errorlevel 1 goto fail
+:: Delay move of dist tool to now, because bootstrap cleared tool directory.
+move .\cmd\dist\dist.exe %GOTOOLDIR%\dist.exe
+%GOTOOLDIR%\go_bootstrap clean -i std
echo .
-echo # Building packages and commands.
-..\bin\tool\go_bootstrap clean std
+if not %GOHOSTARCH% == %GOARCH% goto localbuild
+if not %GOHOSTOS% == %GOOS% goto localbuild
+goto mainbuild
+
+:localbuild
+echo # Building tools for local system. %GOHOSTOS%/%GOHOSTARCH%
+set oldGOOS=%GOOS%
+set oldGOARCH=%GOARCH%
+set GOOS=%GOHOSTOS%
+set GOARCH=%GOHOSTARCH%
+%GOTOOLDIR%\go_bootstrap install -v std
+set GOOS=%oldGOOS%
+set GOARCH=%oldGOARCH%
if errorlevel 1 goto fail
-..\bin\tool\go_bootstrap install -a -v std
+echo .
+
+:mainbuild
+echo # Building packages and commands.
+%GOTOOLDIR%\go_bootstrap install -a -v std
if errorlevel 1 goto fail
-del ..\bin\tool\go_bootstrap.exe
+del %GOTOOLDIR%\go_bootstrap.exe
echo .
if "x%1"=="x--no-banner" goto nobanner
-..\bin\tool\dist banner
+%GOTOOLDIR%\dist banner
:nobanner
goto end
diff --git a/src/pkg/exp/types/gcimporter_test.go b/src/pkg/exp/types/gcimporter_test.go
index 5411f3bcc..c229b5011 100644
--- a/src/pkg/exp/types/gcimporter_test.go
+++ b/src/pkg/exp/types/gcimporter_test.go
@@ -6,7 +6,9 @@ package types
import (
"go/ast"
+ "go/build"
"io/ioutil"
+ "os"
"os/exec"
"path/filepath"
"runtime"
@@ -31,7 +33,7 @@ func init() {
gcPath = gcName
return
}
- gcPath = filepath.Join(runtime.GOROOT(), "/bin/tool/", gcName)
+ gcPath = filepath.Join(build.ToolDir, gcName)
}
func compile(t *testing.T, dirname, filename string) {
@@ -90,6 +92,13 @@ func testDir(t *testing.T, dir string, endTime time.Time) (nimports int) {
}
func TestGcImport(t *testing.T) {
+ // On cross-compile builds, the path will not exist.
+ // Need to use GOHOSTOS, which is not available.
+ if _, err := os.Stat(gcPath); err != nil {
+ t.Logf("skipping test: %v", err)
+ return
+ }
+
compile(t, "testdata", "exports.go")
nimports := 0
diff --git a/src/pkg/go/build/path.go b/src/pkg/go/build/path.go
index 7e931faff..e160ac3b2 100644
--- a/src/pkg/go/build/path.go
+++ b/src/pkg/go/build/path.go
@@ -12,6 +12,9 @@ import (
"runtime"
)
+// ToolDir is the directory containing build tools.
+var ToolDir = filepath.Join(runtime.GOROOT(), "pkg/tool/"+runtime.GOOS+"_"+runtime.GOARCH)
+
// Path is a validated list of Trees derived from $GOROOT and $GOPATH at init.
var Path []*Tree
diff --git a/src/run.bash b/src/run.bash
index 8f282249f..d818751b2 100755
--- a/src/run.bash
+++ b/src/run.bash
@@ -5,7 +5,7 @@
set -e
-eval $(../bin/tool/dist env -p)
+eval $(go tool dist env)
unset CDPATH # in case user has it set