~james-page/ubuntu/trusty/gccgo-go/trunk

« back to all changes in this revision

Viewing changes to .pc/cmdgo.patch/src/cmd/go/pkg.go

  • Committer: James Page
  • Date: 2014-01-22 12:48:35 UTC
  • Revision ID: james.page@canonical.com-20140122124835-6o95klsrdezot0c3
Redo patch

Show diffs side-by-side

added added

removed removed

Lines of Context:
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
 
package main
6
 
 
7
 
import (
8
 
        "bytes"
9
 
        "errors"
10
 
        "fmt"
11
 
        "go/build"
12
 
        "go/scanner"
13
 
        "go/token"
14
 
        "os"
15
 
        pathpkg "path"
16
 
        "path/filepath"
17
 
        "sort"
18
 
        "strings"
19
 
        "time"
20
 
        "unicode"
21
 
)
22
 
 
23
 
// A Package describes a single package found in a directory.
24
 
type Package struct {
25
 
        // Note: These fields are part of the go command's public API.
26
 
        // See list.go.  It is okay to add fields, but not to change or
27
 
        // remove existing ones.  Keep in sync with list.go
28
 
        Dir         string `json:",omitempty"` // directory containing package sources
29
 
        ImportPath  string `json:",omitempty"` // import path of package in dir
30
 
        Name        string `json:",omitempty"` // package name
31
 
        Doc         string `json:",omitempty"` // package documentation string
32
 
        Target      string `json:",omitempty"` // install path
33
 
        Goroot      bool   `json:",omitempty"` // is this package found in the Go root?
34
 
        Standard    bool   `json:",omitempty"` // is this package part of the standard Go library?
35
 
        Stale       bool   `json:",omitempty"` // would 'go install' do anything for this package?
36
 
        Root        string `json:",omitempty"` // Go root or Go path dir containing this package
37
 
        ConflictDir string `json:",omitempty"` // Dir is hidden by this other directory
38
 
 
39
 
        // Source files
40
 
        GoFiles        []string `json:",omitempty"` // .go source files (excluding CgoFiles, TestGoFiles, XTestGoFiles)
41
 
        CgoFiles       []string `json:",omitempty"` // .go sources files that import "C"
42
 
        IgnoredGoFiles []string `json:",omitempty"` // .go sources ignored due to build constraints
43
 
        CFiles         []string `json:",omitempty"` // .c source files
44
 
        CXXFiles       []string `json:",omitempty"` // .cc, .cpp and .cxx source files
45
 
        HFiles         []string `json:",omitempty"` // .h, .hh, .hpp and .hxx source files
46
 
        SFiles         []string `json:",omitempty"` // .s source files
47
 
        SwigFiles      []string `json:",omitempty"` // .swig files
48
 
        SwigCXXFiles   []string `json:",omitempty"` // .swigcxx files
49
 
        SysoFiles      []string `json:",omitempty"` // .syso system object files added to package
50
 
 
51
 
        // Cgo directives
52
 
        CgoCFLAGS    []string `json:",omitempty"` // cgo: flags for C compiler
53
 
        CgoCPPFLAGS  []string `json:",omitempty"` // cgo: flags for C preprocessor
54
 
        CgoCXXFLAGS  []string `json:",omitempty"` // cgo: flags for C++ compiler
55
 
        CgoLDFLAGS   []string `json:",omitempty"` // cgo: flags for linker
56
 
        CgoPkgConfig []string `json:",omitempty"` // cgo: pkg-config names
57
 
 
58
 
        // Dependency information
59
 
        Imports []string `json:",omitempty"` // import paths used by this package
60
 
        Deps    []string `json:",omitempty"` // all (recursively) imported dependencies
61
 
 
62
 
        // Error information
63
 
        Incomplete bool            `json:",omitempty"` // was there an error loading this package or dependencies?
64
 
        Error      *PackageError   `json:",omitempty"` // error loading this package (not dependencies)
65
 
        DepsErrors []*PackageError `json:",omitempty"` // errors loading dependencies
66
 
 
67
 
        // Test information
68
 
        TestGoFiles  []string `json:",omitempty"` // _test.go files in package
69
 
        TestImports  []string `json:",omitempty"` // imports from TestGoFiles
70
 
        XTestGoFiles []string `json:",omitempty"` // _test.go files outside package
71
 
        XTestImports []string `json:",omitempty"` // imports from XTestGoFiles
72
 
 
73
 
        // Unexported fields are not part of the public API.
74
 
        build        *build.Package
75
 
        pkgdir       string // overrides build.PkgDir
76
 
        imports      []*Package
77
 
        deps         []*Package
78
 
        gofiles      []string // GoFiles+CgoFiles+TestGoFiles+XTestGoFiles files, absolute paths
79
 
        sfiles       []string
80
 
        allgofiles   []string             // gofiles + IgnoredGoFiles, absolute paths
81
 
        target       string               // installed file for this package (may be executable)
82
 
        fake         bool                 // synthesized package
83
 
        forceBuild   bool                 // this package must be rebuilt
84
 
        forceLibrary bool                 // this package is a library (even if named "main")
85
 
        cmdline      bool                 // defined by files listed on command line
86
 
        local        bool                 // imported via local path (./ or ../)
87
 
        localPrefix  string               // interpret ./ and ../ imports relative to this prefix
88
 
        exeName      string               // desired name for temporary executable
89
 
        coverMode    string               // preprocess Go source files with the coverage tool in this mode
90
 
        coverVars    map[string]*CoverVar // variables created by coverage analysis
91
 
}
92
 
 
93
 
