~ubuntu-branches/ubuntu/vivid/golang/vivid

« back to all changes in this revision

Viewing changes to .pc/issue54790044_100001_110001.diff/src/cmd/go/build.go

  • Committer: Package Import Robot
  • Author(s): Serge Hallyn
  • Date: 2014-11-18 15:12:26 UTC
  • mfrom: (14.2.12 vivid-proposed)
  • Revision ID: package-import@ubuntu.com-20141118151226-zug7vn93mn3dtiz3
Tags: 2:1.3.2-1ubuntu1
* Merge from Debian unstable.  Remaining changes:
  - 016-armhf-elf-header.patch: Use correct ELF header for armhf binaries.
  - Support co-installability with gccgo-go tool:
    - d/rules,golang-go.install: Rename bin/go -> bin/golang-go
    - d/golang-go.{postinst,prerm}: Install/remove /usr/bin/go using
      alternatives.
  - d/copyright: Amendments for full compiliance with copyright format.
  - d/control: Demote golang-go.tools to Suggests to support Ubuntu MIR.
  - dropped patches (now upstream):
    - d/p/issue27650045_40001_50001.diff
    - d/p/issue28050043_60001_70001.diff
    - d/p/issue54790044_100001_110001.diff

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
 
        "container/heap"
10
 
        "errors"
11
 
        "flag"
12
 
        "fmt"
13
 
        "go/build"
14
 
        "io"
15
 
        "io/ioutil"
16
 
        "log"
17
 
        "os"
18
 
        "os/exec"
19
 
        "path"
20
 
        "path/filepath"
21
 
        "regexp"
22
 
        "runtime"
23
 
        "strconv"
24
 
        "strings"
25
 
        "sync"
26
 
        "time"
27
 
)
28
 
 
29
 
var cmdBuild = &Command{
30
 
        UsageLine: "build [-o output] [build flags] [packages]",
31
 
        Short:     "compile packages and dependencies",
32
 
        Long: `
33
 
Build compiles the packages named by the import paths,
34
 
along with their dependencies, but it does not install the results.
35
 
 
36
 
If the arguments are a list of .go files, build treats them as a list
37
 
of source files specifying a single package.
38
 
 
39
 
When the command line specifies a single main package,
40
 
build writes the resulting executable to output.
41
 
Otherwise build compiles the packages but discards the results,
42
 
serving only as a check that the packages can be built.
43
 
 
44
 
The -o flag specifies the output file name. If not specified, the
45
 
output file name depends on the arguments and derives from the name
46
 
of the package, such as p.a for package p, unless p is 'main'. If
47
 
the package is main and file names are provided, the file name
48
 
derives from the first file name mentioned, such as f1 for 'go build
49
 
f1.go f2.go'; with no files provided ('go build'), the output file
50
 
name is the base name of the containing directory.
51
 
 
52
 
The build flags are shared by the build, install, run, and test commands:
53
 
 
54
 
        -a
55
 
                force rebuilding of packages that are already up-to-date.
56
 
        -n
57
 
                print the commands but do not run them.
58
 
        -p n
59
 
                the number of builds that can be run in parallel.
60
 
                The default is the number of CPUs available.
61
 
        -race
62
 
                enable data race detection.
63
 
                Supported only on linux/amd64, darwin/amd64 and windows/amd64.
64
 
        -v
65
 
                print the names of packages as they are compiled.
66
 
        -work
67
 
                print the name of the temporary work directory and
68
 
                do not delete it when exiting.
69
 
        -x
70
 
                print the commands.
71
 
 
72
 
        -ccflags 'arg list'
73
 
                arguments to pass on each 5c, 6c, or 8c compiler invocation.
74
 
        -compiler name
75
 
                name of compiler to use, as in runtime.Compiler (gccgo or gc).
76
 
        -gccgoflags 'arg list'
77
 
                arguments to pass on each gccgo compiler/linker invocation.
78
 
        -gcflags 'arg list'
79
 
                arguments to pass on each 5g, 6g, or 8g compiler invocation.
80
 
        -installsuffix suffix
81
 
                a suffix to use in the name of the package installation directory,
82
 
                in order to keep output separate from default builds.
83
 
                If using the -race flag, the install suffix is automatically set to race
84
 
                or, if set explicitly, has _race appended to it.
85
 
        -ldflags 'flag list'
86
 
                arguments to pass on each 5l, 6l, or 8l linker invocation.
87
 
        -tags 'tag list'
88
 
                a list of build tags to consider satisfied during the build.
89
 
                See the documentation for the go/build package for
90
 
                more information about build tags.
91
 
 
92
 
The list flags accept a space-separated list of strings. To embed spaces
93
 
in an element in the list, surround it with either single or double quotes.
94
 
 
95
 
For more about specifying packages, see 'go help packages'.
96
 
For more about where packages and binaries are installed,
97
 
run 'go help gopath'.  For more about calling between Go and C/C++,
98
 
run 'go help c'.
99
 
 
100
 
See also: go install, go get, go clean.
101
 
        `,
102
 
}
103
 
 
104
 
func init() {
105
 
        // break init cycle
106
 
        cmdBuild.Run = runBuild
107
 
        cmdInstall.Run = runInstall
108
 
 
109
 
        addBuildFlags(cmdBuild)
110
 
        addBuildFlags(cmdInstall)
111
 
}
112
 
 
113
 
// Flags set by multiple commands.
114
 
var buildA bool               // -a flag
115
 
var buildN bool               // -n flag
116
 
var buildP = runtime.NumCPU() // -p flag
117
 
var buildV bool               // -v flag
118
 
var buildX bool               // -x flag
119
 
var buildO = cmdBuild.Flag.String("o", "", "output file")
120
 
var buildWork bool           // -work flag
121
 
var buildGcflags []string    // -gcflags flag
122
 
var buildCcflags []string    // -ccflags flag
123
 
var buildLdflags []string    // -ldflags flag
124
 
var buildGccgoflags []string // -gccgoflags flag
125
 
var buildRace bool           // -race flag
126
 
 
127
 
var buildContext = build.Default
128
 
var buildToolchain toolchain = noToolchain{}
129
 
 
130
 
// buildCompiler implements flag.Var.
131
 
// It implements Set by updating both
132
 
// buildToolchain and buildContext.Compiler.
133
 
type buildCompiler struct{}
134
 
 
135
 
func (c buildCompiler) Set(value string) error {
136
 
        switch value {
137
 
        case "gc":
138
 
                buildToolchain = gcToolchain{}
139
 
        case "gccgo":
140
 
                buildToolchain = gccgoToolchain{}
141
 
        default:
142
 
                return fmt.Errorf("unknown compiler %q", value)
143
 
        }
144
 
        buildContext.Compiler = value
145
 
        return nil
146
 
}
147
 
 
148
 
func (c buildCompiler) String() string {
149
 
        return buildContext.Compiler
150
 
}
151
 
 
152
 
func init() {
153
 
        switch build.Default.Compiler {
154
 
        case "gc":
155
 
                buildToolchain = gcToolchain{}
156
 
        case "gccgo":
157
 
                buildToolchain = gccgoToolchain{}
158
 
        }
159
 
}
160
 
 
161
 
// addBuildFlags adds the flags common to the build and install commands.
162
 
func addBuildFlags(cmd *Command) {
163
 
        // NOTE: If you add flags here, also add them to testflag.go.
164
 
        cmd.Flag.BoolVar(&buildA, "a", false, "")
165
 
        cmd.Flag.BoolVar(&buildN, "n", false, "")
166
 
        cmd.Flag.IntVar(&buildP, "p", buildP, "")
167
 
        cmd.Flag.StringVar(&buildContext.InstallSuffix, "installsuffix", "", "")
168
 
        cmd.Flag.BoolVar(&buildV, "v", false, "")
169
 
        cmd.Flag.BoolVar(&buildX, "x", false, "")
170
 
        cmd.Flag.BoolVar(&buildWork, "work", false, "")
171
 
        cmd.Flag.Var((*stringsFlag)(&buildGcflags), "gcflags", "")
172
 
        cmd.Flag.Var((*stringsFlag)(&buildCcflags), "ccflags", "")
173
 
        cmd.Flag.Var((*stringsFlag)(&buildLdflags), "ldflags", "")
174
 
        cmd.Flag.Var((*stringsFlag)(&buildGccgoflags), "gccgoflags", "")
175
 
        cmd.Flag.Var((*stringsFlag)(&buildContext.BuildTags), "tags", "")
176
 
        cmd.Flag.Var(buildCompiler{}, "compiler", "")
177
 
        cmd.Flag.BoolVar(&buildRace, "race", false, "")
178
 
}
179
 
 
180
 
func addBuildFlagsNX(cmd *Command) {
181
 
        cmd.Flag.BoolVar(&buildN, "n", false, "")
182
 
        cmd.Flag.BoolVar(&buildX, "x", false, "")
183
 
}
184
 
 
185
 
func isSpaceByte(c byte) bool {
186
 
        return c == ' ' || c == '\t' || c == '\n' || c == '\r'
187
 
}
188
 
 
189
 
// fileExtSplit expects a filename and returns the name
190
 
// and ext (without the dot). If the file has no
191
 
// extension, ext will be empty.
192
 
func fileExtSplit(file string) (name, ext string) {
193
 
        dotExt := filepath.Ext(file)
194
 
        name = file[:len(file)-len(dotExt)]
195
 
        if dotExt != "" {
196
 
                ext = dotExt[1:]
197
 
        }
198
 
        return
199
 
}
200
 
 
201
 
type stringsFlag []string
202
 
 
203
 
func (v *stringsFlag) Set(s string) error {
204
 
        var err error
205
 
        *v, err = splitQuotedFields(s)
206
 
        return err
207
 
}
208
 
 
209
 
func splitQuotedFields(s string) ([]string, error) {
210
 
        // Split fields allowing '' or "" around elements.
211
 
        // Quotes further inside the string do not count.
212
 
        var f []string
213
 
        for len(s) > 0 {
214
 
                for len(s) > 0 && isSpaceByte(s[0]) {
215
 
                        s = s[1:]
216
 
                }
217
 
                if len(s) == 0 {
218
 
                        break
219
 
                }
220
 
                // Accepted quoted string. No unescaping inside.
221
 
                if s[0] == '"' || s[0] == '\'' {
222
 
                        quote := s[0]
223
 
                        s = s[1:]
224
 
                        i := 0
225
 
                        for i < len(s) && s[i] != quote {
226
 
                                i++
227
 
                        }
228
 
                        if i >= len(s) {
229
 
                                return nil, fmt.Errorf("unterminated %c string", quote)
230
 
                        }
231
 
                        f = append(f, s[:i])
232
 
                        s = s[i+1:]
233
 
                        continue
234
 
                }
235
 
                i := 0
236
 
                for i < len(s) && !isSpaceByte(s[i]) {
237
 
                        i++
238
 
                }
239
 
                f = append(f, s[:i])
240
 
                s = s[i:]
241
 
        }
242
 
        return f, nil
243
 
}
244
 
 
245
 
func (v *stringsFlag) String() string {
246
 
        return "<stringsFlag>"
247
 
}
248
 
 
249
 
func runBuild(cmd *Command, args []string) {
250
 
        raceInit()
251
 
        var b builder
252
 
        b.init()
253
 
 
254
 
        pkgs := packagesForBuild(args)
255
 
 
256
 
        if len(pkgs) == 1 && pkgs[0].Name == "main" && *buildO == "" {
257
 
                _, *buildO = path.Split(pkgs[0].ImportPath)
258
 
                *buildO += exeSuffix
259
 
        }
260
 
 
261
 
        // sanity check some often mis-used options
262
 
        switch buildContext.Compiler {
263
 
        case "gccgo":
264
 
                if len(buildGcflags) != 0 {
265
 
                        fmt.Println("go build: when using gccgo toolchain, please pass compiler flags using -gccgoflags, not -gcflags")
266
 
                }
267
 
                if len(buildLdflags) != 0 {
268
 
                        fmt.Println("go build: when using gccgo toolchain, please pass linker flags using -gccgoflags, not -ldflags")
269
 
                }
270
 
        case "gc":
271
 
                if len(buildGccgoflags) != 0 {
272
 
                        fmt.Println("go build: when using gc toolchain, please pass compile flags using -gcflags, and linker flags using -ldflags")
273
 
                }
274
 
        }
275
 
 
276
 
        if *buildO != "" {
277
 
                if len(pkgs) > 1 {
278
 
                        fatalf("go build: cannot use -o with multiple packages")
279
 
                }
280
 
                p := pkgs[0]
281
 
                p.target = "" // must build - not up to date
282
 
                a := b.action(modeInstall, modeBuild, p)
283
 
                a.target = *buildO
284
 
                b.do(a)
285
 
                return
286
 
        }
287
 
 
288
 
        a := &action{}
289
 
        for _, p := range packages(args) {
290
 
                a.deps = append(a.deps, b.action(modeBuild, modeBuild, p))
291
 
        }
292
 
        b.do(a)
293
 
}
294
 
 
295
 
var cmdInstall = &Command{
296
 
        UsageLine: "install [build flags] [packages]",
297
 
        Short:     "compile and install packages and dependencies",
298
 
        Long: `
299
 
Install compiles and installs the packages named by the import paths,
300
 
along with their dependencies.
301
 
 
302
 
For more about the build flags, see 'go help build'.
303
 
For more about specifying packages, see 'go help packages'.
304
 
 
305
 
See also: go build, go get, go clean.
306
 
        `,
307
 
}
308
 
 
309
 
