From: Andrew Gerrand Date: Fri, 24 Jun 2011 03:01:17 +0000 (+1000) Subject: goinstall: build with make by default, add -make flag X-Git-Tag: weekly.2011-06-23~4 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=b4bab6f8b351630211b0617ac91fb532d6aaf16d;p=gostls13.git 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 --- 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)