]> Cypherpunks repositories - gostls13.git/commitdiff
build packages in obj/ subdirectory that mimics $GOROOT/pkg.
authorRuss Cox <rsc@golang.org>
Fri, 17 Apr 2009 03:52:13 +0000 (20:52 -0700)
committerRuss Cox <rsc@golang.org>
Fri, 17 Apr 2009 03:52:13 +0000 (20:52 -0700)
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

src/cmd/gobuild/Makefile
src/cmd/gobuild/gobuild.go
src/cmd/gobuild/makefile.go
src/cmd/gobuild/util.go

index 28e2a2e0343a389dce8592e40c2e4139a1a9c20d..42c2a072b79c10533441364471b6c22ce2eb1633 100644 (file)
@@ -46,14 +46,29 @@ $(O1): newpkg
 $(O2): a1
 $(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
 
-main.$O: gobuild.a
+gobuild: zzgobuild
+
+main.$O: phases
 
 nuke: clean
        rm -f $(HOME)/bin/gobuild
 
-install: gobuild
+install: zzgobuild
        cp gobuild $(HOME)/bin/gobuild
 
index c28419da21cff08116a5de7b84a6160ea50b7062..7622494aa0f21fedb86f4cc3b4da271f51d05543 100644 (file)
@@ -45,6 +45,8 @@ type Phase struct {
 type Info struct {
        Args []string;
        Char string;
+       Dir string;
+       ObjDir string;
        Pkgmap map[string] *Pkg;
        Packages []*Pkg;
        Files map[string] *File;
@@ -99,6 +101,30 @@ func (a FileArray) Swap(i, j int) {
        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 {
        // Build list of imports, local packages, and files.
        // Exclude *_test.go and anything in package main.
@@ -106,7 +132,9 @@ func ScanFiles(filenames []string) *Info {
 
        z := new(Info);
        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.Files = make(map[string] *File);
        z.Imports = make(map[string] bool);
@@ -114,7 +142,7 @@ func ScanFiles(filenames []string) *Info {
        // Read Go files to find out packages and imports.
        var pkg *Pkg;
        for _, filename := range filenames {
-               if strings.HasSuffix(filename, "_test.go") {
+               if strings.Index(filename, "_test.") >= 0 {
                        continue;
                }
                f := new(File);
@@ -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;
 }
 
@@ -176,9 +212,14 @@ func PackageObj(pkg string) string {
 }
 
 func (z *Info) Build() {
+       // Create empty object directory tree.
+       RemoveAll(ObjDir);
+       obj := path.Join(ObjDir, z.Dir) + "/";
+       MkdirAll(obj);
+
        // Create empty archives.
        for pkgname := range z.Pkgmap {
-               ar := PackageObj(pkgname);
+               ar := obj + PackageObj(pkgname);
                os.Remove(ar);
                Archive(ar, nil);
        }
@@ -239,7 +280,7 @@ func (z *Info) Build() {
                                f.Phase = phase;
                        }
                        if len(arfiles) > 0 {
-                               Archive(pkg.Name + ".a", arfiles);
+                               Archive(obj + pkg.Name + ".a", arfiles);
 
                                n := len(p.ArCmds);
                                p.ArCmds = p.ArCmds[0:n+1];
@@ -255,6 +296,7 @@ func (z *Info) Build() {
 }
 
 func (z *Info) Clean() {
+       RemoveAll(ObjDir);
        for pkgname := range z.Pkgmap {
                os.Remove(PackageObj(pkgname));
        }
index cbdad90c072c10cdae4a0f9c583e72e5c86738e0..229dbe21941b39ea8bb2ba55ed09c46c589eff55 100644 (file)
@@ -16,13 +16,15 @@ var makefileTemplate =
        "# DO NOT EDIT.  Automatically generated by gobuild.\n"
        "{Args|args} >Makefile\n"
        "\n"
+       "D={.section Dir}/{@}{.end}\n"
+       "\n"
        "O_arm=5\n"     // TODO(rsc): include something here?
        "O_amd64=6\n"
        "O_386=8\n"
        "OS=568vq\n"
        "\n"
        "O=$(O_$(GOARCH))\n"
-       "GC=$(O)g\n"
+       "GC=$(O)g -I{ObjDir}\n"
        "CC=$(O)c -FVw\n"
        "AS=$(O)a\n"
        "AR=6ar\n"
@@ -30,7 +32,7 @@ var makefileTemplate =
        "default: packages\n"
        "\n"
        "clean:\n"
-       "       rm -f *.[$(OS)] *.a [$(OS)].out\n"
+       "       rm -rf *.[$(OS)] *.a [$(OS)].out {ObjDir}\n"
        "\n"
        "test: packages\n"
        "       gotest\n"
@@ -60,21 +62,22 @@ var makefileTemplate =
        "\n"
        "phases:{.repeated section Phases} a{Phase}{.end}\n"
        "{.repeated section Packages}\n"
-       "{Name}.a: phases\n"
+       "{ObjDir}$D/{Name}.a: phases\n"
        "{.end}\n"
        "\n"
        "{.repeated section Phases}\n"
        "a{Phase}: $(O{Phase})\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"
        "       rm -f $(O{Phase})\n"
        "\n"
        "{.end}\n"
        "\n"
        "newpkg: clean\n"
+       "       mkdir -p {ObjDir}$D\n"
        "{.repeated section Packages}\n"
-       "       $(AR) grc {Name}.a\n"
+       "       $(AR) grc {ObjDir}$D/{Name}.a\n"
        "{.end}\n"
        "\n"
        "$(O1): newpkg\n"
@@ -83,13 +86,14 @@ var makefileTemplate =
        "{.end}\n"
        "\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"
-       "packages:{.repeated section Packages} {Name}.a{.end}\n"
+       "packages:{.repeated section Packages} {ObjDir}$D/{Name}.a{.end}\n"
        "\n"
        "install: packages\n"
+       "       test -d $(GOROOT)/pkg && mkdir -p $(GOROOT)/pkg$D\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"
 
 func argsFmt(w io.Write, x interface{}, format string) {
index 02241728976b52cc8b7b3c49f24c7b856137ac22..8f69f39b45c8ab44bad12aea8c2f559d88df1201 100644 (file)
@@ -6,11 +6,11 @@
 package gobuild
 
 import (
-       "ast";
        "exec";
        "fmt";
+       "go/ast";
+       "go/parser";
        "os";
-       "parser";
        "path";
        "sort";
        "strconv";
@@ -30,6 +30,8 @@ var theChars = map[string] string {
        "arm": "5"
 }
 
+const ObjDir = "_obj"
+
 func fatal(args ...) {
        fmt.Fprintf(os.Stderr, "gobuild: %s\n", fmt.Sprint(args));
        sys.Exit(1);
@@ -124,7 +126,7 @@ func Archive(pkg string, files []string) {
 func Compiler(file string) []string {
        switch {
        case strings.HasSuffix(file, ".go"):
-               return []string{ theChar + "g" };
+               return []string{ theChar + "g", "-I", ObjDir };
        case strings.HasSuffix(file, ".c"):
                return []string{ theChar + "c", "-FVw" };
        case strings.HasSuffix(file, ".s"):
@@ -242,3 +244,37 @@ func SourceFiles(dir string) ([]string, *os.Error) {
        sort.SortStrings(out);
        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);
+       }
+
+}
+