func runInstall(cmd *Command, args []string) {
310
 
        raceInit()
311
 
        pkgs := packagesForBuild(args)
312
 
 
313
 
        for _, p := range pkgs {
314
 
                if p.Target == "" && (!p.Standard || p.ImportPath != "unsafe") {
315
 
                        if p.cmdline {
316
 
                                errorf("go install: no install location for .go files listed on command line (GOBIN not set)")
317
 
                        } else if p.ConflictDir != "" {
318
 
                                errorf("go install: no install location for %s: hidden by %s", p.Dir, p.ConflictDir)
319
 
                        } else {
320
 
                                errorf("go install: no install location for directory %s outside GOPATH", p.Dir)
321
 
                        }
322
 
                }
323
 
        }
324
 
        exitIfErrors()
325
 
 
326
 
        var b builder
327
 
        b.init()
328
 
        a := &action{}
329
 
        for _, p := range pkgs {
330
 
                a.deps = append(a.deps, b.action(modeInstall, modeInstall, p))
331
 
        }
332
 
        b.do(a)
333
 
}
334
 
 
335
 
// Global build parameters (used during package load)
336
 
var (
337
 
        goarch    string
338
 
        goos      string
339
 
        archChar  string
340
 
        exeSuffix string
341
 
)
342
 
 
343
 
func init() {
344
 
        goarch = buildContext.GOARCH
345
 
        goos = buildContext.GOOS
346
 
        if goos == "windows" {
347
 
                exeSuffix = ".exe"
348
 
        }
349
 
        var err error
350
 
        archChar, err = build.ArchChar(goarch)
351
 
        if err != nil {
352
 
                fatalf("%s", err)
353
 
        }
354
 
}
355
 
 
356
 
// A builder holds global state about a build.
357
 
// It does not hold per-package state, because we
358
 
// build packages in parallel, and the builder is shared.
359
 
type builder struct {
360
 
        work        string               // the temporary work directory (ends in filepath.Separator)
361
 
        actionCache map[cacheKey]*action // a cache of already-constructed actions
362
 
        mkdirCache  map[string]bool      // a cache of created directories
363
 
        print       func(args ...interface{}) (int, error)
364
 
 
365
 
        output    sync.Mutex
366
 
        scriptDir string // current directory in printed script
367
 
 
368
 
        exec      sync.Mutex
369
 
        readySema chan bool
370
 
        ready     actionQueue
371
 
}
372
 
 
373
 
// An action represents a single action in the action graph.
374
 
type action struct {
375
 
        p          *Package      // the package this action works on
376
 
        deps       []*action     // actions that must happen before this one
377
 
        triggers   []*action     // inverse of deps
378
 
        cgo        *action       // action for cgo binary if needed
379
 
        args       []string      // additional args for runProgram
380
 
        testOutput *bytes.Buffer // test output buffer
381
 
 
382
 
        f          func(*builder, *action) error // the action itself (nil = no-op)
383
 
        ignoreFail bool                          // whether to run f even if dependencies fail
384
 
 
385
 
        // Generated files, directories.
386
 
        link   bool   // target is executable, not just package
387
 
        pkgdir string // the -I or -L argument to use when importing this package
388
 
        objdir string // directory for intermediate objects
389
 
        objpkg string // the intermediate package .a file created during the action
390
 
        target string // goal of the action: the created package or executable
391
 
 
392
 
        // Execution state.
393
 
        pending  int  // number of deps yet to complete
394
 
        priority int  // relative execution priority
395
 
        failed   bool // whether the action failed
396
 
}
397
 
 
398
 
// cacheKey is the key for the action cache.
399
 
type cacheKey struct {
400
 
        mode buildMode
401
 
        p    *Package
402
 
}
403
 
 
404
 
// buildMode specifies the build mode:
405
 
// are we just building things or also installing the results?
406
 
type buildMode int
407
 
 
408
 
const (
409
 
        modeBuild buildMode = iota
410
 
        modeInstall
411
 
)
412
 
 
413
 
var (
414
 
        goroot       = filepath.Clean(runtime.GOROOT())
415
 
        gobin        = os.Getenv("GOBIN")
416
 
        gorootBin    = filepath.Join(goroot, "bin")
417
 
        gorootSrcPkg = filepath.Join(goroot, "src/pkg")
418
 
        gorootPkg    = filepath.Join(goroot, "pkg")
419
 
        gorootSrc    = filepath.Join(goroot, "src")
420
 
)
421
 
 
422
 
func (b *builder) init() {
423
 
        var err error
424
 
        b.print = func(a ...interface{}) (int, error) {
425
 
                return fmt.Fprint(os.Stderr, a...)
426
 
        }
427
 
        b.actionCache = make(map[cacheKey]*action)
428
 
        b.mkdirCache = make(map[string]bool)
429
 
 
430
 
        if buildN {
431
 
                b.work = "$WORK"
432
 
        } else {
433
 
                b.work, err = ioutil.TempDir("", "go-build")
434
 
                if err != nil {
435
 
                        fatalf("%s", err)
436
 
                }
437
 
                if buildX || buildWork {
438
 
                        fmt.Fprintf(os.Stderr, "WORK=%s\n", b.work)
439
 
                }
440
 
                if !buildWork {
441
 
                        atexit(func() { os.RemoveAll(b.work) })
442
 
                }
443
 
        }
444
 
}
445
 
 
446
 
// goFilesPackage creates a package for building a collection of Go files
447
 
// (typically named on the command line).  The target is named p.a for
448
 
// package p or named after the first Go file for package main.
449
 
func goFilesPackage(gofiles []string) *Package {
450
 
        // TODO: Remove this restriction.
451
 
        for _, f := range gofiles {
452
 
                if !strings.HasSuffix(f, ".go") {
453
 
                        fatalf("named files must be .go files")
454
 
                }
455
 
        }
456
 
 
457
 
        var stk importStack
458
 
        ctxt := buildContext
459
 
        ctxt.UseAllFiles = true
460
 
 
461
 
        // Synthesize fake "directory" that only shows the named files,
462
 
        // to make it look like this is a standard package or
463
 
        // command directory.  So that local imports resolve
464
 
        // consistently, the files must all be in the same directory.
465
 
        var dirent []os.FileInfo
466
 
        var dir string
467
 
        for _, file := range gofiles {
468
 
                fi, err := os.Stat(file)
469
 
                if err != nil {
470
 
                        fatalf("%s", err)
471
 
                }
472
 
                if fi.IsDir() {
473
 
                        fatalf("%s is a directory, should be a Go file", file)
474
 
                }
475
 
                dir1, _ := filepath.Split(file)
476
 
                if dir == "" {
477
 
                        dir = dir1
478
 
                } else if dir != dir1 {
479
 
                        fatalf("named files must all be in one directory; have %s and %s", dir, dir1)
480
 
                }
481
 
                dirent = append(dirent, fi)
482
 
        }
483
 
        ctxt.ReadDir = func(string) ([]os.FileInfo, error) { return dirent, nil }
484
 
 
485
 
        if !filepath.IsAbs(dir) {
486
 
                dir = filepath.Join(cwd, dir)
487
 
        }
488
 
 
489
 
        bp, err := ctxt.ImportDir(dir, 0)
490
 
        pkg := new(Package)
491
 
        pkg.local = true
492
 
        pkg.cmdline = true
493
 
        pkg.load(&stk, bp, err)
494
 
        pkg.localPrefix = dirToImportPath(dir)
495
 
        pkg.ImportPath = "command-line-arguments"
496
 
        pkg.target = ""
497
 
 
498
 
        if pkg.Name == "main" {
499
 
                _, elem := filepath.Split(gofiles[0])
500
 
                exe := elem[:len(elem)-len(".go")] + exeSuffix
501
 
                if *buildO == "" {
502
 
                        *buildO = exe
503
 
                }
504
 
                if gobin != "" {
505
 
                        pkg.target = filepath.Join(gobin, exe)
506
 
                }
507
 
        } else {
508
 
                if *buildO == "" {
509
 
                        *buildO = pkg.Name + ".a"
510
 
                }
511
 
        }
512
 
        pkg.Target = pkg.target
513
 
        pkg.Stale = true
514
 
 
515
 
        computeStale(pkg)
516
 
        return pkg
517
 
}
518
 
 
519
 
// action returns the action for applying the given operation (mode) to the package.
520
 
// depMode is the action to use when building dependencies.
521
 
func (b *builder) action(mode buildMode, depMode buildMode, p *Package) *action {
522
 
        key := cacheKey{mode, p}
523
 
        a := b.actionCache[key]
524
 
        if a != nil {
525
 
                return a
526
 
        }
527
 
 
528
 
        a = &action{p: p, pkgdir: p.build.PkgRoot}
529
 
        if p.pkgdir != "" { // overrides p.t
530
 
                a.pkgdir = p.pkgdir
531
 
        }
532
 
 
533
 
        b.actionCache[key] = a
534
 
 
535
 
        for _, p1 := range p.imports {
536
 
                a.deps = append(a.deps, b.action(depMode, depMode, p1))
537
 
        }
538
 
 
539
 
        // If we are not doing a cross-build, then record the binary we'll
540
 
        // generate for cgo as a dependency of the build of any package
541
 
        // using cgo, to make sure we do not overwrite the binary while
542
 
        // a package is using it.  If this is a cross-build, then the cgo we
543
 
        // are writing is not the cgo we need to use.
544
 
        if goos == runtime.GOOS && goarch == runtime.GOARCH && !buildRace {
545
 
                if len(p.CgoFiles) > 0 || p.Standard && p.ImportPath == "runtime/cgo" {
546
 
                        var stk importStack
547
 
                        p1 := loadPackage("cmd/cgo", &stk)
548
 
                        if p1.Error != nil {
549
 
                                fatalf("load cmd/cgo: %v", p1.Error)
550
 
                        }
551
 
                        a.cgo = b.action(depMode, depMode, p1)
552
 
                        a.deps = append(a.deps, a.cgo)
553
 
                }
554
 
        }
555
 
 
556
 
        if p.Standard {
557
 
                switch p.ImportPath {
558
 
                case "builtin", "unsafe":
559
 
                        // Fake packages - nothing to build.
560
 
                        return a
561
 
                }
562
 
                // gccgo standard library is "fake" too.
563
 
                if _, ok := buildToolchain.(gccgoToolchain); ok {
564
 
                        // the target name is needed for cgo.
565
 
                        a.target = p.target
566
 
                        return a
567
 
                }
568
 
        }
569
 
 
570
 
        if !p.Stale && p.target != "" {
571
 
                // p.Stale==false implies that p.target is up-to-date.
572
 
                // Record target name for use by actions depending on this one.
573
 
                a.target = p.target
574
 
                return a
575
 
        }
576
 
 
577
 
        if p.local && p.target == "" {
578
 
                // Imported via local path.  No permanent target.
579
 
                mode = modeBuild
580
 
        }
581
 
        work := p.pkgdir
582
 
        if work == "" {
583
 
                work = b.work
584
 
        }
585
 
        a.objdir = filepath.Join(work, a.p.ImportPath, "_obj") + string(filepath.Separator)
586
 
        a.objpkg = buildToolchain.pkgpath(work, a.p)
587
 
        a.link = p.Name == "main"
588
 
 
589
 
        switch mode {
590
 
        case modeInstall:
591
 
                a.f = (*builder).install
592
 
                a.deps = []*action{b.action(modeBuild, depMode, p)}
593
 
                a.target = a.p.target
594
 
        case modeBuild:
595
 
                a.f = (*builder).build
596
 
                a.target = a.objpkg
597
 
                if a.link {
598
 
                        // An executable file. (This is the name of a temporary file.)
599
 
                        // Because we run the temporary file in 'go run' and 'go test',
600
 
                        // the name will show up in ps listings. If the caller has specified
601
 
                        // a name, use that instead of a.out. The binary is generated
602
 
                        // in an otherwise empty subdirectory named exe to avoid
603
 
                        // naming conflicts.  The only possible conflict is if we were
604
 
                        // to create a top-level package named exe.
605
 
                        name := "a.out"
606
 
                        if p.exeName != "" {
607
 
                                name = p.exeName
608
 
                        }
609
 
                        a.target = a.objdir + filepath.Join("exe", name) + exeSuffix
610
 
                }
611
 
        }
612
 
 
613
 
        return a
614
 
}
615
 
 
616
 
// actionList returns the list of actions in the dag rooted at root
617
 
// as visited in a depth-first post-order traversal.
618
 
func actionList(root *action) []*action {
619
 
        seen := map[*action]bool{}
620
 
        all := []*action{}
621
 
        var walk func(*action)
622
 
        walk = func(a *action) {
623
 
                if seen[a] {
624
 
                        return
625
 
                }
626
 
                seen[a] = true
627
 
                for _, a1 := range a.deps {
628
 
                        walk(a1)
629
 
                }
630
 
                all = append(all, a)
631
 
        }
632
 
        walk(root)
633
 
        return all
634
 
}
635
 
 
636
 
// do runs the action graph rooted at root.
637
 
