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" |
(...skipping 434 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
445 // to use to find its context. | 445 // to use to find its context. |
446 fmt.Printf("\n#\n# %s\n#\n\n", a.p.ImportPath) | 446 fmt.Printf("\n#\n# %s\n#\n\n", a.p.ImportPath) |
447 } | 447 } |
448 | 448 |
449 // make build directory | 449 // make build directory |
450 obj := a.objdir | 450 obj := a.objdir |
451 if err := b.mkdir(obj); err != nil { | 451 if err := b.mkdir(obj); err != nil { |
452 return err | 452 return err |
453 } | 453 } |
454 | 454 |
455 » var gofiles, cfiles, sfiles, objects []string | 455 » var gofiles, cfiles, sfiles, objects, cgoObjects []string |
456 gofiles = append(gofiles, a.p.GoFiles...) | 456 gofiles = append(gofiles, a.p.GoFiles...) |
457 cfiles = append(cfiles, a.p.CFiles...) | 457 cfiles = append(cfiles, a.p.CFiles...) |
458 sfiles = append(sfiles, a.p.SFiles...) | 458 sfiles = append(sfiles, a.p.SFiles...) |
459 | 459 |
460 // run cgo | 460 // run cgo |
461 if len(a.p.CgoFiles) > 0 { | 461 if len(a.p.CgoFiles) > 0 { |
462 // In a package using cgo, cgo compiles the C and assembly files
with gcc.·· | 462 // In a package using cgo, cgo compiles the C and assembly files
with gcc.·· |
463 // There is one exception: runtime/cgo's job is to bridge the | 463 // There is one exception: runtime/cgo's job is to bridge the |
464 // cgo and non-cgo worlds, so it necessarily has files in both. | 464 // cgo and non-cgo worlds, so it necessarily has files in both. |
465 // In that case gcc only gets the gcc_* files. | 465 // In that case gcc only gets the gcc_* files. |
466 var gccfiles []string | 466 var gccfiles []string |
| 467 println("std?", a.p.Standard, a.p.ImportPath) |
467 if a.p.Standard && a.p.ImportPath == "runtime/cgo" { | 468 if a.p.Standard && a.p.ImportPath == "runtime/cgo" { |
468 filter := func(files, nongcc, gcc []string) ([]string, [
]string) { | 469 filter := func(files, nongcc, gcc []string) ([]string, [
]string) { |
469 for _, f := range files { | 470 for _, f := range files { |
470 if strings.HasPrefix(f, "gcc_") { | 471 if strings.HasPrefix(f, "gcc_") { |
471 gcc = append(gcc, f) | 472 gcc = append(gcc, f) |
472 } else { | 473 } else { |
473 nongcc = append(nongcc, f) | 474 nongcc = append(nongcc, f) |
474 } | 475 } |
475 } | 476 } |
476 return nongcc, gcc | 477 return nongcc, gcc |
477 } | 478 } |
478 cfiles, gccfiles = filter(cfiles, cfiles[:0], gccfiles) | 479 cfiles, gccfiles = filter(cfiles, cfiles[:0], gccfiles) |
479 sfiles, gccfiles = filter(sfiles, sfiles[:0], gccfiles) | 480 sfiles, gccfiles = filter(sfiles, sfiles[:0], gccfiles) |
480 } else { | 481 } else { |
481 gccfiles = append(cfiles, sfiles...) | 482 gccfiles = append(cfiles, sfiles...) |
482 cfiles = nil | 483 cfiles = nil |
483 sfiles = nil | 484 sfiles = nil |
484 } | 485 } |
485 | 486 |
486 outGo, outObj, err := b.cgo(a.p, a.cgo.target, obj, gccfiles) | 487 outGo, outObj, err := b.cgo(a.p, a.cgo.target, obj, gccfiles) |
487 if err != nil { | 488 if err != nil { |
488 return err | 489 return err |
489 } | 490 } |
490 » » objects = append(objects, outObj...) | 491 » » cgoObjects = append(cgoObjects, outObj...) |
491 gofiles = append(gofiles, outGo...) | 492 gofiles = append(gofiles, outGo...) |
492 } | 493 } |
493 | 494 |
494 // prepare Go import path list | 495 // prepare Go import path list |
495 inc := []string{} | 496 inc := []string{} |
496 incMap := map[string]bool{} | 497 incMap := map[string]bool{} |
497 | 498 |
498 incMap[b.work] = true // handled later | 499 incMap[b.work] = true // handled later |
499 incMap[build.Path[0].PkgDir()] = true // goroot | 500 incMap[build.Path[0].PkgDir()] = true // goroot |
500 incMap[""] = true // ignore empty strings | 501 incMap[""] = true // ignore empty strings |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
569 | 570 |
570 // assemble .s files | 571 // assemble .s files |
571 for _, file := range sfiles { | 572 for _, file := range sfiles { |
572 out := file[:len(file)-len(".s")] + "." + b.arch | 573 out := file[:len(file)-len(".s")] + "." + b.arch |
573 if err := b.asm(a.p, obj, obj+out, file); err != nil { | 574 if err := b.asm(a.p, obj, obj+out, file); err != nil { |
574 return err | 575 return err |
575 } | 576 } |
576 objects = append(objects, out) | 577 objects = append(objects, out) |
577 } | 578 } |
578 | 579 |
| 580 // NOTE(rsc): On Windows, it is critically important that the |
| 581 // gcc-compiled objects (cgoObjects) be listed after the ordinary |
| 582 // objects in the archive. I do not know why this is, and I am |
| 583 // not sure I want to know. http://golang.org/issue/2601 |
| 584 objects = append(objects, cgoObjects...) |
| 585 |
579 // pack into archive in obj directory | 586 // pack into archive in obj directory |
580 if err := b.gopack(a.p, obj, a.objpkg, objects); err != nil { | 587 if err := b.gopack(a.p, obj, a.objpkg, objects); err != nil { |
581 return err | 588 return err |
582 } | 589 } |
583 | 590 |
584 // link if needed. | 591 // link if needed. |
585 if a.link { | 592 if a.link { |
586 // command. | 593 // command. |
587 // import paths for compiler are introduced by -I. | 594 // import paths for compiler are introduced by -I. |
588 // for linker, they are introduced by -L. | 595 // for linker, they are introduced by -L. |
(...skipping 321 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
910 return append(a, args...) | 917 return append(a, args...) |
911 } | 918 } |
912 | 919 |
913 var cgoRe = regexp.MustCompile(`[/\\:]`) | 920 var cgoRe = regexp.MustCompile(`[/\\:]`) |
914 | 921 |
915 func (b *builder) cgo(p *Package, cgoExe, obj string, gccfiles []string) (outGo,
outObj []string, err error) { | 922 func (b *builder) cgo(p *Package, cgoExe, obj string, gccfiles []string) (outGo,
outObj []string, err error) { |
916 if b.goos != runtime.GOOS { | 923 if b.goos != runtime.GOOS { |
917 return nil, nil, errors.New("cannot use cgo when compiling for a
different operating system") | 924 return nil, nil, errors.New("cannot use cgo when compiling for a
different operating system") |
918 } | 925 } |
919 | 926 |
| 927 outObj = append(outObj, "") // for importObj, at end of function |
| 928 |
920 // cgo | 929 // cgo |
921 // TODO: CGOPKGPATH, CGO_FLAGS? | 930 // TODO: CGOPKGPATH, CGO_FLAGS? |
922 gofiles := []string{obj + "_cgo_gotypes.go"} | 931 gofiles := []string{obj + "_cgo_gotypes.go"} |
923 cfiles := []string{"_cgo_main.c", "_cgo_export.c"} | 932 cfiles := []string{"_cgo_main.c", "_cgo_export.c"} |
924 for _, fn := range p.CgoFiles { | 933 for _, fn := range p.CgoFiles { |
925 f := cgoRe.ReplaceAllString(fn[:len(fn)-2], "_") | 934 f := cgoRe.ReplaceAllString(fn[:len(fn)-2], "_") |
926 gofiles = append(gofiles, obj+f+"cgo1.go") | 935 gofiles = append(gofiles, obj+f+"cgo1.go") |
927 cfiles = append(cfiles, f+"cgo2.c") | 936 cfiles = append(cfiles, f+"cgo2.c") |
928 } | 937 } |
929 defunC := obj + "_cgo_defun.c" | 938 defunC := obj + "_cgo_defun.c" |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
976 importC := obj + "_cgo_import.c" | 985 importC := obj + "_cgo_import.c" |
977 if err := b.run(p.Dir, p.ImportPath, cgoExe, "-objdir", obj, "-dynimport
", dynobj, "-dynout", importC); err != nil { | 986 if err := b.run(p.Dir, p.ImportPath, cgoExe, "-objdir", obj, "-dynimport
", dynobj, "-dynout", importC); err != nil { |
978 return nil, nil, err | 987 return nil, nil, err |
979 } | 988 } |
980 | 989 |
981 // cc _cgo_import.ARCH | 990 // cc _cgo_import.ARCH |
982 importObj := obj + "_cgo_import." + b.arch | 991 importObj := obj + "_cgo_import." + b.arch |
983 if err := b.cc(p, obj, importObj, importC); err != nil { | 992 if err := b.cc(p, obj, importObj, importC); err != nil { |
984 return nil, nil, err | 993 return nil, nil, err |
985 } | 994 } |
986 » outObj = append(outObj, importObj) | 995 |
| 996 » // NOTE(rsc): The importObj is a 5c/6c/8c object and on Windows |
| 997 » // must be processed before the gcc-generated objects. |
| 998 » // Put it first. We left room above. http://golang.org/issue/2601 |
| 999 » outObj[0] = importObj |
987 | 1000 |
988 return outGo, outObj, nil | 1001 return outGo, outObj, nil |
989 } | 1002 } |
990 | 1003 |
991 // An actionQueue is a priority queue of actions. | 1004 // An actionQueue is a priority queue of actions. |
992 type actionQueue []*action | 1005 type actionQueue []*action |
993 | 1006 |
994 // Implement heap.Interface | 1007 // Implement heap.Interface |
995 func (q *actionQueue) Len() int { return len(*q) } | 1008 func (q *actionQueue) Len() int { return len(*q) } |
996 func (q *actionQueue) Swap(i, j int) { (*q)[i], (*q)[j] = (*q)[j], (*q)[i]
} | 1009 func (q *actionQueue) Swap(i, j int) { (*q)[i], (*q)[j] = (*q)[j], (*q)[i]
} |
997 func (q *actionQueue) Less(i, j int) bool { return (*q)[i].priority < (*q)[j].pr
iority } | 1010 func (q *actionQueue) Less(i, j int) bool { return (*q)[i].priority < (*q)[j].pr
iority } |
998 func (q *actionQueue) Push(x interface{}) { *q = append(*q, x.(*action)) } | 1011 func (q *actionQueue) Push(x interface{}) { *q = append(*q, x.(*action)) } |
999 func (q *actionQueue) Pop() interface{} { | 1012 func (q *actionQueue) Pop() interface{} { |
1000 n := len(*q) - 1 | 1013 n := len(*q) - 1 |
1001 x := (*q)[n] | 1014 x := (*q)[n] |
1002 *q = (*q)[:n] | 1015 *q = (*q)[:n] |
1003 return x | 1016 return x |
1004 } | 1017 } |
1005 | 1018 |
1006 func (q *actionQueue) push(a *action) { | 1019 func (q *actionQueue) push(a *action) { |
1007 heap.Push(q, a) | 1020 heap.Push(q, a) |
1008 } | 1021 } |
1009 | 1022 |
1010 func (q *actionQueue) pop() *action { | 1023 func (q *actionQueue) pop() *action { |
1011 return heap.Pop(q).(*action) | 1024 return heap.Pop(q).(*action) |
1012 } | 1025 } |
OLD | NEW |