LEFT | RIGHT |
(no file at all) | |
1 // Copyright 2011 The Go Authors. All rights reserved. | 1 // Copyright 2011 The Go Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style | 2 // Use of this source code is governed by a BSD-style |
3 // license that can be found in the LICENSE file. | 3 // license that can be found in the LICENSE file. |
4 | 4 |
5 package main | 5 package main |
6 | 6 |
7 import ( | 7 import ( |
8 "bytes" | 8 "bytes" |
9 "fmt" | 9 "fmt" |
10 "go/build" | 10 "go/build" |
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
98 | 98 |
99 // A builder holds global state about a build. | 99 // A builder holds global state about a build. |
100 // It does not hold per-package state, because eventually we will | 100 // It does not hold per-package state, because eventually we will |
101 // build packages in parallel, and the builder will be shared. | 101 // build packages in parallel, and the builder will be shared. |
102 type builder struct { | 102 type builder struct { |
103 work string // the temporary work directory (ends i
n filepath.Separator) | 103 work string // the temporary work directory (ends i
n filepath.Separator) |
104 aflag bool // the -a flag | 104 aflag bool // the -a flag |
105 nflag bool // the -n flag | 105 nflag bool // the -n flag |
106 vflag bool // the -v flag | 106 vflag bool // the -v flag |
107 arch string // e.g., "6" | 107 arch string // e.g., "6" |
| 108 goroot string // the $GOROOT |
108 actionCache map[cacheKey]*action // a cache of already-constructed actio
ns | 109 actionCache map[cacheKey]*action // a cache of already-constructed actio
ns |
109 } | 110 } |
110 | 111 |
111 // An action represents a single action in the action graph. | 112 // An action represents a single action in the action graph. |
112 type action struct { | 113 type action struct { |
113 f func(*builder, *action) error // the action itself | 114 f func(*builder, *action) error // the action itself |
114 | 115 |
115 » p *Package // the package this action works on | 116 » p *Package // the package this action works on |
116 » deps []*action // actions that must happen before this one | 117 » deps []*action // actions that must happen before this one |
117 » done bool // whether the action is done (might have failed) | 118 » done bool // whether the action is done (might have failed) |
118 » failed bool // whether the action failed | 119 » failed bool // whether the action failed |
| 120 » pkgdir string // the -I or -L argument to use when importing this
package |
| 121 » ignoreFail bool // whether to run f even if dependencies fail |
119 | 122 |
120 // Results left for communication with other code. | 123 // Results left for communication with other code. |
121 pkgobj string // the built .a file | 124 pkgobj string // the built .a file |
122 pkgbin string // the built a.out file, if one exists | 125 pkgbin string // the built a.out file, if one exists |
123 } | 126 } |
124 | 127 |
125 // cacheKey is the key for the action cache. | 128 // cacheKey is the key for the action cache. |
126 type cacheKey struct { | 129 type cacheKey struct { |
127 mode buildMode | 130 mode buildMode |
128 p *Package | 131 p *Package |
129 } | 132 } |
130 | 133 |
131 // buildMode specifies the build mode: | 134 // buildMode specifies the build mode: |
132 // are we just building things or also installing the results? | 135 // are we just building things or also installing the results? |
133 type buildMode int | 136 type buildMode int |
134 | 137 |
135 const ( | 138 const ( |
136 modeBuild buildMode = iota | 139 modeBuild buildMode = iota |
137 modeInstall | 140 modeInstall |
138 ) | 141 ) |
139 | 142 |
140 func (b *builder) init(aflag, nflag, vflag bool) { | 143 func (b *builder) init(aflag, nflag, vflag bool) { |
141 var err error | 144 var err error |
142 b.aflag = aflag | 145 b.aflag = aflag |
143 b.nflag = nflag | 146 b.nflag = nflag |
144 b.vflag = vflag | 147 b.vflag = vflag |
145 b.actionCache = make(map[cacheKey]*action) | 148 b.actionCache = make(map[cacheKey]*action) |
| 149 b.goroot = runtime.GOROOT() |
146 | 150 |
147 b.arch, err = build.ArchChar(build.DefaultContext.GOARCH) | 151 b.arch, err = build.ArchChar(build.DefaultContext.GOARCH) |
148 if err != nil { | 152 if err != nil { |
149 fatalf("%s", err) | 153 fatalf("%s", err) |
150 } | 154 } |
151 | 155 |
152 if nflag { | 156 if nflag { |
153 b.work = "$WORK" | 157 b.work = "$WORK" |
154 } else { | 158 } else { |
155 b.work, err = ioutil.TempDir("", "go-build") | 159 b.work, err = ioutil.TempDir("", "go-build") |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
202 | 206 |
203 // action returns the action for applying the given operation (mode) to the pack
age. | 207 // action returns the action for applying the given operation (mode) to the pack
age. |
204 // depMode is the action to use when building dependencies. | 208 // depMode is the action to use when building dependencies. |
205 func (b *builder) action(mode buildMode, depMode buildMode, p *Package) *action
{ | 209 func (b *builder) action(mode buildMode, depMode buildMode, p *Package) *action
{ |
206 key := cacheKey{mode, p} | 210 key := cacheKey{mode, p} |
207 a := b.actionCache[key] | 211 a := b.actionCache[key] |
208 if a != nil { | 212 if a != nil { |
209 return a | 213 return a |
210 } | 214 } |
211 | 215 |
212 » a = &action{p: p} | 216 » a = &action{p: p, pkgdir: p.t.PkgDir()} |
| 217 » if p.pkgdir != "" { // overrides p.t |
| 218 » » a.pkgdir = p.pkgdir |
| 219 » } |
| 220 |
213 b.actionCache[key] = a | 221 b.actionCache[key] = a |
214 | 222 |
215 switch mode { | 223 switch mode { |
216 case modeBuild, modeInstall: | 224 case modeBuild, modeInstall: |
| 225 for _, p1 := range p.imports { |
| 226 a.deps = append(a.deps, b.action(depMode, depMode, p1)) |
| 227 } |
| 228 |
217 if !needInstall(p) && !b.aflag { | 229 if !needInstall(p) && !b.aflag { |
| 230 // TODO: This is not right if the deps above |
| 231 // are not all no-ops too. If fmt is up to date |
| 232 // wrt its own source files, but strconv has |
| 233 // changed, then fmt is not up to date. |
218 a.f = (*builder).nop | 234 a.f = (*builder).nop |
219 return a | 235 return a |
220 } | 236 } |
221 if p.Standard { | 237 if p.Standard { |
222 switch p.ImportPath { | 238 switch p.ImportPath { |
223 case "runtime", "runtime/cgo": | 239 case "runtime", "runtime/cgo": |
224 // Too complex - can't build. | 240 // Too complex - can't build. |
225 a.f = (*builder).nop | 241 a.f = (*builder).nop |
226 return a | 242 return a |
227 case "builtin", "unsafe": | 243 case "builtin", "unsafe": |
228 // Fake packages - nothing to build. | 244 // Fake packages - nothing to build. |
229 a.f = (*builder).nop | 245 a.f = (*builder).nop |
230 return a | 246 return a |
231 } | 247 } |
232 } | 248 } |
233 | 249 |
234 if mode == modeInstall { | 250 if mode == modeInstall { |
235 a.f = (*builder).install | 251 a.f = (*builder).install |
236 a.deps = []*action{b.action(modeBuild, depMode, p)} | 252 a.deps = []*action{b.action(modeBuild, depMode, p)} |
237 return a | 253 return a |
238 } | 254 } |
239 | 255 |
240 a.f = (*builder).build | 256 a.f = (*builder).build |
241 for _, p1 := range p.imports { | |
242 a.deps = append(a.deps, b.action(depMode, depMode, p1)) | |
243 } | |
244 } | 257 } |
245 | 258 |
246 return a | 259 return a |
247 } | 260 } |
248 | 261 |
249 // needInstall reports whether p needs to be built and installed. | 262 // needInstall reports whether p needs to be built and installed. |
250 // That is only true if some source file is newer than the installed package bin
ary. | 263 // That is only true if some source file is newer than the installed package bin
ary. |
251 func needInstall(p *Package) bool { | 264 func needInstall(p *Package) bool { |
252 if p.targ == "" { | 265 if p.targ == "" { |
253 return true | 266 return true |
(...skipping 27 matching lines...) Expand all Loading... |
281 | 294 |
282 // do runs the action graph rooted at a. | 295 // do runs the action graph rooted at a. |
283 func (b *builder) do(a *action) { | 296 func (b *builder) do(a *action) { |
284 if a.done { | 297 if a.done { |
285 return | 298 return |
286 } | 299 } |
287 for _, a1 := range a.deps { | 300 for _, a1 := range a.deps { |
288 b.do(a1) | 301 b.do(a1) |
289 if a1.failed { | 302 if a1.failed { |
290 a.failed = true | 303 a.failed = true |
291 » » » a.done = true | 304 » » » if !a.ignoreFail { |
292 » » » return | 305 » » » » a.done = true |
| 306 » » » » return |
| 307 » » » } |
293 } | 308 } |
294 } | 309 } |
295 if err := a.f(b, a); err != nil { | 310 if err := a.f(b, a); err != nil { |
296 errorf("%s", err) | 311 errorf("%s", err) |
297 a.failed = true | 312 a.failed = true |
298 } | 313 } |
299 a.done = true | 314 a.done = true |
300 } | 315 } |
301 | 316 |
302 func (b *builder) nop(a *action) error { | 317 func (b *builder) nop(a *action) error { |
303 return nil | 318 return nil |
304 } | 319 } |
305 | 320 |
306 // build is the action for building a single package. | 321 // build is the action for building a single package or command. |
307 func (b *builder) build(a *action) error { | 322 func (b *builder) build(a *action) error { |
308 obj := filepath.Join(b.work, filepath.FromSlash(a.p.ImportPath+"/_obj"))
+ string(filepath.Separator) | 323 obj := filepath.Join(b.work, filepath.FromSlash(a.p.ImportPath+"/_obj"))
+ string(filepath.Separator) |
309 » a.pkgobj = filepath.Join(b.work, filepath.FromSlash(a.p.ImportPath+".a")
) | 324 » if a.pkgobj == "" { |
| 325 » » a.pkgobj = filepath.Join(b.work, filepath.FromSlash(a.p.ImportPa
th+".a")) |
| 326 » } |
310 | 327 |
311 // make build directory | 328 // make build directory |
312 if err := b.mkdir(obj); err != nil { | 329 if err := b.mkdir(obj); err != nil { |
313 return err | 330 return err |
314 } | 331 } |
315 | 332 |
316 var objects []string | 333 var objects []string |
317 var gofiles []string | 334 var gofiles []string |
318 gofiles = append(gofiles, a.p.GoFiles...) | 335 gofiles = append(gofiles, a.p.GoFiles...) |
319 | 336 |
320 // run cgo | 337 // run cgo |
321 if len(a.p.CgoFiles) > 0 { | 338 if len(a.p.CgoFiles) > 0 { |
322 outGo, outObj, err := b.cgo(a.p.Dir, obj, a.p.info) | 339 outGo, outObj, err := b.cgo(a.p.Dir, obj, a.p.info) |
323 if err != nil { | 340 if err != nil { |
324 return err | 341 return err |
325 } | 342 } |
326 objects = append(objects, outObj...) | 343 objects = append(objects, outObj...) |
327 gofiles = append(gofiles, outGo...) | 344 gofiles = append(gofiles, outGo...) |
328 } | 345 } |
329 | 346 |
330 // prepare Go import path list | 347 // prepare Go import path list |
331 var inc []string | 348 var inc []string |
332 inc = append(inc, "-I", b.work) | 349 inc = append(inc, "-I", b.work) |
333 incMap := map[string]bool{} | 350 incMap := map[string]bool{} |
334 for _, a1 := range a.deps { | 351 for _, a1 := range a.deps { |
335 » » p1 := a1.p | 352 » » pkgdir := a1.pkgdir |
336 » » if p1.t.Goroot { | 353 » » if pkgdir == build.Path[0].PkgDir() || pkgdir == "" { |
337 continue | 354 continue |
338 } | 355 } |
339 pkgdir := p1.t.PkgDir() | |
340 if !incMap[pkgdir] { | 356 if !incMap[pkgdir] { |
341 incMap[pkgdir] = true | 357 incMap[pkgdir] = true |
342 inc = append(inc, "-I", pkgdir) | 358 inc = append(inc, "-I", pkgdir) |
343 } | 359 } |
344 } | 360 } |
345 | 361 |
346 // compile Go | 362 // compile Go |
347 if len(gofiles) > 0 { | 363 if len(gofiles) > 0 { |
348 out := "_go_.6" | 364 out := "_go_.6" |
349 if err := b.gc(a.p.Dir, obj+out, a.p.ImportPath, inc, gofiles);
err != nil { | 365 if err := b.gc(a.p.Dir, obj+out, a.p.ImportPath, inc, gofiles);
err != nil { |
(...skipping 29 matching lines...) Expand all Loading... |
379 if err := b.ld(a.p.Dir, a.pkgbin, inc, a.pkgobj); err != nil { | 395 if err := b.ld(a.p.Dir, a.pkgbin, inc, a.pkgobj); err != nil { |
380 return err | 396 return err |
381 } | 397 } |
382 } | 398 } |
383 | 399 |
384 return nil | 400 return nil |
385 } | 401 } |
386 | 402 |
387 // install is the action for installing a single package. | 403 // install is the action for installing a single package. |
388 func (b *builder) install(a *action) error { | 404 func (b *builder) install(a *action) error { |
389 » if err := b.build(a); err != nil { | 405 » a1 := a.deps[0] |
390 » » return err | |
391 » } | |
392 | |
393 var src string | 406 var src string |
394 var perm uint32 | 407 var perm uint32 |
395 » if a.pkgbin != "" { | 408 » if a1.pkgbin != "" { |
396 » » src = a.pkgbin | 409 » » src = a1.pkgbin |
397 perm = 0777 | 410 perm = 0777 |
398 } else { | 411 } else { |
399 » » src = a.pkgobj | 412 » » src = a1.pkgobj |
400 perm = 0666 | 413 perm = 0666 |
401 } | 414 } |
402 | 415 |
403 // make target directory | 416 // make target directory |
404 dst := a.p.targ | 417 dst := a.p.targ |
405 dir, _ := filepath.Split(dst) | 418 dir, _ := filepath.Split(dst) |
406 if dir != "" { | 419 if dir != "" { |
407 if err := b.mkdir(dir); err != nil { | 420 if err := b.mkdir(dir); err != nil { |
408 return err | 421 return err |
409 } | 422 } |
(...skipping 203 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
613 | 626 |
614 // cc _cgo_import.ARCH | 627 // cc _cgo_import.ARCH |
615 importObj := obj + "_cgo_import." + b.arch | 628 importObj := obj + "_cgo_import." + b.arch |
616 if err := b.cc(dir, importObj, importC); err != nil { | 629 if err := b.cc(dir, importObj, importC); err != nil { |
617 return nil, nil, err | 630 return nil, nil, err |
618 } | 631 } |
619 outObj = append(outObj, importObj) | 632 outObj = append(outObj, importObj) |
620 | 633 |
621 return outGo, outObj, nil | 634 return outGo, outObj, nil |
622 } | 635 } |
LEFT | RIGHT |