func (b *builder) do(root *action) {
638
 
        // Build list of all actions, assigning depth-first post-order priority.
639
 
        // The original implementation here was a true queue
640
 
        // (using a channel) but it had the effect of getting
641
 
        // distracted by low-level leaf actions to the detriment
642
 
        // of completing higher-level actions.  The order of
643
 
        // work does not matter much to overall execution time,
644
 
        // but when running "go test std" it is nice to see each test
645
 
        // results as soon as possible.  The priorities assigned
646
 
        // ensure that, all else being equal, the execution prefers
647
 
        // to do what it would have done first in a simple depth-first
648
 
        // dependency order traversal.
649
 
        all := actionList(root)
650
 
        for i, a := range all {
651
 
                a.priority = i
652
 
        }
653
 
 
654
 
        b.readySema = make(chan bool, len(all))
655
 
 
656
 
        // Initialize per-action execution state.
657
 
        for _, a := range all {
658
 
                for _, a1 := range a.deps {
659
 
                        a1.triggers = append(a1.triggers, a)
660
 
                }
661
 
                a.pending = len(a.deps)
662
 
                if a.pending == 0 {
663
 
                        b.ready.push(a)
664
 
                        b.readySema <- true
665
 
                }
666
 
        }
667
 
 
668
 
        // Handle runs a single action and takes care of triggering
669
 
        // any actions that are runnable as a result.
670
 
        handle := func(a *action) {
671
 
                var err error
672
 
                if a.f != nil && (!a.failed || a.ignoreFail) {
673
 
                        err = a.f(b, a)
674
 
                }
675
 
 
676
 
                // The actions run in parallel but all the updates to the
677
 
                // shared work state are serialized through b.exec.
678
 
                b.exec.Lock()
679
 
                defer b.exec.Unlock()
680
 
 
681
 
                if err != nil {
682
 
                        if err == errPrintedOutput {
683
 
                                setExitStatus(2)
684
 
                        } else {
685
 
                                errorf("%s", err)
686
 
                        }
687
 
                        a.failed = true
688
 
                }
689
 
 
690
 
                for _, a0 := range a.triggers {
691
 
                        if a.failed {
692
 
                                a0.failed = true
693
 
                        }
694
 
                        if a0.pending--; a0.pending == 0 {
695
 
                                b.ready.push(a0)
696
 
                                b.readySema <- true
697
 
                        }
698
 
                }
699
 
 
700
 
                if a == root {
701
 
                        close(b.readySema)
702
 
                }
703
 
        }
704
 
 
705
 
        var wg sync.WaitGroup
706
 
 
707
 
        // Kick off goroutines according to parallelism.
708
 
        // If we are using the -n flag (just printing commands)
709
 
        // drop the parallelism to 1, both to make the output
710
 
        // deterministic and because there is no real work anyway.
711
 
        par := buildP
712
 
        if buildN {
713
 
                par = 1
714
 
        }
715
 
        for i := 0; i < par; i++ {
716
 
                wg.Add(1)
717
 
                go func() {
718
 
                        defer wg.Done()
719
 
                        for {
720
 
                                select {
721
 
                                case _, ok := <-b.readySema:
722
 
                                        if !ok {
723
 
                                                return
724
 
                                        }
725
 
                                        // Receiving a value from b.readySema entitles
726
 
                                        // us to take from the ready queue.
727
 
                                        b.exec.Lock()
728
 
                                        a := b.ready.pop()
729
 
                                        b.exec.Unlock()
730
 
                                        handle(a)
731
 
                                case <-interrupted:
732
 
                                        setExitStatus(1)
733
 
                                        return
734
 
                                }
735
 
                        }
736
 
                }()
737
 
        }
738
 
 
739
 
        wg.Wait()
740
 
}
741
 
 
742
 
// hasString reports whether s appears in the list of strings.
743
 
func hasString(strings []string, s string) bool {
744
 
        for _, t := range strings {
745
 
                if s == t {
746
 
                        return true
747
 
                }
748
 
        }
749
 
        return false
750
 
}
751
 
 
752
 
// build is the action for building a single package or command.
753
 
func (b *builder) build(a *action) (err error) {
754
 
        // Return an error if the package has CXX files but it's not using
755
 
        // cgo nor SWIG, since the CXX files can only be processed by cgo
756
 
        // and SWIG (it's possible to have packages with C files without
757
 
        // using cgo, they will get compiled with the plan9 C compiler and
758
 
        // linked with the rest of the package).
759
 
        if len(a.p.CXXFiles) > 0 && !a.p.usesCgo() && !a.p.usesSwig() {
760
 
                return fmt.Errorf("can't build package %s because it contains C++ files (%s) but it's not using cgo nor SWIG",
761
 
                        a.p.ImportPath, strings.Join(a.p.CXXFiles, ","))
762
 
        }
763
 
        defer func() {
764
 
                if err != nil && err != errPrintedOutput {
765
 
                        err = fmt.Errorf("go build %s: %v", a.p.ImportPath, err)
766
 
                }
767
 
        }()
768
 
        if buildN {
769
 
                // In -n mode, print a banner between packages.
770
 
                // The banner is five lines so that when changes to
771
 
                // different sections of the bootstrap script have to
772
 
                // be merged, the banners give patch something
773
 
                // to use to find its context.
774
 
                fmt.Printf("\n#\n# %s\n#\n\n", a.p.ImportPath)
775
 
        }
776
 
 
777
 
        if buildV {
778
 
                fmt.Fprintf(os.Stderr, "%s\n", a.p.ImportPath)
779
 
        }
780
 
 
781
 
        if a.p.Standard && a.p.ImportPath == "runtime" && buildContext.Compiler == "gc" &&
782
 
                !hasString(a.p.HFiles, "zasm_"+buildContext.GOOS+"_"+buildContext.GOARCH+".h") {
783
 
                return fmt.Errorf("%s/%s must be bootstrapped using make%v", buildContext.GOOS, buildContext.GOARCH, defaultSuffix())
784
 
        }
785
 
 
786
 
        // Make build directory.
787
 
        obj := a.objdir
788
 
        if err := b.mkdir(obj); err != nil {
789
 
                return err
790
 
        }
791
 
 
792
 
        // make target directory
793
 
        dir, _ := filepath.Split(a.target)
794
 
        if dir != "" {
795
 
                if err := b.mkdir(dir); err != nil {
796
 
                        return err
797
 
                }
798
 
        }
799
 
 
800
 
        var gofiles, cfiles, sfiles, objects, cgoObjects []string
801
 
 
802
 
        // If we're doing coverage, preprocess the .go files and put them in the work directory
803
 
        if a.p.coverMode != "" {
804
 
                for _, file := range a.p.GoFiles {
805
 
                        sourceFile := filepath.Join(a.p.Dir, file)
806
 
                        cover := a.p.coverVars[file]
807
 
                        if cover == nil || isTestFile(file) {
808
 
                                // Not covering this file.
809
 
                                gofiles = append(gofiles, file)
810
 
                                continue
811
 
                        }
812
 
                        coverFile := filepath.Join(obj, file)
813
 
                        if err := b.cover(a, coverFile, sourceFile, 0666, cover.Var); err != nil {
814
 
                                return err
815
 
                        }
816
 
                        gofiles = append(gofiles, coverFile)
817
 
                }
818
 
        } else {
819
 
                gofiles = append(gofiles, a.p.GoFiles...)
820
 
        }
821
 
        cfiles = append(cfiles, a.p.CFiles...)
822
 
        sfiles = append(sfiles, a.p.SFiles...)
823
 
 
824
 
        // Run cgo.
825
 
        if a.p.usesCgo() {
826
 
                // In a package using cgo, cgo compiles the C, C++ and assembly files with gcc.
827
 
                // There is one exception: runtime/cgo's job is to bridge the
828
 
                // cgo and non-cgo worlds, so it necessarily has files in both.
829
 
                // In that case gcc only gets the gcc_* files.
830
 
                var gccfiles []string
831
 
                if a.p.Standard && a.p.ImportPath == "runtime/cgo" {
832
 
                        filter := func(files, nongcc, gcc []string) ([]string, []string) {
833
 
                                for _, f := range files {
834
 
                                        if strings.HasPrefix(f, "gcc_") {
835
 
                                                gcc = append(gcc, f)
836
 
                                        } else {
837
 
                                                nongcc = append(nongcc, f)
838
 
                                        }
839
 
                                }
840
 
                                return nongcc, gcc
841
 
                        }
842
 
                        cfiles, gccfiles = filter(cfiles, cfiles[:0], gccfiles)
843
 
                        sfiles, gccfiles = filter(sfiles, sfiles[:0], gccfiles)
844
 
                } else {
845
 
                        gccfiles = append(cfiles, sfiles...)
846
 
                        cfiles = nil
847
 
                        sfiles = nil
848
 
                }
849
 
 
850
 
                cgoExe := tool("cgo")
851
 
                if a.cgo != nil && a.cgo.target != "" {
852
 
                        cgoExe = a.cgo.target
853
 
                }
854
 
                outGo, outObj, err := b.cgo(a.p, cgoExe, obj, gccfiles, a.p.CXXFiles)
855
 
                if err != nil {
856
 
                        return err
857
 
                }
858
 
                cgoObjects = append(cgoObjects, outObj...)
859
 
                gofiles = append(gofiles, outGo...)
860
 
        }
861
 
 
862
 
        // Run SWIG.
863
 
        if a.p.usesSwig() {
864
 
                // In a package using SWIG, any .c or .s files are
865
 
                // compiled with gcc.
866
 
                gccfiles := append(cfiles, sfiles...)
867
 
                cfiles = nil
868
 
                sfiles = nil
869
 
                outGo, outObj, err := b.swig(a.p, obj, gccfiles, a.p.CXXFiles)
870
 
                if err != nil {
871
 
                        return err
872
 
                }
873
 
                cgoObjects = append(cgoObjects, outObj...)
874
 
                gofiles = append(gofiles, outGo...)
875
 
        }
876
 
 
877
 
        // Prepare Go import path list.
878
 
        inc := b.includeArgs("-I", a.deps)
879
 
 
880
 
        // Compile Go.
881
 
        if len(gofiles) > 0 {
882
 
                ofile, out, err := buildToolchain.gc(b, a.p, obj, inc, gofiles)
883
 
                if len(out) > 0 {
884
 
                        b.showOutput(a.p.Dir, a.p.ImportPath, b.processOutput(out))
885
 
                        if err != nil {
886
 
                                return errPrintedOutput
887
 
                        }
888
 
                }
889
 
                if err != nil {
890
 
                        return err
891
 
                }
892
 
                objects = append(objects, ofile)
893
 
        }
894
 
 
895
 
        // Copy .h files named for goos or goarch or goos_goarch
896
 
        // to names using GOOS and GOARCH.
897
 
        // For example, defs_linux_amd64.h becomes defs_GOOS_GOARCH.h.
898
 
        _goos_goarch := "_" + goos + "_" + goarch
899
 
        _goos := "_" + goos
900
 
        _goarch := "_" + goarch
901
 
        for _, file := range a.p.HFiles {
902
 
                name, ext := fileExtSplit(file)
903
 
                switch {
904
 
                case strings.HasSuffix(name, _goos_goarch):
905
 
                        targ := file[:len(name)-len(_goos_goarch)] + "_GOOS_GOARCH." + ext
906
 
                        if err := b.copyFile(a, obj+targ, filepath.Join(a.p.Dir, file), 0666); err != nil {
907
 
                                return err
908
 
                        }
909
 
                case strings.HasSuffix(name, _goarch):
910
 
                        targ := file[:len(name)-len(_goarch)] + "_GOARCH." + ext
911
 
                        if err := b.copyFile(a, obj+targ, filepath.Join(a.p.Dir, file), 0666); err != nil {
912
 
                                return err
913
 
                        }
914
 
                case strings.HasSuffix(name, _goos):
915
 
                        targ := file[:len(name)-len(_goos)] + "_GOOS." + ext
916
 
                        if err := b.copyFile(a, obj+targ, filepath.Join(a.p.Dir, file), 0666); err != nil {
917
 
                                return err
918
 
                        }
919
 
                }
920
 
        }
921
 
 
922
 
        objExt := archChar
923
 
        if _, ok := buildToolchain.(gccgoToolchain); ok {
924
 
                objExt = "o"
925
 
        }
926
 
 
927
 
        for _, file := range cfiles {
928
 
                out := file[:len(file)-len(".c")] + "." + objExt
929
 
                if err := buildToolchain.cc(b, a.p, obj, obj+out, file); err != nil {
930
 
                        return err
931
 
                }
932
 
                objects = append(objects, out)
933
 
        }
934
 
 
935
 
        // Assemble .s files.
936
 
        for _, file := range sfiles {
937
 
                out := file[:len(file)-len(".s")] + "." + objExt
938
 
                if err := buildToolchain.asm(b, a.p, obj, obj+out, file); err != nil {
939
 
                        return err
940
 
                }
941
 
                objects = append(objects, out)
942
 
        }
943
 
 
944
 
        // NOTE(rsc): On Windows, it is critically important that the
945
 
        // gcc-compiled objects (cgoObjects) be listed after the ordinary
946
 
        // objects in the archive.  I do not know why this is.
947
 
        // http://golang.org/issue/2601
948
 
        objects = append(objects, cgoObjects...)
949
 
 
950
 
        // Add system object files.
951
 
        for _, syso := range a.p.SysoFiles {
952
 
                objects = append(objects, filepath.Join(a.p.Dir, syso))
953
 
        }
954
 
 
955
 
        // Pack into archive in obj directory
956
 
        if err := buildToolchain.pack(b, a.p, obj, a.objpkg, objects); err != nil {
957
 
                return err
958
 
        }
959
 
 
960
 
        // Link if needed.
961
 
        if a.link {
962
 
                // The compiler only cares about direct imports, but the
963
 
                // linker needs the whole dependency tree.
964
 
                all := actionList(a)
965
 
                all = all[:len(all)-1] // drop a
966
 
                if err := buildToolchain.ld(b, a.p, a.target, all, a.objpkg, objects); err != nil {
967
 
                        return err
968
 
                }
969
 
        }
970
 
 
971
 
        return nil
972
 
}
973
 
 
974
 