// CoverVar holds the name of the generated coverage variables targeting the named file.
94
 
type CoverVar struct {
95
 
        File string // local file name
96
 
        Var  string // name of count struct
97
 
}
98
 
 
99
 
func (p *Package) copyBuild(pp *build.Package) {
100
 
        p.build = pp
101
 
 
102
 
        p.Dir = pp.Dir
103
 
        p.ImportPath = pp.ImportPath
104
 
        p.Name = pp.Name
105
 
        p.Doc = pp.Doc
106
 
        p.Root = pp.Root
107
 
        p.ConflictDir = pp.ConflictDir
108
 
        // TODO? Target
109
 
        p.Goroot = pp.Goroot
110
 
        p.Standard = p.Goroot && p.ImportPath != "" && !strings.Contains(p.ImportPath, ".")
111
 
        p.GoFiles = pp.GoFiles
112
 
        p.CgoFiles = pp.CgoFiles
113
 
        p.IgnoredGoFiles = pp.IgnoredGoFiles
114
 
        p.CFiles = pp.CFiles
115
 
        p.CXXFiles = pp.CXXFiles
116
 
        p.HFiles = pp.HFiles
117
 
        p.SFiles = pp.SFiles
118
 
        p.SwigFiles = pp.SwigFiles
119
 
        p.SwigCXXFiles = pp.SwigCXXFiles
120
 
        p.SysoFiles = pp.SysoFiles
121
 
        p.CgoCFLAGS = pp.CgoCFLAGS
122
 
        p.CgoCPPFLAGS = pp.CgoCPPFLAGS
123
 
        p.CgoCXXFLAGS = pp.CgoCXXFLAGS
124
 
        p.CgoLDFLAGS = pp.CgoLDFLAGS
125
 
        p.CgoPkgConfig = pp.CgoPkgConfig
126
 
        p.Imports = pp.Imports
127
 
        p.TestGoFiles = pp.TestGoFiles
128
 
        p.TestImports = pp.TestImports
129
 
        p.XTestGoFiles = pp.XTestGoFiles
130
 
        p.XTestImports = pp.XTestImports
131
 
}
132
 
 
133
 
// A PackageError describes an error loading information about a package.
134
 
type PackageError struct {
135
 
        ImportStack   []string // shortest path from package named on command line to this one
136
 
        Pos           string   // position of error
137
 
        Err           string   // the error itself
138
 
        isImportCycle bool     // the error is an import cycle
139
 
}
140
 
 
141
 
func (p *PackageError) Error() string {
142
 
        // Import cycles deserve special treatment.
143
 
        if p.isImportCycle {
144
 
                return fmt.Sprintf("%s: %s\npackage %s\n", p.Pos, p.Err, strings.Join(p.ImportStack, "\n\timports "))
145
 
        }
146
 
        if p.Pos != "" {
147
 
                // Omit import stack.  The full path to the file where the error
148
 
                // is the most important thing.
149
 
                return p.Pos + ": " + p.Err
150
 
        }
151
 
        if len(p.ImportStack) == 0 {
152
 
                return p.Err
153
 
        }
154
 
        return "package " + strings.Join(p.ImportStack, "\n\timports ") + ": " + p.Err
155
 
}
156
 
 
157
 
// An importStack is a stack of import paths.
158
 
type importStack []string
159
 
 
160
 
func (s *importStack) push(p string) {
161
 
        *s = append(*s, p)
162
 
}
163
 
 
164
 
func (s *importStack) pop() {
165
 
        *s = (*s)[0 : len(*s)-1]
166
 
}
167
 
 
168
 
func (s *importStack) copy() []string {
169
 
        return append([]string{}, *s...)
170
 
}
171
 
 
172
 
// shorterThan returns true if sp is shorter than t.
173
 
// We use this to record the shortest import sequence
174
 
// that leads to a particular package.
175
 
func (sp *importStack) shorterThan(t []string) bool {
176
 
        s := *sp
177
 
        if len(s) != len(t) {
178
 
                return len(s) < len(t)
179
 
        }
180
 
        // If they are the same length, settle ties using string ordering.
181
 
        for i := range s {
182
 
                if s[i] != t[i] {
183
 
                        return s[i] < t[i]
184
 
                }
185
 
        }
186
 
        return false // they are equal
187
 
}
188
 
 
189
 
