Commit 7b848c69 authored by Russ Cox's avatar Russ Cox

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 #2920.

R=golang-dev, r
CC=golang-dev
https://golang.org/cl/5645093
parent 569ef7d4
...@@ -9,5 +9,5 @@ if [ ! -f make.bash ]; then ...@@ -9,5 +9,5 @@ if [ ! -f make.bash ]; then
exit 1 exit 1
fi fi
. ./make.bash --no-banner . ./make.bash --no-banner
bash run.bash --no-rebuild bash run.bash --no-rebuild --banner
../bin/tool/dist banner # print build info $GOTOOLDIR/dist banner # print build info
...@@ -72,7 +72,9 @@ extern char *goroot; ...@@ -72,7 +72,9 @@ extern char *goroot;
extern char *goroot_final; extern char *goroot_final;
extern char *goversion; extern char *goversion;
extern char *workdir; extern char *workdir;
extern char *tooldir;
extern char *slash; extern char *slash;
extern bool rebuildall;
int find(char*, char**, int); int find(char*, char**, int);
void init(void); void init(void);
......
This diff is collapsed.
...@@ -191,7 +191,7 @@ ok: ...@@ -191,7 +191,7 @@ ok:
// Run 6c -DGOOS_goos -DGOARCH_goarch -Iworkdir -a proc.c // Run 6c -DGOOS_goos -DGOARCH_goarch -Iworkdir -a proc.c
// to get acid [sic] output. // to get acid [sic] output.
vreset(&argv); 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, "-DGOOS_%s", goos));
vadd(&argv, bprintf(&b, "-DGOARCH_%s", goarch)); vadd(&argv, bprintf(&b, "-DGOARCH_%s", goarch));
vadd(&argv, bprintf(&b, "-I%s", workdir)); vadd(&argv, bprintf(&b, "-I%s", workdir));
...@@ -287,7 +287,7 @@ mkzruntimedefs(char *dir, char *file) ...@@ -287,7 +287,7 @@ mkzruntimedefs(char *dir, char *file)
// Run 6c -DGOOS_goos -DGOARCH_goarch -Iworkdir -q // Run 6c -DGOOS_goos -DGOARCH_goarch -Iworkdir -q
// on each of the runtimedefs C files. // 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, "-DGOOS_%s", goos));
vadd(&argv, bprintf(&b, "-DGOARCH_%s", goarch)); vadd(&argv, bprintf(&b, "-DGOARCH_%s", goarch));
vadd(&argv, bprintf(&b, "-I%s", workdir)); vadd(&argv, bprintf(&b, "-I%s", workdir));
......
...@@ -709,15 +709,23 @@ goc2c(char *goc, char *c) ...@@ -709,15 +709,23 @@ goc2c(char *goc, char *c)
// TODO: set gcc=1 when using gcc // TODO: set gcc=1 when using gcc
if(!gcc && streq(goarch, "amd64")) { if(!gcc) {
type_table[Uintptr].size = 8; if(streq(goarch, "amd64")) {
type_table[String].size = 16; type_table[Uintptr].size = 8;
type_table[Slice].size = 8+4+4; type_table[String].size = 16;
type_table[Eface].size = 8+8; type_table[Slice].size = 8+4+4;
structround = 8; 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); input = bstr(&in);
output = &out; output = &out;
......
...@@ -145,6 +145,7 @@ static struct { ...@@ -145,6 +145,7 @@ static struct {
int pid; int pid;
int mode; int mode;
char *cmd; char *cmd;
Buf *b;
} bg[MAXBG]; } bg[MAXBG];
static int nbg; static int nbg;
static int maxnbg = nelem(bg); static int maxnbg = nelem(bg);
...@@ -219,6 +220,7 @@ genrun(Buf *b, char *dir, int mode, Vec *argv, int wait) ...@@ -219,6 +220,7 @@ genrun(Buf *b, char *dir, int mode, Vec *argv, int wait)
bg[nbg].pid = pid; bg[nbg].pid = pid;
bg[nbg].mode = mode; bg[nbg].mode = mode;
bg[nbg].cmd = btake(&cmd); bg[nbg].cmd = btake(&cmd);
bg[nbg].b = b;
nbg++; nbg++;
if(wait) if(wait)
...@@ -233,6 +235,7 @@ bgwait1(void) ...@@ -233,6 +235,7 @@ bgwait1(void)
{ {
int i, pid, status, mode; int i, pid, status, mode;
char *cmd; char *cmd;
Buf *b;
errno = 0; errno = 0;
while((pid = wait(&status)) < 0) { while((pid = wait(&status)) < 0) {
...@@ -248,9 +251,13 @@ ok: ...@@ -248,9 +251,13 @@ ok:
cmd = bg[i].cmd; cmd = bg[i].cmd;
mode = bg[i].mode; mode = bg[i].mode;
bg[i].pid = 0; bg[i].pid = 0;
b = bg[i].b;
bg[i].b = nil;
bg[i] = bg[--nbg]; bg[i] = bg[--nbg];
if(mode == CheckExit && (!WIFEXITED(status) || WEXITSTATUS(status) != 0)) { if(mode == CheckExit && (!WIFEXITED(status) || WEXITSTATUS(status) != 0)) {
if(b != nil)
xprintf("%s\n", bstr(b));
fatal("FAILED: %s", cmd); fatal("FAILED: %s", cmd);
} }
xfree(cmd); xfree(cmd);
......
...@@ -347,14 +347,21 @@ func (b *builder) action(mode buildMode, depMode buildMode, p *Package) *action ...@@ -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)) a.deps = append(a.deps, b.action(depMode, depMode, p1))
} }
if len(p.CgoFiles) > 0 { // If we are not doing a cross-build, then record the binary we'll
var stk importStack // generate for cgo as a dependency of the build of any package
p1 := loadPackage("cmd/cgo", &stk) // using cgo, to make sure we do not overwrite the binary while
if p1.Error != nil { // a package is using it. If this is a cross-build, then the cgo we
fatalf("load cmd/cgo: %v", p1.Error) // 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 { if p.Standard {
...@@ -567,7 +574,11 @@ func (b *builder) build(a *action) error { ...@@ -567,7 +574,11 @@ func (b *builder) build(a *action) error {
sfiles = nil 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 { if err != nil {
return err return err
} }
......
...@@ -295,13 +295,14 @@ func scanPackage(ctxt *build.Context, t *build.Tree, arg, importPath, dir string ...@@ -295,13 +295,14 @@ func scanPackage(ctxt *build.Context, t *build.Tree, arg, importPath, dir string
if info.Package == "main" { if info.Package == "main" {
_, elem := filepath.Split(importPath) _, elem := filepath.Split(importPath)
if ctxt.GOOS != toolGOOS || ctxt.GOARCH != toolGOARCH { full := ctxt.GOOS + "_" + ctxt.GOARCH + "/" + elem
// Install cross-compiled binaries to subdirectories of bin.
elem = ctxt.GOOS + "_" + ctxt.GOARCH + "/" + elem
}
if t.Goroot && isGoTool[p.ImportPath] { 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 { } 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) p.target = filepath.Join(t.BinDir(), elem)
} }
if ctxt.GOOS == "windows" { if ctxt.GOOS == "windows" {
......
...@@ -31,7 +31,7 @@ var ( ...@@ -31,7 +31,7 @@ var (
toolGOOS = runtime.GOOS toolGOOS = runtime.GOOS
toolGOARCH = runtime.GOARCH toolGOARCH = runtime.GOARCH
toolIsWindows = toolGOOS == "windows" toolIsWindows = toolGOOS == "windows"
toolDir = filepath.Join(build.Path[0].Path, "bin", "tool") toolDir = build.ToolDir
) )
const toolWindowsExtension = ".exe" const toolWindowsExtension = ".exe"
...@@ -97,6 +97,7 @@ func listTools() { ...@@ -97,6 +97,7 @@ func listTools() {
setExitStatus(2) setExitStatus(2)
return return
} }
sort.Strings(names) sort.Strings(names)
for _, name := range names { for _, name := range names {
// Unify presentation by going to lower case. // Unify presentation by going to lower case.
......
...@@ -61,24 +61,36 @@ mkdir -p ../bin/tool ...@@ -61,24 +61,36 @@ mkdir -p ../bin/tool
export GOROOT="$(cd .. && pwd)" export GOROOT="$(cd .. && pwd)"
GOROOT_FINAL="${GOROOT_FINAL:-$GOROOT}" GOROOT_FINAL="${GOROOT_FINAL:-$GOROOT}"
DEFGOROOT='-DGOROOT_FINAL="'"$GOROOT_FINAL"'"' 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 echo
if [ "$1" = "--dist-tool" ]; then if [ "$1" = "--dist-tool" ]; then
# Stop after building dist tool. # Stop after building dist tool.
mv cmd/dist/dist $GOTOOLDIR/dist
exit 0 exit 0
fi fi
echo '# Building compilers and Go bootstrap tool.' echo "# Building compilers and Go bootstrap tool for host, $GOHOSTOS/$GOHOSTARCH."
../bin/tool/dist bootstrap -v # builds go_bootstrap ./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
echo '# Building packages and commands.' if [ "$GOHOSTARCH" != "$GOARCH" -o "$GOHOSTOS" != "$GOOS" ]; then
../bin/tool/go_bootstrap clean std echo "# Building packages and commands for host, $GOHOSTOS/$GOHOSTARCH."
../bin/tool/go_bootstrap install -a -v std GOOS=$GOHOSTOS GOARCH=$GOHOSTARCH \
rm -f ../bin/tool/go_bootstrap $GOTOOLDIR/go_bootstrap install -v std
echo
fi
echo "# Building packages and commands for $GOOS/$GOARCH."
$GOTOOLDIR/go_bootstrap install -v std
echo echo
rm -f $GOTOOLDIR/go_bootstrap
if [ "$1" != "--no-banner" ]; then if [ "$1" != "--no-banner" ]; then
../bin/tool/dist banner $GOTOOLDIR/dist banner
fi fi
...@@ -25,26 +25,48 @@ echo # Building C bootstrap tool. ...@@ -25,26 +25,48 @@ echo # Building C bootstrap tool.
echo cmd/dist echo cmd/dist
if not exist ..\bin\tool mkdir ..\bin\tool if not exist ..\bin\tool mkdir ..\bin\tool
:: Windows has no glob expansion, so spell out cmd/dist/*.c. :: 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 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 with no arguments prints whether echo is turned on, so echo dot.
echo . echo .
echo # Building compilers and Go bootstrap tool. echo # Building compilers and Go bootstrap tool.
..\bin\tool\dist bootstrap -v .\cmd\dist\dist bootstrap -a -v
if errorlevel 1 goto fail 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 .
echo # Building packages and commands. if not %GOHOSTARCH% == %GOARCH% goto localbuild
..\bin\tool\go_bootstrap clean std 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 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 if errorlevel 1 goto fail
del ..\bin\tool\go_bootstrap.exe del %GOTOOLDIR%\go_bootstrap.exe
echo . echo .
if "x%1"=="x--no-banner" goto nobanner if "x%1"=="x--no-banner" goto nobanner
..\bin\tool\dist banner %GOTOOLDIR%\dist banner
:nobanner :nobanner
goto end goto end
......
...@@ -6,7 +6,9 @@ package types ...@@ -6,7 +6,9 @@ package types
import ( import (
"go/ast" "go/ast"
"go/build"
"io/ioutil" "io/ioutil"
"os"
"os/exec" "os/exec"
"path/filepath" "path/filepath"
"runtime" "runtime"
...@@ -31,7 +33,7 @@ func init() { ...@@ -31,7 +33,7 @@ func init() {
gcPath = gcName gcPath = gcName
return return
} }
gcPath = filepath.Join(runtime.GOROOT(), "/bin/tool/", gcName) gcPath = filepath.Join(build.ToolDir, gcName)
} }
func compile(t *testing.T, dirname, filename string) { func compile(t *testing.T, dirname, filename string) {
...@@ -90,6 +92,13 @@ func testDir(t *testing.T, dir string, endTime time.Time) (nimports int) { ...@@ -90,6 +92,13 @@ func testDir(t *testing.T, dir string, endTime time.Time) (nimports int) {
} }
func TestGcImport(t *testing.T) { 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") compile(t, "testdata", "exports.go")
nimports := 0 nimports := 0
......
...@@ -12,6 +12,9 @@ import ( ...@@ -12,6 +12,9 @@ import (
"runtime" "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. // Path is a validated list of Trees derived from $GOROOT and $GOPATH at init.
var Path []*Tree var Path []*Tree
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
set -e set -e
eval $(../bin/tool/dist env -p) eval $(go tool dist env)
unset CDPATH # in case user has it set unset CDPATH # in case user has it set
......
// $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. // Copyright 2010 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
# Use of this source code is governed by a BSD-style # Use of this source code is governed by a BSD-style
# license that can be found in the LICENSE file. # license that can be found in the LICENSE file.
eval $(../bin/tool/dist env) eval $(go tool dist env)
export GOARCH GOOS GOROOT export GOARCH GOOS GOROOT
export E= export E=
...@@ -34,7 +34,7 @@ failed=0 ...@@ -34,7 +34,7 @@ failed=0
PATH=${GOBIN:-$GOROOT/bin}:`pwd`:/bin:/usr/bin:/usr/local/bin 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. # 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" RUNFILE="/tmp/gorun-$$-$USER"
TMP1FILE="/tmp/gotest1-$$-$USER" TMP1FILE="/tmp/gotest1-$$-$USER"
......
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