// install is the action for installing a single package or executable.
975
 
func (b *builder) install(a *action) (err error) {
976
 
        defer func() {
977
 
                if err != nil && err != errPrintedOutput {
978
 
                        err = fmt.Errorf("go install %s: %v", a.p.ImportPath, err)
979
 
                }
980
 
        }()
981
 
        a1 := a.deps[0]
982
 
        perm := os.FileMode(0666)
983
 
        if a1.link {
984
 
                perm = 0777
985
 
        }
986
 
 
987
 
        // make target directory
988
 
        dir, _ := filepath.Split(a.target)
989
 
        if dir != "" {
990
 
                if err := b.mkdir(dir); err != nil {
991
 
                        return err
992
 
                }
993
 
        }
994
 
 
995
 
        // remove object dir to keep the amount of
996
 
        // garbage down in a large build.  On an operating system
997
 
        // with aggressive buffering, cleaning incrementally like
998
 
        // this keeps the intermediate objects from hitting the disk.
999
 
        if !buildWork {
1000
 
                defer os.RemoveAll(a1.objdir)
1001
 
                defer os.Remove(a1.target)
1002
 
        }
1003
 
 
1004
 
        if a.p.usesSwig() {
1005
 
                for _, f := range stringList(a.p.SwigFiles, a.p.SwigCXXFiles) {
1006
 
                        dir = a.p.swigDir(&buildContext)
1007
 
                        if err := b.mkdir(dir); err != nil {
1008
 
                                return err
1009
 
                        }
1010
 
                        soname := a.p.swigSoname(f)
1011
 
                        source := filepath.Join(a.objdir, soname)
1012
 
                        target := filepath.Join(dir, soname)
1013
 
                        if err = b.copyFile(a, target, source, perm); err != nil {
1014
 
                                return err
1015
 
                        }
1016
 
                }
1017
 
        }
1018
 
 
1019
 
        return b.copyFile(a, a.target, a1.target, perm)
1020
 
}
1021
 
 
1022
 
// includeArgs returns the -I or -L directory list for access
1023
 
// to the results of the list of actions.
1024
 
func (b *builder) includeArgs(flag string, all []*action) []string {
1025
 
        inc := []string{}
1026
 
        incMap := map[string]bool{
1027
 
                b.work:    true, // handled later
1028
 
                gorootPkg: true,
1029
 
                "":        true, // ignore empty strings
1030
 
        }
1031
 
 
1032
 
        // Look in the temporary space for results of test-specific actions.
1033
 
        // This is the $WORK/my/package/_test directory for the
1034
 
        // package being built, so there are few of these.
1035
 
        for _, a1 := range all {
1036
 
                if dir := a1.pkgdir; dir != a1.p.build.PkgRoot && !incMap[dir] {
1037
 
                        incMap[dir] = true
1038
 
                        inc = append(inc, flag, dir)
1039
 
                }
1040
 
        }
1041
 
 
1042
 
        // Also look in $WORK for any non-test packages that have
1043
 
        // been built but not installed.
1044
 
        inc = append(inc, flag, b.work)
1045
 
 
1046
 
        // Finally, look in the installed package directories for each action.
1047
 
        for _, a1 := range all {
1048
 
                if dir := a1.pkgdir; dir == a1.p.build.PkgRoot && !incMap[dir] {
1049
 
                        incMap[dir] = true
1050
 
                        if _, ok := buildToolchain.(gccgoToolchain); ok {
1051
 
                                dir = filepath.Join(dir, "gccgo_"+goos+"_"+goarch)
1052
 
                        } else {
1053
 
                                dir = filepath.Join(dir, goos+"_"+goarch)
1054
 
                                if buildContext.InstallSuffix != "" {
1055
 
                                        dir += "_" + buildContext.InstallSuffix
1056
 
                                }
1057
 
                        }
1058
 
                        inc = append(inc, flag, dir)
1059
 
                }
1060
 
        }
1061
 
 
1062
 
        return inc
1063
 
}
1064
 
 
1065
 
// copyFile is like 'cp src dst'.
1066
 
func (b *builder) copyFile(a *action, dst, src string, perm os.FileMode) error {
1067
 
        if buildN || buildX {
1068
 
                b.showcmd("", "cp %s %s", src, dst)
1069
 
                if buildN {
1070
 
                        return nil
1071
 
                }
1072
 
        }
1073
 
 
1074
 
        sf, err := os.Open(src)
1075
 
        if err != nil {
1076
 
                return err
1077
 
        }
1078
 
        defer sf.Close()
1079
 
 
1080
 
        // Be careful about removing/overwriting dst.
1081
 
        // Do not remove/overwrite if dst exists and is a directory
1082
 
        // or a non-object file.
1083
 
        if fi, err := os.Stat(dst); err == nil {
1084
 
                if fi.IsDir() {
1085
 
                        return fmt.Errorf("build output %q already exists and is a directory", dst)
1086
 
                }
1087
 
                if !isObject(dst) {
1088
 
                        return fmt.Errorf("build output %q already exists and is not an object file", dst)
1089
 
                }
1090
 
        }
1091
 
 
1092
 
        // On Windows, remove lingering ~ file from last attempt.
1093
 
        if toolIsWindows {
1094
 
                if _, err := os.Stat(dst + "~"); err == nil {
1095
 
                        os.Remove(dst + "~")
1096
 
                }
1097
 
        }
1098
 
 
1099
 
        os.Remove(dst)
1100
 
        df, err := os.OpenFile(dst, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, perm)
1101
 
        if err != nil && toolIsWindows {
1102
 
                // Windows does not allow deletion of a binary file
1103
 
                // while it is executing.  Try to move it out of the way.
1104
 
                // If the move fails, which is likely, we'll try again the
1105
 
                // next time we do an install of this binary.
1106
 
                if err := os.Rename(dst, dst+"~"); err == nil {
1107
 
                        os.Remove(dst + "~")
1108
 
                }
1109
 
                df, err = os.OpenFile(dst, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, perm)
1110
 
        }
1111
 
        if err != nil {
1112
 
                return err
1113
 
        }
1114
 
 
1115
 
        _, err = io.Copy(df, sf)
1116
 
        df.Close()
1117
 
        if err != nil {
1118
 
                os.Remove(dst)
1119
 
                return fmt.Errorf("copying %s to %s: %v", src, dst, err)
1120
 
        }
1121
 
        return nil
1122
 
}
1123
 
 
1124
 
// cover runs, in effect,
1125
 
//      go tool cover -mode=b.coverMode -var="varName" -o dst.go src.go
1126
 
func (b *builder) cover(a *action, dst, src string, perm os.FileMode, varName string) error {
1127
 
        return b.run(a.objdir, "cover "+a.p.ImportPath, nil,
1128
 
                tool("cover"),
1129
 
                "-mode", a.p.coverMode,
1130
 
                "-var", varName,
1131
 
                "-o", dst,
1132
 
                src)
1133
 
}
1134
 
 
1135
 
var objectMagic = [][]byte{
1136
 
        {'!', '<', 'a', 'r', 'c', 'h', '>', '\n'},        // Package archive
1137
 
        {'\x7F', 'E', 'L', 'F'},                          // ELF
1138
 
        {0xFE, 0xED, 0xFA, 0xCE},                         // Mach-O big-endian 32-bit
1139
 
        {0xFE, 0xED, 0xFA, 0xCF},                         // Mach-O big-endian 64-bit
1140
 
        {0xCE, 0xFA, 0xED, 0xFE},                         // Mach-O little-endian 32-bit
1141
 
        {0xCF, 0xFA, 0xED, 0xFE},                         // Mach-O little-endian 64-bit
1142
 
        {0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x04, 0x00}, // PE (Windows) as generated by 6l/8l
1143
 
        {0x00, 0x00, 0x01, 0xEB},                         // Plan 9 i386
1144
 
        {0x00, 0x00, 0x8a, 0x97},                         // Plan 9 amd64
1145
 
}
1146
 
 
1147
 
func isObject(s string) bool {
1148
 
        f, err := os.Open(s)
1149
 
        if err != nil {
1150
 
                return false
1151
 
        }
1152
 
        defer f.Close()
1153
 
        buf := make([]byte, 64)
1154
 
        io.ReadFull(f, buf)
1155
 
        for _, magic := range objectMagic {
1156
 
                if bytes.HasPrefix(buf, magic) {
1157
 
                        return true
1158
 
                }
1159
 
        }
1160
 
        return false
1161
 
}
1162
 
 
1163
 
// fmtcmd formats a command in the manner of fmt.Sprintf but also:
1164
 
//
1165
 
//      If dir is non-empty and the script is not in dir right now,
1166
 
//      fmtcmd inserts "cd dir\n" before the command.
1167
 
//
1168
 
//      fmtcmd replaces the value of b.work with $WORK.
1169
 
//      fmtcmd replaces the value of goroot with $GOROOT.
1170
 
//      fmtcmd replaces the value of b.gobin with $GOBIN.
1171
 
//
1172
 
//      fmtcmd replaces the name of the current directory with dot (.)
1173
 
//      but only when it is at the beginning of a space-separated token.
1174
 
//
1175
 
func (b *builder) fmtcmd(dir string, format string, args ...interface{}) string {
1176
 
        cmd := fmt.Sprintf(format, args...)
1177
 
        if dir != "" && dir != "/" {
1178
 
                cmd = strings.Replace(" "+cmd, " "+dir, " .", -1)[1:]
1179
 
                if b.scriptDir != dir {
1180
 
                        b.scriptDir = dir
1181
 
                        cmd = "cd " + dir + "\n" + cmd
1182
 
                }
1183
 
        }
1184
 
        if b.work != "" {
1185
 
                cmd = strings.Replace(cmd, b.work, "$WORK", -1)
1186
 
        }
1187
 
        return cmd
1188
 
}
1189
 
 
1190
 
// showcmd prints the given command to standard output
1191
 
// for the implementation of -n or -x.
1192
 
func (b *builder) showcmd(dir string, format string, args ...interface{}) {
1193
 
        b.output.Lock()
1194
 
        defer b.output.Unlock()
1195
 
        b.print(b.fmtcmd(dir, format, args...) + "\n")
1196
 
}
1197
 
 
1198
 
// showOutput prints "# desc" followed by the given output.
1199
 
// The output is expected to contain references to 'dir', usually
1200
 
// the source directory for the package that has failed to build.
1201
 
// showOutput rewrites mentions of dir with a relative path to dir
1202
 
// when the relative path is shorter.  This is usually more pleasant.
1203
 
// For example, if fmt doesn't compile and we are in src/pkg/html,
1204
 
// the output is
1205
 
//
1206
 
//      $ go build
1207
 
//      # fmt
1208
 
//      ../fmt/print.go:1090: undefined: asdf
1209
 
//      $
1210
 
//
1211
 
// instead of
1212
 
//
1213
 
//      $ go build
1214
 
//      # fmt
1215
 
//      /usr/gopher/go/src/pkg/fmt/print.go:1090: undefined: asdf
1216
 
//      $
1217
 
//
1218
 
// showOutput also replaces references to the work directory with $WORK.
1219
 
//
1220
 
func (b *builder) showOutput(dir, desc, out string) {
1221
 
        prefix := "# " + desc
1222
 
        suffix := "\n" + out
1223
 
        if reldir := shortPath(dir); reldir != dir {
1224
 
                suffix = strings.Replace(suffix, " "+dir, " "+reldir, -1)
1225
 
                suffix = strings.Replace(suffix, "\n"+dir, "\n"+reldir, -1)
1226
 
        }
1227
 
        suffix = strings.Replace(suffix, " "+b.work, " $WORK", -1)
1228
 
 
1229
 
        b.output.Lock()
1230
 
        defer b.output.Unlock()
1231
 
        b.print(prefix, suffix)
1232
 
}
1233
 
 
1234
 
// shortPath returns an absolute or relative name for path, whatever is shorter.
1235
 
func shortPath(path string) string {
1236
 
        if rel, err := filepath.Rel(cwd, path); err == nil && len(rel) < len(path) {
1237
 
                return rel
1238
 
        }
1239
 
        return path
1240
 
}
1241
 
 
1242
 
// relPaths returns a copy of paths with absolute paths
1243
 
// made relative to the current directory if they would be shorter.
1244
 
func relPaths(paths []string) []string {
1245
 
        var out []string
1246
 
        pwd, _ := os.Getwd()
1247
 
        for _, p := range paths {
1248
 
                rel, err := filepath.Rel(pwd, p)
1249
 
                if err == nil && len(rel) < len(p) {
1250
 
                        p = rel
1251
 
                }
1252
 
                out = append(out, p)
1253
 
        }
1254
 
        return out
1255
 
}
1256
 
 
1257
 
// errPrintedOutput is a special error indicating that a command failed
1258
 
// but that it generated output as well, and that output has already
1259
 
// been printed, so there's no point showing 'exit status 1' or whatever
1260
 
// the wait status was.  The main executor, builder.do, knows not to
1261
 
// print this error.
1262
 
var errPrintedOutput = errors.New("already printed output - no need to show error")
1263
 
 
1264
 
var cgoLine = regexp.MustCompile(`\[[^\[\]]+\.cgo1\.go:[0-9]+\]`)
1265
 
 
1266
 
// run runs the command given by cmdline in the directory dir.
1267
 
// If the command fails, run prints information about the failure
1268
 
// and returns a non-nil error.
1269
 