// packageCache is a lookup cache for loadPackage,
190
 
// so that if we look up a package multiple times
191
 
// we return the same pointer each time.
192
 
var packageCache = map[string]*Package{}
193
 
 
194
 
// reloadPackage is like loadPackage but makes sure
195
 
// not to use the package cache.
196
 
func reloadPackage(arg string, stk *importStack) *Package {
197
 
        p := packageCache[arg]
198
 
        if p != nil {
199
 
                delete(packageCache, p.Dir)
200
 
                delete(packageCache, p.ImportPath)
201
 
        }
202
 
        return loadPackage(arg, stk)
203
 
}
204
 
 
205
 
// dirToImportPath returns the pseudo-import path we use for a package
206
 
// outside the Go path.  It begins with _/ and then contains the full path
207
 
// to the directory.  If the package lives in c:\home\gopher\my\pkg then
208
 
// the pseudo-import path is _/c_/home/gopher/my/pkg.
209
 
// Using a pseudo-import path like this makes the ./ imports no longer
210
 
// a special case, so that all the code to deal with ordinary imports works
211
 
// automatically.
212
 
func dirToImportPath(dir string) string {
213
 
        return pathpkg.Join("_", strings.Map(makeImportValid, filepath.ToSlash(dir)))
214
 
}
215
 
 
216
 
func makeImportValid(r rune) rune {
217
 
        // Should match Go spec, compilers, and ../../pkg/go/parser/parser.go:/isValidImport.
218
 
        const illegalChars = `!"#$%&'()*,:;<=>?[\]^{|}` + "`\uFFFD"
219
 
        if !unicode.IsGraphic(r) || unicode.IsSpace(r) || strings.ContainsRune(illegalChars, r) {
220
 
                return '_'
221
 
        }
222
 
        return r
223
 
}
224
 
 
225
 
// loadImport scans the directory named by path, which must be an import path,
226
 
// but possibly a local import path (an absolute file system path or one beginning
227
 
// with ./ or ../).  A local relative path is interpreted relative to srcDir.
228
 
// It returns a *Package describing the package found in that directory.
229
 
func loadImport(path string, srcDir string, stk *importStack, importPos []token.Position) *Package {
230
 
        stk.push(path)
231
 
        defer stk.pop()
232
 
 
233
 
        // Determine canonical identifier for this package.
234
 
        // For a local import the identifier is the pseudo-import path
235
 
        // we create from the full directory to the package.
236
 
        // Otherwise it is the usual import path.
237
 
        importPath := path
238
 
        isLocal := build.IsLocalImport(path)
239
 
        if isLocal {
240
 
                importPath = dirToImportPath(filepath.Join(srcDir, path))
241
 
        }
242
 
        if p := packageCache[importPath]; p != nil {
243
 
                return reusePackage(p, stk)
244
 
        }
245
 
 
246
 
        p := new(Package)
247
 
        p.local = isLocal
248
 
        p.ImportPath = importPath
249
 
        packageCache[importPath] = p
250
 
 
251
 
        // Load package.
252
 
        // Import always returns bp != nil, even if an error occurs,
253
 
        // in order to return partial information.
254
 
        //
255
 
        // TODO: After Go 1, decide when to pass build.AllowBinary here.
256
 
        // See issue 3268 for mistakes to avoid.
257
 
        bp, err := buildContext.Import(path, srcDir, 0)
258
 
        bp.ImportPath = importPath
259
 
        if gobin != "" {
260
 
                bp.BinDir = gobin
261
 
        }
262
 
        p.load(stk, bp, err)
263
 
        if p.Error != nil && len(importPos) > 0 {
264
 
                pos := importPos[0]
265
 
                pos.Filename = shortPath(pos.Filename)
266
 
                p.Error.Pos = pos.String()
267
 
        }
268
 
 
269
 
        return p
270
 
}
271
 
 
272
 
// reusePackage reuses package p to satisfy the import at the top
273
 
// of the import stack stk.  If this use causes an import loop,
274
 
// reusePackage updates p's error information to record the loop.
275
 
func reusePackage(p *Package, stk *importStack) *Package {
276
 
        // We use p.imports==nil to detect a package that
277
 
        // is in the midst of its own loadPackage call
278
 
        // (all the recursion below happens before p.imports gets set).
279
 
        if p.imports == nil {
280
 
                if p.Error == nil {
281
 
                        p.Error = &PackageError{
282
 
                                ImportStack:   stk.copy(),
283
 
                                Err:           "import cycle not allowed",
284
 
                                isImportCycle: true,
285
 
                        }
286
 
                }
287
 
                p.Incomplete = true
288
 
        }
289
 
        // Don't rewrite the import stack in the error if we have an import cycle.
290
 
        // If we do, we'll lose the path that describes the cycle.
291
 
        if p.Error != nil && !p.Error.isImportCycle && stk.shorterThan(p.Error.ImportStack) {
292
 
                p.Error.ImportStack = stk.copy()
293
 
        }
294
 
        return p
295
 
}
296
 
 
297
 
