Commit 9af454c5 authored by Russ Cox's avatar Russ Cox

all: merge dev.cc (929f3210) into master

This brings in cmd/dist written in Go, which is working on the primary builders.

If this breaks your build, you need to get Go 1.4 and put it in $HOME/go1.4
(or, if you want to use some other directory, set $GOROOT_BOOTSTRAP
to that directory).

To build Go 1.4 from source:

	git clone -b release-branch.go1.4 $GOROOT $HOME/go1.4
	cd $HOME/go1.4/src
	./make.bash

Or use a binary release: https://golang.org/dl/.

See https://golang.org/s/go15bootstrap for more information.

Change-Id: Ie4ae834c76ea35e39cc54e9878819a9e51b284d9
parents d5d4e82f 929f3210
This program, dist, is the bootstrapping tool for the Go distribution.
It takes care of building the C programs (like the Go compiler) and
the initial bootstrap copy of the go tool. It also serves as a catch-all
to replace odd jobs previously done with shell scripts.
Dist is itself written in very simple C. All interaction with C libraries,
even standard C libraries, is confined to a single system-specific file
(plan9.c, unix.c, windows.c), to aid portability. Functionality needed
by other files should be exposed via the portability layer. Functions
in the portability layer begin with an x prefix when they would otherwise
use the same name as or be confused for an existing function.
For example, xprintf is the portable printf.
As of Go 1.5, dist and other parts of the compiler toolchain are written
in Go, making bootstrapping a little more involved than in the past.
The approach is to build the current release of Go with an earlier one.
By far the most common data types in dist are strings and arrays of
strings. Instead of using char* and char**, though, dist uses two named
data structures, Buf and Vec, which own all the data they point at.
The Buf operations are functions beginning with b; the Vec operations
are functions beginning with v. The basic form of any function declaring
Bufs or Vecs on the stack should be
The process to install Go 1.x, for x ≥ 5, is:
void
myfunc(void)
{
Buf b1, b2;
Vec v1;
1. Build cmd/dist with Go 1.4.
2. Using dist, build Go 1.x compiler toolchain with Go 1.4.
3. Using dist, rebuild Go 1.x compiler toolchain with itself.
4. Using dist, build Go 1.x cmd/go (as go_bootstrap) with Go 1.x compiler toolchain.
5. Using go_bootstrap, build the remaining Go 1.x standard library and commands.
binit(&b1);
binit(&b2);
vinit(&v1);
NOTE: During the transition from the old C-based toolchain to the Go-based one,
step 2 also builds the parts of the toolchain written in C, and step 3 does not
recompile those.
... main code ...
bprintf(&b1, "hello, world");
vadd(&v1, bstr(&b1)); // v1 takes a copy of its argument
bprintf(&b2, "another string");
vadd(&v1, bstr(&b2)); // v1 now has two strings
Because of backward compatibility, although the steps above say Go 1.4,
in practice any release ≥ Go 1.4 but < Go 1.x will work as the bootstrap base.
bfree(&b1);
bfree(&b2);
vfree(&v1);
}
The binit/vinit calls prepare a buffer or vector for use, initializing the
data structures, and the bfree/vfree calls free any memory they are still
holding onto. Use of this idiom gives us lexically scoped allocations.
See golang.org/s/go15bootstrap for more details.
Compared to Go 1.4 and earlier, dist will also take over much of what used to
be done by make.bash/make.bat/make.rc and all of what used to be done by
run.bash/run.bat/run.rc, because it is nicer to implement that logic in Go
than in three different scripting languages simultaneously.
// 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.
typedef int bool;
// The Time unit is unspecified; we just need to
// be able to compare whether t1 is older than t2 with t1 < t2.
typedef long long Time;
#define nil ((void*)0)
#define nelem(x) (sizeof(x)/sizeof((x)[0]))
#ifndef PLAN9
#define USED(x) ((void)(x))
#endif
// A Buf is a byte buffer, like Go's []byte.
typedef struct Buf Buf;
struct Buf
{
char *p;
int len;
int cap;
};
// A Vec is a string vector, like Go's []string.
typedef struct Vec Vec;
struct Vec
{
char **p;
int len;
int cap;
};
// Modes for run.
enum {
CheckExit = 1,
};
// buf.c
bool bequal(Buf *s, Buf *t);
void bsubst(Buf *b, char *x, char *y);
void bfree(Buf *b);
void bgrow(Buf *b, int n);
void binit(Buf *b);
char* bpathf(Buf *b, char *fmt, ...);
char* bprintf(Buf *b, char *fmt, ...);
void bwritef(Buf *b, char *fmt, ...);
void breset(Buf *b);
char* bstr(Buf *b);
char* btake(Buf *b);
void bwrite(Buf *b, void *v, int n);
void bwriteb(Buf *dst, Buf *src);
void bwritestr(Buf *b, char *p);
void bswap(Buf *b, Buf *b1);
void vadd(Vec *v, char *p);
void vcopy(Vec *dst, char **src, int n);
void vfree(Vec *v);
void vgrow(Vec *v, int n);
void vinit(Vec *v);
void vreset(Vec *v);
void vuniq(Vec *v);
void splitlines(Vec*, char*);
void splitfields(Vec*, char*);
// build.c
extern char *goarch;
extern char *gobin;
extern char *gochar;
extern char *gohostarch;
extern char *gohostos;
extern char *goos;
extern char *goroot;
extern char *goroot_final;
extern char *goextlinkenabled;
extern char *goversion;
extern char *defaultcc;
extern char *defaultcxxtarget;
extern char *defaultcctarget;
extern char *workdir;
extern char *tooldir;
extern char *slash;
extern bool rebuildall;
extern bool defaultclang;
int find(char*, char**, int);
void init(void);
void cmdbanner(int, char**);
void cmdbootstrap(int, char**);
void cmdclean(int, char**);
void cmdenv(int, char**);
void cmdinstall(int, char**);
void cmdversion(int, char**);
// buildgc.c
void gcopnames(char*, char*);
void mkanames(char*, char*);
// buildruntime.c
void mkzasm(char*, char*);
void mkzsys(char*, char*);
void mkzgoarch(char*, char*);
void mkzgoos(char*, char*);
void mkzruntimedefs(char*, char*);
void mkzversion(char*, char*);
void mkzexperiment(char*, char*);
// buildgo.c
void mkzdefaultcc(char*, char*);
// main.c
extern int vflag;
extern int sflag;
void usage(void);
void xmain(int argc, char **argv);
// portability layer (plan9.c, unix.c, windows.c)
bool contains(char *p, char *sep);
void errprintf(char*, ...);
void fatal(char *msg, ...);
bool hasprefix(char *p, char *prefix);
bool hassuffix(char *p, char *suffix);
bool isabs(char*);
bool isdir(char *p);
bool isfile(char *p);
char* lastelem(char*);
Time mtime(char*);
void readfile(Buf*, char*);
void copyfile(char*, char*, int);
void run(Buf *b, char *dir, int mode, char *cmd, ...);
void runv(Buf *b, char *dir, int mode, Vec *argv);
void bgrunv(char *dir, int mode, Vec *argv);
void bgwait(void);
bool streq(char*, char*);
bool cansse2(void);
void writefile(Buf*, char*, int);
void xatexit(void (*f)(void));
void xexit(int);
void xfree(void*);
void xgetenv(Buf *b, char *name);
void xgetwd(Buf *b);
void* xmalloc(int n);
void* xmalloc(int);
int xmemcmp(void*, void*, int);
void xmemmove(void*, void*, int);
void xmkdir(char *p);
void xmkdirall(char*);
Time xmtime(char *p);
void xprintf(char*, ...);
void xqsort(void*, int, int, int(*)(const void*, const void*));
void xreaddir(Vec *dst, char *dir);
void* xrealloc(void*, int);
void xrealwd(Buf *b, char *path);
void xremove(char *p);
void xremoveall(char *p);
void xsetenv(char*, char*);
int xstrcmp(char*, char*);
char* xstrdup(char *p);
int xstrlen(char*);
char* xstrrchr(char*, int);
char* xstrstr(char*, char*);
char* xworkdir(void);
int xsamefile(char*, char*);
char* xgetgoarm(void);
int xtryexecfunc(void (*)(void));
/*
Derived from Inferno include/kern.h.
http://code.google.com/p/inferno-os/source/browse/include/kern.h
Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
Revisions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com). All rights reserved.
Portions Copyright © 2009 The Go Authors. All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
/* command line */
extern char *argv0;
#define ARGBEGIN for((argv0=(argv0?argv0:*argv)),argv++,argc--;\
argv[0] && argv[0][0]=='-' && argv[0][1];\
argc--, argv++) {\
char *_args, *_argt;\
char _argc;\
_args = &argv[0][1];\
if(_args[0]=='-' && _args[1]==0){\
argc--; argv++; break;\
}\
while((_argc = *_args++) != 0)\
switch(_argc)
#define ARGEND _argt=0;USED(_argt);USED(_argc);USED(_args);}USED(argv);USED(argc);
#define ARGF() (_argt=_args, _args="",\
(*_argt? _argt: argv[1]? (argc--, *++argv): 0))
#define EARGF(x) (_argt=_args, _args="",\
(*_argt? _argt: argv[1]? (argc--, *++argv): ((x), fatal("usage"), (char*)0)))
#define ARGC() _argc
// 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.
#include "a.h"
#ifndef __ARMEL__
char *
xgetgoarm(void)
{
return "6";
}
#else
static void useVFPv3(void);
static void useVFPv1(void);
char *
xgetgoarm(void)
{
#if defined(__FreeBSD__)
// FreeBSD has broken VFP support
return "5";
#endif
// NaCl always has VFP support.
if(streq(goos, "nacl") || xtryexecfunc(useVFPv3))
return "7";
else if(xtryexecfunc(useVFPv1))
return "6";
return "5";
}
static void
useVFPv3(void)
{
// try to run VFPv3-only "vmov.f64 d0, #112" instruction
// we can't use that instruction directly, because we
// might be compiling with a soft-float only toolchain.
//
// some newer toolchains are configured to use thumb
// by default, so we need to do some mode changing magic
// here.
// We can use "bx pc; nop" here, but GNU as(1) insists
// on warning us
// "use of r15 in bx in ARM mode is not really useful"
// so we workaround that by using "bx r0"
__asm__ __volatile__ ("mov r0, pc");
__asm__ __volatile__ ("bx r0");
__asm__ __volatile__ (".word 0xeeb70b00"); // vmov.f64 d0, #112
__asm__ __volatile__ (".word 0xe12fff1e"); // bx lr
}
static void
useVFPv1(void)
{
// try to run "vmov.f64 d0, d0" instruction
// we can't use that instruction directly, because we
// might be compiling with a soft-float only toolchain
//
// some newer toolchains are configured to use thumb
// by default, so we need to do some mode changing magic
// here.
// We can use "bx pc; nop" here, but GNU as(1) insists
// on warning us
// "use of r15 in bx in ARM mode is not really useful"
// so we workaround that by using "bx r0"
__asm__ __volatile__ ("mov r0, pc");
__asm__ __volatile__ ("bx r0");
__asm__ __volatile__ (".word 0xeeb00b40"); // vomv.f64 d0, d0
__asm__ __volatile__ (".word 0xe12fff1e"); // bx lr
}
#endif
// 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.
// Byte buffers and string vectors.
#include "a.h"
// binit prepares an uninitialized buffer for use.
void
binit(Buf *b)
{
b->p = nil;
b->len = 0;
b->cap = 0;
}
// breset truncates the buffer back to zero length.
void
breset(Buf *b)
{
b->len = 0;
}
// bfree frees the storage associated with a buffer.
void
bfree(Buf *b)
{
xfree(b->p);
binit(b);
}
// bgrow ensures that the buffer has at least n more bytes
// between its len and cap.
void
bgrow(Buf *b, int n)
{
int want;
want = b->len+n;
if(want > b->cap) {
b->cap = 2*want;
if(b->cap < 64)
b->cap = 64;
b->p = xrealloc(b->p, b->cap);
}
}
// bwrite appends the n bytes at v to the buffer.
void
bwrite(Buf *b, void *v, int n)
{
bgrow(b, n);
xmemmove(b->p+b->len, v, n);
b->len += n;
}
// bwritestr appends the string p to the buffer.
void
bwritestr(Buf *b, char *p)
{
bwrite(b, p, xstrlen(p));
}
// bstr returns a pointer to a NUL-terminated string of the
// buffer contents. The pointer points into the buffer.
char*
bstr(Buf *b)
{
bgrow(b, 1);
b->p[b->len] = '\0';
return b->p;
}
// btake takes ownership of the string form of the buffer.
// After this call, the buffer has zero length and does not
// refer to the memory that btake returned.
char*
btake(Buf *b)
{
char *p;
p = bstr(b);
binit(b);
return p;
}
// bwriteb appends the src buffer to the dst buffer.
void
bwriteb(Buf *dst, Buf *src)
{
bwrite(dst, src->p, src->len);
}
// bequal reports whether the buffers have the same content.
bool
bequal(Buf *s, Buf *t)
{
return s->len == t->len && xmemcmp(s->p, t->p, s->len) == 0;
}
// bsubst rewites b to replace all occurrences of x with y.
void
bsubst(Buf *b, char *x, char *y)
{
char *p;
int nx, ny, pos;
nx = xstrlen(x);
ny = xstrlen(y);
pos = 0;
for(;;) {
p = xstrstr(bstr(b)+pos, x);
if(p == nil)
break;
if(nx != ny) {
if(nx < ny) {
pos = p - b->p;
bgrow(b, ny-nx);
p = b->p + pos;
}
xmemmove(p+ny, p+nx, (b->p+b->len)-(p+nx));
}
xmemmove(p, y, ny);
pos = p+ny - b->p;
b->len += ny - nx;
}
}
// The invariant with the vectors is that v->p[0:v->len] is allocated
// strings that are owned by the vector. The data beyond v->len may
// be garbage.
// vinit prepares an uninitialized vector for use.
void
vinit(Vec *v)
{
v->p = nil;
v->len = 0;
v->cap = 0;
}
// vreset truncates the vector back to zero length.
void
vreset(Vec *v)
{
int i;
for(i=0; i<v->len; i++) {
xfree(v->p[i]);
v->p[i] = nil;
}
v->len = 0;
}
// vfree frees the storage associated with the vector.
void
vfree(Vec *v)
{
vreset(v);
xfree(v->p);
vinit(v);
}
// vgrow ensures that the vector has room for at least
// n more entries between len and cap.
void
vgrow(Vec *v, int n)
{
int want;
want = v->len+n;
if(want > v->cap) {
v->cap = 2*want;
if(v->cap < 64)
v->cap = 64;
v->p = xrealloc(v->p, v->cap*sizeof v->p[0]);
}
}
// vcopy copies the srclen strings at src into the vector.
void
vcopy(Vec *dst, char **src, int srclen)
{
int i;
// use vadd, to make copies of strings
for(i=0; i<srclen; i++)
vadd(dst, src[i]);
}
// vadd adds a copy of the string p to the vector.
void
vadd(Vec *v, char *p)
{
vgrow(v, 1);
if(p != nil)
p = xstrdup(p);
v->p[v->len++] = p;
}
// vaddn adds a string consisting of the n bytes at p to the vector.
static void
vaddn(Vec *v, char *p, int n)
{
char *q;
vgrow(v, 1);
q = xmalloc(n+1);
xmemmove(q, p, n);
q[n] = '\0';
v->p[v->len++] = q;
}
static int
strpcmp(const void *a, const void *b)
{
return xstrcmp(*(char**)a, *(char**)b);
}
// vuniq sorts the vector and then discards duplicates,
// in the manner of sort | uniq.
void
vuniq(Vec *v)
{
int i, n;
xqsort(v->p, v->len, sizeof(v->p[0]), strpcmp);
n = 0;
for(i=0; i<v->len; i++) {
if(n>0 && streq(v->p[i], v->p[n-1]))
xfree(v->p[i]);
else
v->p[n++] = v->p[i];
}
v->len = n;
}
// splitlines replaces the vector v with the result of splitting
// the input p after each \n. If there is a \r immediately before
// each \n, it will be removed.
void
splitlines(Vec *v, char *p)
{
int i;
char *start;
vreset(v);
start = p;
for(i=0; p[i]; i++) {
if((p[i] == '\r' && p[i+1] == '\n') || p[i] == '\n') {
vaddn(v, start, (p+i+1)-start);
if(p[i] == '\r') {
v->p[v->len-1][(p+i)-start] = '\n';
i++;
}
start = p+i+1;
}
}
if(*start != '\0')
vadd(v, start);
}
// splitfields replaces the vector v with the result of splitting
// the input p into non-empty fields containing no spaces.
void
splitfields(Vec *v, char *p)
{
char *start;
vreset(v);
for(;;) {
while(*p == ' ' || *p == '\t' || *p == '\r' || *p == '\n')
p++;
if(*p == '\0')
break;
start = p;
while(*p != ' ' && *p != '\t' && *p != '\r' && *p != '\n' && *p != '\0')
p++;
vaddn(v, start, p-start);
}
}
// 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.
#include "a.h"
/*
* Helpers for building cmd/gc.
*/
// gcopnames creates opnames.h from go.h.
// It finds the OXXX enum, pulls out all the constants
// from OXXX to OEND, and writes a table mapping
// op to string.
void
gcopnames(char *dir, char *file)
{
char *p, *q;
int i, j, end;
Buf in, b, out;
Vec lines, fields;
binit(&in);
binit(&b);
binit(&out);
vinit(&lines);
vinit(&fields);
bwritestr(&out, bprintf(&b, "// auto generated by go tool dist\n"));
bwritestr(&out, bprintf(&b, "static char *opnames[] = {\n"));
readfile(&in, bprintf(&b, "%s/go.h", dir));
splitlines(&lines, bstr(&in));
i = 0;
while(i<lines.len && !contains(lines.p[i], "OXXX"))
i++;
end = 0;
for(; i<lines.len && !end; i++) {
p = xstrstr(lines.p[i], "//");
if(p != nil)
*p = '\0';
end = contains(lines.p[i], "OEND");
splitfields(&fields, lines.p[i]);
for(j=0; j<fields.len; j++) {
q = fields.p[j];
if(*q == 'O')
q++;
p = q+xstrlen(q)-1;
if(*p == ',')
*p = '\0';
bwritestr(&out, bprintf(&b, " [O%s] = \"%s\",\n", q, q));
}
}
bwritestr(&out, bprintf(&b, "};\n"));
writefile(&out, file, 0);
bfree(&in);
bfree(&b);
bfree(&out);
vfree(&lines);
vfree(&fields);
}
static int
xatoi(char *s, char **end)
{
int val = 0;
for(; *s && *s >= '0' && *s <= '9'; ++s)
val = val * 10 + (*s - '0');
*end = s;
return val;
}
// mkanames reads [5689].out.h and writes anames[5689].c
// The format is much the same as the Go opcodes above.
// It also writes out cnames array for C_* constants and the dnames
// array for D_* constants.
void
mkanames(char *dir, char *file)
{
int i, j, ch, n, unknown;
Buf in, b, out, out2;
Vec lines;
char *p, *p2;
Vec dnames[128];
binit(&b);
binit(&in);
binit(&out);
binit(&out2);
vinit(&lines);
for(i=0; i<nelem(dnames); i++)
vinit(&dnames[i]);
ch = file[xstrlen(file)-3];
bprintf(&b, "%s/../cmd/%cl/%c.out.h", dir, ch, ch);
readfile(&in, bstr(&b));
splitlines(&lines, bstr(&in));
// Include link.h so that the extern declaration there is
// checked against the non-extern declaration we are generating.
bwritestr(&out, bprintf(&b, "// auto generated by go tool dist\n"));
bwritestr(&out, bprintf(&b, "#include <u.h>\n"));
bwritestr(&out, bprintf(&b, "#include <libc.h>\n"));
bwritestr(&out, bprintf(&b, "#include <bio.h>\n"));
bwritestr(&out, bprintf(&b, "#include <link.h>\n"));
bwritestr(&out, bprintf(&b, "#include \"../cmd/%cl/%c.out.h\"\n", ch, ch));
bwritestr(&out, bprintf(&b, "\n"));
bwritestr(&out, bprintf(&b, "char* anames%c[] = {\n", ch));
for(i=0; i<lines.len; i++) {
if(hasprefix(lines.p[i], "\tA")) {
p = xstrstr(lines.p[i], ",");
if(p)
*p = '\0';
p = xstrstr(lines.p[i], "\n");
if(p)
*p = '\0';
p = lines.p[i] + 2;
bwritestr(&out, bprintf(&b, "\t\"%s\",\n", p));
}
}
bwritestr(&out, "};\n");
j=0;
bprintf(&out2, "char* cnames%c[] = {\n", ch);
for(i=0; i<lines.len; i++) {
if(hasprefix(lines.p[i], "\tC_")) {
p = xstrstr(lines.p[i], ",");
if(p)
*p = '\0';
p = xstrstr(lines.p[i], "\n");
if(p)
*p = '\0';
p = lines.p[i] + 3;
bwritestr(&out2, bprintf(&b, "\t\"%s\",\n", p));
j++;
}
}
bwritestr(&out2, "};\n");
if(j>0)
bwriteb(&out, &out2);
j=unknown=0;
n=-1;
for(i=0; i<lines.len; i++) {
if(hasprefix(lines.p[i], "\tD_")) {
p = xstrstr(lines.p[i], ",");
if(p)
*p = '\0';
p = xstrstr(lines.p[i], "\n");
if(p)
*p = '\0';
// Parse explicit value, if any
p = xstrstr(lines.p[i], "=");
if(p) {
// Skip space after '='
p2 = p + 1;
while(*p2 == ' ' || *p2 == '\t')
p2++;
n = xatoi(p2, &p2);
// We can't do anything about
// non-numeric values or anything that
// follows
while(*p2 == ' ' || *p2 == '\t')
p2++;
if(*p2 != 0) {
unknown = 1;
continue;
}
// Truncate space before '='
while(*(p-1) == ' ' || *(p-1) == '\t')
p--;
*p = '\0';
unknown = 0;
} else {
n++;
}
if(unknown || n >= nelem(dnames))
continue;
p = lines.p[i] + 3;
if(xstrcmp(p, "LAST") == 0)
continue;
vadd(&dnames[n], p);
j++;
}
}
if(j>0){
bwritestr(&out, bprintf(&b, "char* dnames%c[D_LAST] = {\n", ch));
for(i=0; i<nelem(dnames); i++) {
if(dnames[i].len == 0)
continue;
bwritestr(&out, bprintf(&b, "\t[D_%s] = \"", dnames[i].p[0]));
for(j=0; j<dnames[i].len; j++) {
if(j != 0)
bwritestr(&out, "/");
bwritestr(&out, dnames[i].p[j]);
}
bwritestr(&out, "\",\n");
}
bwritestr(&out, "};\n");
}
writefile(&out, file, 0);
bfree(&b);
bfree(&in);
bfree(&out);
bfree(&out2);
vfree(&lines);
for(i=0; i<nelem(dnames); i++)
vfree(&dnames[i]);
}
// 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.
package main
import (
"bytes"
"fmt"
"strconv"
"strings"
)
/*
* Helpers for building cmd/gc.
*/
// gcopnames creates opnames.h from go.h.
// It finds the OXXX enum, pulls out all the constants
// from OXXX to OEND, and writes a table mapping
// op to string.
func gcopnames(dir, file string) {
var out bytes.Buffer
fmt.Fprintf(&out, "// auto generated by go tool dist\n")
fmt.Fprintf(&out, "static char *opnames[] = {\n")
in := readfile(pathf("%s/go.h", dir))
lines := splitlines(in)
i := 0
for i < len(lines) && !strings.Contains(lines[i], "OXXX") {
i++
}
for _, line := range lines[i:] {
if i := strings.Index(line, "//"); i >= 0 {
line = line[:i]
}
for _, field := range splitfields(line) {
field = strings.TrimPrefix(field, "O")
field = strings.TrimSuffix(field, ",")
fmt.Fprintf(&out, "\t[O%s] = \"%s\",\n", field, field)
}
if strings.Contains(line, "OEND") {
break
}
}
fmt.Fprintf(&out, "};\n")
writefile(out.String(), file, 0)
}
// mkanames reads [5689].out.h and writes anames[5689].c
// The format is much the same as the Go opcodes above.
// It also writes out cnames array for C_* constants and the dnames
// array for D_* constants.
func mkanames(dir, file string) {
ch := file[len(file)-3]
targ := pathf("%s/../cmd/%cl/%c.out.h", dir, ch, ch)
in := readfile(targ)
lines := splitlines(in)
// Include link.h so that the extern declaration there is
// checked against the non-extern declaration we are generating.
var out bytes.Buffer
fmt.Fprintf(&out, "// auto generated by go tool dist\n")
fmt.Fprintf(&out, "#include <u.h>\n")
fmt.Fprintf(&out, "#include <libc.h>\n")
fmt.Fprintf(&out, "#include <bio.h>\n")
fmt.Fprintf(&out, "#include <link.h>\n")
fmt.Fprintf(&out, "#include \"../cmd/%cl/%c.out.h\"\n", ch, ch)
fmt.Fprintf(&out, "\n")
fmt.Fprintf(&out, "char* anames%c[] = {\n", ch)
for _, line := range lines {
if strings.HasPrefix(line, "\tA") {
if i := strings.Index(line, ","); i >= 0 {
line = line[:i]
}
if i := strings.Index(line, "\n"); i >= 0 {
line = line[:i]
}
line = line[2:]
fmt.Fprintf(&out, "\t\"%s\",\n", line)
}
}
fmt.Fprintf(&out, "};\n")
j := 0
var out2 bytes.Buffer
fmt.Fprintf(&out2, "char* cnames%c[] = {\n", ch)
for _, line := range lines {
if strings.HasPrefix(line, "\tC_") {
if i := strings.Index(line, ","); i >= 0 {
line = line[:i]
}
if i := strings.Index(line, "\n"); i >= 0 {
line = line[:i]
}
line = line[3:]
fmt.Fprintf(&out2, "\t\"%s\",\n", line)
j++
}
}
fmt.Fprintf(&out2, "};\n")
if j > 0 {
out.Write(out2.Bytes())
}
var dnames [128][]string
j = 0
unknown := false
n := -1
for _, line := range lines {
if strings.HasPrefix(line, "\tD_") {
if i := strings.Index(line, ","); i >= 0 {
line = line[:i]
}
// Parse explicit value, if any
if i := strings.Index(line, "="); i >= 0 {
value := strings.TrimSpace(line[i+1:])
line = strings.TrimSpace(line[:i])
var err error
n, err = strconv.Atoi(value)
if err != nil {
// We can't do anything about
// non-numeric values or anything that
// follows.
unknown = true
continue
}
unknown = false
} else {
n++
}
if unknown || n < 0 || n >= len(dnames) {
continue
}
line = strings.TrimSpace(line)
line = line[len("D_"):]
if strings.Contains(line, "LAST") {
continue
}
dnames[n] = append(dnames[n], line)
j++
}
}
if j > 0 {
fmt.Fprintf(&out, "char* dnames%c[D_LAST] = {\n", ch)
for _, d := range dnames {
if len(d) == 0 {
continue
}
fmt.Fprintf(&out, "\t[D_%s] = \"", d[0])
for k, name := range d {
if k > 0 {
fmt.Fprintf(&out, "/")
}
fmt.Fprintf(&out, "%s", name)
}
fmt.Fprintf(&out, "\",\n")
}
fmt.Fprintf(&out, "};\n")
}
writefile(out.String(), file, 0)
}
......@@ -2,7 +2,9 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
#include "a.h"
package main
import "fmt"
/*
* Helpers for building cmd/go and cmd/cgo.
......@@ -15,35 +17,23 @@
// const defaultCXX = <defaultcxx>
//
// It is invoked to write cmd/go/zdefaultcc.go
// but we also write cmd/cgo/zdefaultcc.go.
void
mkzdefaultcc(char *dir, char *file)
{
Buf b, out;
USED(dir);
binit(&out);
bprintf(&out,
"// auto generated by go tool dist\n"
"\n"
"package main\n"
"\n"
"const defaultCC = `%s`\n"
// but we also write cmd/cgo/zdefaultcc.go
func mkzdefaultcc(dir, file string) {
var out string
out = fmt.Sprintf(
"// auto generated by go tool dist\n"+
"\n"+
"package main\n"+
"\n"+
"const defaultCC = `%s`\n"+
"const defaultCXX = `%s`\n",
defaultcctarget, defaultcxxtarget);
writefile(&out, file, 0);
defaultcctarget, defaultcxxtarget)
// Convert file name to replace.
binit(&b);
bwritestr(&b, file);
if(slash[0] == '/')
bsubst(&b, "/go/zdefaultcc.go", "/cgo/zdefaultcc.go");
else
bsubst(&b, "\\go\\zdefaultcc.go", "\\cgo\\zdefaultcc.go");
writefile(&out, bstr(&b), 0);
writefile(out, file, 0)
bfree(&b);
bfree(&out);
// Convert file name to replace: turn go into cgo.
i := len(file) - len("go/zdefaultcc.go")
file = file[:i] + "c" + file[i:]
writefile(out, file, 0)
}
......@@ -2,7 +2,12 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
#include "a.h"
package main
import (
"fmt"
"os"
)
/*
* Helpers for building runtime.
......@@ -14,55 +19,28 @@
// const defaultGoroot = <goroot>
// const theVersion = <version>
//
void
mkzversion(char *dir, char *file)
{
Buf b, out;
USED(dir);
binit(&b);
binit(&out);
bwritestr(&out, bprintf(&b,
"// auto generated by go tool dist\n"
"\n"
"package runtime\n"
"\n"
"const defaultGoroot = `%s`\n"
"const theVersion = `%s`\n"
"var buildVersion = theVersion\n", goroot_final, goversion));
writefile(&out, file, 0);
bfree(&b);
bfree(&out);
func mkzversion(dir, file string) {
out := fmt.Sprintf(
"// auto generated by go tool dist\n"+
"\n"+
"package runtime\n"+
"\n"+
"const defaultGoroot = `%s`\n"+
"const theVersion = `%s`\n"+
"var buildVersion = theVersion\n", goroot_final, goversion)
writefile(out, file, 0)
}
// mkzexperiment writes zaexperiment.h (sic):
//
// #define GOEXPERIMENT "experiment string"
//
void
mkzexperiment(char *dir, char *file)
{
Buf b, out, exp;
USED(dir);
binit(&b);
binit(&out);
binit(&exp);
xgetenv(&exp, "GOEXPERIMENT");
bwritestr(&out, bprintf(&b,
"// auto generated by go tool dist\n"
"\n"
"#define GOEXPERIMENT \"%s\"\n", bstr(&exp)));
writefile(&out, file, 0);
func mkzexperiment(dir, file string) {
out := fmt.Sprintf(
"// auto generated by go tool dist\n"+
"\n"+
"#define GOEXPERIMENT \"%s\"\n", os.Getenv("GOEXPERIMENT"))
bfree(&b);
bfree(&out);
bfree(&exp);
writefile(out, file, 0)
}
// Copyright 2015 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.
TEXT ·cpuid(SB),$0-8
MOVL ax+4(FP), AX
CPUID
MOVL info+0(FP), DI
MOVL AX, 0(DI)
MOVL BX, 4(DI)
MOVL CX, 8(DI)
MOVL DX, 12(DI)
RET
// Copyright 2015 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.
TEXT ·cpuid(SB),$0-12
MOVL ax+8(FP), AX
CPUID
MOVQ info+0(FP), DI
MOVL AX, 0(DI)
MOVL BX, 4(DI)
MOVL CX, 8(DI)
MOVL DX, 12(DI)
RET
// Copyright 2015 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.
// +build !386,!amd64
#include "textflag.h"
TEXT ·cpuid(SB),NOSPLIT,$0-0
RET
// 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.
#include "a.h"
int vflag;
int sflag;
char *argv0;
// cmdtab records the available commands.
static struct {
char *name;
void (*f)(int, char**);
} cmdtab[] = {
{"banner", cmdbanner},
{"bootstrap", cmdbootstrap},
{"clean", cmdclean},
{"env", cmdenv},
{"install", cmdinstall},
{"version", cmdversion},
};
// The OS-specific main calls into the portable code here.
void
xmain(int argc, char **argv)
{
int i;
if(argc <= 1)
usage();
for(i=0; i<nelem(cmdtab); i++) {
if(streq(cmdtab[i].name, argv[1])) {
cmdtab[i].f(argc-1, argv+1);
return;
}
}
xprintf("unknown command %s\n", argv[1]);
usage();
}
// 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.
package main
import (
"flag"
"fmt"
"os"
"strconv"
)
// cmdtab records the available commands.
var cmdtab = []struct {
name string
f func()
}{
{"banner", cmdbanner},
{"bootstrap", cmdbootstrap},
{"clean", cmdclean},
{"env", cmdenv},
{"install", cmdinstall},
{"version", cmdversion},
}
// The OS-specific main calls into the portable code here.
func xmain() {
if len(os.Args) < 2 {
usage()
}
cmd := os.Args[1]
os.Args = os.Args[1:] // for flag parsing during cmd
for _, ct := range cmdtab {
if ct.name == cmd {
flag.Usage = func() {
fmt.Fprintf(os.Stderr, "usage: go tool dist %s [options]\n", cmd)
flag.PrintDefaults()
os.Exit(2)
}
ct.f()
return
}
}
xprintf("unknown command %s\n", cmd)
usage()
}
func xflagparse(maxargs int) {
flag.Var((*count)(&vflag), "v", "verbosity")
flag.Parse()
if maxargs >= 0 && flag.NArg() > maxargs {
flag.Usage()
}
}
// count is a flag.Value that is like a flag.Bool and a flag.Int.
// If used as -name, it increments the count, but -name=x sets the count.
// Used for verbose flag -v.
type count int
func (c *count) String() string {
return fmt.Sprint(int(*c))
}
func (c *count) Set(s string) error {
switch s {
case "true":
*c++
case "false":
*c = 0
default:
n, err := strconv.Atoi(s)
if err != nil {
return fmt.Errorf("invalid count %q", s)
}
*c = count(n)
}
return nil
}
func (c *count) IsBoolFlag() bool {
return true
}
This diff is collapsed.
// Copyright 2015 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.
// +build !windows
package main
func sysinit() {
}
// Copyright 2015 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.
package main
import (
"syscall"
"unsafe"
)
var (
modkernel32 = syscall.NewLazyDLL("kernel32.dll")
procGetSystemInfo = modkernel32.NewProc("GetSystemInfo")
)
// see http://msdn.microsoft.com/en-us/library/windows/desktop/ms724958(v=vs.85).aspx
type systeminfo struct {
wProcessorArchitecture uint16
wReserved uint16
dwPageSize uint32
lpMinimumApplicationAddress uintptr
lpMaximumApplicationAddress uintptr
dwActiveProcessorMask uintptr
dwNumberOfProcessors uint32
dwProcessorType uint32
dwAllocationGranularity uint32
wProcessorLevel uint16
wProcessorRevision uint16
}
const (
PROCESSOR_ARCHITECTURE_AMD64 = 9
PROCESSOR_ARCHITECTURE_INTEL = 0
)
var sysinfo systeminfo
func sysinit() {
syscall.Syscall(procGetSystemInfo.Addr(), 1, uintptr(unsafe.Pointer(&sysinfo)), 0, 0)
switch sysinfo.wProcessorArchitecture {
case PROCESSOR_ARCHITECTURE_AMD64:
gohostarch = "amd64"
case PROCESSOR_ARCHITECTURE_INTEL:
gohostarch = "386"
default:
fatal("unknown processor architecture")
}
}
This diff is collapsed.
This diff is collapsed.
// Copyright 2015 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.
#include "textflag.h"
// try to run "vmov.f64 d0, d0" instruction
TEXT ·useVFPv1(SB),NOSPLIT,$0
WORD $0xeeb00b40 // vomv.f64 d0, d0
RET
// try to run VFPv3-only "vmov.f64 d0, #112" instruction
TEXT ·useVFPv3(SB),NOSPLIT,$0
WORD $0xeeb70b00 // vmov.f64 d0, #112
RET
// Copyright 2015 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.
// +build !arm
#include "textflag.h"
TEXT ·useVFPv1(SB),NOSPLIT,$0
RET
TEXT ·useVFPv3(SB),NOSPLIT,$0
RET
This diff is collapsed.
......@@ -3,6 +3,8 @@
# Use of this source code is governed by a BSD-style
# license that can be found in the LICENSE file.
# See golang.org/s/go15bootstrap for an overview of the build process.
# Environment variables that control make.bash:
#
# GOROOT_FINAL: The expected final Go root, baked into binaries.
......@@ -110,26 +112,16 @@ rm -f ./runtime/runtime_defs.go
# Finally! Run the build.
echo '##### Building C bootstrap tool.'
echo '##### Building Go bootstrap tool.'
echo cmd/dist
export GOROOT="$(cd .. && pwd)"
GOROOT_FINAL="${GOROOT_FINAL:-$GOROOT}"
DEFGOROOT='-DGOROOT_FINAL="'"$GOROOT_FINAL"'"'
mflag=""
case "$GOHOSTARCH" in
386) mflag=-m32;;
amd64) mflag=-m64;;
esac
if [ "$(uname)" == "Darwin" ]; then
# golang.org/issue/5261
mflag="$mflag -mmacosx-version-min=10.6"
fi
# if gcc does not exist and $CC is not set, try clang if available.
if [ -z "$CC" -a -z "$(type -t gcc)" -a -n "$(type -t clang)" ]; then
export CC=clang CXX=clang++
GOROOT_BOOTSTRAP=${GOROOT_BOOTSTRAP:-$HOME/go1.4}
if [ ! -x "$GOROOT_BOOTSTRAP/bin/go" ]; then
echo "ERROR: Cannot find $GOROOT_BOOTSTRAP/bin/go." >&2
echo "Set \$GOROOT_BOOTSTRAP to a working Go tree >= Go 1.4." >&2
fi
${CC:-gcc} $mflag -O2 -Wall -Werror -o cmd/dist/dist -Icmd/dist "$DEFGOROOT" cmd/dist/*.c
rm -f cmd/dist/dist
GOROOT="$GOROOT_BOOTSTRAP" GOOS="" GOARCH="" "$GOROOT_BOOTSTRAP/bin/go" build -o cmd/dist/dist ./cmd/dist
# -e doesn't propagate out of eval, so check success by hand.
eval $(./cmd/dist/dist env -p || echo FAIL=true)
......
......@@ -45,24 +45,24 @@ goto fail
:: Clean old generated file that will cause problems in the build.
del /F ".\pkg\runtime\runtime_defs.go" 2>NUL
:: Grab default GOROOT_FINAL and set GOROOT for build.
:: The expression %VAR:\=\\% means to take %VAR%
:: and apply the substitution \ = \\, escaping the
:: backslashes. Then we wrap that in quotes to create
:: a C string.
:: Set GOROOT for build.
cd ..
set GOROOT=%CD%
cd src
if "x%GOROOT_FINAL%"=="x" set GOROOT_FINAL=%GOROOT%
set DEFGOROOT=-DGOROOT_FINAL="\"%GOROOT_FINAL:\=\\%\""
echo ##### Building C bootstrap tool.
echo ##### Building Go 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 cmd/dist/dist.exe -Icmd/dist %DEFGOROOT% cmd/dist/buf.c cmd/dist/build.c cmd/dist/buildgc.c cmd/dist/buildgo.c cmd/dist/buildruntime.c cmd/dist/main.c cmd/dist/windows.c cmd/dist/arm.c
if "x%GOROOT_BOOTSTRAP%"=="x" set GOROOT_BOOTSTRAP=%HOMEDRIVE%%HOMEPATH%\Go1.4
if not exist "%GOROOT_BOOTSTRAP%\bin\go.exe" goto bootstrapfail
setlocal
set GOROOT=%GOROOT_BOOTSTRAP%
set GOOS=
set GOARCH=
"%GOROOT_BOOTSTRAP%\bin\go" build -o cmd\dist\dist.exe .\cmd\dist
endlocal
if errorlevel 1 goto fail
.\cmd\dist\dist env -wp >env.bat
.\cmd\dist\dist env -w -p >env.bat
if errorlevel 1 goto fail
call env.bat
del env.bat
......@@ -113,6 +113,10 @@ mkdir "%GOTOOLDIR%" 2>NUL
copy cmd\dist\dist.exe "%GOTOOLDIR%\"
goto end
:bootstrapfail
echo ERROR: Cannot find %GOROOT_BOOTSTRAP%\bin\go.exe
echo "Set GOROOT_BOOTSTRAP to a working Go tree >= Go 1.4."
:fail
set GOBUILDFAIL=1
if x%GOBUILDEXIT%==x1 exit %GOBUILDFAIL%
......
......@@ -3,6 +3,8 @@
# Use of this source code is governed by a BSD-style
# license that can be found in the LICENSE file.
# See golang.org/s/go15bootstrap for an overview of the build process.
# Environment variables that control make.rc:
#
# GOROOT_FINAL: The expected final Go root, baked into binaries.
......@@ -45,17 +47,18 @@ rm -f ./runtime/runtime_defs.go
# Determine the host compiler toolchain.
eval `{grep '^(CC|LD|O)=' /$objtype/mkfile}
echo '# Building C bootstrap tool.'
echo '# Building Go bootstrap tool.'
echo cmd/dist
GOROOT = `{cd .. && pwd}
if(! ~ $#GOROOT_FINAL 1)
GOROOT_FINAL = $GOROOT
DEFGOROOT='-DGOROOT_FINAL="'$GOROOT_FINAL'"'
for(i in cmd/dist/*.c)
$CC -FTVwp+ -DPLAN9 $DEFGOROOT $i
$LD -o cmd/dist/dist *.$O
rm *.$O
if(! ~ $#GOROOT_BOOTSTRAP 1)
GOROOT_BOOTSTRAP = $home/go1.4
if(! test -x $GOROOT_BOOTSTRAP/bin/go){
echo 'ERROR: Cannot find '$GOROOT_BOOTSTRAP'/bin/go.' >[1=2]
echo 'Set $GOROOT_BOOTSTRAP to a working Go tree >= Go 1.4.' >[1=2]
exit bootstrap
}
rm -f cmd/dist/dist
GOROOT=$GOROOT_BOOTSTRAP GOOS='' GOARCH='' $GOROOT_BOOTSTRAP/bin/go build -o cmd/dist/dist ./cmd/dist
eval `{./cmd/dist/dist env -9}
echo
......
#!/usr/bin/env bash
# Copyright 2009 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.
set -e
case "`uname`" in
Darwin)
;;
*)
exit 0
esac
# Check that the go command exists
if ! go help >/dev/null 2>&1; then
echo "The go command is not in your PATH." >&2
exit 2
fi
eval $(go env)
if ! [ -x $GOTOOLDIR/prof ]; then
echo "You don't need to run sudo.bash." >&2
exit 2
fi
if [[ ! -d /usr/local/bin ]]; then
echo 1>&2 'sudo.bash: problem with /usr/local/bin; cannot install tools.'
exit 2
fi
cd $(dirname $0)
for i in prof
do
# Remove old binaries if present
sudo rm -f /usr/local/bin/6$i
# Install new binaries
sudo cp $GOTOOLDIR/$i /usr/local/bin/go$i
sudo chgrp procmod /usr/local/bin/go$i
sudo chmod g+s /usr/local/bin/go$i
done
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