func (b *builder) run(dir string, desc string, env []string, cmdargs ...interface{}) error {
1270
 
        out, err := b.runOut(dir, desc, env, cmdargs...)
1271
 
        if len(out) > 0 {
1272
 
                if desc == "" {
1273
 
                        desc = b.fmtcmd(dir, "%s", strings.Join(stringList(cmdargs...), " "))
1274
 
                }
1275
 
                b.showOutput(dir, desc, b.processOutput(out))
1276
 
                if err != nil {
1277
 
                        err = errPrintedOutput
1278
 
                }
1279
 
        }
1280
 
        return err
1281
 
}
1282
 
 
1283
 
// processOutput prepares the output of runOut to be output to the console.
1284
 
func (b *builder) processOutput(out []byte) string {
1285
 
        if out[len(out)-1] != '\n' {
1286
 
                out = append(out, '\n')
1287
 
        }
1288
 
        messages := string(out)
1289
 
        // Fix up output referring to cgo-generated code to be more readable.
1290
 
        // Replace x.go:19[/tmp/.../x.cgo1.go:18] with x.go:19.
1291
 
        // Replace _Ctype_foo with C.foo.
1292
 
        // If we're using -x, assume we're debugging and want the full dump, so disable the rewrite.
1293
 
        if !buildX && cgoLine.MatchString(messages) {
1294
 
                messages = cgoLine.ReplaceAllString(messages, "")
1295
 
                messages = strings.Replace(messages, "type _Ctype_", "type C.", -1)
1296
 
        }
1297
 
        return messages
1298
 
}
1299
 
 
1300
 
// runOut runs the command given by cmdline in the directory dir.
1301
 
// It returns the command output and any errors that occurred.
1302
 
func (b *builder) runOut(dir string, desc string, env []string, cmdargs ...interface{}) ([]byte, error) {
1303
 
        cmdline := stringList(cmdargs...)
1304
 
        if buildN || buildX {
1305
 
                b.showcmd(dir, "%s", joinUnambiguously(cmdline))
1306
 
                if buildN {
1307
 
                        return nil, nil
1308
 
                }
1309
 
        }
1310
 
 
1311
 
        nbusy := 0
1312
 
        for {
1313
 
                var buf bytes.Buffer
1314
 
                cmd := exec.Command(cmdline[0], cmdline[1:]...)
1315
 
                cmd.Stdout = &buf
1316
 
                cmd.Stderr = &buf
1317
 
                cmd.Dir = dir
1318
 
                cmd.Env = mergeEnvLists(env, envForDir(cmd.Dir))
1319
 
                err := cmd.Run()
1320
 
 
1321
 
                // cmd.Run will fail on Unix if some other process has the binary
1322
 
                // we want to run open for writing.  This can happen here because
1323
 
                // we build and install the cgo command and then run it.
1324
 
                // If another command was kicked off while we were writing the
1325
 
                // cgo binary, the child process for that command may be holding
1326
 
                // a reference to the fd, keeping us from running exec.
1327
 
                //
1328
 
                // But, you might reasonably wonder, how can this happen?
1329
 
                // The cgo fd, like all our fds, is close-on-exec, so that we need
1330
 
                // not worry about other processes inheriting the fd accidentally.
1331
 
                // The answer is that running a command is fork and exec.
1332
 
                // A child forked while the cgo fd is open inherits that fd.
1333
 
                // Until the child has called exec, it holds the fd open and the
1334
 
                // kernel will not let us run cgo.  Even if the child were to close
1335
 
                // the fd explicitly, it would still be open from the time of the fork
1336
 
                // until the time of the explicit close, and the race would remain.
1337
 
                //
1338
 
                // On Unix systems, this results in ETXTBSY, which formats
1339
 
                // as "text file busy".  Rather than hard-code specific error cases,
1340
 
                // we just look for that string.  If this happens, sleep a little
1341
 
                // and try again.  We let this happen three times, with increasing
1342
 
                // sleep lengths: 100+200+400 ms = 0.7 seconds.
1343
 
                //
1344
 
                // An alternate solution might be to split the cmd.Run into
1345
 
                // separate cmd.Start and cmd.Wait, and then use an RWLock
1346
 
                // to make sure that copyFile only executes when no cmd.Start
1347
 
                // call is in progress.  However, cmd.Start (really syscall.forkExec)
1348
 
                // only guarantees that when it returns, the exec is committed to
1349
 
                // happen and succeed.  It uses a close-on-exec file descriptor
1350
 
                // itself to determine this, so we know that when cmd.Start returns,
1351
 
                // at least one close-on-exec file descriptor has been closed.
1352
 
                // However, we cannot be sure that all of them have been closed,
1353
 
                // so the program might still encounter ETXTBSY even with such
1354
 
                // an RWLock.  The race window would be smaller, perhaps, but not
1355
 
                // guaranteed to be gone.
1356
 
                //
1357
 
                // Sleeping when we observe the race seems to be the most reliable
1358
 
                // option we have.
1359
 
                //
1360
 
                // http://golang.org/issue/3001
1361
 
                //
1362
 
                if err != nil && nbusy < 3 && strings.Contains(err.Error(), "text file busy") {
1363
 
                        time.Sleep(100 * time.Millisecond << uint(nbusy))
1364
 
                        nbusy++
1365
 
                        continue
1366
 
                }
1367
 
 
1368
 
                return buf.Bytes(), err
1369
 
        }
1370
 
}
1371
 
 
1372
 
// joinUnambiguously prints the slice, quoting where necessary to make the
1373
 
// output unambiguous.
1374
 
// TODO: See issue 5279. The printing of commands needs a complete redo.
1375
 
func joinUnambiguously(a []string) string {
1376
 
        var buf bytes.Buffer
1377
 
        for i, s := range a {
1378
 
                if i > 0 {
1379
 
                        buf.WriteByte(' ')
1380
 
                }
1381
 
                q := strconv.Quote(s)
1382
 
                if s == "" || strings.Contains(s, " ") || len(q) > len(s)+2 {
1383
 
                        buf.WriteString(q)
1384
 
                } else {
1385
 
                        buf.WriteString(s)
1386
 
                }
1387
 
        }
1388
 
        return buf.String()
1389
 
}
1390
 
 
1391
 
// mkdir makes the named directory.
1392
 
func (b *builder) mkdir(dir string) error {
1393
 
        b.exec.Lock()
1394
 
        defer b.exec.Unlock()
1395
 
        // We can be a little aggressive about being
1396
 
        // sure directories exist.  Skip repeated calls.
1397
 
        if b.mkdirCache[dir] {
1398
 
                return nil
1399
 
        }
1400
 
        b.mkdirCache[dir] = true
1401
 
 
1402
 
        if buildN || buildX {
1403
 
                b.showcmd("", "mkdir -p %s", dir)
1404
 
                if buildN {
1405
 
                        return nil
1406
 
                }
1407
 
        }
1408
 
 
1409
 
        if err := os.MkdirAll(dir, 0777); err != nil {
1410
 
                return err
1411
 
        }
1412
 
        return nil
1413
 
}
1414
 
 
1415
 
// mkAbs returns an absolute path corresponding to
1416
 
// evaluating f in the directory dir.
1417
 
// We always pass absolute paths of source files so that
1418
 
// the error messages will include the full path to a file
1419
 
// in need of attention.
1420
 
func mkAbs(dir, f string) string {
1421
 
        // Leave absolute paths alone.
1422
 
        // Also, during -n mode we use the pseudo-directory $WORK
1423
 
        // instead of creating an actual work directory that won't be used.
1424
 
        // Leave paths beginning with $WORK alone too.
1425
 
        if filepath.IsAbs(f) || strings.HasPrefix(f, "$WORK") {
1426
 
                return f
1427
 
        }
1428
 
        return filepath.Join(dir, f)
1429
 
}
1430
 
 
1431
 
type toolchain interface {
1432
 
        // gc runs the compiler in a specific directory on a set of files
1433
 
        // and returns the name of the generated output file.
1434
 
        // The compiler runs in the directory dir.
1435
 
        gc(b *builder, p *Package, obj string, importArgs []string, gofiles []string) (ofile string, out []byte, err error)
1436
 
        // cc runs the toolchain's C compiler in a directory on a C file
1437
 
        // to produce an output file.
1438
 
        cc(b *builder, p *Package, objdir, ofile, cfile string) error
1439
 
        // asm runs the assembler in a specific directory on a specific file
1440
 
        // to generate the named output file.
1441
 
        asm(b *builder, p *Package, obj, ofile, sfile string) error
1442
 
        // pkgpath builds an appropriate path for a temporary package file.
1443
 
        pkgpath(basedir string, p *Package) string
1444
 
        // pack runs the archive packer in a specific directory to create
1445
 
        // an archive from a set of object files.
1446
 
        // typically it is run in the object directory.
1447
 
        pack(b *builder, p *Package, objDir, afile string, ofiles []string) error
1448
 
        // ld runs the linker to create a package starting at mainpkg.
1449
 
        ld(b *builder, p *Package, out string, allactions []*action, mainpkg string, ofiles []string) error
1450
 
 
1451
 
        compiler() string
1452
 
        linker() string
1453
 
}
1454
 
 
1455
 
type noToolchain struct{}
1456
 
 
1457
 
func noCompiler() error {
1458
 
        log.Fatalf("unknown compiler %q", buildContext.Compiler)
1459
 
        return nil
1460
 
}
1461
 
 
1462
 
func (noToolchain) compiler() string {
1463
 
        noCompiler()
1464
 
        return ""
1465
 
}
1466
 
 
1467
 
func (noToolchain) linker() string {
1468
 
        noCompiler()
1469
 
        return ""
1470
 
}
1471
 
 
1472
 
func (noToolchain) gc(b *builder, p *Package, obj string, importArgs []string, gofiles []string) (ofile string, out []byte, err error) {
1473
 
        return "", nil, noCompiler()
1474
 
}
1475
 
 
1476
 
func (noToolchain) asm(b *builder, p *Package, obj, ofile, sfile string) error {
1477
 
        return noCompiler()
1478
 
}
1479
 
 
1480
 
func (noToolchain) pkgpath(basedir string, p *Package) string {
1481
 
        noCompiler()
1482
 
        return ""
1483
 
}
1484
 
 
1485
 
func (noToolchain) pack(b *builder, p *Package, objDir, afile string, ofiles []string) error {
1486
 
        return noCompiler()
1487
 
}
1488
 
 
1489
 
func (noToolchain) ld(b *builder, p *Package, out string, allactions []*action, mainpkg string, ofiles []string) error {
1490
 
        return noCompiler()
1491
 
}
1492
 
 
1493
 
func (noToolchain) cc(b *builder, p *Package, objdir, ofile, cfile string) error {
1494
 
        return noCompiler()
1495
 
}
1496
 
 
1497
 
// The Go toolchain.
1498
 
type gcToolchain struct{}
1499
 
 
1500
 
func (gcToolchain) compiler() string {
1501
 
        return tool(archChar + "g")
1502
 
}
1503
 
 
1504
 
func (gcToolchain) linker() string {
1505
 
        return tool(archChar + "l")
1506
 
}
1507
 
 
1508
 
func (gcToolchain) gc(b *builder, p *Package, obj string, importArgs []string, gofiles []string) (ofile string, output []byte, err error) {
1509
 
        out := "_go_." + archChar
1510
 
        ofile = obj + out
1511
 
        gcargs := []string{"-p", p.ImportPath}
1512
 
        if p.Standard && p.ImportPath == "runtime" {
1513
 
                // runtime compiles with a special 6g flag to emit
1514
 
                // additional reflect type data.
1515
 
                gcargs = append(gcargs, "-+")
1516
 
        }
1517
 
 
1518
 
        // If we're giving the compiler the entire package (no C etc files), tell it that,
1519
 
        // so that it can give good error messages about forward declarations.
1520
 
        // Exceptions: a few standard packages have forward declarations for
1521
 
        // pieces supplied behind-the-scenes by package runtime.
1522
 
        extFiles := len(p.CgoFiles) + len(p.CFiles) + len(p.CXXFiles) + len(p.SFiles) + len(p.SysoFiles) + len(p.SwigFiles) + len(p.SwigCXXFiles)
1523
 
        if p.Standard {
1524
 
                switch p.ImportPath {
1525
 
                case "os", "runtime/pprof", "sync", "time":
1526
 
                        extFiles++
1527
 
                }
1528
 
        }
1529
 
        if extFiles == 0 {
1530
 
                gcargs = append(gcargs, "-complete")
1531
 
        }
1532
 
        if buildContext.InstallSuffix != "" {
1533
 
                gcargs = append(gcargs, "-installsuffix", buildContext.InstallSuffix)
1534
 
        }
1535
 
 
1536
 
        args := stringList(tool(archChar+"g"), "-o", ofile, buildGcflags, gcargs, "-D", p.localPrefix, importArgs)
1537
 
        for _, f := range gofiles {
1538
 
                args = append(args, mkAbs(p.Dir, f))
1539
 
        }
1540
 
 
1541
 
        output, err = b.runOut(p.Dir, p.ImportPath, nil, args)
1542
 
        return ofile, output, err
1543
 
}
1544
 
 
1545
 
func (gcToolchain) asm(b *builder, p *Package, obj, ofile, sfile string) error {
1546
 
        sfile = mkAbs(p.Dir, sfile)
1547
 
        return b.run(p.Dir, p.ImportPath, nil, tool(archChar+"a"), "-I", obj, "-o", ofile, "-D", "GOOS_"+goos, "-D", "GOARCH_"+goarch, sfile)
1548
 
}
1549
 
 
1550
 