type targetDir int
298
 
 
299
 
const (
300
 
        toRoot targetDir = iota // to bin dir inside package root (default)
301
 
        toTool                  // GOROOT/pkg/tool
302
 
        toBin                   // GOROOT/bin
303
 
)
304
 
 
305
 
// goTools is a map of Go program import path to install target directory.
306
 
var goTools = map[string]targetDir{
307
 
        "cmd/api":                              toTool,
308
 
        "cmd/cgo":                              toTool,
309
 
        "cmd/fix":                              toTool,
310
 
        "cmd/yacc":                             toTool,
311
 
        "code.google.com/p/go.tools/cmd/cover": toTool,
312
 
        "code.google.com/p/go.tools/cmd/godoc": toBin,
313
 
        "code.google.com/p/go.tools/cmd/vet":   toTool,
314
 
}
315
 
 
316
 
// expandScanner expands a scanner.List error into all the errors in the list.
317
 
// The default Error method only shows the first error.
318
 
func expandScanner(err error) error {
319
 
        // Look for parser errors.
320
 
        if err, ok := err.(scanner.ErrorList); ok {
321
 
                // Prepare error with \n before each message.
322
 
                // When printed in something like context: %v
323
 
                // this will put the leading file positions each on
324
 
                // its own line.  It will also show all the errors
325
 
                // instead of just the first, as err.Error does.
326
 
                var buf bytes.Buffer
327
 
                for _, e := range err {
328
 
                        e.Pos.Filename = shortPath(e.Pos.Filename)
329
 
                        buf.WriteString("\n")
330
 
                        buf.WriteString(e.Error())
331
 
                }
332
 
                return errors.New(buf.String())
333
 
        }
334
 
        return err
335
 
}
336
 
 
337
 
var raceExclude = map[string]bool{
338
 
        "runtime/race": true,
339
 
        "runtime/cgo":  true,
340
 
        "cmd/cgo":      true,
341
 
        "syscall":      true,
342
 
        "errors":       true,
343
 
}
344
 
 
345
 
var cgoExclude = map[string]bool{
346
 
        "runtime/cgo": true,
347
 
}
348
 
 
349
 
var cgoSyscallExclude = map[string]bool{
350
 
        "runtime/cgo":  true,
351
 
        "runtime/race": true,
352
 
}
353
 
 
354
 
// load populates p using information from bp, err, which should
355
 
// be the result of calling build.Context.Import.
356
 
