aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Gerrand <adg@golang.org>2011-06-24 13:01:17 +1000
committerAndrew Gerrand <adg@golang.org>2011-06-24 13:01:17 +1000
commitb4bab6f8b351630211b0617ac91fb532d6aaf16d (patch)
tree541f6f8d250ee2bd3451bfaf6ae455dbf6fefdc9
parent73d741fd5b767f671dc3bb466ae28c51b0222f8c (diff)
downloadgo-b4bab6f8b351630211b0617ac91fb532d6aaf16d.tar.gz
go-b4bab6f8b351630211b0617ac91fb532d6aaf16d.zip
goinstall: build with make by default, add -make flag
This is a temporary measure until go/build can build cgo packages. R=golang-dev, r CC=golang-dev https://golang.org/cl/4627056
-rw-r--r--src/cmd/goinstall/Makefile1
-rw-r--r--src/cmd/goinstall/main.go49
-rw-r--r--src/cmd/goinstall/make.go180
3 files changed, 210 insertions, 20 deletions
diff --git a/src/cmd/goinstall/Makefile b/src/cmd/goinstall/Makefile
index 399d294adc..f61354f39f 100644
--- a/src/cmd/goinstall/Makefile
+++ b/src/cmd/goinstall/Makefile
@@ -8,5 +8,6 @@ TARG=goinstall
GOFILES=\
download.go\
main.go\
+ make.go\
include ../../Make.cmd
diff --git a/src/cmd/goinstall/main.go b/src/cmd/goinstall/main.go
index c4383aa077..bdf8469a00 100644
--- a/src/cmd/goinstall/main.go
+++ b/src/cmd/goinstall/main.go
@@ -41,6 +41,7 @@ var (
doInstall = flag.Bool("install", true, "build and install")
clean = flag.Bool("clean", false, "clean the package directory before installing")
nuke = flag.Bool("nuke", false, "clean the package directory and target before installing")
+ useMake = flag.Bool("make", true, "use make to build and install")
verbose = flag.Bool("v", false, "verbose")
)
@@ -211,27 +212,35 @@ func install(pkg, parent string) {
}
// Install this package.
- script, err := build.Build(tree, pkg, dirInfo)
- if err != nil {
- errorf("%s: install: %v\n", pkg, err)
- return
- }
- if *nuke {
- printf("%s: nuke\n", pkg)
- script.Nuke()
- } else if *clean {
- printf("%s: clean\n", pkg)
- script.Clean()
- }
- if *doInstall {
- if script.Stale() {
- printf("%s: install\n", pkg)
- if err := script.Run(); err != nil {
- errorf("%s: install: %v\n", pkg, err)
- return
+ if *useMake {
+ err := domake(dir, pkg, tree, dirInfo.IsCommand())
+ if err != nil {
+ errorf("%s: install: %v\n", pkg, err)
+ return
+ }
+ } else {
+ script, err := build.Build(tree, pkg, dirInfo)
+ if err != nil {
+ errorf("%s: install: %v\n", pkg, err)
+ return
+ }
+ if *nuke {
+ printf("%s: nuke\n", pkg)
+ script.Nuke()
+ } else if *clean {
+ printf("%s: clean\n", pkg)
+ script.Clean()
+ }
+ if *doInstall {
+ if script.Stale() {
+ printf("%s: install\n", pkg)
+ if err := script.Run(); err != nil {
+ errorf("%s: install: %v\n", pkg, err)
+ return
+ }
+ } else {
+ printf("%s: up-to-date\n", pkg)
}
- } else {
- printf("%s: up-to-date\n", pkg)
}
}
if remote {
diff --git a/src/cmd/goinstall/make.go b/src/cmd/goinstall/make.go
new file mode 100644
index 0000000000..0fd9b02a84
--- /dev/null
+++ b/src/cmd/goinstall/make.go
@@ -0,0 +1,180 @@
+// 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.
+
+// Run "make install" to build package.
+
+package main
+
+import (
+ "bytes"
+ "go/build"
+ "os"
+ "path/filepath"
+ "strings"
+ "template"
+)
+
+// domake builds the package in dir.
+// domake generates a standard Makefile and passes it
+// to make on standard input.
+func domake(dir, pkg string, tree *build.Tree, isCmd bool) (err os.Error) {
+ makefile, err := makeMakefile(dir, pkg, tree, isCmd)
+ if err != nil {
+ return err
+ }
+ cmd := []string{"bash", "gomake", "-f-"}
+ if *nuke {
+ cmd = append(cmd, "nuke")
+ } else if *clean {
+ cmd = append(cmd, "clean")
+ }
+ cmd = append(cmd, "install")
+ return run(dir, makefile, cmd...)
+}
+
+// makeMakefile computes the standard Makefile for the directory dir
+// installing as package pkg. It includes all *.go files in the directory
+// except those in package main and those ending in _test.go.
+func makeMakefile(dir, pkg string, tree *build.Tree, isCmd bool) ([]byte, os.Error) {
+ if !safeName(pkg) {
+ return nil, os.NewError("unsafe name: " + pkg)
+ }
+ targ := pkg
+ targDir := tree.PkgDir()
+ if isCmd {
+ // use the last part of the package name for targ
+ _, targ = filepath.Split(pkg)
+ targDir = tree.BinDir()
+ }
+ dirInfo, err := build.ScanDir(dir, isCmd)
+ if err != nil {
+ return nil, err
+ }
+
+ cgoFiles := dirInfo.CgoFiles
+ isCgo := make(map[string]bool, len(cgoFiles))
+ for _, file := range cgoFiles {
+ if !safeName(file) {
+ return nil, os.NewError("bad name: " + file)
+ }
+ isCgo[file] = true
+ }
+
+ goFiles := make([]string, 0, len(dirInfo.GoFiles))
+ for _, file := range dirInfo.GoFiles {
+ if !safeName(file) {
+ return nil, os.NewError("unsafe name: " + file)
+ }
+ if !isCgo[file] {
+ goFiles = append(goFiles, file)
+ }
+ }
+
+ oFiles := make([]string, 0, len(dirInfo.CFiles)+len(dirInfo.SFiles))
+ cgoOFiles := make([]string, 0, len(dirInfo.CFiles))
+ for _, file := range dirInfo.CFiles {
+ if !safeName(file) {
+ return nil, os.NewError("unsafe name: " + file)
+ }
+ // When cgo is in use, C files are compiled with gcc,
+ // otherwise they're compiled with gc.
+ if len(cgoFiles) > 0 {
+ cgoOFiles = append(cgoOFiles, file[:len(file)-2]+".o")
+ } else {
+ oFiles = append(oFiles, file[:len(file)-2]+".$O")
+ }
+ }
+
+ for _, file := range dirInfo.SFiles {
+ if !safeName(file) {
+ return nil, os.NewError("unsafe name: " + file)
+ }
+ oFiles = append(oFiles, file[:len(file)-2]+".$O")
+ }
+
+ var imports []string
+ for _, t := range build.Path {
+ imports = append(imports, t.PkgDir())
+ }
+
+ var buf bytes.Buffer
+ md := makedata{targ, targDir, "pkg", goFiles, oFiles, cgoFiles, cgoOFiles, imports}
+ if isCmd {
+ md.Type = "cmd"
+ }
+ if err := makefileTemplate.Execute(&buf, &md); err != nil {
+ return nil, err
+ }
+ return buf.Bytes(), nil
+}
+
+var safeBytes = []byte("+-./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz")
+
+func safeName(s string) bool {
+ if s == "" {
+ return false
+ }
+ if strings.Contains(s, "..") {
+ return false
+ }
+ for i := 0; i < len(s); i++ {
+ if c := s[i]; c < 0x80 && bytes.IndexByte(safeBytes, c) < 0 {
+ return false
+ }
+ }
+ return true
+}
+
+// makedata is the data type for the makefileTemplate.
+type makedata struct {
+ Targ string // build target
+ TargDir string // build target directory
+ Type string // build type: "pkg" or "cmd"
+ GoFiles []string // list of non-cgo .go files
+ OFiles []string // list of .$O files
+ CgoFiles []string // list of cgo .go files
+ CgoOFiles []string // list of cgo .o files, without extension
+ Imports []string // gc/ld import paths
+}
+
+var makefileTemplate = template.MustParse(`
+include $(GOROOT)/src/Make.inc
+
+TARG={Targ}
+TARGDIR={TargDir}
+
+{.section GoFiles}
+GOFILES=\
+{.repeated section @}
+ {@}\
+{.end}
+
+{.end}
+{.section OFiles}
+OFILES=\
+{.repeated section @}
+ {@}\
+{.end}
+
+{.end}
+{.section CgoFiles}
+CGOFILES=\
+{.repeated section @}
+ {@}\
+{.end}
+
+{.end}
+{.section CgoOFiles}
+CGO_OFILES=\
+{.repeated section @}
+ {@}\
+{.end}
+
+{.end}
+GCIMPORTS={.repeated section Imports}-I "{@}" {.end}
+LDIMPORTS={.repeated section Imports}-L "{@}" {.end}
+
+include $(GOROOT)/src/Make.{Type}
+`,
+ nil)