1
0
mirror of https://github.com/golang/go synced 2024-11-18 08:14:41 -07:00

make gobuild failures more readable.

1. ar reports names of objects with duplicate text symbols.
2. gobuild only shows first line of error output for each failed command.
3. gobuild ignores files that begin with ascii non-alphanumeric non _.

; gobuild
$ 6g -I _obj gobuild.go
  gobuild.go:150: PackageImports: undefined
$ 6g -I _obj makefile.go
  makefile.go:102: ShellString: undefined
$ 6g -I _obj util.go
  util.go:114: syntax error near zzz
gobuild: stalemate
;

; gobuild
$ 6ar grc _obj/gobuild.a util.6 util1.6
  duplicate text symbol: util1.6 and util.6: gobuild·Build
$ 6g -I _obj gobuild.go
  gobuild.go:150: PackageImports: undefined
$ 6g -I _obj makefile.go
  makefile.go:102: ShellString: undefined
gobuild: stalemate
;

R=r
DELTA=95  (49 added, 9 deleted, 37 changed)
OCL=29625
CL=29640
This commit is contained in:
Russ Cox 2009-05-29 18:12:04 -07:00
parent 705f9af38e
commit 91395ae689
3 changed files with 77 additions and 37 deletions

View File

@ -58,6 +58,7 @@
typedef struct Arsymref
{
char *name;
char *file;
int type;
int len;
vlong offset;
@ -87,6 +88,7 @@ typedef struct Arfile /* Temp file control block - one per tempfile */
typedef struct Hashchain
{
char *name;
char *file;
struct Hashchain *next;
} Hashchain;
@ -148,7 +150,7 @@ void arread(Biobuf*, Armember*, int);
void arstream(int, Arfile*);
int arwrite(int, Armember*);
int bamatch(char*, char*);
int duplicate(char*);
int duplicate(char*, char**);
Armember *getdir(Biobuf*);
void getpkgdef(char**, int*);
int getspace(void);
@ -743,6 +745,7 @@ objsym(Sym *s, void *p)
int n;
Arsymref *as;
Arfile *ap;
char *ofile;
if (s->type != 'T' && s->type != 'D')
return;
@ -750,9 +753,10 @@ objsym(Sym *s, void *p)
as = armalloc(sizeof(Arsymref));
as->offset = ap->size;
as->name = arstrdup(s->name);
if(s->type == 'T' && duplicate(as->name)) {
as->file = arstrdup(file);
if(s->type == 'T' && duplicate(as->name, &ofile)) {
dupfound = 1;
fprint(2, "duplicate text symbol: %s\n", as->name);
fprint(2, "duplicate text symbol: %s and %s: %s\n", as->file, ofile, as->name);
free(as->name);
free(as);
return;
@ -783,7 +787,7 @@ hashstr(char *name)
}
int
duplicate(char *name)
duplicate(char *name, char **ofile)
{
Hashchain *p;
int h;
@ -791,12 +795,16 @@ duplicate(char *name)
h = hashstr(name) % NHASH;
for(p = hash[h]; p; p = p->next)
if(strcmp(p->name, name) == 0)
if(strcmp(p->name, name) == 0) {
*ofile = p->file;
return 1;
}
p = armalloc(sizeof(Hashchain));
p->next = hash[h];
p->name = name;
p->file = file;
hash[h] = p;
*ofile = nil;
return 0;
}
@ -893,7 +901,7 @@ getdir(Biobuf *b)
while(*--cp==' ')
;
cp[1] = '\0';
file = name;
file = arstrdup(name);
bp->date = strtol(bp->hdr.date, 0, 0);
bp->size = strtol(bp->hdr.size, 0, 0);
return bp;
@ -1487,7 +1495,6 @@ loadpkgdata(char *data, int len)
char *p, *ep, *prefix, *name, *def;
Import *x;
file = arstrdup(file);
p = data;
ep = data + len;
while(parsepkgdata(&p, ep, &export, &prefix, &name, &def) > 0) {

View File

@ -14,6 +14,8 @@ import (
"sort";
"strings";
"template";
"unicode";
"utf8";
)
type Pkg struct
@ -148,9 +150,16 @@ func ScanFiles(filenames []string) *Info {
f := new(File);
f.Name = filename;
if path.Ext(filename) == ".go" {
rune, _ := utf8.DecodeRuneInString(filename);
if rune != '_' && !unicode.IsLetter(rune) && !unicode.IsDecimalDigit(rune) {
// Ignore files with funny leading letters,
// to avoid editor files like .foo.go and ~foo.go.
continue;
}
pkgname, imp, err := PackageImports(filename);
if err != nil {
fatal("parsing", filename, err.String());
fatal("parsing %s: %s", filename, err);
}
if pkgname == "main" {
continue;
@ -182,7 +191,7 @@ func ScanFiles(filenames []string) *Info {
// non-Go file: fill in package name.
// Must only be a single package in this directory.
if len(z.Pkgmap) != 1 {
fatal("cannot determine package for ", f.Name);
fatal("cannot determine package for %s", f.Name);
}
f.Pkg = pkg;
}
@ -240,7 +249,7 @@ func (z *Info) Build() {
fail = fail[0:0];
success = success[0:0];
for _, f := range pending {
if !Build(Compiler(f.Name), f.Name, false) {
if !Build(Compiler(f.Name), f.Name, 0) {
PushFile(&fail, f);
} else {
if *verbose {
@ -252,7 +261,7 @@ func (z *Info) Build() {
if len(success) == 0 {
// Nothing ran; give up.
for _, f := range fail {
Build(Compiler(f.Name), f.Name, true);
Build(Compiler(f.Name), f.Name, ShowErrors | ForceDisplay);
}
fatal("stalemate");
}
@ -310,7 +319,7 @@ func Main() {
var err os.Error;
filenames, err= SourceFiles(".");
if err != nil {
fatal("reading .: ", err.String());
fatal("reading .: %s", err.String());
}
}
@ -319,11 +328,11 @@ func Main() {
if *writeMakefile {
t, err := template.Parse(makefileTemplate, makefileMap);
if err != nil {
fatal("template.Parse: ", err.String());
fatal("template.Parse: %s", err.String());
}
err = t.Execute(state, os.Stdout);
if err != nil {
fatal("template.Expand: ", err.String());
fatal("template.Expand: %s", err.String());
}
}
}

View File

@ -6,8 +6,10 @@
package gobuild
import (
"bufio";
"exec";
"fmt";
"io";
"go/ast";
"go/parser";
"os";
@ -17,6 +19,11 @@ import (
"strings";
)
const (
ShowErrors = 1<<iota;
ForceDisplay;
)
var (
theChar string;
goarch string;
@ -32,8 +39,8 @@ var theChars = map[string] string {
const ObjDir = "_obj"
func fatal(args ...) {
fmt.Fprintf(os.Stderr, "gobuild: %s\n", fmt.Sprint(args));
func fatal(format string, args ...) {
fmt.Fprintf(os.Stderr, "gobuild: %s\n", fmt.Sprintf(format, args));
os.Exit(1);
}
@ -45,7 +52,7 @@ func init() {
var ok bool;
theChar, ok = theChars[goarch];
if !ok {
fatal("unknown $GOARCH: ", goarch);
fatal("unknown $GOARCH: %s", goarch);
}
var binaries = []string{
@ -58,7 +65,7 @@ func init() {
for i, v := range binaries {
var s string;
if s, err = exec.LookPath(v); err != nil {
fatal("cannot find binary ", v);
fatal("cannot find binary %s", v);
}
bin[v] = s;
}
@ -79,38 +86,55 @@ func PushString(v *[]string, p string) {
}
func run(argv []string, display bool) (ok bool) {
func run(argv []string, flag int) (ok bool) {
argv0 := bin[argv[0]];
output := exec.DevNull;
if display {
output = exec.PassThrough;
null, err := os.Open("/dev/null", os.O_RDWR, 0);
if err != nil {
fatal("open /dev/null: %s", err);
}
p, err1 := exec.Run(argv0, argv, os.Environ(), exec.DevNull, output, output);
if err1 != nil {
defer null.Close();
r, w, err := os.Pipe();
if err != nil {
fatal("pipe: %s", err);
}
pid, err := os.ForkExec(argv0, argv, os.Environ(), "", []*os.File{null, w, w});
defer r.Close();
w.Close();
if err != nil {
return false;
}
w, err2 := p.Wait(0);
if err2 != nil {
return false;
}
return w.Exited() && w.ExitStatus() == 0;
}
func Build(cmd []string, file string, display bool) (ok bool) {
if display {
// Read the first line of output, if any. Discard the rest.
// If there is output and ShowErrors is set, show it,
// preceded by a shell command line.
// If ForceDisplay is set, we show the command even
// if there's no output; this gets set if we're just trying
// to keep the user informed.
b := bufio.NewReader(r);
line, err := b.ReadLineString('\n', true);
if flag & ShowErrors != 0 && line != "" || flag & ForceDisplay != 0 {
fmt.Fprint(os.Stderr, "$ ");
for i, s := range cmd {
for i, s := range argv {
fmt.Fprint(os.Stderr, s, " ");
}
fmt.Fprint(os.Stderr, file, "\n");
fmt.Fprint(os.Stderr, "\n");
fmt.Fprint(os.Stderr, " ", line);
io.Copy(r, null); // don't let process block on pipe
}
waitmsg, err := os.Wait(pid, 0);
if err != nil {
return false;
}
return waitmsg.Exited() && waitmsg.ExitStatus() == 0;
}
func Build(cmd []string, file string, flag int) (ok bool) {
var argv []string;
for i, c := range cmd {
PushString(&argv, c);
}
PushString(&argv, file);
return run(argv, display);
return run(argv, flag);
}
func Archive(pkg string, files []string) {
@ -118,7 +142,7 @@ func Archive(pkg string, files []string) {
for i, file := range files {
PushString(&argv, file);
}
if !run(argv, true) {
if !run(argv, ShowErrors) {
fatal("archive failed");
}
}
@ -132,7 +156,7 @@ func Compiler(file string) []string {
case strings.HasSuffix(file, ".s"):
return []string{ theChar + "a" };
}
fatal("don't know how to compile ", file);
fatal("don't know how to compile %s", file);
return nil;
}