func (p *Package) load(stk *importStack, bp *build.Package, err error) *Package {
357
 
        p.copyBuild(bp)
358
 
 
359
 
        // The localPrefix is the path we interpret ./ imports relative to.
360
 
        // Synthesized main packages sometimes override this.
361
 
        p.localPrefix = dirToImportPath(p.Dir)
362
 
 
363
 
        if err != nil {
364
 
                p.Incomplete = true
365
 
                err = expandScanner(err)
366
 
                p.Error = &PackageError{
367
 
                        ImportStack: stk.copy(),
368
 
                        Err:         err.Error(),
369
 
                }
370
 
                return p
371
 
        }
372
 
 
373
 
        if p.Name == "main" {
374
 
                _, elem := filepath.Split(p.Dir)
375
 
                full := buildContext.GOOS + "_" + buildContext.GOARCH + "/" + elem
376
 
                if buildContext.GOOS != toolGOOS || buildContext.GOARCH != toolGOARCH {
377
 
                        // Install cross-compiled binaries to subdirectories of bin.
378
 
                        elem = full
379
 
                }
380
 
                if p.build.BinDir != gobin && goTools[p.ImportPath] == toBin {
381
 
                        // Override BinDir.
382
 
                        // This is from a subrepo but installs to $GOROOT/bin
383
 
                        // by default anyway (like godoc).
384
 
                        p.target = filepath.Join(gorootBin, elem)
385
 
                } else if p.build.BinDir != "" {
386
 
                        // Install to GOBIN or bin of GOPATH entry.
387
 
                        p.target = filepath.Join(p.build.BinDir, elem)
388
 
                }
389
 
                if goTools[p.ImportPath] == toTool {
390
 
                        // This is for 'go tool'.
391
 
                        // Override all the usual logic and force it into the tool directory.
392
 
                        p.target = filepath.Join(gorootPkg, "tool", full)
393
 
                }
394
 
                if p.target != "" && buildContext.GOOS == "windows" {
395
 
                        p.target += ".exe"
396
 
                }
397
 
        } else if p.local {
398
 
                // Local import turned into absolute path.
399
 
                // No permanent install target.
400
 
                p.target = ""
401
 
        } else {
402
 
                p.target = p.build.PkgObj
403
 
        }
404
 
 
405
 
        importPaths := p.Imports
406
 
        // Packages that use cgo import runtime/cgo implicitly.
407
 
        // Packages that use cgo also import syscall implicitly,
408
 
        // to wrap errno.
409
 
        // Exclude certain packages to avoid circular dependencies.
410
 
        if len(p.CgoFiles) > 0 && (!p.Standard || !cgoExclude[p.ImportPath]) {
411
 
                importPaths = append(importPaths, "runtime/cgo")
412
 
        }
413
 
        if len(p.CgoFiles) > 0 && (!p.Standard || !cgoSyscallExclude[p.ImportPath]) {
414
 
                importPaths = append(importPaths, "syscall")
415
 
        }
416
 
        // Everything depends on runtime, except runtime and unsafe.
417
 
        if !p.Standard || (p.ImportPath != "runtime" && p.ImportPath != "unsafe") {
418
 
                importPaths = append(importPaths, "runtime")
419
 
                // When race detection enabled everything depends on runtime/race.
420
 
                // Exclude certain packages to avoid circular dependencies.
421
 
                if buildRace && (!p.Standard || !raceExclude[p.ImportPath]) {
422
 
                        importPaths = append(importPaths, "runtime/race")
423
 
                }
424
 
        }
425
 
 
426
 
        // Build list of full paths to all Go files in the package,
427
 
        // for use by commands like go fmt.
428
 
        p.gofiles = stringList(p.GoFiles, p.CgoFiles, p.TestGoFiles, p.XTestGoFiles)
429
 
        for i := range p.gofiles {
430
 
                p.gofiles[i] = filepath.Join(p.Dir, p.gofiles[i])
431
 
        }
432
 
        sort.Strings(p.gofiles)
433
 
 
434
 
        p.sfiles = stringList(p.SFiles)
435
 
        for i := range p.sfiles {
436
 
                p.sfiles[i] = filepath.Join(p.Dir, p.sfiles[i])
437
 
        }
438
 
        sort.Strings(p.sfiles)
439
 
 
440
 
        p.allgofiles = stringList(p.IgnoredGoFiles)
441
 
        for i := range p.allgofiles {
442
 
                p.allgofiles[i] = filepath.Join(p.Dir, p.allgofiles[i])
443
 
        }
444
 
        p.allgofiles = append(p.allgofiles, p.gofiles...)
445
 
        sort.Strings(p.allgofiles)
446
 
 
447
 
        // Check for case-insensitive collision of input files.
448
 
        // To avoid problems on case-insensitive files, we reject any package
449
 
        // where two different input files have equal names under a case-insensitive
450
 
        // comparison.
451
 
        f1, f2 := foldDup(stringList(
452
 
                p.GoFiles,
453
 
                p.CgoFiles,
454
 
                p.IgnoredGoFiles,
455
 
                p.CFiles,
456
 
                p.CXXFiles,
457
 
                p.HFiles,
458
 
                p.SFiles,
459
 
                p.SysoFiles,
460
 
                p.SwigFiles,
461
 
                p.SwigCXXFiles,
462
 
                p.TestGoFiles,
463
 
                p.XTestGoFiles,
464
 
        ))
465
 
        if f1 != "" {
466
 
                p.Error = &PackageError{
467
 
                        ImportStack: stk.copy(),
468
 
                        Err:         fmt.Sprintf("case-insensitive file name collision: %q and %q", f1, f2),
469
 
                }
470
 
                return p
471
 
        }
472
 
 
473
 
        // Build list of imported packages and full dependency list.
474
 
        imports := make([]*Package, 0, len(p.Imports))
475
 
        deps := make(map[string]bool)
476
 
        for i, path := range importPaths {
477
 
                if path == "C" {
478
 
                        continue
479
 
                }
480
 
                p1 := loadImport(path, p.Dir, stk, p.build.ImportPos[path])
481
 
                if p1.local {
482
 
                        if !p.local && p.Error == nil {
483
 
                                p.Error = &PackageError{
484
 
                                        ImportStack: stk.copy(),
485
 
                                        Err:         fmt.Sprintf("local import %q in non-local package", path),
486
 
                                }
487
 
                                pos := p.build.ImportPos[path]
488
 
                                if len(pos) > 0 {
489
 
                                        p.Error.Pos = pos[0].String()
490
 
                                }
491
 
                        }
492
 
                        path = p1.ImportPath
493
 
                        importPaths[i] = path
494
 
                }
495
 
                deps[path] = true
496
 
                imports = append(imports, p1)
497
 
                for _, dep := range p1.Deps {
498
 
                        deps[dep] = true
499
 
                }
500
 
                if p1.Incomplete {
501
 
                        p.Incomplete = true
502
 
                }
503
 
        }
504
 
        p.imports = imports
505
 
 
506
 
        p.Deps = make([]string, 0, len(deps))
507
 
        for dep := range deps {
508
 
                p.Deps = append(p.Deps, dep)
509
 
        }
510
 
        sort.Strings(p.Deps)
511
 
        for _, dep := range p.Deps {
512
 
                p1 := packageCache[dep]
513
 
                if p1 == nil {
514
 
                        panic("impossible: missing entry in package cache for " + dep + " imported by " + p.ImportPath)
515
 
                }
516
 
                p.deps = append(p.deps, p1)
517
 
                if p1.Error != nil {
518
 
                        p.DepsErrors = append(p.DepsErrors, p1.Error)
519
 
                }
520
 
        }
521
 
 
522
 
        // unsafe is a fake package.
523
 
        if p.Standard && (p.ImportPath == "unsafe" || buildContext.Compiler == "gccgo") {
524
 
                p.target = ""
525
 
        }
526
 
        p.Target = p.target
527
 
 
528
 
        // In the absence of errors lower in the dependency tree,
529
 
        // check for case-insensitive collisions of import paths.
530
 
        if len(p.DepsErrors) == 0 {
531
 
                dep1, dep2 := foldDup(p.Deps)
532
 
                if dep1 != "" {
533
 
                        p.Error = &PackageError{
534
 
                                ImportStack: stk.copy(),
535
 
                                Err:         fmt.Sprintf("case-insensitive import collision: %q and %q", dep1, dep2),
536
 
                        }
537
 
                        return p
538
 
                }
539
 
        }
540
 
 
541
 
        return p
542
 
}
543
 
 
544
 
