diff options
Diffstat (limited to 'src/pkg/go/build/build.go')
-rw-r--r-- | src/pkg/go/build/build.go | 428 |
1 files changed, 0 insertions, 428 deletions
diff --git a/src/pkg/go/build/build.go b/src/pkg/go/build/build.go deleted file mode 100644 index d83a6666e..000000000 --- a/src/pkg/go/build/build.go +++ /dev/null @@ -1,428 +0,0 @@ -// Copyright 2011 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. - -// Package build provides tools for building Go packages. -package build - -import ( - "bytes" - "exec" - "fmt" - "os" - "path/filepath" - "regexp" - "runtime" - "strings" -) - -// Build produces a build Script for the given package. -func Build(tree *Tree, pkg string, info *DirInfo) (*Script, os.Error) { - s := &Script{} - b := &build{ - script: s, - path: filepath.Join(tree.SrcDir(), pkg), - } - b.obj = b.abs("_obj") + string(filepath.Separator) - - b.goarch = runtime.GOARCH - if g := os.Getenv("GOARCH"); g != "" { - b.goarch = g - } - var err os.Error - b.arch, err = ArchChar(b.goarch) - if err != nil { - return nil, err - } - - // add import object files to list of Inputs - for _, pkg := range info.Imports { - t, p, err := FindTree(pkg) - if err != nil && err != ErrNotFound { - // FindTree should always be able to suggest an import - // path and tree. The path must be malformed - // (for example, an absolute or relative path). - return nil, os.NewError("build: invalid import: " + pkg) - } - s.addInput(filepath.Join(t.PkgDir(), p+".a")) - } - - // .go files to be built with gc - gofiles := b.abss(info.GoFiles...) - s.addInput(gofiles...) - - var ofiles []string // object files to be linked or packed - - // make build directory - b.mkdir(b.obj) - s.addIntermediate(b.obj) - - // cgo - if len(info.CgoFiles) > 0 { - cgoFiles := b.abss(info.CgoFiles...) - s.addInput(cgoFiles...) - outGo, outObj := b.cgo(cgoFiles) - gofiles = append(gofiles, outGo...) - ofiles = append(ofiles, outObj...) - s.addIntermediate(outGo...) - s.addIntermediate(outObj...) - } - - // compile - if len(gofiles) > 0 { - ofile := b.obj + "_go_." + b.arch - b.gc(ofile, gofiles...) - ofiles = append(ofiles, ofile) - s.addIntermediate(ofile) - } - - // assemble - for _, sfile := range info.SFiles { - ofile := b.obj + sfile[:len(sfile)-1] + b.arch - sfile = b.abs(sfile) - s.addInput(sfile) - b.asm(ofile, sfile) - ofiles = append(ofiles, ofile) - s.addIntermediate(ofile) - } - - if len(ofiles) == 0 { - return nil, os.NewError("make: no object files to build") - } - - // choose target file - var targ string - if info.IsCommand() { - // use the last part of the import path as binary name - _, bin := filepath.Split(pkg) - if runtime.GOOS == "windows" { - bin += ".exe" - } - targ = filepath.Join(tree.BinDir(), bin) - } else { - targ = filepath.Join(tree.PkgDir(), pkg+".a") - } - - // make target directory - targDir, _ := filepath.Split(targ) - b.mkdir(targDir) - - // link binary or pack object - if info.IsCommand() { - b.ld(targ, ofiles...) - } else { - b.gopack(targ, ofiles...) - } - s.Output = append(s.Output, targ) - - return b.script, nil -} - -// A Script describes the build process for a Go package. -// The Input, Intermediate, and Output fields are lists of absolute paths. -type Script struct { - Cmd []*Cmd - Input []string - Intermediate []string - Output []string -} - -func (s *Script) addInput(file ...string) { - s.Input = append(s.Input, file...) -} - -func (s *Script) addIntermediate(file ...string) { - s.Intermediate = append(s.Intermediate, file...) -} - -// Run runs the Script's Cmds in order. -func (s *Script) Run() os.Error { - for _, c := range s.Cmd { - if err := c.Run(); err != nil { - return err - } - } - return nil -} - -// Stale returns true if the build's inputs are newer than its outputs. -func (s *Script) Stale() bool { - var latest int64 - // get latest mtime of outputs - for _, file := range s.Output { - fi, err := os.Stat(file) - if err != nil { - // any error reading output files means stale - return true - } - if m := fi.Mtime_ns; m > latest { - latest = m - } - } - for _, file := range s.Input { - fi, err := os.Stat(file) - if err != nil || fi.Mtime_ns > latest { - // any error reading input files means stale - // (attempt to rebuild to figure out why) - return true - } - } - return false -} - -// Clean removes the Script's Intermediate files. -// It tries to remove every file and returns the first error it encounters. -func (s *Script) Clean() (err os.Error) { - // Reverse order so that directories get removed after the files they contain. - for i := len(s.Intermediate) - 1; i >= 0; i-- { - if e := os.Remove(s.Intermediate[i]); err == nil { - err = e - } - } - return -} - -// Clean removes the Script's Intermediate and Output files. -// It tries to remove every file and returns the first error it encounters. -func (s *Script) Nuke() (err os.Error) { - // Reverse order so that directories get removed after the files they contain. - for i := len(s.Output) - 1; i >= 0; i-- { - if e := os.Remove(s.Output[i]); err == nil { - err = e - } - } - if e := s.Clean(); err == nil { - err = e - } - return -} - -// A Cmd describes an individual build command. -type Cmd struct { - Args []string // command-line - Stdout string // write standard output to this file, "" is passthrough - Dir string // working directory - Env []string // environment - Input []string // file paths (dependencies) - Output []string // file paths -} - -func (c *Cmd) String() string { - return strings.Join(c.Args, " ") -} - -// Run executes the Cmd. -func (c *Cmd) Run() os.Error { - out := new(bytes.Buffer) - cmd := exec.Command(c.Args[0], c.Args[1:]...) - cmd.Dir = c.Dir - cmd.Env = c.Env - cmd.Stdout = out - cmd.Stderr = out - if c.Stdout != "" { - f, err := os.Create(c.Stdout) - if err != nil { - return err - } - defer f.Close() - cmd.Stdout = f - } - if err := cmd.Run(); err != nil { - return fmt.Errorf("command %q: %v\n%v", c, err, out) - } - return nil -} - -// ArchChar returns the architecture character for the given goarch. -// For example, ArchChar("amd64") returns "6". -func ArchChar(goarch string) (string, os.Error) { - switch goarch { - case "386": - return "8", nil - case "amd64": - return "6", nil - case "arm": - return "5", nil - } - return "", os.NewError("unsupported GOARCH " + goarch) -} - -type build struct { - script *Script - path string - obj string - goarch string - arch string -} - -func (b *build) abs(file string) string { - if filepath.IsAbs(file) { - return file - } - return filepath.Join(b.path, file) -} - -func (b *build) abss(file ...string) []string { - s := make([]string, len(file)) - for i, f := range file { - s[i] = b.abs(f) - } - return s -} - -func (b *build) add(c Cmd) { - b.script.Cmd = append(b.script.Cmd, &c) -} - -func (b *build) mkdir(name string) { - b.add(Cmd{ - Args: []string{"mkdir", "-p", name}, - Output: []string{name}, - }) -} - -func (b *build) gc(ofile string, gofiles ...string) { - gc := b.arch + "g" - args := append([]string{gc, "-o", ofile}, gcImportArgs...) - args = append(args, gofiles...) - b.add(Cmd{ - Args: args, - Input: gofiles, - Output: []string{ofile}, - }) -} - -func (b *build) asm(ofile string, sfile string) { - asm := b.arch + "a" - b.add(Cmd{ - Args: []string{asm, "-o", ofile, sfile}, - Input: []string{sfile}, - Output: []string{ofile}, - }) -} - -func (b *build) ld(targ string, ofiles ...string) { - ld := b.arch + "l" - args := append([]string{ld, "-o", targ}, ldImportArgs...) - args = append(args, ofiles...) - b.add(Cmd{ - Args: args, - Input: ofiles, - Output: []string{targ}, - }) -} - -func (b *build) gopack(targ string, ofiles ...string) { - b.add(Cmd{ - Args: append([]string{"gopack", "grc", targ}, ofiles...), - Input: ofiles, - Output: []string{targ}, - }) -} - -func (b *build) cc(ofile string, cfiles ...string) { - cc := b.arch + "c" - dir := fmt.Sprintf("%s_%s", runtime.GOOS, runtime.GOARCH) - inc := filepath.Join(runtime.GOROOT(), "pkg", dir) - args := []string{cc, "-FVw", "-I", inc, "-o", ofile} - b.add(Cmd{ - Args: append(args, cfiles...), - Input: cfiles, - Output: []string{ofile}, - }) -} - -func (b *build) gccCompile(ofile, cfile string) { - b.add(Cmd{ - Args: b.gccArgs("-o", ofile, "-c", cfile), - Input: []string{cfile}, - Output: []string{ofile}, - }) -} - -func (b *build) gccLink(ofile string, ofiles ...string) { - b.add(Cmd{ - Args: append(b.gccArgs("-o", ofile), ofiles...), - Input: ofiles, - Output: []string{ofile}, - }) -} - -func (b *build) gccArgs(args ...string) []string { - // TODO(adg): HOST_CC - a := []string{"gcc", "-I", b.path, "-g", "-fPIC", "-O2"} - switch b.arch { - case "8": - a = append(a, "-m32") - case "6": - a = append(a, "-m64") - } - return append(a, args...) -} - -var cgoRe = regexp.MustCompile(`[/\\:]`) - -func (b *build) cgo(cgofiles []string) (outGo, outObj []string) { - // cgo - // TODO(adg): CGOPKGPATH - // TODO(adg): CGO_FLAGS - gofiles := []string{b.obj + "_cgo_gotypes.go"} - cfiles := []string{b.obj + "_cgo_main.c", b.obj + "_cgo_export.c"} - for _, fn := range cgofiles { - f := b.obj + cgoRe.ReplaceAllString(fn[:len(fn)-2], "_") - gofiles = append(gofiles, f+"cgo1.go") - cfiles = append(cfiles, f+"cgo2.c") - } - defunC := b.obj + "_cgo_defun.c" - output := append([]string{defunC}, cfiles...) - output = append(output, gofiles...) - b.add(Cmd{ - Args: append([]string{"cgo", "--"}, cgofiles...), - Dir: b.path, - Env: append(os.Environ(), "GOARCH="+b.goarch), - Input: cgofiles, - Output: output, - }) - outGo = append(outGo, gofiles...) - exportH := filepath.Join(b.path, "_cgo_export.h") - b.script.addIntermediate(defunC, exportH, b.obj+"_cgo_flags") - b.script.addIntermediate(cfiles...) - - // cc _cgo_defun.c - defunObj := b.obj + "_cgo_defun." + b.arch - b.cc(defunObj, defunC) - outObj = append(outObj, defunObj) - - // gcc - linkobj := make([]string, 0, len(cfiles)) - for _, cfile := range cfiles { - ofile := cfile[:len(cfile)-1] + "o" - b.gccCompile(ofile, cfile) - linkobj = append(linkobj, ofile) - if !strings.HasSuffix(ofile, "_cgo_main.o") { - outObj = append(outObj, ofile) - } else { - b.script.addIntermediate(ofile) - } - } - dynObj := b.obj + "_cgo_.o" - b.gccLink(dynObj, linkobj...) - b.script.addIntermediate(dynObj) - - // cgo -dynimport - importC := b.obj + "_cgo_import.c" - b.add(Cmd{ - Args: []string{"cgo", "-dynimport", dynObj}, - Stdout: importC, - Input: []string{dynObj}, - Output: []string{importC}, - }) - b.script.addIntermediate(importC) - - // cc _cgo_import.ARCH - importObj := b.obj + "_cgo_import." + b.arch - b.cc(importObj, importC) - outObj = append(outObj, importObj) - - return -} |