OLD | NEW |
(Empty) | |
| 1 // Copyright 2011 The Go Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style |
| 3 // license that can be found in the LICENSE file. |
| 4 |
| 5 // Run "make install" to build package. |
| 6 |
| 7 package main |
| 8 |
| 9 import ( |
| 10 "bytes" |
| 11 "go/build" |
| 12 "os" |
| 13 "path/filepath" |
| 14 "strings" |
| 15 "template" |
| 16 ) |
| 17 |
| 18 // domake builds the package in dir. |
| 19 // domake generates a standard Makefile and passes it |
| 20 // to make on standard input. |
| 21 func domake(dir, pkg string, tree *build.Tree, isCmd bool) (err os.Error) { |
| 22 makefile, err := makeMakefile(dir, pkg, tree, isCmd) |
| 23 if err != nil { |
| 24 return err |
| 25 } |
| 26 cmd := []string{"bash", "gomake", "-f-"} |
| 27 if *nuke { |
| 28 cmd = append(cmd, "nuke") |
| 29 } else if *clean { |
| 30 cmd = append(cmd, "clean") |
| 31 } |
| 32 cmd = append(cmd, "install") |
| 33 return run(dir, makefile, cmd...) |
| 34 } |
| 35 |
| 36 // makeMakefile computes the standard Makefile for the directory dir |
| 37 // installing as package pkg. It includes all *.go files in the directory |
| 38 // except those in package main and those ending in _test.go. |
| 39 func makeMakefile(dir, pkg string, tree *build.Tree, isCmd bool) ([]byte, os.Err
or) { |
| 40 if !safeName(pkg) { |
| 41 return nil, os.NewError("unsafe name: " + pkg) |
| 42 } |
| 43 targ := pkg |
| 44 targDir := tree.PkgDir() |
| 45 if isCmd { |
| 46 // use the last part of the package name for targ |
| 47 _, targ = filepath.Split(pkg) |
| 48 targDir = tree.BinDir() |
| 49 } |
| 50 dirInfo, err := build.ScanDir(dir, isCmd) |
| 51 if err != nil { |
| 52 return nil, err |
| 53 } |
| 54 |
| 55 cgoFiles := dirInfo.CgoFiles |
| 56 isCgo := make(map[string]bool, len(cgoFiles)) |
| 57 for _, file := range cgoFiles { |
| 58 if !safeName(file) { |
| 59 return nil, os.NewError("bad name: " + file) |
| 60 } |
| 61 isCgo[file] = true |
| 62 } |
| 63 |
| 64 goFiles := make([]string, 0, len(dirInfo.GoFiles)) |
| 65 for _, file := range dirInfo.GoFiles { |
| 66 if !safeName(file) { |
| 67 return nil, os.NewError("unsafe name: " + file) |
| 68 } |
| 69 if !isCgo[file] { |
| 70 goFiles = append(goFiles, file) |
| 71 } |
| 72 } |
| 73 |
| 74 oFiles := make([]string, 0, len(dirInfo.CFiles)+len(dirInfo.SFiles)) |
| 75 cgoOFiles := make([]string, 0, len(dirInfo.CFiles)) |
| 76 for _, file := range dirInfo.CFiles { |
| 77 if !safeName(file) { |
| 78 return nil, os.NewError("unsafe name: " + file) |
| 79 } |
| 80 // When cgo is in use, C files are compiled with gcc, |
| 81 // otherwise they're compiled with gc. |
| 82 if len(cgoFiles) > 0 { |
| 83 cgoOFiles = append(cgoOFiles, file[:len(file)-2]+".o") |
| 84 } else { |
| 85 oFiles = append(oFiles, file[:len(file)-2]+".$O") |
| 86 } |
| 87 } |
| 88 |
| 89 for _, file := range dirInfo.SFiles { |
| 90 if !safeName(file) { |
| 91 return nil, os.NewError("unsafe name: " + file) |
| 92 } |
| 93 oFiles = append(oFiles, file[:len(file)-2]+".$O") |
| 94 } |
| 95 |
| 96 var imports []string |
| 97 for _, t := range build.Path { |
| 98 imports = append(imports, t.PkgDir()) |
| 99 } |
| 100 |
| 101 var buf bytes.Buffer |
| 102 md := makedata{targ, targDir, "pkg", goFiles, oFiles, cgoFiles, cgoOFile
s, imports} |
| 103 if isCmd { |
| 104 md.Type = "cmd" |
| 105 } |
| 106 if err := makefileTemplate.Execute(&buf, &md); err != nil { |
| 107 return nil, err |
| 108 } |
| 109 return buf.Bytes(), nil |
| 110 } |
| 111 |
| 112 var safeBytes = []byte("+-./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmno
pqrstuvwxyz") |
| 113 |
| 114 func safeName(s string) bool { |
| 115 if s == "" { |
| 116 return false |
| 117 } |
| 118 if strings.Contains(s, "..") { |
| 119 return false |
| 120 } |
| 121 for i := 0; i < len(s); i++ { |
| 122 if c := s[i]; c < 0x80 && bytes.IndexByte(safeBytes, c) < 0 { |
| 123 return false |
| 124 } |
| 125 } |
| 126 return true |
| 127 } |
| 128 |
| 129 // makedata is the data type for the makefileTemplate. |
| 130 type makedata struct { |
| 131 Targ string // build target |
| 132 TargDir string // build target directory |
| 133 Type string // build type: "pkg" or "cmd" |
| 134 GoFiles []string // list of non-cgo .go files |
| 135 OFiles []string // list of .$O files |
| 136 CgoFiles []string // list of cgo .go files |
| 137 CgoOFiles []string // list of cgo .o files, without extension |
| 138 Imports []string // gc/ld import paths |
| 139 } |
| 140 |
| 141 var makefileTemplate = template.MustParse(` |
| 142 include $(GOROOT)/src/Make.inc |
| 143 |
| 144 TARG={Targ} |
| 145 TARGDIR={TargDir} |
| 146 |
| 147 {.section GoFiles} |
| 148 GOFILES=\ |
| 149 {.repeated section @} |
| 150 {@}\ |
| 151 {.end} |
| 152 |
| 153 {.end} |
| 154 {.section OFiles} |
| 155 OFILES=\ |
| 156 {.repeated section @} |
| 157 {@}\ |
| 158 {.end} |
| 159 |
| 160 {.end} |
| 161 {.section CgoFiles} |
| 162 CGOFILES=\ |
| 163 {.repeated section @} |
| 164 {@}\ |
| 165 {.end} |
| 166 |
| 167 {.end} |
| 168 {.section CgoOFiles} |
| 169 CGO_OFILES=\ |
| 170 {.repeated section @} |
| 171 {@}\ |
| 172 {.end} |
| 173 |
| 174 {.end} |
| 175 GCIMPORTS={.repeated section Imports}-I "{@}" {.end} |
| 176 LDIMPORTS={.repeated section Imports}-L "{@}" {.end} |
| 177 |
| 178 include $(GOROOT)/src/Make.{Type} |
| 179 `, |
| 180 nil) |
OLD | NEW |