// usesSwig reports whether the package needs to run SWIG.
545
 
func (p *Package) usesSwig() bool {
546
 
        return len(p.SwigFiles) > 0 || len(p.SwigCXXFiles) > 0
547
 
}
548
 
 
549
 
// usesCgo reports whether the package needs to run cgo
550
 
func (p *Package) usesCgo() bool {
551
 
        return len(p.CgoFiles) > 0
552
 
}
553
 
 
554
 
// swigSoname returns the name of the shared library we create for a
555
 
// SWIG input file.
556
 
func (p *Package) swigSoname(file string) string {
557
 
        return strings.Replace(p.ImportPath, "/", "-", -1) + "-" + strings.Replace(file, ".", "-", -1) + ".so"
558
 
}
559
 
 
560
 
// swigDir returns the name of the shared SWIG directory for a
561
 
// package.
562
 
func (p *Package) swigDir(ctxt *build.Context) string {
563
 
        dir := p.build.PkgRoot
564
 
        if ctxt.Compiler == "gccgo" {
565
 
                dir = filepath.Join(dir, "gccgo_"+ctxt.GOOS+"_"+ctxt.GOARCH)
566
 
        } else {
567
 
                dir = filepath.Join(dir, ctxt.GOOS+"_"+ctxt.GOARCH)
568
 
        }
569
 
        return filepath.Join(dir, "swig")
570
 
}
571
 
 
572
 
// packageList returns the list of packages in the dag rooted at roots
573
 
// as visited in a depth-first post-order traversal.
574
 
func packageList(roots []*Package) []*Package {
575
 
        seen := map[*Package]bool{}
576
 
        all := []*Package{}
577
 
        var walk func(*Package)
578
 
        walk = func(p *Package) {
579
 
                if seen[p] {
580
 
                        return
581
 
                }
582
 
                seen[p] = true
583
 
                for _, p1 := range p.imports {
584
 
                        walk(p1)
585
 
                }
586
 
                all = append(all, p)
587
 
        }
588
 
        for _, root := range roots {
589
 
                walk(root)
590
 
        }
591
 
        return all
592
 
}
593
 
 
594
 
// computeStale computes the Stale flag in the package dag that starts
595
 
// at the named pkgs (command-line arguments).
596
 
func computeStale(pkgs ...*Package) {
597
 
        topRoot := map[string]bool{}
598
 
        for _, p := range pkgs {
599
 
                topRoot[p.Root] = true
600
 
        }
601
 
 
602
 
        for _, p := range packageList(pkgs) {
603
 
                p.Stale = isStale(p, topRoot)
604
 
        }
605
 
}
606
 
 
607
 
// isStale reports whether package p needs to be rebuilt.
608
 
