1
0
mirror of https://github.com/golang/go synced 2024-11-25 13:07:57 -07:00

goinstall: support building executable commands

This CL gives goinstall the ability to build commands,
not just packages.

"goinstall foo.googlecode.com/hg/bar" will build the command named
"bar" and install it to GOBIN. "goinstall ." will use the name of the
local directory as the command name.

R=rsc, niemeyer
CC=golang-dev
https://golang.org/cl/4426045
This commit is contained in:
Andrew Gerrand 2011-04-20 12:02:29 +10:00
parent 6a186d38d1
commit aaa6ce2301
2 changed files with 32 additions and 18 deletions

View File

@ -192,18 +192,11 @@ func install(pkg, parent string) {
install(p, pkg) install(p, pkg)
} }
} }
if dirInfo.pkgName == "main" {
if !errors {
fmt.Fprintf(os.Stderr, "%s: %s's dependencies are installed.\n", argv0, pkg)
}
errors = true
visit[pkg] = done
return
}
// Install this package. // Install this package.
if !errors { if !errors {
if err := domake(dir, pkg, local); err != nil { isCmd := dirInfo.pkgName == "main"
if err := domake(dir, pkg, local, isCmd); err != nil {
fmt.Fprintf(os.Stderr, "%s: installing %s: %s\n", argv0, pkg, err) fmt.Fprintf(os.Stderr, "%s: installing %s: %s\n", argv0, pkg, err)
errors = true errors = true
} else if !local && *logPkgs { } else if !local && *logPkgs {

View File

@ -9,6 +9,7 @@ package main
import ( import (
"bytes" "bytes"
"os" "os"
"path/filepath"
"template" "template"
) )
@ -17,7 +18,7 @@ import (
// For non-local packages or packages without Makefiles, // For non-local packages or packages without Makefiles,
// domake generates a standard Makefile and passes it // domake generates a standard Makefile and passes it
// to make on standard input. // to make on standard input.
func domake(dir, pkg string, local bool) (err os.Error) { func domake(dir, pkg string, local, isCmd bool) (err os.Error) {
needMakefile := true needMakefile := true
if local { if local {
_, err := os.Stat(dir + "/Makefile") _, err := os.Stat(dir + "/Makefile")
@ -28,7 +29,7 @@ func domake(dir, pkg string, local bool) (err os.Error) {
cmd := []string{"gomake"} cmd := []string{"gomake"}
var makefile []byte var makefile []byte
if needMakefile { if needMakefile {
if makefile, err = makeMakefile(dir, pkg); err != nil { if makefile, err = makeMakefile(dir, pkg, isCmd); err != nil {
return err return err
} }
cmd = append(cmd, "-f-") cmd = append(cmd, "-f-")
@ -43,11 +44,24 @@ func domake(dir, pkg string, local bool) (err os.Error) {
// makeMakefile computes the standard Makefile for the directory dir // makeMakefile computes the standard Makefile for the directory dir
// installing as package pkg. It includes all *.go files in the directory // installing as package pkg. It includes all *.go files in the directory
// except those in package main and those ending in _test.go. // except those in package main and those ending in _test.go.
func makeMakefile(dir, pkg string) ([]byte, os.Error) { func makeMakefile(dir, pkg string, isCmd bool) ([]byte, os.Error) {
if !safeName(pkg) { targ := pkg
if isCmd {
// use the last part of the package name only
_, targ = filepath.Split(pkg)
// if building the working dir use the directory name
if targ == "." {
d, err := filepath.Abs(dir)
if err != nil {
return nil, os.NewError("finding path: " + err.String())
}
_, targ = filepath.Split(d)
}
}
if !safeName(targ) {
return nil, os.ErrorString("unsafe name: " + pkg) return nil, os.ErrorString("unsafe name: " + pkg)
} }
dirInfo, err := scanDir(dir, false) dirInfo, err := scanDir(dir, isCmd)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -94,7 +108,10 @@ func makeMakefile(dir, pkg string) ([]byte, os.Error) {
} }
var buf bytes.Buffer var buf bytes.Buffer
md := makedata{pkg, goFiles, oFiles, cgoFiles, cgoOFiles} md := makedata{targ, "pkg", goFiles, oFiles, cgoFiles, cgoOFiles}
if isCmd {
md.Type = "cmd"
}
if err := makefileTemplate.Execute(&buf, &md); err != nil { if err := makefileTemplate.Execute(&buf, &md); err != nil {
return nil, err return nil, err
} }
@ -104,6 +121,9 @@ func makeMakefile(dir, pkg string) ([]byte, os.Error) {
var safeBytes = []byte("+-./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz") var safeBytes = []byte("+-./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz")
func safeName(s string) bool { func safeName(s string) bool {
if len(s) == 0 {
return false
}
for i := 0; i < len(s); i++ { for i := 0; i < len(s); i++ {
if c := s[i]; c < 0x80 && bytes.IndexByte(safeBytes, c) < 0 { if c := s[i]; c < 0x80 && bytes.IndexByte(safeBytes, c) < 0 {
return false return false
@ -114,7 +134,8 @@ func safeName(s string) bool {
// makedata is the data type for the makefileTemplate. // makedata is the data type for the makefileTemplate.
type makedata struct { type makedata struct {
Pkg string // package import path Targ string // build target
Type string // build type: "pkg" or "cmd"
GoFiles []string // list of non-cgo .go files GoFiles []string // list of non-cgo .go files
OFiles []string // list of .$O files OFiles []string // list of .$O files
CgoFiles []string // list of cgo .go files CgoFiles []string // list of cgo .go files
@ -124,7 +145,7 @@ type makedata struct {
var makefileTemplate = template.MustParse(` var makefileTemplate = template.MustParse(`
include $(GOROOT)/src/Make.inc include $(GOROOT)/src/Make.inc
TARG={Pkg} TARG={Targ}
{.section GoFiles} {.section GoFiles}
GOFILES=\ GOFILES=\
@ -154,6 +175,6 @@ CGO_OFILES=\
{.end} {.end}
{.end} {.end}
include $(GOROOT)/src/Make.pkg include $(GOROOT)/src/Make.{Type}
`, `,
nil) nil)