Commit 0f153ec6 authored by Russ Cox's avatar Russ Cox

build packages in obj/ subdirectory that mimics $GOROOT/pkg.

for example, if building in src/lib/container,
objects go in obj/container/, so that 6g -Iobj
will find "container/vector".

install packages in hierarchy in $GOROOT.

this change only updates gobuild.
another change will have to update all
the sources to refer to "container/vector" etc
and regenerate all the Makefiles.

there are some pretty lame functions here
(e.g., Mkdir, Remove, the Getenv("PWD"))
but i will implement better ones in another CL.

R=r
DELTA=117  (99 added, 2 deleted, 16 changed)
OCL=27550
CL=27574
parent 3761da2d
...@@ -46,14 +46,29 @@ $(O1): newpkg ...@@ -46,14 +46,29 @@ $(O1): newpkg
$(O2): a1 $(O2): a1
$(O3): a2 $(O3): a2
gobuild: main.$O gobuild.a # zzgobuild is a fake target that will always run, even if
# "gobuild" existed at the beginning of the make.
# The problem is that if you "make install" and install
# depends on gobuild and this rule says gobuild,
# and gobuild.a depends on phases, "phases" gets
# run, which cleans everything and then rebuilds
# gobuild.a. So now make thinks gobuild was up to date
# to begin with (and it ran "phases" just for good measure)
# but in fact gobuild is gone ("phases" removed it).
#
# Calling the target zzgobuild instead means that
# make will always run this rule, rebuilding gobuild
# before trying to install it. Sigh.
zzgobuild: main.$O gobuild.a
$(LD) -o gobuild main.$O $(LD) -o gobuild main.$O
main.$O: gobuild.a gobuild: zzgobuild
main.$O: phases
nuke: clean nuke: clean
rm -f $(HOME)/bin/gobuild rm -f $(HOME)/bin/gobuild
install: gobuild install: zzgobuild
cp gobuild $(HOME)/bin/gobuild cp gobuild $(HOME)/bin/gobuild
...@@ -45,6 +45,8 @@ type Phase struct { ...@@ -45,6 +45,8 @@ type Phase struct {
type Info struct { type Info struct {
Args []string; Args []string;
Char string; Char string;
Dir string;
ObjDir string;
Pkgmap map[string] *Pkg; Pkgmap map[string] *Pkg;
Packages []*Pkg; Packages []*Pkg;
Files map[string] *File; Files map[string] *File;
...@@ -99,6 +101,30 @@ func (a FileArray) Swap(i, j int) { ...@@ -99,6 +101,30 @@ func (a FileArray) Swap(i, j int) {
a[i], a[j] = a[j], a[i] a[i], a[j] = a[j], a[i]
} }
// If current directory is under $GOROOT/src/lib, return the
// path relative to there. Otherwise return "".
func PkgDir() string {
goroot, err := os.Getenv("GOROOT");
if err != nil || goroot == "" {
return ""
}
srcroot := path.Clean(goroot + "/src/lib/");
pwd, err1 := os.Getenv("PWD"); // TODO(rsc): real pwd
if err1 != nil || pwd == "" {
return ""
}
if pwd == srcroot {
return ""
}
n := len(srcroot);
if len(pwd) < n || pwd[n] != '/' || pwd[0:n] != srcroot {
return ""
}
dir := pwd[n+1:len(pwd)];
return dir;
}
func ScanFiles(filenames []string) *Info { func ScanFiles(filenames []string) *Info {
// Build list of imports, local packages, and files. // Build list of imports, local packages, and files.
// Exclude *_test.go and anything in package main. // Exclude *_test.go and anything in package main.
...@@ -106,7 +132,9 @@ func ScanFiles(filenames []string) *Info { ...@@ -106,7 +132,9 @@ func ScanFiles(filenames []string) *Info {
z := new(Info); z := new(Info);
z.Args = sys.Args; z.Args = sys.Args;
z.Char = theChar; z.Dir = PkgDir();
z.Char = theChar; // for template
z.ObjDir = ObjDir; // for template
z.Pkgmap = make(map[string] *Pkg); z.Pkgmap = make(map[string] *Pkg);
z.Files = make(map[string] *File); z.Files = make(map[string] *File);
z.Imports = make(map[string] bool); z.Imports = make(map[string] bool);
...@@ -114,7 +142,7 @@ func ScanFiles(filenames []string) *Info { ...@@ -114,7 +142,7 @@ func ScanFiles(filenames []string) *Info {
// Read Go files to find out packages and imports. // Read Go files to find out packages and imports.
var pkg *Pkg; var pkg *Pkg;
for _, filename := range filenames { for _, filename := range filenames {
if strings.HasSuffix(filename, "_test.go") { if strings.Index(filename, "_test.") >= 0 {
continue; continue;
} }
f := new(File); f := new(File);
...@@ -168,6 +196,14 @@ func ScanFiles(filenames []string) *Info { ...@@ -168,6 +196,14 @@ func ScanFiles(filenames []string) *Info {
} }
} }
// Update destination directory.
// If destination directory has same
// name as package name, cut it off.
dir, name := path.Split(z.Dir);
if len(z.Packages) == 1 && z.Packages[0].Name == name {
z.Dir = dir;
}
return z; return z;
} }
...@@ -176,9 +212,14 @@ func PackageObj(pkg string) string { ...@@ -176,9 +212,14 @@ func PackageObj(pkg string) string {
} }
func (z *Info) Build() { func (z *Info) Build() {
// Create empty object directory tree.
RemoveAll(ObjDir);
obj := path.Join(ObjDir, z.Dir) + "/";
MkdirAll(obj);
// Create empty archives. // Create empty archives.
for pkgname := range z.Pkgmap { for pkgname := range z.Pkgmap {
ar := PackageObj(pkgname); ar := obj + PackageObj(pkgname);
os.Remove(ar); os.Remove(ar);
Archive(ar, nil); Archive(ar, nil);
} }
...@@ -239,7 +280,7 @@ func (z *Info) Build() { ...@@ -239,7 +280,7 @@ func (z *Info) Build() {
f.Phase = phase; f.Phase = phase;
} }
if len(arfiles) > 0 { if len(arfiles) > 0 {
Archive(pkg.Name + ".a", arfiles); Archive(obj + pkg.Name + ".a", arfiles);
n := len(p.ArCmds); n := len(p.ArCmds);
p.ArCmds = p.ArCmds[0:n+1]; p.ArCmds = p.ArCmds[0:n+1];
...@@ -255,6 +296,7 @@ func (z *Info) Build() { ...@@ -255,6 +296,7 @@ func (z *Info) Build() {
} }
func (z *Info) Clean() { func (z *Info) Clean() {
RemoveAll(ObjDir);
for pkgname := range z.Pkgmap { for pkgname := range z.Pkgmap {
os.Remove(PackageObj(pkgname)); os.Remove(PackageObj(pkgname));
} }
......
...@@ -16,13 +16,15 @@ var makefileTemplate = ...@@ -16,13 +16,15 @@ var makefileTemplate =
"# DO NOT EDIT. Automatically generated by gobuild.\n" "# DO NOT EDIT. Automatically generated by gobuild.\n"
"{Args|args} >Makefile\n" "{Args|args} >Makefile\n"
"\n" "\n"
"D={.section Dir}/{@}{.end}\n"
"\n"
"O_arm=5\n" // TODO(rsc): include something here? "O_arm=5\n" // TODO(rsc): include something here?
"O_amd64=6\n" "O_amd64=6\n"
"O_386=8\n" "O_386=8\n"
"OS=568vq\n" "OS=568vq\n"
"\n" "\n"
"O=$(O_$(GOARCH))\n" "O=$(O_$(GOARCH))\n"
"GC=$(O)g\n" "GC=$(O)g -I{ObjDir}\n"
"CC=$(O)c -FVw\n" "CC=$(O)c -FVw\n"
"AS=$(O)a\n" "AS=$(O)a\n"
"AR=6ar\n" "AR=6ar\n"
...@@ -30,7 +32,7 @@ var makefileTemplate = ...@@ -30,7 +32,7 @@ var makefileTemplate =
"default: packages\n" "default: packages\n"
"\n" "\n"
"clean:\n" "clean:\n"
" rm -f *.[$(OS)] *.a [$(OS)].out\n" " rm -rf *.[$(OS)] *.a [$(OS)].out {ObjDir}\n"
"\n" "\n"
"test: packages\n" "test: packages\n"
" gotest\n" " gotest\n"
...@@ -60,21 +62,22 @@ var makefileTemplate = ...@@ -60,21 +62,22 @@ var makefileTemplate =
"\n" "\n"
"phases:{.repeated section Phases} a{Phase}{.end}\n" "phases:{.repeated section Phases} a{Phase}{.end}\n"
"{.repeated section Packages}\n" "{.repeated section Packages}\n"
"{Name}.a: phases\n" "{ObjDir}$D/{Name}.a: phases\n"
"{.end}\n" "{.end}\n"
"\n" "\n"
"{.repeated section Phases}\n" "{.repeated section Phases}\n"
"a{Phase}: $(O{Phase})\n" "a{Phase}: $(O{Phase})\n"
"{.repeated section ArCmds}\n" "{.repeated section ArCmds}\n"
" $(AR) grc {.section Pkg}{Name}.a{.end}{.repeated section Files} {Name|basename}.$O{.end}\n" " $(AR) grc {ObjDir}$D/{.section Pkg}{Name}.a{.end}{.repeated section Files} {Name|basename}.$O{.end}\n"
"{.end}\n" "{.end}\n"
" rm -f $(O{Phase})\n" " rm -f $(O{Phase})\n"
"\n" "\n"
"{.end}\n" "{.end}\n"
"\n" "\n"
"newpkg: clean\n" "newpkg: clean\n"
" mkdir -p {ObjDir}$D\n"
"{.repeated section Packages}\n" "{.repeated section Packages}\n"
" $(AR) grc {Name}.a\n" " $(AR) grc {ObjDir}$D/{Name}.a\n"
"{.end}\n" "{.end}\n"
"\n" "\n"
"$(O1): newpkg\n" "$(O1): newpkg\n"
...@@ -83,13 +86,14 @@ var makefileTemplate = ...@@ -83,13 +86,14 @@ var makefileTemplate =
"{.end}\n" "{.end}\n"
"\n" "\n"
"nuke: clean\n" "nuke: clean\n"
" rm -f{.repeated section Packages} $(GOROOT)/pkg/{Name}.a{.end}\n" " rm -f{.repeated section Packages} $(GOROOT)/pkg$D/{Name}.a{.end}\n"
"\n" "\n"
"packages:{.repeated section Packages} {Name}.a{.end}\n" "packages:{.repeated section Packages} {ObjDir}$D/{Name}.a{.end}\n"
"\n" "\n"
"install: packages\n" "install: packages\n"
" test -d $(GOROOT)/pkg && mkdir -p $(GOROOT)/pkg$D\n"
"{.repeated section Packages}\n" "{.repeated section Packages}\n"
" cp {Name}.a $(GOROOT)/pkg/{Name}.a\n" " cp {ObjDir}$D/{Name}.a $(GOROOT)/pkg$D/{Name}.a\n"
"{.end}\n" "{.end}\n"
func argsFmt(w io.Write, x interface{}, format string) { func argsFmt(w io.Write, x interface{}, format string) {
......
...@@ -6,11 +6,11 @@ ...@@ -6,11 +6,11 @@
package gobuild package gobuild
import ( import (
"ast";
"exec"; "exec";
"fmt"; "fmt";
"go/ast";
"go/parser";
"os"; "os";
"parser";
"path"; "path";
"sort"; "sort";
"strconv"; "strconv";
...@@ -30,6 +30,8 @@ var theChars = map[string] string { ...@@ -30,6 +30,8 @@ var theChars = map[string] string {
"arm": "5" "arm": "5"
} }
const ObjDir = "_obj"
func fatal(args ...) { func fatal(args ...) {
fmt.Fprintf(os.Stderr, "gobuild: %s\n", fmt.Sprint(args)); fmt.Fprintf(os.Stderr, "gobuild: %s\n", fmt.Sprint(args));
sys.Exit(1); sys.Exit(1);
...@@ -124,7 +126,7 @@ func Archive(pkg string, files []string) { ...@@ -124,7 +126,7 @@ func Archive(pkg string, files []string) {
func Compiler(file string) []string { func Compiler(file string) []string {
switch { switch {
case strings.HasSuffix(file, ".go"): case strings.HasSuffix(file, ".go"):
return []string{ theChar + "g" }; return []string{ theChar + "g", "-I", ObjDir };
case strings.HasSuffix(file, ".c"): case strings.HasSuffix(file, ".c"):
return []string{ theChar + "c", "-FVw" }; return []string{ theChar + "c", "-FVw" };
case strings.HasSuffix(file, ".s"): case strings.HasSuffix(file, ".s"):
...@@ -242,3 +244,37 @@ func SourceFiles(dir string) ([]string, *os.Error) { ...@@ -242,3 +244,37 @@ func SourceFiles(dir string) ([]string, *os.Error) {
sort.SortStrings(out); sort.SortStrings(out);
return out, nil; return out, nil;
} }
// TODO(rsc): Implement these for real as
// os.MkdirAll and os.RemoveAll and then
// make these wrappers that call fatal on error.
func MkdirAll(name string) {
p, err := exec.Run("/bin/mkdir", []string{"mkdir", "-p", name}, os.Environ(), exec.DevNull, exec.PassThrough, exec.PassThrough);
if err != nil {
fatal("run /bin/mkdir: %v", err);
}
w, err1 := p.Wait(0);
if err1 != nil {
fatal("wait /bin/mkdir: %v", err);
}
if !w.Exited() || w.ExitStatus() != 0 {
fatal("/bin/mkdir: %v", w);
}
}
func RemoveAll(name string) {
p, err := exec.Run("/bin/rm", []string{"rm", "-rf", name}, os.Environ(), exec.DevNull, exec.PassThrough, exec.PassThrough);
if err != nil {
fatal("run /bin/rm: %v", err);
}
w, err1 := p.Wait(0);
if err1 != nil {
fatal("wait /bin/rm: %v", err);
}
if !w.Exited() || w.ExitStatus() != 0 {
fatal("/bin/rm: %v", w);
}
}
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