func isStale(p *Package, topRoot map[string]bool) bool {
609
 
        if p.Standard && (p.ImportPath == "unsafe" || buildContext.Compiler == "gccgo") {
610
 
                // fake, builtin package
611
 
                return false
612
 
        }
613
 
        if p.Error != nil {
614
 
                return true
615
 
        }
616
 
 
617
 
        // A package without Go sources means we only found
618
 
        // the installed .a file.  Since we don't know how to rebuild
619
 
        // it, it can't be stale, even if -a is set.  This enables binary-only
620
 
        // distributions of Go packages, although such binaries are
621
 
        // only useful with the specific version of the toolchain that
622
 
        // created them.
623
 
        if len(p.gofiles) == 0 && !p.usesSwig() {
624
 
                return false
625
 
        }
626
 
 
627
 
        if buildA || p.target == "" || p.Stale {
628
 
                return true
629
 
        }
630
 
 
631
 
        // Package is stale if completely unbuilt.
632
 
        var built time.Time
633
 
        if fi, err := os.Stat(p.target); err == nil {
634
 
                built = fi.ModTime()
635
 
        }
636
 
        if built.IsZero() {
637
 
                return true
638
 
        }
639
 
 
640
 
        olderThan := func(file string) bool {
641
 
                fi, err := os.Stat(file)
642
 
                return err != nil || fi.ModTime().After(built)
643
 
        }
644
 
 
645
 
        // Package is stale if a dependency is, or if a dependency is newer.
646
 
        for _, p1 := range p.deps {
647
 
                if p1.Stale || p1.target != "" && olderThan(p1.target) {
648
 
                        return true
649
 
                }
650
 
        }
651
 
 
652
 
        // As a courtesy to developers installing new versions of the compiler
653
 
        // frequently, define that packages are stale if they are
654
 
        // older than the compiler, and commands if they are older than
655
 
        // the linker.  This heuristic will not work if the binaries are
656
 
        // back-dated, as some binary distributions may do, but it does handle
657
 
        // a very common case.
658
 
        // See issue 3036.
659
 
        // Assume code in $GOROOT is up to date, since it may not be writeable.
660
 
        // See issue 4106.
661
 
        if p.Root != goroot {
662
 
                if olderThan(buildToolchain.compiler()) {
663
 
                        return true
664
 
                }
665
 
                if p.build.IsCommand() && olderThan(buildToolchain.linker()) {
666
 
                        return true
667
 
                }
668
 
        }
669
 
 
670
 
        // Have installed copy, probably built using current compilers,
671
 
        // and built after its imported packages.  The only reason now
672
 
        // that we'd have to rebuild it is if the sources were newer than
673
 
        // the package.   If a package p is not in the same tree as any
674
 
        // package named on the command-line, assume it is up-to-date
675
 
        // no matter what the modification times on the source files indicate.
676
 
        // This avoids rebuilding $GOROOT packages when people are
677
 
        // working outside the Go root, and it effectively makes each tree
678
 
        // listed in $GOPATH a separate compilation world.
679
 
        // See issue 3149.
680
 
        if p.Root != "" && !topRoot[p.Root] {
681
 
                return false
682
 
        }
683
 
 
684
 
        srcs := stringList(p.GoFiles, p.CFiles, p.CXXFiles, p.HFiles, p.SFiles, p.CgoFiles, p.SysoFiles, p.SwigFiles, p.SwigCXXFiles)
685
 
        for _, src := range srcs {
686
 
                if olderThan(filepath.Join(p.Dir, src)) {
687
 
                        return true
688
 
                }
689
 
        }
690
 
 
691
 
        return false
692
 
}
693
 
 
694
 
var cwd, _ = os.Getwd()
695
 
 
696
 
var cmdCache = map[string]*Package{}
697
 
 
698
 
// loadPackage is like loadImport but is used for command-line arguments,
699
 
// not for paths found in import statements.  In addition to ordinary import paths,
700
 
// loadPackage accepts pseudo-paths beginning with cmd/ to denote commands
701
 
// in the Go command directory, as well as paths to those directories.
702
 
func loadPackage(arg string, stk *importStack) *Package {
703
 
        if build.IsLocalImport(arg) {
704
 
                dir := arg
705
 
                if !filepath.IsAbs(dir) {
706
 
                        if abs, err := filepath.Abs(dir); err == nil {
707
 
                                // interpret relative to current directory
708
 
                                dir = abs
709
 
                        }
710
 
                }
711
 
                if sub, ok := hasSubdir(gorootSrc, dir); ok && strings.HasPrefix(sub, "cmd/") && !strings.Contains(sub[4:], "/") {
712
 
                        arg = sub
713
 
                }
714
 
        }
715
 
        if strings.HasPrefix(arg, "cmd/") {
716
 
                if p := cmdCache[arg]; p != nil {
717
 
                        return p
718
 
                }
719
 
                stk.push(arg)
720
 
                defer stk.pop()
721
 
 
722
 
                if strings.Contains(arg[4:], "/") {
723
 
                        p := &Package{
724
 
                                Error: &PackageError{
725
 
                                        ImportStack: stk.copy(),
726
 
                                        Err:         fmt.Sprintf("invalid import path: cmd/... is reserved for Go commands"),
727
 
                                },
728
 
                        }
729
 
                        return p
730
 
                }
731
 
 
732
 
                bp, err := buildContext.ImportDir(filepath.Join(gorootSrc, arg), 0)
733
 
                bp.ImportPath = arg
734
 
                bp.Goroot = true
735
 
                bp.BinDir = gorootBin
736
 
                if gobin != "" {
737
 
                        bp.BinDir = gobin
738
 
                }
739
 
                bp.Root = goroot
740
 
                bp.SrcRoot = gorootSrc
741
 
                p := new(Package)
742
 
                cmdCache[arg] = p
743
 
                p.load(stk, bp, err)
744
 
                if p.Error == nil && p.Name != "main" {
745
 
                        p.Error = &PackageError{
746
 
                                ImportStack: stk.copy(),
747
 
                                Err:         fmt.Sprintf("expected package main but found package %s in %s", p.Name, p.Dir),
748
 
                        }
749
 
                }
750
 
                return p
751
 
        }
752
 
 
753
 
        // Wasn't a command; must be a package.
754
 
        // If it is a local import path but names a standard package,
755
 
        // we treat it as if the user specified the standard package.
756
 
        // This lets you run go test ./ioutil in package io and be
757
 
        // referring to io/ioutil rather than a hypothetical import of
758
 
        // "./ioutil".
759
 
        if build.IsLocalImport(arg) {
760
 
                bp, _ := buildContext.ImportDir(filepath.Join(cwd, arg), build.FindOnly)
761
 
                if bp.ImportPath != "" && bp.ImportPath != "." {
762
 
                        arg = bp.ImportPath
763
 
                }
764
 
        }
765
 
 
766
 
        return loadImport(arg, cwd, stk, nil)
767
 
}
768
 
 
769
 
