summaryrefslogtreecommitdiff
path: root/src/pkg/go/build/build.go
diff options
context:
space:
mode:
Diffstat (limited to 'src/pkg/go/build/build.go')
-rw-r--r--src/pkg/go/build/build.go428
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
-}