Commit 91395ae6 authored by Russ Cox's avatar Russ Cox

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
parent 705f9af3
...@@ -58,6 +58,7 @@ ...@@ -58,6 +58,7 @@
typedef struct Arsymref typedef struct Arsymref
{ {
char *name; char *name;
char *file;
int type; int type;
int len; int len;
vlong offset; vlong offset;
...@@ -87,6 +88,7 @@ typedef struct Arfile /* Temp file control block - one per tempfile */ ...@@ -87,6 +88,7 @@ typedef struct Arfile /* Temp file control block - one per tempfile */
typedef struct Hashchain typedef struct Hashchain
{ {
char *name; char *name;
char *file;
struct Hashchain *next; struct Hashchain *next;
} Hashchain; } Hashchain;
...@@ -148,7 +150,7 @@ void arread(Biobuf*, Armember*, int); ...@@ -148,7 +150,7 @@ void arread(Biobuf*, Armember*, int);
void arstream(int, Arfile*); void arstream(int, Arfile*);
int arwrite(int, Armember*); int arwrite(int, Armember*);
int bamatch(char*, char*); int bamatch(char*, char*);
int duplicate(char*); int duplicate(char*, char**);
Armember *getdir(Biobuf*); Armember *getdir(Biobuf*);
void getpkgdef(char**, int*); void getpkgdef(char**, int*);
int getspace(void); int getspace(void);
...@@ -743,6 +745,7 @@ objsym(Sym *s, void *p) ...@@ -743,6 +745,7 @@ objsym(Sym *s, void *p)
int n; int n;
Arsymref *as; Arsymref *as;
Arfile *ap; Arfile *ap;
char *ofile;
if (s->type != 'T' && s->type != 'D') if (s->type != 'T' && s->type != 'D')
return; return;
...@@ -750,9 +753,10 @@ objsym(Sym *s, void *p) ...@@ -750,9 +753,10 @@ objsym(Sym *s, void *p)
as = armalloc(sizeof(Arsymref)); as = armalloc(sizeof(Arsymref));
as->offset = ap->size; as->offset = ap->size;
as->name = arstrdup(s->name); 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; 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->name);
free(as); free(as);
return; return;
...@@ -783,7 +787,7 @@ hashstr(char *name) ...@@ -783,7 +787,7 @@ hashstr(char *name)
} }
int int
duplicate(char *name) duplicate(char *name, char **ofile)
{ {
Hashchain *p; Hashchain *p;
int h; int h;
...@@ -791,12 +795,16 @@ duplicate(char *name) ...@@ -791,12 +795,16 @@ duplicate(char *name)
h = hashstr(name) % NHASH; h = hashstr(name) % NHASH;
for(p = hash[h]; p; p = p->next) 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; return 1;
}
p = armalloc(sizeof(Hashchain)); p = armalloc(sizeof(Hashchain));
p->next = hash[h]; p->next = hash[h];
p->name = name; p->name = name;
p->file = file;
hash[h] = p; hash[h] = p;
*ofile = nil;
return 0; return 0;
} }
...@@ -893,7 +901,7 @@ getdir(Biobuf *b) ...@@ -893,7 +901,7 @@ getdir(Biobuf *b)
while(*--cp==' ') while(*--cp==' ')
; ;
cp[1] = '\0'; cp[1] = '\0';
file = name; file = arstrdup(name);
bp->date = strtol(bp->hdr.date, 0, 0); bp->date = strtol(bp->hdr.date, 0, 0);
bp->size = strtol(bp->hdr.size, 0, 0); bp->size = strtol(bp->hdr.size, 0, 0);
return bp; return bp;
...@@ -1487,7 +1495,6 @@ loadpkgdata(char *data, int len) ...@@ -1487,7 +1495,6 @@ loadpkgdata(char *data, int len)
char *p, *ep, *prefix, *name, *def; char *p, *ep, *prefix, *name, *def;
Import *x; Import *x;
file = arstrdup(file);
p = data; p = data;
ep = data + len; ep = data + len;
while(parsepkgdata(&p, ep, &export, &prefix, &name, &def) > 0) { while(parsepkgdata(&p, ep, &export, &prefix, &name, &def) > 0) {
......
...@@ -14,6 +14,8 @@ import ( ...@@ -14,6 +14,8 @@ import (
"sort"; "sort";
"strings"; "strings";
"template"; "template";
"unicode";
"utf8";
) )
type Pkg struct type Pkg struct
...@@ -148,9 +150,16 @@ func ScanFiles(filenames []string) *Info { ...@@ -148,9 +150,16 @@ func ScanFiles(filenames []string) *Info {
f := new(File); f := new(File);
f.Name = filename; f.Name = filename;
if path.Ext(filename) == ".go" { 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); pkgname, imp, err := PackageImports(filename);
if err != nil { if err != nil {
fatal("parsing", filename, err.String()); fatal("parsing %s: %s", filename, err);
} }
if pkgname == "main" { if pkgname == "main" {
continue; continue;
...@@ -182,7 +191,7 @@ func ScanFiles(filenames []string) *Info { ...@@ -182,7 +191,7 @@ func ScanFiles(filenames []string) *Info {
// non-Go file: fill in package name. // non-Go file: fill in package name.
// Must only be a single package in this directory. // Must only be a single package in this directory.
if len(z.Pkgmap) != 1 { if len(z.Pkgmap) != 1 {
fatal("cannot determine package for ", f.Name); fatal("cannot determine package for %s", f.Name);
} }
f.Pkg = pkg; f.Pkg = pkg;
} }
...@@ -240,7 +249,7 @@ func (z *Info) Build() { ...@@ -240,7 +249,7 @@ func (z *Info) Build() {
fail = fail[0:0]; fail = fail[0:0];
success = success[0:0]; success = success[0:0];
for _, f := range pending { for _, f := range pending {
if !Build(Compiler(f.Name), f.Name, false) { if !Build(Compiler(f.Name), f.Name, 0) {
PushFile(&fail, f); PushFile(&fail, f);
} else { } else {
if *verbose { if *verbose {
...@@ -252,7 +261,7 @@ func (z *Info) Build() { ...@@ -252,7 +261,7 @@ func (z *Info) Build() {
if len(success) == 0 { if len(success) == 0 {
// Nothing ran; give up. // Nothing ran; give up.
for _, f := range fail { for _, f := range fail {
Build(Compiler(f.Name), f.Name, true); Build(Compiler(f.Name), f.Name, ShowErrors | ForceDisplay);
} }
fatal("stalemate"); fatal("stalemate");
} }
...@@ -310,7 +319,7 @@ func Main() { ...@@ -310,7 +319,7 @@ func Main() {
var err os.Error; var err os.Error;
filenames, err= SourceFiles("."); filenames, err= SourceFiles(".");
if err != nil { if err != nil {
fatal("reading .: ", err.String()); fatal("reading .: %s", err.String());
} }
} }
...@@ -319,11 +328,11 @@ func Main() { ...@@ -319,11 +328,11 @@ func Main() {
if *writeMakefile { if *writeMakefile {
t, err := template.Parse(makefileTemplate, makefileMap); t, err := template.Parse(makefileTemplate, makefileMap);
if err != nil { if err != nil {
fatal("template.Parse: ", err.String()); fatal("template.Parse: %s", err.String());
} }
err = t.Execute(state, os.Stdout); err = t.Execute(state, os.Stdout);
if err != nil { if err != nil {
fatal("template.Expand: ", err.String()); fatal("template.Expand: %s", err.String());
} }
} }
} }
......
...@@ -6,8 +6,10 @@ ...@@ -6,8 +6,10 @@
package gobuild package gobuild
import ( import (
"bufio";
"exec"; "exec";
"fmt"; "fmt";
"io";
"go/ast"; "go/ast";
"go/parser"; "go/parser";
"os"; "os";
...@@ -17,6 +19,11 @@ import ( ...@@ -17,6 +19,11 @@ import (
"strings"; "strings";
) )
const (
ShowErrors = 1<<iota;
ForceDisplay;
)
var ( var (
theChar string; theChar string;
goarch string; goarch string;
...@@ -32,8 +39,8 @@ var theChars = map[string] string { ...@@ -32,8 +39,8 @@ var theChars = map[string] string {
const ObjDir = "_obj" const ObjDir = "_obj"
func fatal(args ...) { func fatal(format string, args ...) {
fmt.Fprintf(os.Stderr, "gobuild: %s\n", fmt.Sprint(args)); fmt.Fprintf(os.Stderr, "gobuild: %s\n", fmt.Sprintf(format, args));
os.Exit(1); os.Exit(1);
} }
...@@ -45,7 +52,7 @@ func init() { ...@@ -45,7 +52,7 @@ func init() {
var ok bool; var ok bool;
theChar, ok = theChars[goarch]; theChar, ok = theChars[goarch];
if !ok { if !ok {
fatal("unknown $GOARCH: ", goarch); fatal("unknown $GOARCH: %s", goarch);
} }
var binaries = []string{ var binaries = []string{
...@@ -58,7 +65,7 @@ func init() { ...@@ -58,7 +65,7 @@ func init() {
for i, v := range binaries { for i, v := range binaries {
var s string; var s string;
if s, err = exec.LookPath(v); err != nil { if s, err = exec.LookPath(v); err != nil {
fatal("cannot find binary ", v); fatal("cannot find binary %s", v);
} }
bin[v] = s; bin[v] = s;
} }
...@@ -79,38 +86,55 @@ func PushString(v *[]string, p string) { ...@@ -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]]; argv0 := bin[argv[0]];
output := exec.DevNull; null, err := os.Open("/dev/null", os.O_RDWR, 0);
if display { if err != nil {
output = exec.PassThrough; fatal("open /dev/null: %s", err);
} }
p, err1 := exec.Run(argv0, argv, os.Environ(), exec.DevNull, output, output); defer null.Close();
if err1 != nil { r, w, err := os.Pipe();
return false; if err != nil {
fatal("pipe: %s", err);
} }
w, err2 := p.Wait(0); pid, err := os.ForkExec(argv0, argv, os.Environ(), "", []*os.File{null, w, w});
if err2 != nil { defer r.Close();
w.Close();
if err != nil {
return false; return false;
} }
return w.Exited() && w.ExitStatus() == 0;
}
func Build(cmd []string, file string, display bool) (ok bool) { // Read the first line of output, if any. Discard the rest.
if display { // 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, "$ "); fmt.Fprint(os.Stderr, "$ ");
for i, s := range cmd { for i, s := range argv {
fmt.Fprint(os.Stderr, s, " "); 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; var argv []string;
for i, c := range cmd { for i, c := range cmd {
PushString(&argv, c); PushString(&argv, c);
} }
PushString(&argv, file); PushString(&argv, file);
return run(argv, display); return run(argv, flag);
} }
func Archive(pkg string, files []string) { func Archive(pkg string, files []string) {
...@@ -118,7 +142,7 @@ func Archive(pkg string, files []string) { ...@@ -118,7 +142,7 @@ func Archive(pkg string, files []string) {
for i, file := range files { for i, file := range files {
PushString(&argv, file); PushString(&argv, file);
} }
if !run(argv, true) { if !run(argv, ShowErrors) {
fatal("archive failed"); fatal("archive failed");
} }
} }
...@@ -132,7 +156,7 @@ func Compiler(file string) []string { ...@@ -132,7 +156,7 @@ func Compiler(file string) []string {
case strings.HasSuffix(file, ".s"): case strings.HasSuffix(file, ".s"):
return []string{ theChar + "a" }; return []string{ theChar + "a" };
} }
fatal("don't know how to compile ", file); fatal("don't know how to compile %s", file);
return nil; return nil;
} }
......
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