// packages returns the packages named by the
770
 
// command line arguments 'args'.  If a named package
771
 
// cannot be loaded at all (for example, if the directory does not exist),
772
 
// then packages prints an error and does not include that
773
 
// package in the results.  However, if errors occur trying
774
 
// to load dependencies of a named package, the named
775
 
// package is still returned, with p.Incomplete = true
776
 
// and details in p.DepsErrors.
777
 
func packages(args []string) []*Package {
778
 
        var pkgs []*Package
779
 
        for _, pkg := range packagesAndErrors(args) {
780
 
                if pkg.Error != nil {
781
 
                        errorf("can't load package: %s", pkg.Error)
782
 
                        continue
783
 
                }
784
 
                pkgs = append(pkgs, pkg)
785
 
        }
786
 
        return pkgs
787
 
}
788
 
 
789
 
// packagesAndErrors is like 'packages' but returns a
790
 
// *Package for every argument, even the ones that
791
 
// cannot be loaded at all.
792
 
// The packages that fail to load will have p.Error != nil.
793
 
func packagesAndErrors(args []string) []*Package {
794
 
        if len(args) > 0 && strings.HasSuffix(args[0], ".go") {
795
 
                return []*Package{goFilesPackage(args)}
796
 
        }
797
 
 
798
 
        args = importPaths(args)
799
 
        var pkgs []*Package
800
 
        var stk importStack
801
 
        var set = make(map[string]bool)
802
 
 
803
 
        for _, arg := range args {
804
 
                if !set[arg] {
805
 
                        pkgs = append(pkgs, loadPackage(arg, &stk))
806
 
                        set[arg] = true
807
 
                }
808
 
        }
809
 
        computeStale(pkgs...)
810
 
 
811
 
        return pkgs
812
 
}
813
 
 
814
 
// packagesForBuild is like 'packages' but fails if any of
815
 
// the packages or their dependencies have errors
816
 
// (cannot be built).
817
 
func packagesForBuild(args []string) []*Package {
818
 
        pkgs := packagesAndErrors(args)
819
 
        printed := map[*PackageError]bool{}
820
 
        for _, pkg := range pkgs {
821
 
                if pkg.Error != nil {
822
 
                        errorf("can't load package: %s", pkg.Error)
823
 
                }
824
 
                for _, err := range pkg.DepsErrors {
825
 
                        // Since these are errors in dependencies,
826
 
                        // the same error might show up multiple times,
827
 
                        // once in each package that depends on it.
828
 
                        // Only print each once.
829
 
                        if !printed[err] {
830
 
                                printed[err] = true
831
 
                                errorf("%s", err)
832
 
                        }
833
 
                }
834
 
        }
835
 
        exitIfErrors()
836
 
        return pkgs
837
 
}
838
 
 
839
 
// hasSubdir reports whether dir is a subdirectory of
840
 
// (possibly multiple levels below) root.
841
 
// If so, it sets rel to the path fragment that must be
842
 
// appended to root to reach dir.
843
 
func hasSubdir(root, dir string) (rel string, ok bool) {
844
 
        if p, err := filepath.EvalSymlinks(root); err == nil {
845
 
                root = p
846
 
        }
847
 
        if p, err := filepath.EvalSymlinks(dir); err == nil {
848
 
                dir = p
849
 
        }
850
 
        const sep = string(filepath.Separator)
851
 
        root = filepath.Clean(root)
852
 
        if !strings.HasSuffix(root, sep) {
853
 
                root += sep
854
 
        }
855
 
        dir = filepath.Clean(dir)
856
 
        if !strings.HasPrefix(dir, root) {
857
 
                return "", false
858
 
        }
859
 
        return filepath.ToSlash(dir[len(root):]), true
860
 
}