func (gcToolchain) pkgpath(basedir string, p *Package) string {
1551
 
        end := filepath.FromSlash(p.ImportPath + ".a")
1552
 
        return filepath.Join(basedir, end)
1553
 
}
1554
 
 
1555
 
func (gcToolchain) pack(b *builder, p *Package, objDir, afile string, ofiles []string) error {
1556
 
        var absOfiles []string
1557
 
        for _, f := range ofiles {
1558
 
                absOfiles = append(absOfiles, mkAbs(objDir, f))
1559
 
        }
1560
 
        return b.run(p.Dir, p.ImportPath, nil, tool("pack"), "grcP", b.work, mkAbs(objDir, afile), absOfiles)
1561
 
}
1562
 
 
1563
 
func (gcToolchain) ld(b *builder, p *Package, out string, allactions []*action, mainpkg string, ofiles []string) error {
1564
 
        importArgs := b.includeArgs("-L", allactions)
1565
 
        swigDirs := make(map[string]bool)
1566
 
        swigArg := []string{}
1567
 
        cxx := false
1568
 
        for _, a := range allactions {
1569
 
                if a.p != nil && a.p.usesSwig() {
1570
 
                        sd := a.p.swigDir(&buildContext)
1571
 
                        if len(swigArg) == 0 {
1572
 
                                swigArg = []string{"-r", sd}
1573
 
                        } else if !swigDirs[sd] {
1574
 
                                swigArg[1] += ":"
1575
 
                                swigArg[1] += sd
1576
 
                        }
1577
 
                        swigDirs[sd] = true
1578
 
                        if a.objdir != "" && !swigDirs[a.objdir] {
1579
 
                                swigArg[1] += ":"
1580
 
                                swigArg[1] += a.objdir
1581
 
                                swigDirs[a.objdir] = true
1582
 
                        }
1583
 
                }
1584
 
                if a.p != nil && len(a.p.CXXFiles) > 0 {
1585
 
                        cxx = true
1586
 
                }
1587
 
        }
1588
 
        ldflags := buildLdflags
1589
 
        if buildContext.InstallSuffix != "" {
1590
 
                ldflags = append(ldflags, "-installsuffix", buildContext.InstallSuffix)
1591
 
        }
1592
 
        if cxx {
1593
 
                // The program includes C++ code.  If the user has not
1594
 
                // specified the -extld option, then default to
1595
 
                // linking with the compiler named by the CXX
1596
 
                // environment variable, or g++ if CXX is not set.
1597
 
                extld := false
1598
 
                for _, f := range ldflags {
1599
 
                        if f == "-extld" || strings.HasPrefix(f, "-extld=") {
1600
 
                                extld = true
1601
 
                                break
1602
 
                        }
1603
 
                }
1604
 
                if !extld {
1605
 
                        compiler := strings.Fields(os.Getenv("CXX"))
1606
 
                        if len(compiler) == 0 {
1607
 
                                compiler = []string{"g++"}
1608
 
                        }
1609
 
                        ldflags = append(ldflags, "-extld="+compiler[0])
1610
 
                        if len(compiler) > 1 {
1611
 
                                extldflags := false
1612
 
                                add := strings.Join(compiler[1:], " ")
1613
 
                                for i, f := range ldflags {
1614
 
                                        if f == "-extldflags" && i+1 < len(ldflags) {
1615
 
                                                ldflags[i+1] = add + " " + ldflags[i+1]
1616
 
                                                extldflags = true
1617
 
                                                break
1618
 
                                        } else if strings.HasPrefix(f, "-extldflags=") {
1619
 
                                                ldflags[i] = "-extldflags=" + add + " " + ldflags[i][len("-extldflags="):]
1620
 
                                                extldflags = true
1621
 
                                                break
1622
 
                                        }
1623
 
                                }
1624
 
                                if !extldflags {
1625
 
                                        ldflags = append(ldflags, "-extldflags="+add)
1626
 
                                }
1627
 
                        }
1628
 
                }
1629
 
        }
1630
 
        return b.run(".", p.ImportPath, nil, tool(archChar+"l"), "-o", out, importArgs, swigArg, ldflags, mainpkg)
1631
 
}
1632
 
 
1633
 
func (gcToolchain) cc(b *builder, p *Package, objdir, ofile, cfile string) error {
1634
 
        inc := filepath.Join(goroot, "pkg", fmt.Sprintf("%s_%s", goos, goarch))
1635
 
        cfile = mkAbs(p.Dir, cfile)
1636
 
        args := stringList(tool(archChar+"c"), "-F", "-V", "-w", "-I", objdir, "-I", inc, "-o", ofile, buildCcflags, "-D", "GOOS_"+goos, "-D", "GOARCH_"+goarch, cfile)
1637
 
        return b.run(p.Dir, p.ImportPath, nil, args)
1638
 
}
1639
 
 
1640
 
// The Gccgo toolchain.
1641
 
type gccgoToolchain struct{}
1642
 
 
1643
 
var gccgoBin, _ = exec.LookPath("gccgo")
1644
 
 
1645
 
func (gccgoToolchain) compiler() string {
1646
 
        return gccgoBin
1647
 
}
1648
 
 
1649
 
func (gccgoToolchain) linker() string {
1650
 
        return gccgoBin
1651
 
}
1652
 
 
1653
 
func (gccgoToolchain) gc(b *builder, p *Package, obj string, importArgs []string, gofiles []string) (ofile string, output []byte, err error) {
1654
 
        out := p.Name + ".o"
1655
 
        ofile = obj + out
1656
 
        gcargs := []string{"-g"}
1657
 
        gcargs = append(gcargs, b.gccArchArgs()...)
1658
 
        if pkgpath := gccgoPkgpath(p); pkgpath != "" {
1659
 
                gcargs = append(gcargs, "-fgo-pkgpath="+pkgpath)
1660
 
        }
1661
 
        if p.localPrefix != "" {
1662
 
                gcargs = append(gcargs, "-fgo-relative-import-path="+p.localPrefix)
1663
 
        }
1664
 
        args := stringList("gccgo", importArgs, "-c", gcargs, "-o", ofile, buildGccgoflags)
1665
 
        for _, f := range gofiles {
1666
 
                args = append(args, mkAbs(p.Dir, f))
1667
 
        }
1668
 
 
1669
 
        output, err = b.runOut(p.Dir, p.ImportPath, nil, args)
1670
 
        return ofile, output, err
1671
 
}
1672
 
 
1673
 
func (gccgoToolchain) asm(b *builder, p *Package, obj, ofile, sfile string) error {
1674
 
        sfile = mkAbs(p.Dir, sfile)
1675
 
        defs := []string{"-D", "GOOS_" + goos, "-D", "GOARCH_" + goarch}
1676
 
        if pkgpath := gccgoCleanPkgpath(p); pkgpath != "" {
1677
 
                defs = append(defs, `-D`, `GOPKGPATH="`+pkgpath+`"`)
1678
 
        }
1679
 
        defs = append(defs, b.gccArchArgs()...)
1680
 
        return b.run(p.Dir, p.ImportPath, nil, "gccgo", "-I", obj, "-o", ofile, defs, sfile)
1681
 
}
1682
 
 
1683
 
func (gccgoToolchain) pkgpath(basedir string, p *Package) string {
1684
 
        end := filepath.FromSlash(p.ImportPath + ".a")
1685
 
        afile := filepath.Join(basedir, end)
1686
 
        // add "lib" to the final element
1687
 
        return filepath.Join(filepath.Dir(afile), "lib"+filepath.Base(afile))
1688
 
}
1689
 
 
1690
 
func (gccgoToolchain) pack(b *builder, p *Package, objDir, afile string, ofiles []string) error {
1691
 
        var absOfiles []string
1692
 
        for _, f := range ofiles {
1693
 
                absOfiles = append(absOfiles, mkAbs(objDir, f))
1694
 
        }
1695
 
        return b.run(p.Dir, p.ImportPath, nil, "ar", "cru", mkAbs(objDir, afile), absOfiles)
1696
 
}
1697
 
 
1698
 
func (tools gccgoToolchain) ld(b *builder, p *Package, out string, allactions []*action, mainpkg string, ofiles []string) error {
1699
 
        // gccgo needs explicit linking with all package dependencies,
1700
 
        // and all LDFLAGS from cgo dependencies.
1701
 
        afilesSeen := make(map[*Package]bool)
1702
 
        afiles := []string{}
1703
 
        sfiles := []string{}
1704
 
        ldflags := b.gccArchArgs()
1705
 
        cgoldflags := []string{}
1706
 
        usesCgo := false
1707
 
        cxx := false
1708
 
        for _, a := range allactions {
1709
 
                if a.p != nil {
1710
 
                        if !a.p.Standard {
1711
 
                                if !afilesSeen[a.p] || a.objpkg != a.target {
1712
 
                                        afilesSeen[a.p] = true
1713
 
                                        afiles = append(afiles, a.target)
1714
 
                                }
1715
 
                        }
1716
 
                        cgoldflags = append(cgoldflags, a.p.CgoLDFLAGS...)
1717
 
                        if len(a.p.CgoFiles) > 0 {
1718
 
                                usesCgo = true
1719
 
                        }
1720
 
                        if a.p.usesSwig() {
1721
 
                                sd := a.p.swigDir(&buildContext)
1722
 
                                if a.objdir != "" {
1723
 
                                        sd = a.objdir
1724
 
                                }
1725
 
                                for _, f := range stringList(a.p.SwigFiles, a.p.SwigCXXFiles) {
1726
 
                                        soname := a.p.swigSoname(f)
1727
 
                                        sfiles = append(sfiles, filepath.Join(sd, soname))
1728
 
                                }
1729
 
                                usesCgo = true
1730
 
                        }
1731
 
                        if len(a.p.CXXFiles) > 0 {
1732
 
                                cxx = true
1733
 
                        }
1734
 
                }
1735
 
        }
1736
 
        ldflags = append(ldflags, afiles...)
1737
 
        ldflags = append(ldflags, sfiles...)
1738
 
        ldflags = append(ldflags, cgoldflags...)
1739
 
        if usesCgo && goos == "linux" {
1740
 
                ldflags = append(ldflags, "-Wl,-E")
1741
 
        }
1742
 
        if cxx {
1743
 
                ldflags = append(ldflags, "-lstdc++")
1744
 
        }
1745
 
        return b.run(".", p.ImportPath, nil, "gccgo", "-o", out, ofiles, "-Wl,-(", ldflags, "-Wl,-)", buildGccgoflags)
1746
 
}
1747
 
 
1748
 
func (gccgoToolchain) cc(b *builder, p *Package, objdir, ofile, cfile string) error {
1749
 
        inc := filepath.Join(goroot, "pkg", fmt.Sprintf("%s_%s", goos, goarch))
1750
 
        cfile = mkAbs(p.Dir, cfile)
1751
 
        defs := []string{"-D", "GOOS_" + goos, "-D", "GOARCH_" + goarch}
1752
 
        defs = append(defs, b.gccArchArgs()...)
1753
 
        if pkgpath := gccgoCleanPkgpath(p); pkgpath != "" {
1754
 
                defs = append(defs, `-D`, `GOPKGPATH="`+pkgpath+`"`)
1755
 
        }
1756
 
        // TODO: Support using clang here (during gccgo build)?
1757
 
        return b.run(p.Dir, p.ImportPath, nil, "gcc", "-Wall", "-g",
1758
 
                "-I", objdir, "-I", inc, "-o", ofile, defs, "-c", cfile)
1759
 
}
1760
 
 
1761
 
func gccgoPkgpath(p *Package) string {
1762
 
        if p.build.IsCommand() && !p.forceLibrary {
1763
 
                return ""
1764
 
        }
1765
 
        return p.ImportPath
1766
 
}
1767
 
 
1768
 
func gccgoCleanPkgpath(p *Package) string {
1769
 
        clean := func(r rune) rune {
1770
 
                switch {
1771
 
                case 'A' <= r && r <= 'Z', 'a' <= r && r <= 'z',
1772
 
                        '0' <= r && r <= '9':
1773
 
                        return r
1774
 
                }
1775
 
                return '_'
1776
 
        }
1777
 
        return strings.Map(clean, gccgoPkgpath(p))
1778
 
}
1779
 
 
1780
 
// libgcc returns the filename for libgcc, as determined by invoking gcc with
1781
 
// the -print-libgcc-file-name option.
1782
 
func (b *builder) libgcc(p *Package) (string, error) {
1783
 
        var buf bytes.Buffer
1784
 
 
1785
 
        gccCmd := b.gccCmd(p.Dir)
1786
 
 
1787
 
        prev := b.print
1788
 
        if buildN {
1789
 
                // In -n mode we temporarily swap out the builder's
1790
 
                // print function to capture the command-line. This
1791
 
                // let's us assign it to $LIBGCC and produce a valid
1792
 
                // buildscript for cgo packages.
1793
 
                b.print = func(a ...interface{}) (int, error) {
1794
 
                        return fmt.Fprint(&buf, a...)
1795
 
                }
1796
 
        }
1797
 
        f, err := b.runOut(p.Dir, p.ImportPath, nil, gccCmd, "-print-libgcc-file-name")
1798
 
        if err != nil {
1799
 
                return "", fmt.Errorf("gcc -print-libgcc-file-name: %v (%s)", err, f)
1800
 
        }
1801
 
        if buildN {
1802
 
                s := fmt.Sprintf("LIBGCC=$(%s)\n", buf.Next(buf.Len()-1))
1803
 
                b.print = prev
1804
 
                b.print(s)
1805
 
                return "$LIBGCC", nil
1806
 
        }
1807
 
 
1808
 
        // clang might not be able to find libgcc, and in that case,
1809
 
        // it will simply return "libgcc.a", which is of no use to us.
1810
 
        if strings.Contains(gccCmd[0], "clang") && !filepath.IsAbs(string(f)) {
1811
 
                return "", nil
1812
 
        }
1813
 
 
1814
 
        return strings.Trim(string(f), "\r\n"), nil
1815
 
}
1816
 
 
1817
 
