]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/dist: cross-compiling fixes
authorRuss Cox <rsc@golang.org>
Tue, 14 Feb 2012 03:31:51 +0000 (22:31 -0500)
committerRuss Cox <rsc@golang.org>
Tue, 14 Feb 2012 03:31:51 +0000 (22:31 -0500)
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 #2920.

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

16 files changed:
src/all.bash
src/cmd/dist/a.h
src/cmd/dist/build.c
src/cmd/dist/buildruntime.c
src/cmd/dist/goc2c.c
src/cmd/dist/unix.c
src/cmd/go/build.go
src/cmd/go/pkg.go
src/cmd/go/tool.go
src/make.bash
src/make.bat
src/pkg/exp/types/gcimporter_test.go
src/pkg/go/build/path.go
src/run.bash
test/fixedbugs/bug302.go
test/run

index d80a09d11623606445aefc9a9a71a1c705e11127..932b65dc070f63574bcc5fb1047565e43b5236c2 100755 (executable)
@@ -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
index e90f7fe65d8008634aa250af371ccab1d5346e97..3fbace3f6d23bc5c609a8b46c5ba84d866aa1ec7 100644 (file)
@@ -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);
index c8984300b092926411e9bd58c0b1bfb3118f6af7..72097230a1196fac0bed4be975a65cf583bc75e3 100644 (file)
 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,11 +293,8 @@ 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);
 
@@ -293,21 +302,42 @@ setup(void)
        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);
 }
 
index dfecc2be0d6252e5ac9ea84c4b324d84a7e72d71..03ebd345fd910a5b6fbadb2d95578de1409467bc 100644 (file)
@@ -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));
index 6829dedc78c6642bc35336d08bfbb99ddac08d24..2443c30b10b3c18702f34034ba3a81add935a4f1 100644 (file)
@@ -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;
 
index 632ebbcdbad1d0e0d4b70bab3600666cb48c1236..5aedbed18d1432f98937abbd48972242b74543e4 100644 (file)
@@ -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);
index da046eedbc26c989f67e9a8bf5998c9330413d46..b8af30e370b61b51db3b3555c77518ad8aa5c960 100644 (file)
@@ -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
                }
index e9fe845c56d7e41836d2796634852773b5b0466b..00c5d30b50dec76a00435a5db2d5a8171aa38cc9 100644 (file)
@@ -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" {
index 0ec5cf6a747734154bba9153948d2b2e6fca3a23..19b0d37dc001ca11580b18616ed49bf71069d9da 100644 (file)
@@ -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.
index 81ceeb7298da0dfcd4e8e1cbdef5dbdc3cf90f51..e30743b6831adba404571fd5a24072f71324c78d 100755 (executable)
@@ -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
index 010e418c015413b9a3ad425e66f1c7e7bfb9be12..6618bc4ed98283a2fc6a0d04f96a06c1ade7eca3 100644 (file)
@@ -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
index 5411f3bccef61c16e81d99d3d4ff85d720c4334a..c229b50113db32b43a9c4914c7c2ba8fae41f7dd 100644 (file)
@@ -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
index 7e931faff1926a43f36044f9ff8cde7aee6cc919..e160ac3b280bb13aad02c8605838542b1dc7c915 100644 (file)
@@ -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
 
index 8f282249fb832265c36db454843ad31d4ea277b5..d818751b2c68fd2a4a19e6df01964f287acae528 100755 (executable)
@@ -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
 
index b42db7f72be6529619ff9548416dc5b7408f6bce..1088b2f3c29a2b0feea404542e6e4940afe30714 100644 (file)
@@ -1,4 +1,4 @@
-// $G $D/bug302.dir/p.go && "$GOROOT"/bin/tool/pack grc pp.a p.$A && $G $D/bug302.dir/main.go
+// $G $D/bug302.dir/p.go && pack grc pp.a p.$A && $G $D/bug302.dir/main.go
 
 // Copyright 2010 The Go Authors.  All rights reserved.
 // Use of this source code is governed by a BSD-style
index 4b0481caa8bde0607500d56b41a26bc20845f911..7f4c350fa328be7ebb4621c3c641c81ae38f876d 100755 (executable)
--- a/test/run
+++ b/test/run
@@ -3,7 +3,7 @@
 # Use of this source code is governed by a BSD-style
 # license that can be found in the LICENSE file.
 
-eval $(../bin/tool/dist env)
+eval $(go tool dist env)
 export GOARCH GOOS GOROOT
 export E=
 
@@ -34,7 +34,7 @@ failed=0
 PATH=${GOBIN:-$GOROOT/bin}:`pwd`:/bin:/usr/bin:/usr/local/bin
 
 # TODO: We add the tool directory to the PATH to avoid thinking about a better way.
-PATH="$GOROOT/bin/tool":$PATH
+PATH="$GOTOOLDIR:$PATH"
 
 RUNFILE="/tmp/gorun-$$-$USER"
 TMP1FILE="/tmp/gotest1-$$-$USER"