aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorRuss Cox <rsc@golang.org>2012-02-04 00:48:31 -0500
committerRuss Cox <rsc@golang.org>2012-02-04 00:48:31 -0500
commit4c1abd6c64085a005b0d9d54eee97cd0c06151b2 (patch)
tree94d176b30f80a1cc44f5764db962f8b8f8960cb1 /src
parent67b277c3b92daa16777d307f3c48aff06abe1305 (diff)
downloadgo-4c1abd6c64085a005b0d9d54eee97cd0c06151b2.tar.xz
build: dist-based build for windows
R=golang-dev, bradfitz, iant, alex.brainman, go.peter.90 CC=golang-dev https://golang.org/cl/5630047
Diffstat (limited to 'src')
-rw-r--r--src/all.bat18
-rw-r--r--src/cmd/dist/windows.c229
-rw-r--r--src/make.bat52
-rw-r--r--src/run.bat47
4 files changed, 288 insertions, 58 deletions
diff --git a/src/all.bat b/src/all.bat
new file mode 100644
index 0000000000..93e07b578a
--- /dev/null
+++ b/src/all.bat
@@ -0,0 +1,18 @@
+:: Copyright 2012 The Go Authors. All rights reserved.
+:: Use of this source code is governed by a BSD-style
+:: license that can be found in the LICENSE file.
+@echo off
+
+if exist make.bat goto ok
+echo all.bat must be run from go\src
+:: cannot exit: would kill parent command interpreter
+goto end
+:ok
+
+call make.bat --no-banner
+if %GOBUILDFAIL%==1 goto end
+call run.bat --no-rebuild
+if %GOBUILDFAIL%==1 goto end
+..\bin\tool\dist banner
+
+:end
diff --git a/src/cmd/dist/windows.c b/src/cmd/dist/windows.c
index 2d82587bd2..89bd3d733a 100644
--- a/src/cmd/dist/windows.c
+++ b/src/cmd/dist/windows.c
@@ -94,8 +94,7 @@ toutf(Buf *b, Rune *r)
static void
torune(Rune **rp, char *p)
{
- int i, n;
- Rune *r, *w, r1;
+ Rune *r, *w;
r = xmalloc((strlen(p)+1) * sizeof r[0]);
w = r;
@@ -125,7 +124,6 @@ errstr(void)
void
xgetenv(Buf *b, char *name)
{
- char *p;
Rune *buf;
int n;
Rune *r;
@@ -169,6 +167,42 @@ bprintf(Buf *b, char *fmt, ...)
return bstr(b);
}
+void
+bwritef(Buf *b, char *fmt, ...)
+{
+ va_list arg;
+ char buf[4096];
+
+ // no reset
+ va_start(arg, fmt);
+ vsnprintf(buf, sizeof buf, fmt, arg);
+ va_end(arg);
+ bwritestr(b, buf);
+}
+
+// bpathf is like bprintf but replaces / with \ in the result,
+// to make it a canonical windows file path.
+char*
+bpathf(Buf *b, char *fmt, ...)
+{
+ int i;
+ va_list arg;
+ char buf[4096];
+
+ breset(b);
+ va_start(arg, fmt);
+ vsnprintf(buf, sizeof buf, fmt, arg);
+ va_end(arg);
+ bwritestr(b, buf);
+
+ for(i=0; i<b->len; i++)
+ if(b->p[i] == '/')
+ b->p[i] = '\\';
+
+ return bstr(b);
+}
+
+
static void
breadfrom(Buf *b, HANDLE h)
{
@@ -179,8 +213,10 @@ breadfrom(Buf *b, HANDLE h)
fatal("unlikely file size in readfrom");
bgrow(b, 4096);
n = 0;
- if(!ReadFile(h, b->p+b->len, 4096, &n, nil))
- fatal("ReadFile: %s", errstr());
+ if(!ReadFile(h, b->p+b->len, 4096, &n, nil)) {
+ // Happens for pipe reads.
+ break;
+ }
if(n == 0)
break;
b->len += n;
@@ -188,36 +224,71 @@ breadfrom(Buf *b, HANDLE h)
}
void
+run(Buf *b, char *dir, int mode, char *cmd, ...)
+{
+ va_list arg;
+ Vec argv;
+ char *p;
+
+ vinit(&argv);
+ vadd(&argv, cmd);
+ va_start(arg, cmd);
+ while((p = va_arg(arg, char*)) != nil)
+ vadd(&argv, p);
+ va_end(arg);
+
+ runv(b, dir, mode, &argv);
+
+ vfree(&argv);
+}
+
+static void genrun(Buf*, char*, int, Vec*, int);
+
+void
runv(Buf *b, char *dir, int mode, Vec *argv)
{
+ genrun(b, dir, mode, argv, 1);
+}
+
+void
+bgrunv(char *dir, int mode, Vec *argv)
+{
+ genrun(nil, dir, mode, argv, 0);
+}
+
+#define MAXBG 4 /* maximum number of jobs to run at once */
+
+static struct {
+ PROCESS_INFORMATION pi;
+ int mode;
+ char *cmd;
+} bg[MAXBG];
+
+static int nbg;
+
+static void bgwait1(void);
+
+static void
+genrun(Buf *b, char *dir, int mode, Vec *argv, int wait)
+{
int i, j, nslash;
Buf cmd;
- char *e, *q;
+ char *q;
Rune *rcmd, *rexe, *rdir;
STARTUPINFOW si;
PROCESS_INFORMATION pi;
HANDLE p[2];
- DWORD code;
+
+ while(nbg >= nelem(bg))
+ bgwait1();
binit(&cmd);
- for(i=0; i<argv->len; i++) {
- if(i > 0)
- bwritestr(&cmd, " ");
- q = argv->p[i];
- if(workdir != nil && hasprefix(q, workdir)) {
- bwritestr(&cmd, "$WORK");
- q += strlen(workdir);
- }
- bwritestr(&cmd, q);
- }
- //xprintf("%s\n", bstr(&cmd));
- breset(&cmd);
for(i=0; i<argv->len; i++) {
if(i > 0)
bwritestr(&cmd, " ");
q = argv->p[i];
- if(contains(q, " ") || contains(q, "\t") || contains(q, "\\") || contains(q, "\"")) {
+ if(contains(q, " ") || contains(q, "\t") || contains(q, "\"") || contains(q, "\\\\") || hassuffix(q, "\\")) {
bwritestr(&cmd, "\"");
nslash = 0;
for(; *q; q++) {
@@ -242,6 +313,8 @@ runv(Buf *b, char *dir, int mode, Vec *argv)
bwritestr(&cmd, q);
}
}
+ if(vflag > 1)
+ xprintf("%s\n", bstr(&cmd));
torune(&rcmd, bstr(&cmd));
rexe = nil;
@@ -257,8 +330,13 @@ runv(Buf *b, char *dir, int mode, Vec *argv)
si.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE);
si.hStdError = GetStdHandle(STD_ERROR_HANDLE);
} else {
+ SECURITY_ATTRIBUTES seci;
+
+ memset(&seci, 0, sizeof seci);
+ seci.nLength = sizeof seci;
+ seci.bInheritHandle = 1;
breset(b);
- if(!CreatePipe(&p[0], &p[1], nil, 0))
+ if(!CreatePipe(&p[0], &p[1], &seci, 0))
fatal("CreatePipe: %s", errstr());
si.hStdOutput = p[1];
si.hStdError = p[1];
@@ -279,31 +357,55 @@ runv(Buf *b, char *dir, int mode, Vec *argv)
breadfrom(b, p[0]);
CloseHandle(p[0]);
}
- WaitForSingleObject(pi.hProcess, INFINITE);
- if(!GetExitCodeProcess(pi.hProcess, &code))
+ if(nbg < 0)
+ fatal("bad bookkeeping");
+ bg[nbg].pi = pi;
+ bg[nbg].mode = mode;
+ bg[nbg].cmd = btake(&cmd);
+ nbg++;
+
+ if(wait)
+ bgwait();
+
+ bfree(&cmd);
+}
+
+// bgwait1 waits for a single background job
+static void
+bgwait1(void)
+{
+ int i, mode;
+ char *cmd;
+ HANDLE bgh[MAXBG];
+ DWORD code;
+
+ if(nbg == 0)
+ fatal("bgwait1: nothing left");
+
+ for(i=0; i<nbg; i++)
+ bgh[i] = bg[i].pi.hProcess;
+ i = WaitForMultipleObjects(nbg, bgh, FALSE, INFINITE);
+ if(i < 0 || i >= nbg)
+ fatal("WaitForMultipleObjects: %s", errstr());
+
+ cmd = bg[i].cmd;
+ mode = bg[i].mode;
+ if(!GetExitCodeProcess(bg[i].pi.hProcess, &code))
fatal("GetExitCodeProcess: %s", errstr());
if(mode==CheckExit && code != 0)
- fatal("%s failed", argv->p[0]);
+ fatal("FAILED: %s", cmd);
+ CloseHandle(bg[i].pi.hProcess);
+ CloseHandle(bg[i].pi.hThread);
+
+ bg[i] = bg[--nbg];
}
void
-run(Buf *b, char *dir, int mode, char *cmd, ...)
+bgwait(void)
{
- va_list arg;
- Vec argv;
- char *p;
-
- vinit(&argv);
- vadd(&argv, cmd);
- va_start(arg, cmd);
- while((p = va_arg(arg, char*)) != nil)
- vadd(&argv, p);
- va_end(arg);
-
- runv(b, dir, mode, &argv);
-
- vfree(&argv);
+ while(nbg > 0)
+ bgwait1();
}
// rgetwd returns a rune string form of the current directory's path.
@@ -313,7 +415,7 @@ rgetwd(void)
int n;
Rune *r;
- n = GetCurrentDirectory(0, nil);
+ n = GetCurrentDirectoryW(0, nil);
r = xmalloc((n+1)*sizeof r[0]);
GetCurrentDirectoryW(n+1, r);
r[n] = '\0';
@@ -334,7 +436,6 @@ xgetwd(Buf *b)
void
xrealwd(Buf *b, char *path)
{
- int n;
Rune *old;
Rune *rnew;
@@ -354,25 +455,25 @@ xrealwd(Buf *b, char *path)
bool
isdir(char *p)
{
- int attr;
+ DWORD attr;
Rune *r;
torune(&r, p);
attr = GetFileAttributesW(r);
xfree(r);
- return attr >= 0 && (attr & FILE_ATTRIBUTE_DIRECTORY);
+ return attr != INVALID_FILE_ATTRIBUTES && (attr & FILE_ATTRIBUTE_DIRECTORY);
}
bool
isfile(char *p)
{
- int attr;
+ DWORD attr;
Rune *r;
torune(&r, p);
attr = GetFileAttributesW(r);
xfree(r);
- return attr >= 0 && !(attr & FILE_ATTRIBUTE_DIRECTORY);
+ return attr != INVALID_FILE_ATTRIBUTES && !(attr & FILE_ATTRIBUTE_DIRECTORY);
}
Time
@@ -381,7 +482,6 @@ mtime(char *p)
HANDLE h;
WIN32_FIND_DATAW data;
Rune *r;
- Time t;
FILETIME *ft;
torune(&r, p);
@@ -389,6 +489,7 @@ mtime(char *p)
xfree(r);
if(h == INVALID_HANDLE_VALUE)
return 0;
+ FindClose(h);
ft = &data.ftLastWriteTime;
return (Time)ft->dwLowDateTime + ((Time)ft->dwHighDateTime<<32);
}
@@ -396,10 +497,10 @@ mtime(char *p)
bool
isabs(char *p)
{
- // "c:/" or "c:\"
+ // c:/ or c:\ at beginning
if(('A' <= p[0] && p[0] <= 'Z') || ('a' <= p[0] && p[0] <= 'z'))
return p[1] == ':' && (p[2] == '/' || p[2] == '\\');
- // "/" or "\"
+ // / or \ at beginning
return p[0] == '/' || p[0] == '\\';
}
@@ -409,6 +510,8 @@ readfile(Buf *b, char *file)
HANDLE h;
Rune *r;
+ if(vflag > 2)
+ xprintf("read %s\n", file);
torune(&r, file);
h = CreateFileW(r, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE, nil, OPEN_EXISTING, 0, 0);
if(h == INVALID_HANDLE_VALUE)
@@ -424,6 +527,8 @@ writefile(Buf *b, char *file)
Rune *r;
DWORD n;
+ if(vflag > 2)
+ xprintf("write %s\n", file);
torune(&r, file);
h = CreateFileW(r, GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE, nil, CREATE_ALWAYS, 0, 0);
if(h == INVALID_HANDLE_VALUE)
@@ -582,8 +687,7 @@ fatal(char *msg, ...)
vsnprintf(buf1, sizeof buf1, msg, arg);
va_end(arg);
- fprintf(stderr, "cbuild: %s\n", buf1);
- fflush(stderr);
+ xprintf("go tool dist: %s\n", buf1);
ExitProcess(1);
}
@@ -717,26 +821,35 @@ xprintf(char *fmt, ...)
va_end(arg);
n = 0;
WriteFile(GetStdHandle(STD_OUTPUT_HANDLE), buf, strlen(buf), &n, 0);
- fflush(stdout);
}
int
main(int argc, char **argv)
{
- char *p;
+ SYSTEM_INFO si;
setvbuf(stdout, nil, _IOLBF, 0);
setvbuf(stderr, nil, _IOLBF, 0);
- p = argv[0];
- if(hassuffix(p, "bin/go-tool/dist.exe") || hassuffix(p, "bin\\go-tool\\dist.exe")) {
- default_goroot = xstrdup(p);
- default_goroot[strlen(p)-strlen("bin/go-tool/dist.exe")] = '\0';
- }
-
+ default_goroot = DEFAULT_GOROOT;
+
slash = "\\";
gohostos = "windows";
+
+ GetSystemInfo(&si);
+ switch(si.wProcessorArchitecture) {
+ case PROCESSOR_ARCHITECTURE_AMD64:
+ gohostarch = "amd64";
+ break;
+ case PROCESSOR_ARCHITECTURE_INTEL:
+ gohostarch = "386";
+ break;
+ default:
+ fatal("unknown processor architecture");
+ }
+
init();
+
xmain(argc, argv);
return 0;
}
diff --git a/src/make.bat b/src/make.bat
new file mode 100644
index 0000000000..34f4361506
--- /dev/null
+++ b/src/make.bat
@@ -0,0 +1,52 @@
+:: Copyright 2012 The Go Authors. All rights reserved.
+:: Use of this source code is governed by a BSD-style
+:: license that can be found in the LICENSE file.
+::@echo off
+
+set GOBUILDFAIL=0
+
+if exist make.bat goto ok
+echo Must run make.bat from Go src directory.
+goto fail
+:ok
+
+:: Grab default $GOROOT, escape \ for C string.
+:: The expression %CD:\=\\% means to take %CD%
+:: and apply the substitution \ = \\, escaping the
+:: backslashes. Then we wrap that in quotes to create
+:: a C string.
+cd ..
+set DEFGOROOT=-DDEFAULT_GOROOT="\"%CD:\=\\%\""
+cd src
+
+echo # Building C bootstrap tool.
+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
+if errorlevel 1 goto fail
+:: 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
+if errorlevel 1 goto fail
+echo .
+
+echo # Building packages and commands.
+..\bin\tool\go_bootstrap clean std
+if errorlevel 1 goto fail
+..\bin\tool\go_bootstrap install -a -v std
+if errorlevel 1 goto fail
+del ..\bin\tool\go_bootstrap.exe
+echo .
+
+if x%1==x--no-banner goto nobanner
+..\bin\tool\dist banner
+:nobanner
+
+goto end
+
+:fail
+set GOBUILDFAIL=1
+
+:end
diff --git a/src/run.bat b/src/run.bat
new file mode 100644
index 0000000000..89ed10d7a8
--- /dev/null
+++ b/src/run.bat
@@ -0,0 +1,47 @@
+:: Copyright 2012 The Go Authors. All rights reserved.
+:: Use of this source code is governed by a BSD-style
+:: license that can be found in the LICENSE file.
+@echo off
+
+set GOOLDPATH=%PATH%
+set GOBUILDFAIL=0
+
+..\bin\tool\dist env -wp >env.bat
+if errorlevel 1 goto fail
+call env.bat
+del env.bat
+
+rem TODO avoid rebuild if possible
+
+if x%1==x--no-rebuild goto norebuild
+echo # Building packages and commands.
+go install -a -v std
+if errorlevel 1 goto fail
+echo .
+:norebuild
+
+echo # Testing packages.
+go test std -short -timeout=120s
+if errorlevel 1 goto fail
+echo .
+
+echo # runtime -cpu=1,2,4
+go test runtime -short -timeout=120s -cpu=1,2,4
+if errorlevel 1 goto fail
+echo .
+
+echo # sync -cpu=10
+go test sync -short -timeout=120s -cpu=10
+if errorlevel 1 goto fail
+echo .
+
+:: TODO: The other tests in run.bash, especially $GOROOT/test/run.
+
+echo ALL TESTS PASSED
+goto end
+
+:fail
+set GOBUILDFAIL=1
+
+:end
+set PATH=%GOOLDPATH%