// gcc runs the gcc C compiler to create an object from a single C file.
1818
 
func (b *builder) gcc(p *Package, out string, flags []string, cfile string) error {
1819
 
        return b.ccompile(p, out, flags, cfile, b.gccCmd(p.Dir))
1820
 
}
1821
 
 
1822
 
// gxx runs the g++ C++ compiler to create an object from a single C++ file.
1823
 
func (b *builder) gxx(p *Package, out string, flags []string, cxxfile string) error {
1824
 
        return b.ccompile(p, out, flags, cxxfile, b.gxxCmd(p.Dir))
1825
 
}
1826
 
 
1827
 
// ccompile runs the given C or C++ compiler and creates an object from a single source file.
1828
 
func (b *builder) ccompile(p *Package, out string, flags []string, file string, compiler []string) error {
1829
 
        file = mkAbs(p.Dir, file)
1830
 
        return b.run(p.Dir, p.ImportPath, nil, compiler, flags, "-o", out, "-c", file)
1831
 
}
1832
 
 
1833
 
// gccld runs the gcc linker to create an executable from a set of object files.
1834
 
func (b *builder) gccld(p *Package, out string, flags []string, obj []string) error {
1835
 
        var cmd []string
1836
 
        if len(p.CXXFiles) > 0 {
1837
 
                cmd = b.gxxCmd(p.Dir)
1838
 
        } else {
1839
 
                cmd = b.gccCmd(p.Dir)
1840
 
        }
1841
 
        return b.run(p.Dir, p.ImportPath, nil, cmd, "-o", out, obj, flags)
1842
 
}
1843
 
 
1844
 
// gccCmd returns a gcc command line prefix
1845
 
// defaultCC is defined in zdefaultcc.go, written by cmd/dist.
1846
 
func (b *builder) gccCmd(objdir string) []string {
1847
 
        return b.ccompilerCmd("CC", defaultCC, objdir)
1848
 
}
1849
 
 
1850
 
// gxxCmd returns a g++ command line prefix
1851
 
// defaultCXX is defined in zdefaultcc.go, written by cmd/dist.
1852
 
func (b *builder) gxxCmd(objdir string) []string {
1853
 
        return b.ccompilerCmd("CXX", defaultCXX, objdir)
1854
 
}
1855
 
 
1856
 
// ccompilerCmd returns a command line prefix for the given environment
1857
 
// variable and using the default command when the variable is empty
1858
 
func (b *builder) ccompilerCmd(envvar, defcmd, objdir string) []string {
1859
 
        // NOTE: env.go's mkEnv knows that the first three
1860
 
        // strings returned are "gcc", "-I", objdir (and cuts them off).
1861
 
 
1862
 
        compiler := strings.Fields(os.Getenv(envvar))
1863
 
        if len(compiler) == 0 {
1864
 
                compiler = strings.Fields(defcmd)
1865
 
        }
1866
 
        a := []string{compiler[0], "-I", objdir, "-g", "-O2"}
1867
 
        a = append(a, compiler[1:]...)
1868
 
 
1869
 
        // Definitely want -fPIC but on Windows gcc complains
1870
 
        // "-fPIC ignored for target (all code is position independent)"
1871
 
        if goos != "windows" {
1872
 
                a = append(a, "-fPIC")
1873
 
        }
1874
 
        a = append(a, b.gccArchArgs()...)
1875
 
        // gcc-4.5 and beyond require explicit "-pthread" flag
1876
 
        // for multithreading with pthread library.
1877
 
        if buildContext.CgoEnabled {
1878
 
                switch goos {
1879
 
                case "windows":
1880
 
                        a = append(a, "-mthreads")
1881
 
                default:
1882
 
                        a = append(a, "-pthread")
1883
 
                }
1884
 
        }
1885
 
 
1886
 
        if strings.Contains(a[0], "clang") {
1887
 
                // disable ASCII art in clang errors, if possible
1888
 
                a = append(a, "-fno-caret-diagnostics")
1889
 
                // clang is too smart about command-line arguments
1890
 
                a = append(a, "-Qunused-arguments")
1891
 
        }
1892
 
 
1893
 
        // On OS X, some of the compilers behave as if -fno-common
1894
 
        // is always set, and the Mach-O linker in 6l/8l assumes this.
1895
 
        // See http://golang.org/issue/3253.
1896
 
        if goos == "darwin" {
1897
 
                a = append(a, "-fno-common")
1898
 
        }
1899
 
 
1900
 
        return a
1901
 
}
1902
 
 
1903
 
// gccArchArgs returns arguments to pass to gcc based on the architecture.
1904
 
func (b *builder) gccArchArgs() []string {
1905
 
        switch archChar {
1906
 
        case "8":
1907
 
                return []string{"-m32"}
1908
 
        case "6":
1909
 
                return []string{"-m64"}
1910
 
        case "5":
1911
 
                return []string{"-marm"} // not thumb
1912
 
        }
1913
 
        return nil
1914
 
}
1915
 
 
1916
 
func envList(key string) []string {
1917
 
        return strings.Fields(os.Getenv(key))
1918
 
}
1919
 
 
1920
 
var cgoRe = regexp.MustCompile(`[/\\:]`)
1921
 
 
1922
 
var (
1923
 
        cgoLibGccFile     string
1924
 
        cgoLibGccErr      error
1925
 
        cgoLibGccFileOnce sync.Once
1926
 
)
1927
 
 
1928
 
func (b *builder) cgo(p *Package, cgoExe, obj string, gccfiles []string, gxxfiles []string) (outGo, outObj []string, err error) {
1929
 
        if goos != toolGOOS {
1930
 
                return nil, nil, errors.New("cannot use cgo when compiling for a different operating system")
1931
 
        }
1932
 
 
1933
 
        cgoCPPFLAGS := stringList(envList("CGO_CPPFLAGS"), p.CgoCPPFLAGS)
1934
 
        cgoCFLAGS := stringList(envList("CGO_CFLAGS"), p.CgoCFLAGS)
1935
 
        cgoCXXFLAGS := stringList(envList("CGO_CXXFLAGS"), p.CgoCXXFLAGS)
1936
 
        cgoLDFLAGS := stringList(envList("CGO_LDFLAGS"), p.CgoLDFLAGS)
1937
 
 
1938
 
        if pkgs := p.CgoPkgConfig; len(pkgs) > 0 {
1939
 
                out, err := b.runOut(p.Dir, p.ImportPath, nil, "pkg-config", "--cflags", pkgs)
1940
 
                if err != nil {
1941
 
                        b.showOutput(p.Dir, "pkg-config --cflags "+strings.Join(pkgs, " "), string(out))
1942
 
                        b.print(err.Error() + "\n")
1943
 
                        return nil, nil, errPrintedOutput
1944
 
                }
1945
 
                if len(out) > 0 {
1946
 
                        cgoCPPFLAGS = append(cgoCPPFLAGS, strings.Fields(string(out))...)
1947
 
                }
1948
 
                out, err = b.runOut(p.Dir, p.ImportPath, nil, "pkg-config", "--libs", pkgs)
1949
 
                if err != nil {
1950
 
                        b.showOutput(p.Dir, "pkg-config --libs "+strings.Join(pkgs, " "), string(out))
1951
 
                        b.print(err.Error() + "\n")
1952
 
                        return nil, nil, errPrintedOutput
1953
 
                }
1954
 
                if len(out) > 0 {
1955
 
                        cgoLDFLAGS = append(cgoLDFLAGS, strings.Fields(string(out))...)
1956
 
                }
1957
 
        }
1958
 
 
1959
 
        // Allows including _cgo_export.h from .[ch] files in the package.
1960
 
        cgoCPPFLAGS = append(cgoCPPFLAGS, "-I", obj)
1961
 
 
1962
 
        // cgo
1963
 
        // TODO: CGOPKGPATH, CGO_FLAGS?
1964
 
        gofiles := []string{obj + "_cgo_gotypes.go"}
1965
 
        cfiles := []string{"_cgo_main.c", "_cgo_export.c"}
1966
 
        for _, fn := range p.CgoFiles {
1967
 
                f := cgoRe.ReplaceAllString(fn[:len(fn)-2], "_")
1968
 
                gofiles = append(gofiles, obj+f+"cgo1.go")
1969
 
                cfiles = append(cfiles, f+"cgo2.c")
1970
 
        }
1971
 
        defunC := obj + "_cgo_defun.c"
1972
 
 
1973
 
        cgoflags := []string{}
1974
 
        // TODO: make cgo not depend on $GOARCH?
1975
 
 
1976
 
        objExt := archChar
1977
 
 
1978
 
        if p.Standard && p.ImportPath == "runtime/cgo" {
1979
 
                cgoflags = append(cgoflags, "-import_runtime_cgo=false")
1980
 
        }
1981
 
        if p.Standard && (p.ImportPath == "runtime/race" || p.ImportPath == "runtime/cgo") {
1982
 
                cgoflags = append(cgoflags, "-import_syscall=false")
1983
 
        }
1984
 
 
1985
 
        // Update $CGO_LDFLAGS with p.CgoLDFLAGS.
1986
 
        var cgoenv []string
1987
 
        if len(cgoLDFLAGS) > 0 {
1988
 
                flags := make([]string, len(cgoLDFLAGS))
1989
 
                for i, f := range cgoLDFLAGS {
1990
 
                        flags[i] = strconv.Quote(f)
1991
 
                }
1992
 
                cgoenv = []string{"CGO_LDFLAGS=" + strings.Join(flags, " ")}
1993
 
        }
1994
 
 
1995
 
        if _, ok := buildToolchain.(gccgoToolchain); ok {
1996
 
                cgoflags = append(cgoflags, "-gccgo")
1997
 
                if pkgpath := gccgoPkgpath(p); pkgpath != "" {
1998
 
                        cgoflags = append(cgoflags, "-gccgopkgpath="+pkgpath)
1999
 
                }
2000
 
                objExt = "o"
2001
 
        }
2002
 
        if err := b.run(p.Dir, p.ImportPath, cgoenv, cgoExe, "-objdir", obj, cgoflags, "--", cgoCPPFLAGS, cgoCFLAGS, p.CgoFiles); err != nil {
2003
 
                return nil, nil, err
2004
 
        }
2005
 
        outGo = append(outGo, gofiles...)
2006
 
 
2007
 
        // cc _cgo_defun.c
2008
 
        defunObj := obj + "_cgo_defun." + objExt
2009
 
        if err := buildToolchain.cc(b, p, obj, defunObj, defunC); err != nil {
2010
 
                return nil, nil, err
2011
 
        }
2012
 
        outObj = append(outObj, defunObj)
2013
 
 
2014
 
        // gcc
2015
 
        var linkobj []string
2016
 
 
2017
 
        var bareLDFLAGS []string
2018
 
        // filter out -lsomelib, -l somelib, *.{so,dll,dylib}, and (on Darwin) -framework X
2019
 
        for i := 0; i < len(cgoLDFLAGS); i++ {
2020
 
                f := cgoLDFLAGS[i]
2021
 
                switch {
2022
 
                // skip "-lc" or "-l somelib"
2023
 
                case strings.HasPrefix(f, "-l"):
2024
 
                        if f == "-l" {
2025
 
                                i++
2026
 
                        }
2027
 
                // skip "-framework X" on Darwin
2028
 
                case goos == "darwin" && f == "-framework":
2029
 
                        i++
2030
 
                // skip "*.{dylib,so,dll}"
2031
 
                case strings.HasSuffix(f, ".dylib"),
2032
 
                        strings.HasSuffix(f, ".so"),
2033
 
                        strings.HasSuffix(f, ".dll"):
2034
 
                        continue
2035
 
                default:
2036
 
                        bareLDFLAGS = append(bareLDFLAGS, f)
2037
 
                }
2038
 
        }
2039
 
 
2040
 
        cgoLibGccFileOnce.Do(func() {
2041
 
                cgoLibGccFile, cgoLibGccErr = b.libgcc(p)
2042
 
        })
2043
 
        if cgoLibGccFile == "" && cgoLibGccErr != nil {
2044
 
                return nil, nil, err
2045
 
        }
2046
 
 
2047
 
        var staticLibs []string
2048
 
        if goos == "windows" {
2049
 
                // libmingw32 and libmingwex might also use libgcc, so libgcc must come last,
2050
 
                // and they also have some inter-dependencies, so must use linker groups.
2051
 
                staticLibs = []string{"-Wl,--start-group", "-lmingwex", "-lmingw32", "-Wl,--end-group"}
2052
 
        }
2053
 
        if cgoLibGccFile != "" {
2054
 
                staticLibs = append(staticLibs, cgoLibGccFile)
2055
 
        }
2056
 
 
2057
 
        cflags := stringList(cgoCPPFLAGS, cgoCFLAGS)
2058
 
        for _, cfile := range cfiles {
2059
 
                ofile := obj + cfile[:len(cfile)-1] + "o"
2060
 
                if err := b.gcc(p, ofile, cflags, obj+cfile); err != nil {
2061
 
                        return nil, nil, err
2062
 
                }
2063
 
                linkobj = append(linkobj, ofile)
2064
 
                if !strings.HasSuffix(ofile, "_cgo_main.o") {
2065
 
                        outObj = append(outObj, ofile)
2066
 
                }
2067
 
        }
2068
 
 
2069
 
        for _, file := range gccfiles {
2070
 
                ofile := obj + cgoRe.ReplaceAllString(file[:len(file)-1], "_") + "o"
2071
 
                if err := b.gcc(p, ofile, cflags, file); err != nil {
2072
 
                        return nil, nil, err
2073
 
                }
2074
 
                linkobj = append(linkobj, ofile)
2075
 
                outObj = append(outObj, ofile)
2076
 
        }
2077
 
 
2078
 
        cxxflags := stringList(cgoCPPFLAGS, cgoCXXFLAGS)
2079
 
        for _, file := range gxxfiles {
2080
 
                // Append .o to the file, just in case the pkg has file.c and file.cpp
2081
 
                ofile := obj + cgoRe.ReplaceAllString(file, "_") + ".o"
2082
 
                if err := b.gxx(p, ofile, cxxflags, file); err != nil {
2083
 
                        return nil, nil, err
2084
 
                }
2085
 
                linkobj = append(linkobj, ofile)
2086
 
                outObj = append(outObj, ofile)
2087
 
        }
2088
 
 
2089
 
        linkobj = append(linkobj, p.SysoFiles...)
2090
 
        dynobj := obj + "_cgo_.o"
2091
 
        if goarch == "arm" && goos == "linux" { // we need to use -pie for Linux/ARM to get accurate imported sym
2092
 
                cgoLDFLAGS = append(cgoLDFLAGS, "-pie")
2093
 
        }
2094
 
        if err := b.gccld(p, dynobj, cgoLDFLAGS, linkobj); err != nil {
2095
 
                return nil, nil, err
2096
 
        }
2097
 
        if goarch == "arm" && goos == "linux" { // but we don't need -pie for normal cgo programs
2098
 
                cgoLDFLAGS = cgoLDFLAGS[0 : len(cgoLDFLAGS)-1]
2099
 
        }
2100
 
 
2101
 
        if _, ok := buildToolchain.(gccgoToolchain); ok {
2102
 
                // we don't use dynimport when using gccgo.
2103
 
                return outGo, outObj, nil
2104
 
        }
2105
 
 
2106
 
        // cgo -dynimport
2107
 
        importC := obj + "_cgo_import.c"
2108
 
        cgoflags = []string{}
2109
 
        if p.Standard && p.ImportPath == "runtime/cgo" {
2110
 
                cgoflags = append(cgoflags, "-dynlinker") // record path to dynamic linker
2111
 
        }
2112
 
        if err := b.run(p.Dir, p.ImportPath, nil, cgoExe, "-objdir", obj, "-dynimport", dynobj, "-dynout", importC, cgoflags); err != nil {
2113
 
                return nil, nil, err
2114
 
        }
2115
 
 
2116
 
        // cc _cgo_import.ARCH
2117
 
        importObj := obj + "_cgo_import." + objExt
2118
 
        if err := buildToolchain.cc(b, p, obj, importObj, importC); err != nil {
2119
 
                return nil, nil, err
2120
 
        }
2121
 
 
2122
 
        ofile := obj + "_all.o"
2123
 
        var gccObjs, nonGccObjs []string
2124
 
        for _, f := range outObj {
2125
 
                if strings.HasSuffix(f, ".o") {
2126
 
                        gccObjs = append(gccObjs, f)
2127
 
                } else {
2128
 
                        nonGccObjs = append(nonGccObjs, f)
2129
 
                }
2130
 
        }
2131
 
        if err := b.gccld(p, ofile, stringList(bareLDFLAGS, "-Wl,-r", "-nostdlib", staticLibs), gccObjs); err != nil {
2132
 
                return nil, nil, err
2133
 
        }
2134
 
 
2135
 
        // NOTE(rsc): The importObj is a 5c/6c/8c object and on Windows
2136
 
        // must be processed before the gcc-generated objects.
2137
 
        // Put it first.  http://golang.org/issue/2601
2138
 
        outObj = stringList(importObj, nonGccObjs, ofile)
2139
 
 
2140
 
        return outGo, outObj, nil
2141
 
}
2142
 
 
2143
 
