OLD | NEW |
1 // Copyright 2011 The Go Authors. All rights reserved. | 1 // Copyright 2011 The Go Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style | 2 // Use of this source code is governed by a BSD-style |
3 // license that can be found in the LICENSE file. | 3 // license that can be found in the LICENSE file. |
4 | 4 |
5 package main | 5 package main |
6 | 6 |
7 import ( | 7 import ( |
8 "bytes" | 8 "bytes" |
9 "container/heap" | 9 "container/heap" |
10 "errors" | 10 "errors" |
11 "fmt" | 11 "fmt" |
12 "go/build" | 12 "go/build" |
13 "io" | 13 "io" |
14 "io/ioutil" | 14 "io/ioutil" |
15 "os" | 15 "os" |
16 "os/exec" | 16 "os/exec" |
17 "path" | 17 "path" |
18 "path/filepath" | 18 "path/filepath" |
19 "regexp" | 19 "regexp" |
20 "runtime" | 20 "runtime" |
21 "strings" | 21 "strings" |
22 "sync" | 22 "sync" |
23 ) | 23 ) |
24 | 24 |
25 var cmdBuild = &Command{ | 25 var cmdBuild = &Command{ |
26 » UsageLine: "build [-a] [-n] [-o output] [-p n] [-v] [-x] [-work] [import
path... | gofiles...]", | 26 » UsageLine: "build [-o output] [build flags] [packages]", |
27 Short: "compile packages and dependencies", | 27 Short: "compile packages and dependencies", |
28 Long: ` | 28 Long: ` |
29 Build compiles the packages named by the import paths, | 29 Build compiles the packages named by the import paths, |
30 along with their dependencies, but it does not install the results. | 30 along with their dependencies, but it does not install the results. |
31 | 31 |
32 If the arguments are a list of .go files, build treats them as a list | 32 If the arguments are a list of .go files, build treats them as a list |
33 of source files specifying a single package. | 33 of source files specifying a single package. |
34 | 34 |
35 When the command line specifies a single main package, | 35 When the command line specifies a single main package, |
36 build writes the resulting executable to output (default a.out). | 36 build writes the resulting executable to output. |
37 Otherwise build compiles the packages but discards the results, | 37 Otherwise build compiles the packages but discards the results, |
38 serving only as a check that the packages can be built. | 38 serving only as a check that the packages can be built. |
39 | 39 |
40 The -a flag forces rebuilding of packages that are already up-to-date. | 40 The -o flag specifies the output file name. If not specified, the |
41 The -n flag prints the commands but does not run them. | 41 name is packagename.a (for a non-main package) or the base |
42 The -v flag prints the names of packages as they are compiled. | 42 name of the first source file (for a main package). |
43 The -x flag prints the commands. | |
44 | 43 |
45 The -o flag specifies the output file name. | 44 The build flags are shared by the build, install, run, and test commands: |
46 It is an error to use -o when the command line specifies multiple packages. | |
47 | 45 |
48 The -p flag specifies the number of builds that can be run in parallel. | 46 » -a |
49 The default is the number of CPUs available. | 47 » » force rebuilding of packages that are already up-to-date. |
| 48 » -n |
| 49 » » print the commands but does not run them. |
| 50 » -p n |
| 51 » » the number of builds that can be run in parallel. |
| 52 » » The default is the number of CPUs available. |
| 53 » -v |
| 54 » » print the names of packages as they are compiled. |
| 55 » -work |
| 56 » » print the name of the temporary work directory and |
| 57 » » do not delete it when exiting. |
| 58 » -x |
| 59 » » print the commands. |
50 | 60 |
51 The -work flag causes build to print the name of the temporary work | 61 » -gccgoflags 'arg list' |
52 directory and not delete it when exiting. | 62 » » arguments to pass on each gccgo compiler/linker invocation |
| 63 » -gcflags 'arg list' |
| 64 » » arguments to pass on each 5g, 6g, or 8g compiler invocation |
| 65 » -ldflags 'flag list' |
| 66 » » arguments to pass on each 5l, 6l, or 8l linker invocation |
| 67 » -tags 'tag list' |
| 68 » » a list of build tags to consider satisfied during the build. |
| 69 » » See the documentation for the go/build package for |
| 70 » » more information about build tags. |
53 | 71 |
54 For more about import paths, see 'go help importpath'. | 72 For more about specifying packages, see 'go help packages'. |
55 | 73 |
56 See also: go install, go get, go clean. | 74 See also: go install, go get, go clean. |
57 `, | 75 `, |
58 } | 76 } |
59 | 77 |
60 func init() { | 78 func init() { |
61 // break init cycle | 79 // break init cycle |
62 cmdBuild.Run = runBuild | 80 cmdBuild.Run = runBuild |
63 cmdInstall.Run = runInstall | 81 cmdInstall.Run = runInstall |
64 | 82 |
65 addBuildFlags(cmdBuild) | 83 addBuildFlags(cmdBuild) |
66 addBuildFlags(cmdInstall) | 84 addBuildFlags(cmdInstall) |
67 } | 85 } |
68 | 86 |
69 // Flags set by multiple commands. | 87 // Flags set by multiple commands. |
70 var buildA bool // -a flag | 88 var buildA bool // -a flag |
71 var buildN bool // -n flag | 89 var buildN bool // -n flag |
72 var buildP = runtime.NumCPU() // -p flag | 90 var buildP = runtime.NumCPU() // -p flag |
73 var buildV bool // -v flag | 91 var buildV bool // -v flag |
74 var buildX bool // -x flag | 92 var buildX bool // -x flag |
75 var buildO = cmdBuild.Flag.String("o", "", "output file") | 93 var buildO = cmdBuild.Flag.String("o", "", "output file") |
76 var buildWork bool // -work flag | 94 var buildWork bool // -work flag |
| 95 var buildGcflags []string // -gcflags flag |
| 96 var buildLdflags []string // -ldflags flag |
| 97 var buildGccgoflags []string // -gccgoflags flag |
77 | 98 |
78 var buildContext = build.DefaultContext | 99 var buildContext = build.Default |
79 | 100 |
80 // addBuildFlags adds the flags common to the build and install commands. | 101 // addBuildFlags adds the flags common to the build and install commands. |
81 func addBuildFlags(cmd *Command) { | 102 func addBuildFlags(cmd *Command) { |
82 cmd.Flag.BoolVar(&buildA, "a", false, "") | 103 cmd.Flag.BoolVar(&buildA, "a", false, "") |
83 cmd.Flag.BoolVar(&buildN, "n", false, "") | 104 cmd.Flag.BoolVar(&buildN, "n", false, "") |
84 cmd.Flag.IntVar(&buildP, "p", buildP, "") | 105 cmd.Flag.IntVar(&buildP, "p", buildP, "") |
85 cmd.Flag.BoolVar(&buildV, "v", false, "") | 106 cmd.Flag.BoolVar(&buildV, "v", false, "") |
86 cmd.Flag.BoolVar(&buildX, "x", false, "") | 107 cmd.Flag.BoolVar(&buildX, "x", false, "") |
87 cmd.Flag.BoolVar(&buildWork, "work", false, "") | 108 cmd.Flag.BoolVar(&buildWork, "work", false, "") |
88 | 109 » cmd.Flag.Var((*stringsFlag)(&buildGcflags), "gcflags", "") |
89 » // TODO(rsc): This -t flag is used by buildscript.sh but | 110 » cmd.Flag.Var((*stringsFlag)(&buildLdflags), "ldflags", "") |
90 » // not documented. Should be documented but the | 111 » cmd.Flag.Var((*stringsFlag)(&buildGccgoflags), "gccgoflags", "") |
91 » // usage lines are getting too long. Probably need to say | 112 » cmd.Flag.Var((*stringsFlag)(&buildContext.BuildTags), "tags", "") |
92 » // that these flags are applicable to every command and | |
93 » // document them in one help message instead of on every | |
94 » // command's help message. | |
95 » cmd.Flag.Var((*stringsFlag)(&buildContext.BuildTags), "t", "") | |
96 } | 113 } |
97 | 114 |
98 type stringsFlag []string | 115 type stringsFlag []string |
99 | 116 |
100 func (v *stringsFlag) Set(s string) error { | 117 func (v *stringsFlag) Set(s string) error { |
101 » *v = append(*v, s) | 118 » *v = strings.Fields(s) |
102 return nil | 119 return nil |
103 } | 120 } |
104 | 121 |
105 func (v *stringsFlag) String() string { | 122 func (v *stringsFlag) String() string { |
106 return "<stringsFlag>" | 123 return "<stringsFlag>" |
107 } | 124 } |
108 | 125 |
109 func runBuild(cmd *Command, args []string) { | 126 func runBuild(cmd *Command, args []string) { |
110 var b builder | 127 var b builder |
111 b.init() | 128 b.init() |
112 | 129 |
113 » var pkgs []*Package | 130 » pkgs := packagesForBuild(args) |
114 » if len(args) > 0 && strings.HasSuffix(args[0], ".go") { | |
115 » » pkg := goFilesPackage(args, "") | |
116 » » pkgs = append(pkgs, pkg) | |
117 » } else { | |
118 » » pkgs = packagesForBuild(args) | |
119 » } | |
120 | 131 |
121 if len(pkgs) == 1 && pkgs[0].Name == "main" && *buildO == "" { | 132 if len(pkgs) == 1 && pkgs[0].Name == "main" && *buildO == "" { |
122 _, *buildO = path.Split(pkgs[0].ImportPath) | 133 _, *buildO = path.Split(pkgs[0].ImportPath) |
123 » » if b.goos == "windows" { | 134 » » if goos == "windows" { |
124 *buildO += ".exe" | 135 *buildO += ".exe" |
125 } | 136 } |
126 } | 137 } |
127 | 138 |
128 if *buildO != "" { | 139 if *buildO != "" { |
129 if len(pkgs) > 1 { | 140 if len(pkgs) > 1 { |
130 fatalf("go build: cannot use -o with multiple packages") | 141 fatalf("go build: cannot use -o with multiple packages") |
131 } | 142 } |
132 p := pkgs[0] | 143 p := pkgs[0] |
133 p.target = "" // must build - not up to date | 144 p.target = "" // must build - not up to date |
134 a := b.action(modeInstall, modeBuild, p) | 145 a := b.action(modeInstall, modeBuild, p) |
135 a.target = *buildO | 146 a.target = *buildO |
136 b.do(a) | 147 b.do(a) |
137 return | 148 return |
138 } | 149 } |
139 | 150 |
140 a := &action{} | 151 a := &action{} |
141 for _, p := range packages(args) { | 152 for _, p := range packages(args) { |
142 a.deps = append(a.deps, b.action(modeBuild, modeBuild, p)) | 153 a.deps = append(a.deps, b.action(modeBuild, modeBuild, p)) |
143 } | 154 } |
144 b.do(a) | 155 b.do(a) |
145 } | 156 } |
146 | 157 |
147 var cmdInstall = &Command{ | 158 var cmdInstall = &Command{ |
148 » UsageLine: "install [-a] [-n] [-p n] [-v] [-x] [-work] [importpath...]", | 159 » UsageLine: "install [build flags] [packages]", |
149 Short: "compile and install packages and dependencies", | 160 Short: "compile and install packages and dependencies", |
150 Long: ` | 161 Long: ` |
151 Install compiles and installs the packages named by the import paths, | 162 Install compiles and installs the packages named by the import paths, |
152 along with their dependencies. | 163 along with their dependencies. |
153 | 164 |
154 The -a flag forces reinstallation of packages that are already up-to-date. | 165 For more about the build flags, see 'go help build'. |
155 The -n flag prints the commands but does not run them. | 166 For more about specifying packages, see 'go help packages'. |
156 The -v flag prints the names of packages as they are compiled. | |
157 The -x flag prints the commands. | |
158 | |
159 The -p flag specifies the number of builds that can be run in parallel. | |
160 The default is the number of CPUs available. | |
161 | |
162 The -work flag causes build to print the name of the temporary work | |
163 directory and not delete it when exiting. | |
164 | |
165 For more about import paths, see 'go help importpath'. | |
166 | 167 |
167 See also: go build, go get, go clean. | 168 See also: go build, go get, go clean. |
168 `, | 169 `, |
169 } | 170 } |
170 | 171 |
171 func runInstall(cmd *Command, args []string) { | 172 func runInstall(cmd *Command, args []string) { |
172 pkgs := packagesForBuild(args) | 173 pkgs := packagesForBuild(args) |
173 | 174 |
| 175 for _, p := range pkgs { |
| 176 if p.Target == "" && (!p.Standard || p.ImportPath != "unsafe") { |
| 177 errorf("go install: no install location for %s", p.Impor
tPath) |
| 178 } |
| 179 } |
| 180 exitIfErrors() |
| 181 |
174 var b builder | 182 var b builder |
175 b.init() | 183 b.init() |
176 a := &action{} | 184 a := &action{} |
177 for _, p := range pkgs { | 185 for _, p := range pkgs { |
178 a.deps = append(a.deps, b.action(modeInstall, modeInstall, p)) | 186 a.deps = append(a.deps, b.action(modeInstall, modeInstall, p)) |
179 } | 187 } |
180 b.do(a) | 188 b.do(a) |
181 } | 189 } |
182 | 190 |
| 191 // Global build parameters (used during package load) |
| 192 var ( |
| 193 goarch string |
| 194 goos string |
| 195 archChar string |
| 196 exeSuffix string |
| 197 ) |
| 198 |
| 199 func init() { |
| 200 goarch = buildContext.GOARCH |
| 201 goos = buildContext.GOOS |
| 202 if goos == "windows" { |
| 203 exeSuffix = ".exe" |
| 204 } |
| 205 var err error |
| 206 archChar, err = build.ArchChar(goarch) |
| 207 if err != nil { |
| 208 fatalf("%s", err) |
| 209 } |
| 210 } |
| 211 |
183 // A builder holds global state about a build. | 212 // A builder holds global state about a build. |
184 // It does not hold per-package state, because eventually we will | 213 // It does not hold per-package state, because we |
185 // build packages in parallel, and the builder will be shared. | 214 // build packages in parallel, and the builder is shared. |
186 type builder struct { | 215 type builder struct { |
187 work string // the temporary work directory (ends i
n filepath.Separator) | 216 work string // the temporary work directory (ends i
n filepath.Separator) |
188 arch string // e.g., "6" | |
189 goarch string // the $GOARCH | |
190 goos string // the $GOOS | |
191 exe string // the executable suffix - "" or ".exe" | |
192 gcflags []string // additional flags for Go compiler | |
193 actionCache map[cacheKey]*action // a cache of already-constructed actio
ns | 217 actionCache map[cacheKey]*action // a cache of already-constructed actio
ns |
194 mkdirCache map[string]bool // a cache of created directories | 218 mkdirCache map[string]bool // a cache of created directories |
195 print func(args ...interface{}) (int, error) | 219 print func(args ...interface{}) (int, error) |
196 | 220 |
197 output sync.Mutex | 221 output sync.Mutex |
198 scriptDir string // current directory in printed script | 222 scriptDir string // current directory in printed script |
199 | 223 |
200 exec sync.Mutex | 224 exec sync.Mutex |
201 readySema chan bool | 225 readySema chan bool |
202 ready actionQueue | 226 ready actionQueue |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
236 // buildMode specifies the build mode: | 260 // buildMode specifies the build mode: |
237 // are we just building things or also installing the results? | 261 // are we just building things or also installing the results? |
238 type buildMode int | 262 type buildMode int |
239 | 263 |
240 const ( | 264 const ( |
241 modeBuild buildMode = iota | 265 modeBuild buildMode = iota |
242 modeInstall | 266 modeInstall |
243 ) | 267 ) |
244 | 268 |
245 var ( | 269 var ( |
246 » gobin = build.Path[0].BinDir() | 270 » goroot = filepath.Clean(runtime.GOROOT()) |
247 » goroot = build.Path[0].Path | 271 » gobin = defaultGobin() |
| 272 » gorootSrcPkg = filepath.Join(goroot, "src/pkg") |
| 273 » gorootPkg = filepath.Join(goroot, "pkg") |
| 274 » gorootSrc = filepath.Join(goroot, "src") |
248 ) | 275 ) |
249 | 276 |
| 277 func defaultGobin() string { |
| 278 if s := os.Getenv("GOBIN"); s != "" { |
| 279 return s |
| 280 } |
| 281 return filepath.Join(goroot, "bin") |
| 282 } |
| 283 |
250 func (b *builder) init() { | 284 func (b *builder) init() { |
251 var err error | 285 var err error |
252 b.print = fmt.Print | 286 b.print = fmt.Print |
253 b.actionCache = make(map[cacheKey]*action) | 287 b.actionCache = make(map[cacheKey]*action) |
254 b.mkdirCache = make(map[string]bool) | 288 b.mkdirCache = make(map[string]bool) |
255 b.goarch = buildContext.GOARCH | |
256 b.goos = buildContext.GOOS | |
257 if b.goos == "windows" { | |
258 b.exe = ".exe" | |
259 } | |
260 b.gcflags = strings.Fields(os.Getenv("GCFLAGS")) | |
261 | |
262 b.arch, err = build.ArchChar(b.goarch) | |
263 if err != nil { | |
264 fatalf("%s", err) | |
265 } | |
266 | 289 |
267 if buildN { | 290 if buildN { |
268 b.work = "$WORK" | 291 b.work = "$WORK" |
269 } else { | 292 } else { |
270 b.work, err = ioutil.TempDir("", "go-build") | 293 b.work, err = ioutil.TempDir("", "go-build") |
271 if err != nil { | 294 if err != nil { |
272 fatalf("%s", err) | 295 fatalf("%s", err) |
273 } | 296 } |
274 if buildX || buildWork { | 297 if buildX || buildWork { |
275 fmt.Printf("WORK=%s\n", b.work) | 298 fmt.Printf("WORK=%s\n", b.work) |
276 } | 299 } |
277 if !buildWork { | 300 if !buildWork { |
278 atexit(func() { os.RemoveAll(b.work) }) | 301 atexit(func() { os.RemoveAll(b.work) }) |
279 } | 302 } |
280 } | 303 } |
281 } | 304 } |
282 | 305 |
283 // goFilesPackage creates a package for building a collection of Go files | 306 // goFilesPackage creates a package for building a collection of Go files |
284 // (typically named on the command line). If target is given, the package | 307 // (typically named on the command line). The target is named p.a for |
285 // target is target. Otherwise, the target is named p.a for | |
286 // package p or named after the first Go file for package main. | 308 // package p or named after the first Go file for package main. |
287 func goFilesPackage(gofiles []string, target string) *Package { | 309 func goFilesPackage(gofiles []string) *Package { |
288 // TODO: Remove this restriction. | 310 // TODO: Remove this restriction. |
289 for _, f := range gofiles { | 311 for _, f := range gofiles { |
290 » » if !strings.HasSuffix(f, ".go") || strings.Contains(f, "/") || s
trings.Contains(f, string(filepath.Separator)) { | 312 » » if !strings.HasSuffix(f, ".go") { |
291 » » » fatalf("named files must be in current directory and .go
files") | 313 » » » fatalf("named files must be .go files") |
292 } | 314 } |
293 } | 315 } |
294 | 316 |
295 » // Synthesize fake "directory" that only shows those two files, | 317 » var stk importStack |
| 318 » ctxt := buildContext |
| 319 » ctxt.UseAllFiles = true |
| 320 |
| 321 » // Synthesize fake "directory" that only shows the named files, |
296 // to make it look like this is a standard package or | 322 // to make it look like this is a standard package or |
297 » // command directory. | 323 » // command directory. So that local imports resolve |
298 » var dir []os.FileInfo | 324 » // consistently, the files must all be in the same directory. |
| 325 » var dirent []os.FileInfo |
| 326 » var dir string |
299 for _, file := range gofiles { | 327 for _, file := range gofiles { |
300 fi, err := os.Stat(file) | 328 fi, err := os.Stat(file) |
301 if err != nil { | 329 if err != nil { |
302 fatalf("%s", err) | 330 fatalf("%s", err) |
303 } | 331 } |
304 if fi.IsDir() { | 332 if fi.IsDir() { |
305 fatalf("%s is a directory, should be a Go file", file) | 333 fatalf("%s is a directory, should be a Go file", file) |
306 } | 334 } |
307 » » dir = append(dir, fi) | 335 » » dir1, _ := filepath.Split(file) |
| 336 » » if dir == "" { |
| 337 » » » dir = dir1 |
| 338 » » } else if dir != dir1 { |
| 339 » » » fatalf("named files must all be in one directory; have %
s and %s", dir, dir1) |
| 340 » » } |
| 341 » » dirent = append(dirent, fi) |
308 } | 342 } |
309 » ctxt := buildContext | 343 » ctxt.ReadDir = func(string) ([]os.FileInfo, error) { return dirent, nil
} |
310 » ctxt.ReadDir = func(string) ([]os.FileInfo, error) { return dir, nil } | 344 |
311 » pwd, _ := os.Getwd() | 345 » if !filepath.IsAbs(dir) { |
312 » var stk importStack | 346 » » dir = filepath.Join(cwd, dir) |
313 » pkg := scanPackage(&ctxt, &build.Tree{Path: "."}, "<command line>", "<co
mmand line>", pwd+"/.", &stk, true) | |
314 » if pkg.Error != nil { | |
315 » » fatalf("%s", pkg.Error) | |
316 } | 347 } |
317 » printed := map[error]bool{} | 348 |
318 » for _, err := range pkg.DepsErrors { | 349 » bp, err := ctxt.ImportDir(dir, 0) |
319 » » // Since these are errors in dependencies, | 350 » pkg := new(Package) |
320 » » // the same error might show up multiple times, | 351 » pkg.load(&stk, bp, err) |
321 » » // once in each package that depends on it. | 352 |
322 » » // Only print each once. | 353 » pkg.ImportPath = "command-line arguments" |
323 » » if !printed[err] { | 354 » if *buildO == "" { |
324 » » » printed[err] = true | 355 » » if pkg.Name == "main" { |
325 » » » errorf("%s", err) | 356 » » » _, elem := filepath.Split(gofiles[0]) |
| 357 » » » *buildO = elem[:len(elem)-len(".go")] |
| 358 » » } else { |
| 359 » » » *buildO = pkg.Name + ".a" |
326 } | 360 } |
327 } | 361 } |
328 » if target != "" { | 362 » pkg.target = "" |
329 » » pkg.target = target | 363 » pkg.Target = "" |
330 » } else if pkg.Name == "main" { | 364 » pkg.Stale = true |
331 » » pkg.target = gofiles[0][:len(gofiles[0])-len(".go")] | 365 |
332 » } else { | 366 » computeStale([]*Package{pkg}) |
333 » » pkg.target = pkg.Name + ".a" | |
334 » } | |
335 » pkg.ImportPath = "_/" + pkg.target | |
336 » exitIfErrors() | |
337 return pkg | 367 return pkg |
338 } | 368 } |
339 | 369 |
340 // action returns the action for applying the given operation (mode) to the pack
age. | 370 // action returns the action for applying the given operation (mode) to the pack
age. |
341 // depMode is the action to use when building dependencies. | 371 // depMode is the action to use when building dependencies. |
342 func (b *builder) action(mode buildMode, depMode buildMode, p *Package) *action
{ | 372 func (b *builder) action(mode buildMode, depMode buildMode, p *Package) *action
{ |
343 key := cacheKey{mode, p} | 373 key := cacheKey{mode, p} |
344 a := b.actionCache[key] | 374 a := b.actionCache[key] |
345 if a != nil { | 375 if a != nil { |
346 return a | 376 return a |
347 } | 377 } |
348 | 378 |
349 » a = &action{p: p, pkgdir: p.t.PkgDir()} | 379 » a = &action{p: p, pkgdir: p.build.PkgRoot} |
350 if p.pkgdir != "" { // overrides p.t | 380 if p.pkgdir != "" { // overrides p.t |
351 a.pkgdir = p.pkgdir | 381 a.pkgdir = p.pkgdir |
352 } | 382 } |
353 | 383 |
354 b.actionCache[key] = a | 384 b.actionCache[key] = a |
355 | 385 |
356 for _, p1 := range p.imports { | 386 for _, p1 := range p.imports { |
357 a.deps = append(a.deps, b.action(depMode, depMode, p1)) | 387 a.deps = append(a.deps, b.action(depMode, depMode, p1)) |
358 } | 388 } |
359 | 389 |
360 // If we are not doing a cross-build, then record the binary we'll | 390 // If we are not doing a cross-build, then record the binary we'll |
361 // generate for cgo as a dependency of the build of any package | 391 // generate for cgo as a dependency of the build of any package |
362 // using cgo, to make sure we do not overwrite the binary while | 392 // using cgo, to make sure we do not overwrite the binary while |
363 // a package is using it. If this is a cross-build, then the cgo we | 393 // a package is using it. If this is a cross-build, then the cgo we |
364 // are writing is not the cgo we need to use. | 394 // are writing is not the cgo we need to use. |
365 » if b.goos == runtime.GOOS && b.goarch == runtime.GOARCH { | 395 » if goos == runtime.GOOS && goarch == runtime.GOARCH { |
366 if len(p.CgoFiles) > 0 || p.Standard && p.ImportPath == "runtime
/cgo" { | 396 if len(p.CgoFiles) > 0 || p.Standard && p.ImportPath == "runtime
/cgo" { |
367 var stk importStack | 397 var stk importStack |
368 p1 := loadPackage("cmd/cgo", &stk) | 398 p1 := loadPackage("cmd/cgo", &stk) |
369 if p1.Error != nil { | 399 if p1.Error != nil { |
370 fatalf("load cmd/cgo: %v", p1.Error) | 400 fatalf("load cmd/cgo: %v", p1.Error) |
371 } | 401 } |
372 a.cgo = b.action(depMode, depMode, p1) | 402 a.cgo = b.action(depMode, depMode, p1) |
373 a.deps = append(a.deps, a.cgo) | 403 a.deps = append(a.deps, a.cgo) |
374 } | 404 } |
375 } | 405 } |
376 | 406 |
377 if p.Standard { | 407 if p.Standard { |
378 switch p.ImportPath { | 408 switch p.ImportPath { |
379 case "builtin", "unsafe": | 409 case "builtin", "unsafe": |
380 // Fake packages - nothing to build. | 410 // Fake packages - nothing to build. |
381 return a | 411 return a |
382 } | 412 } |
383 // gccgo standard library is "fake" too. | 413 // gccgo standard library is "fake" too. |
384 if _, ok := buildToolchain.(gccgoToolchain); ok { | 414 if _, ok := buildToolchain.(gccgoToolchain); ok { |
385 // the target name is needed for cgo. | 415 // the target name is needed for cgo. |
386 a.target = p.target | 416 a.target = p.target |
387 return a | 417 return a |
388 } | 418 } |
389 } | 419 } |
390 | 420 |
391 » if !p.Stale && !buildA && p.target != "" { | 421 » if !p.Stale && p.target != "" { |
392 // p.Stale==false implies that p.target is up-to-date. | 422 // p.Stale==false implies that p.target is up-to-date. |
393 // Record target name for use by actions depending on this one. | 423 // Record target name for use by actions depending on this one. |
394 a.target = p.target | 424 a.target = p.target |
395 return a | 425 return a |
396 } | 426 } |
397 | 427 |
398 » a.objdir = filepath.Join(b.work, filepath.FromSlash(a.p.ImportPath+"/_ob
j")) + string(filepath.Separator) | 428 » prefix := "obj" |
399 » a.objpkg = buildToolchain.pkgpath(b.work, a.p) | 429 » if p.target == "" && p.Dir == p.ImportPath { |
| 430 » » // Imported via local path. No permanent target. |
| 431 » » mode = modeBuild |
| 432 » » prefix = "local" |
| 433 » } |
| 434 » a.objdir = filepath.Join(b.work, prefix, a.p.ImportPath, "_obj") + strin
g(filepath.Separator) |
| 435 » a.objpkg = buildToolchain.pkgpath(b.work+"/"+prefix, a.p, false) |
400 a.link = p.Name == "main" | 436 a.link = p.Name == "main" |
401 | 437 |
402 switch mode { | 438 switch mode { |
403 case modeInstall: | 439 case modeInstall: |
404 a.f = (*builder).install | 440 a.f = (*builder).install |
405 a.deps = []*action{b.action(modeBuild, depMode, p)} | 441 a.deps = []*action{b.action(modeBuild, depMode, p)} |
406 a.target = a.p.target | 442 a.target = a.p.target |
407 case modeBuild: | 443 case modeBuild: |
408 a.f = (*builder).build | 444 a.f = (*builder).build |
409 a.target = a.objpkg | 445 a.target = a.objpkg |
410 if a.link { | 446 if a.link { |
411 // An executable file. | 447 // An executable file. |
412 // (This is the name of a temporary file.) | 448 // (This is the name of a temporary file.) |
413 » » » a.target = a.objdir + "a.out" + b.exe | 449 » » » a.target = a.objdir + "a.out" + exeSuffix |
414 } | 450 } |
415 } | 451 } |
416 | 452 |
417 return a | 453 return a |
418 } | 454 } |
419 | 455 |
420 // actionList returns the list of actions in the dag rooted at root | 456 // actionList returns the list of actions in the dag rooted at root |
421 // as visited in a depth-first post-order traversal. | 457 // as visited in a depth-first post-order traversal. |
422 func actionList(root *action) []*action { | 458 func actionList(root *action) []*action { |
423 seen := map[*action]bool{} | 459 seen := map[*action]bool{} |
(...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
553 return err | 589 return err |
554 } | 590 } |
555 | 591 |
556 var gofiles, cfiles, sfiles, objects, cgoObjects []string | 592 var gofiles, cfiles, sfiles, objects, cgoObjects []string |
557 gofiles = append(gofiles, a.p.GoFiles...) | 593 gofiles = append(gofiles, a.p.GoFiles...) |
558 cfiles = append(cfiles, a.p.CFiles...) | 594 cfiles = append(cfiles, a.p.CFiles...) |
559 sfiles = append(sfiles, a.p.SFiles...) | 595 sfiles = append(sfiles, a.p.SFiles...) |
560 | 596 |
561 // Run cgo. | 597 // Run cgo. |
562 if len(a.p.CgoFiles) > 0 { | 598 if len(a.p.CgoFiles) > 0 { |
563 » » // In a package using cgo, cgo compiles the C and assembly files
with gcc. | 599 » » // In a package using cgo, cgo compiles the C and assembly files
with gcc. |
564 // There is one exception: runtime/cgo's job is to bridge the | 600 // There is one exception: runtime/cgo's job is to bridge the |
565 // cgo and non-cgo worlds, so it necessarily has files in both. | 601 // cgo and non-cgo worlds, so it necessarily has files in both. |
566 // In that case gcc only gets the gcc_* files. | 602 // In that case gcc only gets the gcc_* files. |
567 var gccfiles []string | 603 var gccfiles []string |
568 if a.p.Standard && a.p.ImportPath == "runtime/cgo" { | 604 if a.p.Standard && a.p.ImportPath == "runtime/cgo" { |
569 filter := func(files, nongcc, gcc []string) ([]string, [
]string) { | 605 filter := func(files, nongcc, gcc []string) ([]string, [
]string) { |
570 for _, f := range files { | 606 for _, f := range files { |
571 if strings.HasPrefix(f, "gcc_") { | 607 if strings.HasPrefix(f, "gcc_") { |
572 gcc = append(gcc, f) | 608 gcc = append(gcc, f) |
573 } else { | 609 } else { |
(...skipping 18 matching lines...) Expand all Loading... |
592 if err != nil { | 628 if err != nil { |
593 return err | 629 return err |
594 } | 630 } |
595 cgoObjects = append(cgoObjects, outObj...) | 631 cgoObjects = append(cgoObjects, outObj...) |
596 gofiles = append(gofiles, outGo...) | 632 gofiles = append(gofiles, outGo...) |
597 } | 633 } |
598 | 634 |
599 // Prepare Go import path list. | 635 // Prepare Go import path list. |
600 inc := b.includeArgs("-I", a.deps) | 636 inc := b.includeArgs("-I", a.deps) |
601 | 637 |
| 638 // In what directory shall we run the Go compiler? |
| 639 // We only pass absolute paths, so most of the time it doesn't matter. |
| 640 // Default to the root directory. |
| 641 // However, if the package contains local imports (./ or ../) |
| 642 // then we need to run the compiler in a directory in the parallel |
| 643 // tree of local package objects, so that those imports resolve to the |
| 644 // compiled package objects. |
| 645 gcdir := filepath.Clean("/") |
| 646 for _, imp := range a.p.Imports { |
| 647 if build.IsLocalImport(imp) { |
| 648 dir := a.p.Dir |
| 649 if filepath.Separator == '\\' { |
| 650 // Avoid use of : on Windows. |
| 651 dir = strings.Replace(dir, ":", "_", -1) |
| 652 } |
| 653 gcdir = filepath.Join(b.work, "local", dir) |
| 654 if err := b.mkdir(gcdir); err != nil { |
| 655 return err |
| 656 } |
| 657 break |
| 658 } |
| 659 } |
| 660 |
602 // Compile Go. | 661 // Compile Go. |
603 if len(gofiles) > 0 { | 662 if len(gofiles) > 0 { |
604 » » if out, err := buildToolchain.gc(b, a.p, obj, inc, gofiles); err
!= nil { | 663 » » if out, err := buildToolchain.gc(b, a.p, obj, gcdir, inc, gofile
s); err != nil { |
605 return err | 664 return err |
606 } else { | 665 } else { |
607 objects = append(objects, out) | 666 objects = append(objects, out) |
608 } | 667 } |
609 } | 668 } |
610 | 669 |
611 // Copy .h files named for goos or goarch or goos_goarch | 670 // Copy .h files named for goos or goarch or goos_goarch |
612 // to names using GOOS and GOARCH. | 671 // to names using GOOS and GOARCH. |
613 // For example, defs_linux_amd64.h becomes defs_GOOS_GOARCH.h. | 672 // For example, defs_linux_amd64.h becomes defs_GOOS_GOARCH.h. |
614 » _goos_goarch := "_" + b.goos + "_" + b.goarch + ".h" | 673 » _goos_goarch := "_" + goos + "_" + goarch + ".h" |
615 » _goos := "_" + b.goos + ".h" | 674 » _goos := "_" + goos + ".h" |
616 » _goarch := "_" + b.goarch + ".h" | 675 » _goarch := "_" + goarch + ".h" |
617 for _, file := range a.p.HFiles { | 676 for _, file := range a.p.HFiles { |
618 switch { | 677 switch { |
619 case strings.HasSuffix(file, _goos_goarch): | 678 case strings.HasSuffix(file, _goos_goarch): |
620 targ := file[:len(file)-len(_goos_goarch)] + "_GOOS_GOAR
CH.h" | 679 targ := file[:len(file)-len(_goos_goarch)] + "_GOOS_GOAR
CH.h" |
621 » » » if err := b.copyFile(obj+targ, filepath.Join(a.p.Dir, fi
le), 0666); err != nil { | 680 » » » if err := b.copyFile(a, obj+targ, filepath.Join(a.p.Dir,
file), 0666); err != nil { |
622 return err | 681 return err |
623 } | 682 } |
624 case strings.HasSuffix(file, _goarch): | 683 case strings.HasSuffix(file, _goarch): |
625 targ := file[:len(file)-len(_goarch)] + "_GOARCH.h" | 684 targ := file[:len(file)-len(_goarch)] + "_GOARCH.h" |
626 » » » if err := b.copyFile(obj+targ, filepath.Join(a.p.Dir, fi
le), 0666); err != nil { | 685 » » » if err := b.copyFile(a, obj+targ, filepath.Join(a.p.Dir,
file), 0666); err != nil { |
627 return err | 686 return err |
628 } | 687 } |
629 case strings.HasSuffix(file, _goos): | 688 case strings.HasSuffix(file, _goos): |
630 targ := file[:len(file)-len(_goos)] + "_GOOS.h" | 689 targ := file[:len(file)-len(_goos)] + "_GOOS.h" |
631 » » » if err := b.copyFile(obj+targ, filepath.Join(a.p.Dir, fi
le), 0666); err != nil { | 690 » » » if err := b.copyFile(a, obj+targ, filepath.Join(a.p.Dir,
file), 0666); err != nil { |
632 return err | 691 return err |
633 } | 692 } |
634 } | 693 } |
635 } | 694 } |
636 | 695 |
637 for _, file := range cfiles { | 696 for _, file := range cfiles { |
638 » » out := file[:len(file)-len(".c")] + "." + b.arch | 697 » » out := file[:len(file)-len(".c")] + "." + archChar |
639 if err := buildToolchain.cc(b, a.p, obj, obj+out, file); err !=
nil { | 698 if err := buildToolchain.cc(b, a.p, obj, obj+out, file); err !=
nil { |
640 return err | 699 return err |
641 } | 700 } |
642 objects = append(objects, out) | 701 objects = append(objects, out) |
643 } | 702 } |
644 | 703 |
645 // Assemble .s files. | 704 // Assemble .s files. |
646 for _, file := range sfiles { | 705 for _, file := range sfiles { |
647 » » out := file[:len(file)-len(".s")] + "." + b.arch | 706 » » out := file[:len(file)-len(".s")] + "." + archChar |
648 if err := buildToolchain.asm(b, a.p, obj, obj+out, file); err !=
nil { | 707 if err := buildToolchain.asm(b, a.p, obj, obj+out, file); err !=
nil { |
649 return err | 708 return err |
650 } | 709 } |
651 objects = append(objects, out) | 710 objects = append(objects, out) |
652 } | 711 } |
653 | 712 |
654 // NOTE(rsc): On Windows, it is critically important that the | 713 // NOTE(rsc): On Windows, it is critically important that the |
655 // gcc-compiled objects (cgoObjects) be listed after the ordinary | 714 // gcc-compiled objects (cgoObjects) be listed after the ordinary |
656 // objects in the archive. I do not know why this is. | 715 // objects in the archive. I do not know why this is. |
657 // http://golang.org/issue/2601 | 716 // http://golang.org/issue/2601 |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
694 | 753 |
695 // remove object dir to keep the amount of | 754 // remove object dir to keep the amount of |
696 // garbage down in a large build. On an operating system | 755 // garbage down in a large build. On an operating system |
697 // with aggressive buffering, cleaning incrementally like | 756 // with aggressive buffering, cleaning incrementally like |
698 // this keeps the intermediate objects from hitting the disk. | 757 // this keeps the intermediate objects from hitting the disk. |
699 if !buildWork { | 758 if !buildWork { |
700 defer os.RemoveAll(a1.objdir) | 759 defer os.RemoveAll(a1.objdir) |
701 defer os.Remove(a1.target) | 760 defer os.Remove(a1.target) |
702 } | 761 } |
703 | 762 |
704 » return b.copyFile(a.target, a1.target, perm) | 763 » return b.copyFile(a, a.target, a1.target, perm) |
705 } | 764 } |
706 | 765 |
707 // includeArgs returns the -I or -L directory list for access | 766 // includeArgs returns the -I or -L directory list for access |
708 // to the results of the list of actions. | 767 // to the results of the list of actions. |
709 func (b *builder) includeArgs(flag string, all []*action) []string { | 768 func (b *builder) includeArgs(flag string, all []*action) []string { |
710 inc := []string{} | 769 inc := []string{} |
711 incMap := map[string]bool{ | 770 incMap := map[string]bool{ |
712 » » b.work: true, // handled later | 771 » » b.work + "/obj": true, // handled later |
713 » » build.Path[0].PkgDir(): true, // goroot | 772 » » gorootPkg: true, |
714 » » "": true, // ignore empty strings | 773 » » "": true, // ignore empty strings |
715 } | 774 } |
716 | 775 |
717 // Look in the temporary space for results of test-specific actions. | 776 // Look in the temporary space for results of test-specific actions. |
718 // This is the $WORK/my/package/_test directory for the | 777 // This is the $WORK/my/package/_test directory for the |
719 // package being built, so there are few of these. | 778 // package being built, so there are few of these. |
720 for _, a1 := range all { | 779 for _, a1 := range all { |
721 » » if dir := a1.pkgdir; dir != a1.p.t.PkgDir() && !incMap[dir] { | 780 » » if dir := a1.pkgdir; dir != a1.p.build.PkgRoot && !incMap[dir] { |
722 incMap[dir] = true | 781 incMap[dir] = true |
723 inc = append(inc, flag, dir) | 782 inc = append(inc, flag, dir) |
724 } | 783 } |
725 } | 784 } |
726 | 785 |
727 // Also look in $WORK for any non-test packages that have | 786 // Also look in $WORK for any non-test packages that have |
728 // been built but not installed. | 787 // been built but not installed. |
729 » inc = append(inc, flag, b.work) | 788 » inc = append(inc, flag, b.work+"/obj") |
730 | 789 |
731 // Finally, look in the installed package directories for each action. | 790 // Finally, look in the installed package directories for each action. |
732 for _, a1 := range all { | 791 for _, a1 := range all { |
733 » » if dir := a1.pkgdir; dir == a1.p.t.PkgDir() && !incMap[dir] { | 792 » » if dir := a1.pkgdir; dir == a1.p.build.PkgRoot && !incMap[dir] { |
734 if _, ok := buildToolchain.(gccgoToolchain); ok { | 793 if _, ok := buildToolchain.(gccgoToolchain); ok { |
735 dir = filepath.Join(filepath.Dir(dir), "gccgo",
filepath.Base(dir)) | 794 dir = filepath.Join(filepath.Dir(dir), "gccgo",
filepath.Base(dir)) |
736 } | 795 } |
737 incMap[dir] = true | 796 incMap[dir] = true |
738 inc = append(inc, flag, dir) | 797 inc = append(inc, flag, dir) |
739 } | 798 } |
740 } | 799 } |
741 | 800 |
742 return inc | 801 return inc |
743 } | 802 } |
744 | 803 |
745 // copyFile is like 'cp src dst'. | 804 // copyFile is like 'cp src dst'. |
746 func (b *builder) copyFile(dst, src string, perm os.FileMode) error { | 805 func (b *builder) copyFile(a *action, dst, src string, perm os.FileMode) error { |
747 if buildN || buildX { | 806 if buildN || buildX { |
748 b.showcmd("", "cp %s %s", src, dst) | 807 b.showcmd("", "cp %s %s", src, dst) |
749 if buildN { | 808 if buildN { |
750 return nil | 809 return nil |
751 } | 810 } |
752 } | 811 } |
753 | 812 |
754 sf, err := os.Open(src) | 813 sf, err := os.Open(src) |
755 if err != nil { | 814 if err != nil { |
756 return err | 815 return err |
(...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
882 // $ go build | 941 // $ go build |
883 // # fmt | 942 // # fmt |
884 // /usr/gopher/go/src/pkg/fmt/print.go:1090: undefined: asdf | 943 // /usr/gopher/go/src/pkg/fmt/print.go:1090: undefined: asdf |
885 // $ | 944 // $ |
886 // | 945 // |
887 // showOutput also replaces references to the work directory with $WORK. | 946 // showOutput also replaces references to the work directory with $WORK. |
888 // | 947 // |
889 func (b *builder) showOutput(dir, desc, out string) { | 948 func (b *builder) showOutput(dir, desc, out string) { |
890 prefix := "# " + desc | 949 prefix := "# " + desc |
891 suffix := "\n" + out | 950 suffix := "\n" + out |
892 » pwd, _ := os.Getwd() | 951 » if reldir := shortPath(dir); reldir != dir { |
893 » if reldir, err := filepath.Rel(pwd, dir); err == nil && len(reldir) < le
n(dir) { | |
894 suffix = strings.Replace(suffix, " "+dir, " "+reldir, -1) | 952 suffix = strings.Replace(suffix, " "+dir, " "+reldir, -1) |
895 suffix = strings.Replace(suffix, "\n"+dir, "\n"+reldir, -1) | 953 suffix = strings.Replace(suffix, "\n"+dir, "\n"+reldir, -1) |
896 } | 954 } |
897 suffix = strings.Replace(suffix, " "+b.work, " $WORK", -1) | 955 suffix = strings.Replace(suffix, " "+b.work, " $WORK", -1) |
898 | 956 |
899 b.output.Lock() | 957 b.output.Lock() |
900 defer b.output.Unlock() | 958 defer b.output.Unlock() |
901 b.print(prefix, suffix) | 959 b.print(prefix, suffix) |
902 } | 960 } |
903 | 961 |
| 962 // shortPath returns an absolute or relative name for path, whatever is shorter. |
| 963 func shortPath(path string) string { |
| 964 if rel, err := filepath.Rel(cwd, path); err == nil && len(rel) < len(pat
h) { |
| 965 return rel |
| 966 } |
| 967 return path |
| 968 } |
| 969 |
904 // relPaths returns a copy of paths with absolute paths | 970 // relPaths returns a copy of paths with absolute paths |
905 // made relative to the current directory if they would be shorter. | 971 // made relative to the current directory if they would be shorter. |
906 func relPaths(paths []string) []string { | 972 func relPaths(paths []string) []string { |
907 var out []string | 973 var out []string |
908 pwd, _ := os.Getwd() | 974 pwd, _ := os.Getwd() |
909 for _, p := range paths { | 975 for _, p := range paths { |
910 rel, err := filepath.Rel(pwd, p) | 976 rel, err := filepath.Rel(pwd, p) |
911 if err == nil && len(rel) < len(p) { | 977 if err == nil && len(rel) < len(p) { |
912 p = rel | 978 p = rel |
913 } | 979 } |
914 out = append(out, p) | 980 out = append(out, p) |
915 } | 981 } |
916 return out | 982 return out |
917 } | 983 } |
918 | 984 |
919 // errPrintedOutput is a special error indicating that a command failed | 985 // errPrintedOutput is a special error indicating that a command failed |
920 // but that it generated output as well, and that output has already | 986 // but that it generated output as well, and that output has already |
921 // been printed, so there's no point showing 'exit status 1' or whatever | 987 // been printed, so there's no point showing 'exit status 1' or whatever |
922 // the wait status was. The main executor, builder.do, knows not to | 988 // the wait status was. The main executor, builder.do, knows not to |
923 // print this error. | 989 // print this error. |
924 var errPrintedOutput = errors.New("already printed output - no need to show erro
r") | 990 var errPrintedOutput = errors.New("already printed output - no need to show erro
r") |
925 | 991 |
926 // run runs the command given by cmdline in the directory dir. | 992 // run runs the command given by cmdline in the directory dir. |
927 // If the commnd fails, run prints information about the failure | 993 // If the commnd fails, run prints information about the failure |
928 // and returns a non-nil error. | 994 // and returns a non-nil error. |
929 func (b *builder) run(dir string, desc string, cmdargs ...interface{}) error { | 995 func (b *builder) run(dir, shortenDir string, desc string, cmdargs ...interface{
}) error { |
930 out, err := b.runOut(dir, desc, cmdargs...) | 996 out, err := b.runOut(dir, desc, cmdargs...) |
931 if len(out) > 0 { | 997 if len(out) > 0 { |
932 if out[len(out)-1] != '\n' { | 998 if out[len(out)-1] != '\n' { |
933 out = append(out, '\n') | 999 out = append(out, '\n') |
934 } | 1000 } |
935 if desc == "" { | 1001 if desc == "" { |
936 desc = b.fmtcmd(dir, "%s", strings.Join(stringList(cmdar
gs...), " ")) | 1002 desc = b.fmtcmd(dir, "%s", strings.Join(stringList(cmdar
gs...), " ")) |
937 } | 1003 } |
938 » » b.showOutput(dir, desc, string(out)) | 1004 » » b.showOutput(shortenDir, desc, string(out)) |
939 if err != nil { | 1005 if err != nil { |
940 err = errPrintedOutput | 1006 err = errPrintedOutput |
941 } | 1007 } |
942 } | 1008 } |
943 return err | 1009 return err |
944 } | 1010 } |
945 | 1011 |
946 // runOut runs the command given by cmdline in the directory dir. | 1012 // runOut runs the command given by cmdline in the directory dir. |
947 // It returns the command output and any errors that occurred. | 1013 // It returns the command output and any errors that occurred. |
948 func (b *builder) runOut(dir string, desc string, cmdargs ...interface{}) ([]byt
e, error) { | 1014 func (b *builder) runOut(dir string, desc string, cmdargs ...interface{}) ([]byt
e, error) { |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
999 // instead of creating an actual work directory that won't be used. | 1065 // instead of creating an actual work directory that won't be used. |
1000 // Leave paths beginning with $WORK alone too. | 1066 // Leave paths beginning with $WORK alone too. |
1001 if filepath.IsAbs(f) || strings.HasPrefix(f, "$WORK") { | 1067 if filepath.IsAbs(f) || strings.HasPrefix(f, "$WORK") { |
1002 return f | 1068 return f |
1003 } | 1069 } |
1004 return filepath.Join(dir, f) | 1070 return filepath.Join(dir, f) |
1005 } | 1071 } |
1006 | 1072 |
1007 type toolchain interface { | 1073 type toolchain interface { |
1008 // gc runs the compiler in a specific directory on a set of files | 1074 // gc runs the compiler in a specific directory on a set of files |
1009 » // and returns the name of the generated output file. | 1075 » // and returns the name of the generated output file. |
1010 » gc(b *builder, p *Package, obj string, importArgs []string, gofiles []st
ring) (ofile string, err error) | 1076 » // The compiler runs in the directory dir. |
| 1077 » gc(b *builder, p *Package, obj, dir string, importArgs []string, gofiles
[]string) (ofile string, err error) |
1011 // cc runs the toolchain's C compiler in a directory on a C file | 1078 // cc runs the toolchain's C compiler in a directory on a C file |
1012 // to produce an output file. | 1079 // to produce an output file. |
1013 cc(b *builder, p *Package, objdir, ofile, cfile string) error | 1080 cc(b *builder, p *Package, objdir, ofile, cfile string) error |
1014 // asm runs the assembler in a specific directory on a specific file | 1081 // asm runs the assembler in a specific directory on a specific file |
1015 » // to generate the named output file. | 1082 » // to generate the named output file. |
1016 asm(b *builder, p *Package, obj, ofile, sfile string) error | 1083 asm(b *builder, p *Package, obj, ofile, sfile string) error |
1017 // pkgpath creates the appropriate destination path for a package file. | 1084 // pkgpath creates the appropriate destination path for a package file. |
1018 » pkgpath(basedir string, p *Package) string | 1085 » pkgpath(basedir string, p *Package, install bool) string |
1019 // pack runs the archive packer in a specific directory to create | 1086 // pack runs the archive packer in a specific directory to create |
1020 // an archive from a set of object files. | 1087 // an archive from a set of object files. |
1021 // typically it is run in the object directory. | 1088 // typically it is run in the object directory. |
1022 pack(b *builder, p *Package, objDir, afile string, ofiles []string) erro
r | 1089 pack(b *builder, p *Package, objDir, afile string, ofiles []string) erro
r |
1023 // ld runs the linker to create a package starting at mainpkg. | 1090 // ld runs the linker to create a package starting at mainpkg. |
1024 ld(b *builder, p *Package, out string, allactions []*action, mainpkg str
ing, ofiles []string) error | 1091 ld(b *builder, p *Package, out string, allactions []*action, mainpkg str
ing, ofiles []string) error |
| 1092 |
| 1093 compiler() string |
| 1094 linker() string |
1025 } | 1095 } |
1026 | 1096 |
1027 type goToolchain struct{} | 1097 type goToolchain struct{} |
1028 type gccgoToolchain struct{} | 1098 type gccgoToolchain struct{} |
1029 | 1099 |
1030 var buildToolchain toolchain | 1100 var buildToolchain toolchain |
1031 | 1101 |
1032 func init() { | 1102 func init() { |
| 1103 // TODO(rsc): Decide how to trigger gccgo. Issue 3157. |
1033 if os.Getenv("GC") == "gccgo" { | 1104 if os.Getenv("GC") == "gccgo" { |
1034 buildToolchain = gccgoToolchain{} | 1105 buildToolchain = gccgoToolchain{} |
1035 } else { | 1106 } else { |
1036 buildToolchain = goToolchain{} | 1107 buildToolchain = goToolchain{} |
1037 } | 1108 } |
1038 } | 1109 } |
1039 | 1110 |
1040 // The Go toolchain. | 1111 // The Go toolchain. |
1041 | 1112 |
1042 func (goToolchain) gc(b *builder, p *Package, obj string, importArgs []string, g
ofiles []string) (ofile string, err error) { | 1113 func (goToolchain) compiler() string { |
1043 » out := "_go_." + b.arch | 1114 » return tool(archChar + "g") |
| 1115 } |
| 1116 |
| 1117 func (goToolchain) linker() string { |
| 1118 » return tool(archChar + "l") |
| 1119 } |
| 1120 |
| 1121 func (goToolchain) gc(b *builder, p *Package, obj, dir string, importArgs []stri
ng, gofiles []string) (ofile string, err error) { |
| 1122 » out := "_go_." + archChar |
1044 ofile = obj + out | 1123 ofile = obj + out |
1045 gcargs := []string{"-p", p.ImportPath} | 1124 gcargs := []string{"-p", p.ImportPath} |
1046 if p.Standard && p.ImportPath == "runtime" { | 1125 if p.Standard && p.ImportPath == "runtime" { |
1047 // runtime compiles with a special 6g flag to emit | 1126 // runtime compiles with a special 6g flag to emit |
1048 // additional reflect type data. | 1127 // additional reflect type data. |
1049 gcargs = append(gcargs, "-+") | 1128 gcargs = append(gcargs, "-+") |
1050 } | 1129 } |
1051 | 1130 |
1052 » args := stringList(tool(b.arch+"g"), "-o", ofile, b.gcflags, gcargs, imp
ortArgs) | 1131 » args := stringList(tool(archChar+"g"), "-o", ofile, buildGcflags, gcargs
, importArgs) |
1053 for _, f := range gofiles { | 1132 for _, f := range gofiles { |
1054 args = append(args, mkAbs(p.Dir, f)) | 1133 args = append(args, mkAbs(p.Dir, f)) |
1055 } | 1134 } |
1056 » return ofile, b.run(p.Dir, p.ImportPath, args) | 1135 » return ofile, b.run(dir, p.Dir, p.ImportPath, args) |
1057 } | 1136 } |
1058 | 1137 |
1059 func (goToolchain) asm(b *builder, p *Package, obj, ofile, sfile string) error { | 1138 func (goToolchain) asm(b *builder, p *Package, obj, ofile, sfile string) error { |
1060 sfile = mkAbs(p.Dir, sfile) | 1139 sfile = mkAbs(p.Dir, sfile) |
1061 » return b.run(p.Dir, p.ImportPath, tool(b.arch+"a"), "-I", obj, "-o", ofi
le, "-DGOOS_"+b.goos, "-DGOARCH_"+b.goarch, sfile) | 1140 » return b.run(p.Dir, p.Dir, p.ImportPath, tool(archChar+"a"), "-I", obj,
"-o", ofile, "-DGOOS_"+goos, "-DGOARCH_"+goarch, sfile) |
1062 } | 1141 } |
1063 | 1142 |
1064 func (goToolchain) pkgpath(basedir string, p *Package) string { | 1143 func (goToolchain) pkgpath(basedir string, p *Package, install bool) string { |
1065 » return filepath.Join(basedir, filepath.FromSlash(p.ImportPath+".a")) | 1144 » end := filepath.FromSlash(p.ImportPath + ".a") |
| 1145 » if install { |
| 1146 » » return filepath.Join(basedir, buildContext.GOOS+"_"+buildContext
.GOARCH, end) |
| 1147 » } |
| 1148 » return filepath.Join(basedir, end) |
1066 } | 1149 } |
1067 | 1150 |
1068 func (goToolchain) pack(b *builder, p *Package, objDir, afile string, ofiles []s
tring) error { | 1151 func (goToolchain) pack(b *builder, p *Package, objDir, afile string, ofiles []s
tring) error { |
1069 var absOfiles []string | 1152 var absOfiles []string |
1070 for _, f := range ofiles { | 1153 for _, f := range ofiles { |
1071 absOfiles = append(absOfiles, mkAbs(objDir, f)) | 1154 absOfiles = append(absOfiles, mkAbs(objDir, f)) |
1072 } | 1155 } |
1073 » return b.run(p.Dir, p.ImportPath, tool("pack"), "grc", mkAbs(objDir, afi
le), absOfiles) | 1156 » return b.run(p.Dir, p.Dir, p.ImportPath, tool("pack"), "grc", mkAbs(objD
ir, afile), absOfiles) |
1074 } | 1157 } |
1075 | 1158 |
1076 func (goToolchain) ld(b *builder, p *Package, out string, allactions []*action,
mainpkg string, ofiles []string) error { | 1159 func (goToolchain) ld(b *builder, p *Package, out string, allactions []*action,
mainpkg string, ofiles []string) error { |
1077 importArgs := b.includeArgs("-L", allactions) | 1160 importArgs := b.includeArgs("-L", allactions) |
1078 » return b.run(p.Dir, p.ImportPath, tool(b.arch+"l"), "-o", out, importArg
s, mainpkg) | 1161 » return b.run(p.Dir, p.Dir, p.ImportPath, tool(archChar+"l"), "-o", out,
importArgs, buildLdflags, mainpkg) |
1079 } | 1162 } |
1080 | 1163 |
1081 func (goToolchain) cc(b *builder, p *Package, objdir, ofile, cfile string) error
{ | 1164 func (goToolchain) cc(b *builder, p *Package, objdir, ofile, cfile string) error
{ |
1082 » inc := filepath.Join(goroot, "pkg", fmt.Sprintf("%s_%s", b.goos, b.goarc
h)) | 1165 » inc := filepath.Join(goroot, "pkg", fmt.Sprintf("%s_%s", goos, goarch)) |
1083 cfile = mkAbs(p.Dir, cfile) | 1166 cfile = mkAbs(p.Dir, cfile) |
1084 » return b.run(p.Dir, p.ImportPath, tool(b.arch+"c"), "-FVw", | 1167 » return b.run(p.Dir, p.Dir, p.ImportPath, tool(archChar+"c"), "-FVw", |
1085 "-I", objdir, "-I", inc, "-o", ofile, | 1168 "-I", objdir, "-I", inc, "-o", ofile, |
1086 » » "-DGOOS_"+b.goos, "-DGOARCH_"+b.goarch, cfile) | 1169 » » "-DGOOS_"+goos, "-DGOARCH_"+goarch, cfile) |
1087 } | 1170 } |
1088 | 1171 |
1089 // The Gccgo toolchain. | 1172 // The Gccgo toolchain. |
1090 | 1173 |
1091 func (gccgoToolchain) gc(b *builder, p *Package, obj string, importArgs []string
, gofiles []string) (ofile string, err error) { | 1174 var gccgoBin, _ = exec.LookPath("gccgo") |
| 1175 |
| 1176 func (gccgoToolchain) compiler() string { |
| 1177 » return gccgoBin |
| 1178 } |
| 1179 |
| 1180 func (gccgoToolchain) linker() string { |
| 1181 » return gccgoBin |
| 1182 } |
| 1183 |
| 1184 func (gccgoToolchain) gc(b *builder, p *Package, obj, dir string, importArgs []s
tring, gofiles []string) (ofile string, err error) { |
1092 out := p.Name + ".o" | 1185 out := p.Name + ".o" |
1093 ofile = obj + out | 1186 ofile = obj + out |
1094 gcargs := []string{"-g"} | 1187 gcargs := []string{"-g"} |
1095 if p.Name != "main" { | 1188 if p.Name != "main" { |
1096 if p.fake { | 1189 if p.fake { |
1097 gcargs = append(gcargs, "-fgo-prefix=fake_"+p.ImportPath
) | 1190 gcargs = append(gcargs, "-fgo-prefix=fake_"+p.ImportPath
) |
1098 } else { | 1191 } else { |
1099 gcargs = append(gcargs, "-fgo-prefix=go_"+p.ImportPath) | 1192 gcargs = append(gcargs, "-fgo-prefix=go_"+p.ImportPath) |
1100 } | 1193 } |
1101 } | 1194 } |
1102 » args := stringList("gccgo", importArgs, "-c", b.gcflags, gcargs, "-o", o
file) | 1195 » args := stringList("gccgo", importArgs, "-c", gcargs, "-o", ofile, build
Gccgoflags) |
1103 for _, f := range gofiles { | 1196 for _, f := range gofiles { |
1104 args = append(args, mkAbs(p.Dir, f)) | 1197 args = append(args, mkAbs(p.Dir, f)) |
1105 } | 1198 } |
1106 » return ofile, b.run(p.Dir, p.ImportPath, args) | 1199 » return ofile, b.run(dir, p.Dir, p.ImportPath, args) |
1107 } | 1200 } |
1108 | 1201 |
1109 func (gccgoToolchain) asm(b *builder, p *Package, obj, ofile, sfile string) erro
r { | 1202 func (gccgoToolchain) asm(b *builder, p *Package, obj, ofile, sfile string) erro
r { |
1110 sfile = mkAbs(p.Dir, sfile) | 1203 sfile = mkAbs(p.Dir, sfile) |
1111 » return b.run(p.Dir, p.ImportPath, "gccgo", "-I", obj, "-o", ofile, "-DGO
OS_"+b.goos, "-DGOARCH_"+b.goarch, sfile) | 1204 » return b.run(p.Dir, p.Dir, p.ImportPath, "gccgo", "-I", obj, "-o", ofile
, "-DGOOS_"+goos, "-DGOARCH_"+goarch, sfile) |
1112 } | 1205 } |
1113 | 1206 |
1114 func (gccgoToolchain) pkgpath(basedir string, p *Package) string { | 1207 func (gccgoToolchain) pkgpath(basedir string, p *Package, install bool) string { |
1115 » afile := filepath.Join(basedir, filepath.FromSlash(p.ImportPath+".a")) | 1208 » // NOTE: Apparently gccgo does not distinguish different trees |
1116 » // prepend "lib" to the basename | 1209 » // using goos_goarch, so install is ignored here. |
| 1210 » afile := filepath.Join(basedir, "gccgo", filepath.FromSlash(p.ImportPath
+".a")) |
| 1211 » // add "lib" to the final element |
1117 return filepath.Join(filepath.Dir(afile), "lib"+filepath.Base(afile)) | 1212 return filepath.Join(filepath.Dir(afile), "lib"+filepath.Base(afile)) |
1118 } | 1213 } |
1119 | 1214 |
1120 func (gccgoToolchain) pack(b *builder, p *Package, objDir, afile string, ofiles
[]string) error { | 1215 func (gccgoToolchain) pack(b *builder, p *Package, objDir, afile string, ofiles
[]string) error { |
1121 var absOfiles []string | 1216 var absOfiles []string |
1122 for _, f := range ofiles { | 1217 for _, f := range ofiles { |
1123 absOfiles = append(absOfiles, mkAbs(objDir, f)) | 1218 absOfiles = append(absOfiles, mkAbs(objDir, f)) |
1124 } | 1219 } |
1125 » return b.run(p.Dir, p.ImportPath, "ar", "cru", mkAbs(objDir, afile), abs
Ofiles) | 1220 » return b.run(p.Dir, p.Dir, p.ImportPath, "ar", "cru", mkAbs(objDir, afil
e), absOfiles) |
1126 } | 1221 } |
1127 | 1222 |
1128 func (tools gccgoToolchain) ld(b *builder, p *Package, out string, allactions []
*action, mainpkg string, ofiles []string) error { | 1223 func (tools gccgoToolchain) ld(b *builder, p *Package, out string, allactions []
*action, mainpkg string, ofiles []string) error { |
1129 // gccgo needs explicit linking with all package dependencies, | 1224 // gccgo needs explicit linking with all package dependencies, |
1130 // and all LDFLAGS from cgo dependencies | 1225 // and all LDFLAGS from cgo dependencies |
1131 afiles := []string{} | 1226 afiles := []string{} |
1132 ldflags := []string{} | 1227 ldflags := []string{} |
1133 seen := map[*Package]bool{} | 1228 seen := map[*Package]bool{} |
1134 for _, a := range allactions { | 1229 for _, a := range allactions { |
1135 if a.p != nil && !seen[a.p] { | 1230 if a.p != nil && !seen[a.p] { |
1136 seen[a.p] = true | 1231 seen[a.p] = true |
1137 if !a.p.Standard { | 1232 if !a.p.Standard { |
1138 afiles = append(afiles, a.target) | 1233 afiles = append(afiles, a.target) |
1139 } | 1234 } |
1140 ldflags = append(ldflags, a.p.CgoLDFLAGS...) | 1235 ldflags = append(ldflags, a.p.CgoLDFLAGS...) |
1141 } | 1236 } |
1142 } | 1237 } |
1143 » return b.run(p.Dir, p.ImportPath, "gccgo", "-o", out, ofiles, "-Wl,-(",
afiles, ldflags, "-Wl,-)") | 1238 |
| 1239 » return b.run(p.Dir, p.Dir, p.ImportPath, "gccgo", "-o", out, buildGccgof
lags, ofiles, "-Wl,-(", afiles, ldflags, "-Wl,-)") |
1144 } | 1240 } |
1145 | 1241 |
1146 func (gccgoToolchain) cc(b *builder, p *Package, objdir, ofile, cfile string) er
ror { | 1242 func (gccgoToolchain) cc(b *builder, p *Package, objdir, ofile, cfile string) er
ror { |
1147 » inc := filepath.Join(goroot, "pkg", fmt.Sprintf("%s_%s", b.goos, b.goarc
h)) | 1243 » inc := filepath.Join(goroot, "pkg", fmt.Sprintf("%s_%s", goos, goarch)) |
1148 cfile = mkAbs(p.Dir, cfile) | 1244 cfile = mkAbs(p.Dir, cfile) |
1149 » return b.run(p.Dir, p.ImportPath, "gcc", "-Wall", "-g", | 1245 » return b.run(p.Dir, p.Dir, p.ImportPath, "gcc", "-Wall", "-g", |
1150 "-I", objdir, "-I", inc, "-o", ofile, | 1246 "-I", objdir, "-I", inc, "-o", ofile, |
1151 » » "-DGOOS_"+b.goos, "-DGOARCH_"+b.goarch, "-c", cfile) | 1247 » » "-DGOOS_"+goos, "-DGOARCH_"+goarch, "-c", cfile) |
1152 } | 1248 } |
1153 | 1249 |
1154 // gcc runs the gcc C compiler to create an object from a single C file. | 1250 // gcc runs the gcc C compiler to create an object from a single C file. |
1155 func (b *builder) gcc(p *Package, out string, flags []string, cfile string) erro
r { | 1251 func (b *builder) gcc(p *Package, out string, flags []string, cfile string) erro
r { |
1156 cfile = mkAbs(p.Dir, cfile) | 1252 cfile = mkAbs(p.Dir, cfile) |
1157 » return b.run(p.Dir, p.ImportPath, b.gccCmd(p.Dir), flags, "-o", out, "-c
", cfile) | 1253 » return b.run(p.Dir, p.Dir, p.ImportPath, b.gccCmd(p.Dir), flags, "-o", o
ut, "-c", cfile) |
1158 } | 1254 } |
1159 | 1255 |
1160 // gccld runs the gcc linker to create an executable from a set of object files | 1256 // gccld runs the gcc linker to create an executable from a set of object files |
1161 func (b *builder) gccld(p *Package, out string, flags []string, obj []string) er
ror { | 1257 func (b *builder) gccld(p *Package, out string, flags []string, obj []string) er
ror { |
1162 » return b.run(p.Dir, p.ImportPath, b.gccCmd(p.Dir), "-o", out, obj, flags
) | 1258 » return b.run(p.Dir, p.Dir, p.ImportPath, b.gccCmd(p.Dir), "-o", out, obj
, flags) |
1163 } | 1259 } |
1164 | 1260 |
1165 // gccCmd returns a gcc command line prefix | 1261 // gccCmd returns a gcc command line prefix |
1166 func (b *builder) gccCmd(objdir string) []string { | 1262 func (b *builder) gccCmd(objdir string) []string { |
1167 // TODO: HOST_CC? | 1263 // TODO: HOST_CC? |
1168 a := []string{"gcc", "-I", objdir, "-g", "-O2"} | 1264 a := []string{"gcc", "-I", objdir, "-g", "-O2"} |
1169 | 1265 |
1170 // Definitely want -fPIC but on Windows gcc complains | 1266 // Definitely want -fPIC but on Windows gcc complains |
1171 // "-fPIC ignored for target (all code is position independent)" | 1267 // "-fPIC ignored for target (all code is position independent)" |
1172 » if b.goos != "windows" { | 1268 » if goos != "windows" { |
1173 a = append(a, "-fPIC") | 1269 a = append(a, "-fPIC") |
1174 } | 1270 } |
1175 » switch b.arch { | 1271 » switch archChar { |
1176 case "8": | 1272 case "8": |
1177 a = append(a, "-m32") | 1273 a = append(a, "-m32") |
1178 case "6": | 1274 case "6": |
1179 a = append(a, "-m64") | 1275 a = append(a, "-m64") |
1180 } | 1276 } |
1181 // gcc-4.5 and beyond require explicit "-pthread" flag | 1277 // gcc-4.5 and beyond require explicit "-pthread" flag |
1182 // for multithreading with pthread library. | 1278 // for multithreading with pthread library. |
1183 if buildContext.CgoEnabled { | 1279 if buildContext.CgoEnabled { |
1184 » » switch b.goos { | 1280 » » switch goos { |
1185 case "windows": | 1281 case "windows": |
1186 a = append(a, "-mthreads") | 1282 a = append(a, "-mthreads") |
1187 default: | 1283 default: |
1188 a = append(a, "-pthread") | 1284 a = append(a, "-pthread") |
1189 } | 1285 } |
1190 } | 1286 } |
1191 return a | 1287 return a |
1192 } | 1288 } |
1193 | 1289 |
1194 func envList(key string) []string { | 1290 func envList(key string) []string { |
1195 return strings.Fields(os.Getenv(key)) | 1291 return strings.Fields(os.Getenv(key)) |
1196 } | 1292 } |
1197 | 1293 |
1198 var cgoRe = regexp.MustCompile(`[/\\:]`) | 1294 var cgoRe = regexp.MustCompile(`[/\\:]`) |
1199 | 1295 |
1200 func (b *builder) cgo(p *Package, cgoExe, obj string, gccfiles []string) (outGo,
outObj []string, err error) { | 1296 func (b *builder) cgo(p *Package, cgoExe, obj string, gccfiles []string) (outGo,
outObj []string, err error) { |
1201 » if b.goos != toolGOOS { | 1297 » if goos != toolGOOS { |
1202 return nil, nil, errors.New("cannot use cgo when compiling for a
different operating system") | 1298 return nil, nil, errors.New("cannot use cgo when compiling for a
different operating system") |
1203 } | 1299 } |
1204 | 1300 |
1205 » cgoCFLAGS := stringList(envList("CGO_CFLAGS"), p.info.CgoCFLAGS) | 1301 » cgoCFLAGS := stringList(envList("CGO_CFLAGS"), p.CgoCFLAGS) |
1206 » cgoLDFLAGS := stringList(envList("CGO_LDFLAGS"), p.info.CgoLDFLAGS) | 1302 » cgoLDFLAGS := stringList(envList("CGO_LDFLAGS"), p.CgoLDFLAGS) |
1207 | 1303 |
1208 » if pkgs := p.info.CgoPkgConfig; len(pkgs) > 0 { | 1304 » if pkgs := p.CgoPkgConfig; len(pkgs) > 0 { |
1209 out, err := b.runOut(p.Dir, p.ImportPath, "pkg-config", "--cflag
s", pkgs) | 1305 out, err := b.runOut(p.Dir, p.ImportPath, "pkg-config", "--cflag
s", pkgs) |
1210 if err != nil { | 1306 if err != nil { |
1211 b.showOutput(p.Dir, "pkg-config --cflags "+strings.Join(
pkgs, " "), string(out)) | 1307 b.showOutput(p.Dir, "pkg-config --cflags "+strings.Join(
pkgs, " "), string(out)) |
1212 b.print(err.Error() + "\n") | 1308 b.print(err.Error() + "\n") |
1213 return nil, nil, errPrintedOutput | 1309 return nil, nil, errPrintedOutput |
1214 } | 1310 } |
1215 if len(out) > 0 { | 1311 if len(out) > 0 { |
1216 cgoCFLAGS = append(cgoCFLAGS, strings.Fields(string(out)
)...) | 1312 cgoCFLAGS = append(cgoCFLAGS, strings.Fields(string(out)
)...) |
1217 } | 1313 } |
1218 out, err = b.runOut(p.Dir, p.ImportPath, "pkg-config", "--libs",
pkgs) | 1314 out, err = b.runOut(p.Dir, p.ImportPath, "pkg-config", "--libs",
pkgs) |
(...skipping 23 matching lines...) Expand all Loading... |
1242 | 1338 |
1243 cgoflags := []string{} | 1339 cgoflags := []string{} |
1244 // TODO: make cgo not depend on $GOARCH? | 1340 // TODO: make cgo not depend on $GOARCH? |
1245 | 1341 |
1246 if p.Standard && p.ImportPath == "runtime/cgo" { | 1342 if p.Standard && p.ImportPath == "runtime/cgo" { |
1247 cgoflags = append(cgoflags, "-import_runtime_cgo=false") | 1343 cgoflags = append(cgoflags, "-import_runtime_cgo=false") |
1248 } | 1344 } |
1249 if _, ok := buildToolchain.(gccgoToolchain); ok { | 1345 if _, ok := buildToolchain.(gccgoToolchain); ok { |
1250 cgoflags = append(cgoflags, "-gccgo") | 1346 cgoflags = append(cgoflags, "-gccgo") |
1251 } | 1347 } |
1252 » if err := b.run(p.Dir, p.ImportPath, cgoExe, "-objdir", obj, cgoflags, "
--", cgoCFLAGS, p.CgoFiles); err != nil { | 1348 » if err := b.run(p.Dir, p.Dir, p.ImportPath, cgoExe, "-objdir", obj, cgof
lags, "--", cgoCFLAGS, p.CgoFiles); err != nil { |
1253 return nil, nil, err | 1349 return nil, nil, err |
1254 } | 1350 } |
1255 outGo = append(outGo, gofiles...) | 1351 outGo = append(outGo, gofiles...) |
1256 | 1352 |
1257 // cc _cgo_defun.c | 1353 // cc _cgo_defun.c |
1258 » defunObj := obj + "_cgo_defun." + b.arch | 1354 » defunObj := obj + "_cgo_defun." + archChar |
1259 if err := buildToolchain.cc(b, p, obj, defunObj, defunC); err != nil { | 1355 if err := buildToolchain.cc(b, p, obj, defunObj, defunC); err != nil { |
1260 return nil, nil, err | 1356 return nil, nil, err |
1261 } | 1357 } |
1262 outObj = append(outObj, defunObj) | 1358 outObj = append(outObj, defunObj) |
1263 | 1359 |
1264 // gcc | 1360 // gcc |
1265 var linkobj []string | 1361 var linkobj []string |
1266 for _, cfile := range cfiles { | 1362 for _, cfile := range cfiles { |
1267 ofile := obj + cfile[:len(cfile)-1] + "o" | 1363 ofile := obj + cfile[:len(cfile)-1] + "o" |
1268 if err := b.gcc(p, ofile, cgoCFLAGS, obj+cfile); err != nil { | 1364 if err := b.gcc(p, ofile, cgoCFLAGS, obj+cfile); err != nil { |
(...skipping 17 matching lines...) Expand all Loading... |
1286 return nil, nil, err | 1382 return nil, nil, err |
1287 } | 1383 } |
1288 | 1384 |
1289 if _, ok := buildToolchain.(gccgoToolchain); ok { | 1385 if _, ok := buildToolchain.(gccgoToolchain); ok { |
1290 // we don't use dynimport when using gccgo. | 1386 // we don't use dynimport when using gccgo. |
1291 return outGo, outObj, nil | 1387 return outGo, outObj, nil |
1292 } | 1388 } |
1293 | 1389 |
1294 // cgo -dynimport | 1390 // cgo -dynimport |
1295 importC := obj + "_cgo_import.c" | 1391 importC := obj + "_cgo_import.c" |
1296 » if err := b.run(p.Dir, p.ImportPath, cgoExe, "-objdir", obj, "-dynimport
", dynobj, "-dynout", importC); err != nil { | 1392 » if err := b.run(p.Dir, p.Dir, p.ImportPath, cgoExe, "-objdir", obj, "-dy
nimport", dynobj, "-dynout", importC); err != nil { |
1297 return nil, nil, err | 1393 return nil, nil, err |
1298 } | 1394 } |
1299 | 1395 |
1300 // cc _cgo_import.ARCH | 1396 // cc _cgo_import.ARCH |
1301 » importObj := obj + "_cgo_import." + b.arch | 1397 » importObj := obj + "_cgo_import." + archChar |
1302 if err := buildToolchain.cc(b, p, obj, importObj, importC); err != nil { | 1398 if err := buildToolchain.cc(b, p, obj, importObj, importC); err != nil { |
1303 return nil, nil, err | 1399 return nil, nil, err |
1304 } | 1400 } |
1305 | 1401 |
1306 // NOTE(rsc): The importObj is a 5c/6c/8c object and on Windows | 1402 // NOTE(rsc): The importObj is a 5c/6c/8c object and on Windows |
1307 // must be processed before the gcc-generated objects. | 1403 // must be processed before the gcc-generated objects. |
1308 // Put it first. http://golang.org/issue/2601 | 1404 // Put it first. http://golang.org/issue/2601 |
1309 outObj = append([]string{importObj}, outObj...) | 1405 outObj = append([]string{importObj}, outObj...) |
1310 | 1406 |
1311 return outGo, outObj, nil | 1407 return outGo, outObj, nil |
(...skipping 14 matching lines...) Expand all Loading... |
1326 return x | 1422 return x |
1327 } | 1423 } |
1328 | 1424 |
1329 func (q *actionQueue) push(a *action) { | 1425 func (q *actionQueue) push(a *action) { |
1330 heap.Push(q, a) | 1426 heap.Push(q, a) |
1331 } | 1427 } |
1332 | 1428 |
1333 func (q *actionQueue) pop() *action { | 1429 func (q *actionQueue) pop() *action { |
1334 return heap.Pop(q).(*action) | 1430 return heap.Pop(q).(*action) |
1335 } | 1431 } |
OLD | NEW |