From 72e3b204e4f535a40f8465b8fc2434330496885e Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Fri, 19 Sep 2008 11:55:46 -0700 Subject: [PATCH] add gobuild. use gobuild-generated Makefile for math and os. other makefile tweaks. move math/main.go to test/math.go R=r OCL=15529 CL=15537 --- src/clean.bash | 17 +- src/cmd/gobuild/Makefile | 20 ++ src/cmd/gobuild/gobuild.c | 340 +++++++++++++++++++++++++++ src/lib/clean.bash | 2 +- src/lib/make.bash | 2 - src/lib/math/Makefile | 89 ++++--- src/lib/math/clean.bash | 7 - src/lib/math/make.bash | 11 - src/lib/math/math.go | 48 ---- src/lib/os/Makefile | 46 ++-- src/libbio/Makefile | 2 + src/libmach_amd64/Makefile | 6 +- src/make.bash | 31 +-- src/runtime/clean.bash | 11 - src/runtime/make.bash | 9 - src/lib/math/main.go => test/math.go | 6 +- 16 files changed, 471 insertions(+), 176 deletions(-) create mode 100644 src/cmd/gobuild/Makefile create mode 100644 src/cmd/gobuild/gobuild.c delete mode 100644 src/lib/math/clean.bash delete mode 100644 src/lib/math/make.bash delete mode 100644 src/lib/math/math.go delete mode 100644 src/runtime/clean.bash delete mode 100644 src/runtime/make.bash rename src/lib/math/main.go => test/math.go (98%) diff --git a/src/clean.bash b/src/clean.bash index cba2129cfa7..36b0c99fb5f 100755 --- a/src/clean.bash +++ b/src/clean.bash @@ -3,16 +3,15 @@ # Use of this source code is governed by a BSD-style # license that can be found in the LICENSE file. -for i in lib9 libbio libmach_amd64 libregexp syscall +for i in lib9 libbio libmach_amd64 libregexp syscall cmd runtime lib do cd $i - make clean - cd .. -done - -for i in cmd runtime lib -do - cd $i - bash clean.bash + case $i in + cmd | lib) + bash clean.bash + ;; + *) + make clean + esac cd .. done diff --git a/src/cmd/gobuild/Makefile b/src/cmd/gobuild/Makefile new file mode 100644 index 00000000000..3393990336c --- /dev/null +++ b/src/cmd/gobuild/Makefile @@ -0,0 +1,20 @@ +# 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. + +include ../../Make.conf + +TARG=gobuild +OFILES=\ + gobuild.$O\ + +$(TARG): $(OFILES) + $(LD) -o $(TARG) -L$(GOROOT)/lib $(OFILES) -lbio -l9 + +clean: + rm -f $(OFILES) $(TARG) + +install: $(TARG) + cp $(TARG) $(BIN)/$(TARG) + +$(OFILES): $(HFILES) diff --git a/src/cmd/gobuild/gobuild.c b/src/cmd/gobuild/gobuild.c new file mode 100644 index 00000000000..0fdf68e19bf --- /dev/null +++ b/src/cmd/gobuild/gobuild.c @@ -0,0 +1,340 @@ +// 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. + +// Build a collection of go programs into a single package. + +#include +#include +#include +#include + +void +usage(void) +{ + fprint(2, "usage: gobuild [-m] packagename *.go *.c *.s\n"); + exits("usage"); +} + +int chatty; +int devnull; // fd of /dev/null +int makefile; // generate Makefile +char *thechar; // object character + +// Info about when to compile a particular file. +typedef struct Job Job; +struct Job +{ + char *name; + int pass; +}; + +// Run the command in argv. +// Return -1 if it fails (non-zero exit status). +// Return 0 on success. +// Showoutput controls whether to let output from command display +// on standard output and standard error. +int +run(char **argv, int showoutput) +{ + int pid, i; + Waitmsg *w; + vlong n0, n1; + + n0 = nsec(); + pid = fork(); + if(pid < 0) + sysfatal("fork: %r"); + if(pid == 0){ + dup(devnull, 0); + if(!showoutput){ + dup(devnull, 1); + dup(devnull, 2); + } + if(devnull > 2) + close(devnull); + exec(argv[0], argv); + fprint(2, "exec %s: %r\n", argv[0]); + exit(1); + } + w = waitfor(pid); + n1 = nsec(); + if(w == nil) + sysfatal("waitfor %d: %r", pid); + if(chatty > 1){ + fprint(2, "%5.3f", (n1-n0)/1.e9); + for(i=0; argv[i]; i++) + fprint(2, " %s", argv[i]); + if(w->msg[0]) + fprint(2, " [%s]", w->msg); + fprint(2, "\n"); + } + if(w->msg[0]) + return -1; + return 0; +} + +// Build the file using the compiler cc. +// Return -1 on error, 0 on success. +// If show is set, print the command and the output. +int +buildcc(char *cc, char *file, int show) +{ + char *argv[3]; + + if(show) + fprint(2, "$ %s %s\n", cc, file); + argv[0] = cc; + argv[1] = file; + argv[2] = nil; + return run(argv, show); +} + +// Return bool whether s ends in suffix. +int +suffix(char *s, char *suffix) +{ + int n1, n2; + + n1 = strlen(s); + n2 = strlen(suffix); + if(n1>n2 && strcmp(s+n1-n2, suffix) == 0) + return 1; + return 0; +} + +// Return the name of the compiler for file. +char* +compiler(char *file) +{ + static char buf[20]; + + if(suffix(file, ".go")) + snprint(buf, sizeof buf, "%sg", thechar); + else if(suffix(file, ".c")) + snprint(buf, sizeof buf, "%sc", thechar); + else if(suffix(file, ".s")) + snprint(buf, sizeof buf, "%sa", thechar); + else + sysfatal("don't know how to build %s", file); + return buf; +} + +// Return the object name for file, replacing the +// .c or .g or .a with .suffix. +char* +goobj(char *file, char *suffix) +{ + char *p; + + p = strrchr(file, '.'); + if(p == nil) + sysfatal("don't know object name for %s", file); + return smprint("%.*s.%s", utfnlen(file, p-file), file, suffix); +} + +// Makefile preamble template. +char preamble[] = + "O=%s\n" + "GC=$(O)g\n" + "CC=$(O)c -w\n" + "AS=$(O)a\n" + "AR=$(O)ar\n" + "\n" + "PKG=$(GOROOT)/pkg/%s.a\n" + "\n" + "install: $(PKG)\n" + "\n" + "nuke: clean\n" + "\trm -f $(PKG)\n" + "\n" + "clean:\n" + "\trm -f *.$O *.a\n" + "\n" + "%%.$O: %%.go\n" + "\t$(GC) $*.go\n" + "\n" + "%%.$O: %%.c\n" + "\t$(CC) $*.c\n" + "\n" + "%%.$O: %%.s\n" + "\t$(AS) $*.s\n" + "\n" +; + +void +main(int argc, char **argv) +{ + int i, o, p, n, pass, nar, njob, nthis, nnext, oargc; + char **ar, **next, **this, **tmp, *goarch, *goroot, *pkgname, *pkgpath, **oargv; + Job *job; + Biobuf bout; + + oargc = argc; + oargv = argv; + + ARGBEGIN{ + default: + usage(); + case 'm': + makefile = 1; + break; + case 'v': + chatty++; + break; + }ARGEND + + if(argc < 2) + usage(); + + goarch = getenv("GOARCH"); + if(goarch == nil) + sysfatal("no $GOARCH"); + if(strcmp(goarch, "amd64") == 0) + thechar = "6"; + else + sysfatal("unknown $GOARCH"); + + goroot = getenv("GOROOT"); + if(goroot == nil) + sysfatal("no $GOROOT"); + + pkgname = argv[0]; + if(strchr(pkgname, '.')){ + fprint(2, "pkgname has dot\n"); + usage(); + } + + pkgpath = smprint("%s/pkg/%s.a", goroot, pkgname); + unlink(pkgpath); + if(chatty) + fprint(2, "pkg %s\n", pkgpath); + + if((devnull = open("/dev/null", ORDWR)) < 0) + sysfatal("open /dev/null: %r"); + + // Compile by repeated passes: build as many .6 as you can, + // put them all in the archive, and repeat. + // + // "this" contains the list of files to compile in this pass. + // "next" contains the list of files to re-try in the next pass. + // "job" contains the list of files that are done, annotated + // with their pass numbers. + // "ar" contains the ar command line to run at the end + // of the pass. + + n = argc-1; + this = malloc(n*sizeof this[0]); + next = malloc(n*sizeof next[0]); + job = malloc(n*sizeof job[0]); + ar = malloc((n+4)*sizeof job[0]); + if(this == nil || next == nil || job == 0 || ar == 0) + sysfatal("malloc: %r"); + + // Initial "this" is the files given on the command line. + for(i=0; i 0; pass++){ + nnext = 0; + nar = 3; + + // Try to build. + for(i=0; i 60){ + Bprint(&bout, "\\\n# "); + o = Boffset(&bout); + } + Bprint(&bout, " %s", oargv[i]); + } + Bprint(&bout, "\n"); + Bprint(&bout, preamble, thechar, pkgname); + + // O2=\ + // os_file.$O\ + // os_time.$O\ + // + p = -1; + for(i=0; i e { - panic a, " ", b, "\n"; + panic(a, " ", b, "\n"); } }