// Run SWIG on all SWIG input files.
2144
 
// TODO: Don't build a shared library, once SWIG emits the necessary
2145
 
// pragmas for external linking.
2146
 
func (b *builder) swig(p *Package, obj string, gccfiles, gxxfiles []string) (outGo, outObj []string, err error) {
2147
 
 
2148
 
        var extraObj []string
2149
 
        for _, file := range gccfiles {
2150
 
                ofile := obj + cgoRe.ReplaceAllString(file[:len(file)-1], "_") + "o"
2151
 
                if err := b.gcc(p, ofile, nil, file); err != nil {
2152
 
                        return nil, nil, err
2153
 
                }
2154
 
                extraObj = append(extraObj, ofile)
2155
 
        }
2156
 
 
2157
 
        for _, file := range gxxfiles {
2158
 
                // Append .o to the file, just in case the pkg has file.c and file.cpp
2159
 
                ofile := obj + cgoRe.ReplaceAllString(file, "_") + ".o"
2160
 
                if err := b.gxx(p, ofile, nil, file); err != nil {
2161
 
                        return nil, nil, err
2162
 
                }
2163
 
                extraObj = append(extraObj, ofile)
2164
 
        }
2165
 
 
2166
 
        intgosize, err := b.swigIntSize(obj)
2167
 
        if err != nil {
2168
 
                return nil, nil, err
2169
 
        }
2170
 
 
2171
 
        for _, f := range p.SwigFiles {
2172
 
                goFile, objFile, err := b.swigOne(p, f, obj, false, intgosize, extraObj)
2173
 
                if err != nil {
2174
 
                        return nil, nil, err
2175
 
                }
2176
 
                if goFile != "" {
2177
 
                        outGo = append(outGo, goFile)
2178
 
                }
2179
 
                if objFile != "" {
2180
 
                        outObj = append(outObj, objFile)
2181
 
                }
2182
 
        }
2183
 
        for _, f := range p.SwigCXXFiles {
2184
 
                goFile, objFile, err := b.swigOne(p, f, obj, true, intgosize, extraObj)
2185
 
                if err != nil {
2186
 
                        return nil, nil, err
2187
 
                }
2188
 
                if goFile != "" {
2189
 
                        outGo = append(outGo, goFile)
2190
 
                }
2191
 
                if objFile != "" {
2192
 
                        outObj = append(outObj, objFile)
2193
 
                }
2194
 
        }
2195
 
        return outGo, outObj, nil
2196
 
}
2197
 
 
2198
 
// This code fails to build if sizeof(int) <= 32
2199
 
const swigIntSizeCode = `
2200
 
package main
2201
 
const i int = 1 << 32
2202
 
`
2203
 
 
2204
 
// Determine the size of int on the target system for the -intgosize option
2205
 
// of swig >= 2.0.9
2206
 
func (b *builder) swigIntSize(obj string) (intsize string, err error) {
2207
 
        if buildN {
2208
 
                return "$INTBITS", nil
2209
 
        }
2210
 
        src := filepath.Join(b.work, "swig_intsize.go")
2211
 
        if err = ioutil.WriteFile(src, []byte(swigIntSizeCode), 0644); err != nil {
2212
 
                return
2213
 
        }
2214
 
        srcs := []string{src}
2215
 
 
2216
 
        p := goFilesPackage(srcs)
2217
 
 
2218
 
        if _, _, e := buildToolchain.gc(b, p, obj, nil, srcs); e != nil {
2219
 
                return "32", nil
2220
 
        }
2221
 
        return "64", nil
2222
 
}
2223
 
 
2224
 
// Run SWIG on one SWIG input file.
2225
 
func (b *builder) swigOne(p *Package, file, obj string, cxx bool, intgosize string, extraObj []string) (outGo, outObj string, err error) {
2226
 
        n := 5 // length of ".swig"
2227
 
        if cxx {
2228
 
                n = 8 // length of ".swigcxx"
2229
 
        }
2230
 
        base := file[:len(file)-n]
2231
 
        goFile := base + ".go"
2232
 
        cBase := base + "_gc."
2233
 
        gccBase := base + "_wrap."
2234
 
        gccExt := "c"
2235
 
        if cxx {
2236
 
                gccExt = "cxx"
2237
 
        }
2238
 
        soname := p.swigSoname(file)
2239
 
 
2240
 
        _, gccgo := buildToolchain.(gccgoToolchain)
2241
 
 
2242
 
        // swig
2243
 
        args := []string{
2244
 
                "-go",
2245
 
                "-intgosize", intgosize,
2246
 
                "-module", base,
2247
 
                "-soname", soname,
2248
 
                "-o", obj + gccBase + gccExt,
2249
 
                "-outdir", obj,
2250
 
        }
2251
 
        if gccgo {
2252
 
                args = append(args, "-gccgo")
2253
 
        }
2254
 
        if cxx {
2255
 
                args = append(args, "-c++")
2256
 
        }
2257
 
 
2258
 
        if out, err := b.runOut(p.Dir, p.ImportPath, nil, "swig", args, file); err != nil {
2259
 
                if len(out) > 0 {
2260
 
                        if bytes.Contains(out, []byte("Unrecognized option -intgosize")) {
2261
 
                                return "", "", errors.New("must have SWIG version >= 2.0.9\n")
2262
 
                        }
2263
 
                        b.showOutput(p.Dir, p.ImportPath, b.processOutput(out))
2264
 
                        return "", "", errPrintedOutput
2265
 
                }
2266
 
                return "", "", err
2267
 
        }
2268
 
 
2269
 
        var cObj string
2270
 
        if !gccgo {
2271
 
                // cc
2272
 
                cObj = obj + cBase + archChar
2273
 
                if err := buildToolchain.cc(b, p, obj, cObj, obj+cBase+"c"); err != nil {
2274
 
                        return "", "", err
2275
 
                }
2276
 
        }
2277
 
 
2278
 
        // gcc
2279
 
        gccObj := obj + gccBase + "o"
2280
 
        if err := b.gcc(p, gccObj, []string{"-g", "-fPIC", "-O2"}, obj+gccBase+gccExt); err != nil {
2281
 
                return "", "", err
2282
 
        }
2283
 
 
2284
 
        // create shared library
2285
 
        osldflags := map[string][]string{
2286
 
                "darwin":  {"-dynamiclib", "-Wl,-undefined,dynamic_lookup"},
2287
 
                "freebsd": {"-shared", "-lpthread", "-lm"},
2288
 
                "linux":   {"-shared", "-lpthread", "-lm"},
2289
 
                "windows": {"-shared", "-lm", "-mthreads"},
2290
 
        }
2291
 
        var cxxlib []string
2292
 
        if cxx {
2293
 
                cxxlib = []string{"-lstdc++"}
2294
 
        }
2295
 
        ldflags := stringList(osldflags[goos], cxxlib)
2296
 
        target := filepath.Join(obj, soname)
2297
 
        b.run(p.Dir, p.ImportPath, nil, b.gccCmd(p.Dir), "-o", target, gccObj, extraObj, ldflags)
2298
 
 
2299
 
        return obj + goFile, cObj, nil
2300
 
}
2301
 
 
2302
 
// An actionQueue is a priority queue of actions.
2303
 
type actionQueue []*action
2304
 
 
2305
 
// Implement heap.Interface
2306
 
func (q *actionQueue) Len() int           { return len(*q) }
2307
 
func (q *actionQueue) Swap(i, j int)      { (*q)[i], (*q)[j] = (*q)[j], (*q)[i] }
2308
 
func (q *actionQueue) Less(i, j int) bool { return (*q)[i].priority < (*q)[j].priority }
2309
 
func (q *actionQueue) Push(x interface{}) { *q = append(*q, x.(*action)) }
2310
 
func (q *actionQueue) Pop() interface{} {
2311
 
        n := len(*q) - 1
2312
 
        x := (*q)[n]
2313
 
        *q = (*q)[:n]
2314
 
        return x
2315
 
}
2316
 
 
2317
 
func (q *actionQueue) push(a *action) {
2318
 
        heap.Push(q, a)
2319
 
}
2320
 
 
2321
 
func (q *actionQueue) pop() *action {
2322
 
        return heap.Pop(q).(*action)
2323
 
}
2324
 
 
2325
 
func raceInit() {
2326
 
        if !buildRace {
2327
 
                return
2328
 
        }
2329
 
        if goarch != "amd64" || goos != "linux" && goos != "darwin" && goos != "windows" {
2330
 
                fmt.Fprintf(os.Stderr, "go %s: -race is only supported on linux/amd64, darwin/amd64 and windows/amd64\n", flag.Args()[0])
2331
 
                os.Exit(2)
2332
 
        }
2333
 
        buildGcflags = append(buildGcflags, "-race")
2334
 
        buildLdflags = append(buildLdflags, "-race")
2335
 
        buildCcflags = append(buildCcflags, "-D", "RACE")
2336
 
        if buildContext.InstallSuffix != "" {
2337
 
                buildContext.InstallSuffix += "_"
2338
 
        }
2339
 
        buildContext.InstallSuffix += "race"
2340
 
        buildContext.BuildTags = append(buildContext.BuildTags, "race")
2341
 
}
2342
 
 
2343
 
// defaultSuffix returns file extension used for command files in
2344
 
// current os environment.
2345
 
func defaultSuffix() string {
2346
 
        switch runtime.GOOS {
2347
 
        case "windows":
2348
 
                return ".bat"
2349
 
        case "plan9":
2350
 
                return ".rc"
2351
 
        default:
2352
 
                return ".bash"
2353
 
        }
2354
 
}