Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(133)

Delta Between Two Patch Sets: src/cmd/go/build.go

Issue 8248043: code review 8248043: cmd/go: Add support for including C++ files in packages (Closed)
Left Patch Set: diff -r fb78cf8fd5b5 https://code.google.com/p/go Created 10 years, 12 months ago
Right Patch Set: diff -r e86ab7e59e50 https://code.google.com/p/go Created 10 years, 10 months ago
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
Left: Side by side diff | Download
Right: Side by side diff | Download
« no previous file with change/comment | « src/cmd/cgo/doc.go ('k') | src/cmd/go/doc.go » ('j') | no next file with change/comment »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
LEFTRIGHT
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 "flag" 11 "flag"
12 "fmt" 12 "fmt"
13 "go/build" 13 "go/build"
14 "io" 14 "io"
15 "io/ioutil" 15 "io/ioutil"
16 "log" 16 "log"
17 "os" 17 "os"
18 "os/exec" 18 "os/exec"
19 "path" 19 "path"
20 "path/filepath" 20 "path/filepath"
21 "regexp" 21 "regexp"
22 "runtime" 22 "runtime"
23 "strconv"
23 "strings" 24 "strings"
24 "sync" 25 "sync"
25 "time" 26 "time"
26 ) 27 )
27 28
28 var cmdBuild = &Command{ 29 var cmdBuild = &Command{
29 UsageLine: "build [-o output] [build flags] [packages]", 30 UsageLine: "build [-o output] [build flags] [packages]",
30 Short: "compile packages and dependencies", 31 Short: "compile packages and dependencies",
31 Long: ` 32 Long: `
32 Build compiles the packages named by the import paths, 33 Build compiles the packages named by the import paths,
(...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after
175 cmd.Flag.BoolVar(&buildRace, "race", false, "") 176 cmd.Flag.BoolVar(&buildRace, "race", false, "")
176 } 177 }
177 178
178 func addBuildFlagsNX(cmd *Command) { 179 func addBuildFlagsNX(cmd *Command) {
179 cmd.Flag.BoolVar(&buildN, "n", false, "") 180 cmd.Flag.BoolVar(&buildN, "n", false, "")
180 cmd.Flag.BoolVar(&buildX, "x", false, "") 181 cmd.Flag.BoolVar(&buildX, "x", false, "")
181 } 182 }
182 183
183 func isSpaceByte(c byte) bool { 184 func isSpaceByte(c byte) bool {
184 return c == ' ' || c == '\t' || c == '\n' || c == '\r' 185 return c == ' ' || c == '\t' || c == '\n' || c == '\r'
186 }
187
188 // fileExtSplit expects a filename and returns the name
189 // and ext (without the dot). If the file has no
190 // extension, ext will be empty.
191 func fileExtSplit(file string) (name, ext string) {
192 dotExt := filepath.Ext(file)
193 name = file[:len(file)-len(dotExt)]
194 if dotExt != "" {
195 ext = dotExt[1:]
196 }
197 return
185 } 198 }
186 199
187 type stringsFlag []string 200 type stringsFlag []string
188 201
189 func (v *stringsFlag) Set(s string) error { 202 func (v *stringsFlag) Set(s string) error {
190 var err error 203 var err error
191 *v, err = splitQuotedFields(s) 204 *v, err = splitQuotedFields(s)
192 return err 205 return err
193 } 206 }
194 207
(...skipping 524 matching lines...) Expand 10 before | Expand all | Expand 10 after
719 for _, t := range strings { 732 for _, t := range strings {
720 if s == t { 733 if s == t {
721 return true 734 return true
722 } 735 }
723 } 736 }
724 return false 737 return false
725 } 738 }
726 739
727 // build is the action for building a single package or command. 740 // build is the action for building a single package or command.
728 func (b *builder) build(a *action) (err error) { 741 func (b *builder) build(a *action) (err error) {
742 // Return an error if the package has CXX files but it's not using
743 // cgo nor SWIG, since the CXX files can only be processed by cgo
744 // and SWIG (it's possible to have packages with C files without
745 // using cgo, they will get compiled with the plan9 C compiler and
746 // linked with the rest of the package).
747 if len(a.p.CXXFiles) > 0 && !a.p.usesCgo() && !a.p.usesSwig() {
748 return fmt.Errorf("can't build package %s because it contains C+ + files (%s) but it's not using cgo nor SWIG",
749 a.p.ImportPath, strings.Join(a.p.CXXFiles, ","))
750 }
729 defer func() { 751 defer func() {
730 if err != nil && err != errPrintedOutput { 752 if err != nil && err != errPrintedOutput {
731 err = fmt.Errorf("go build %s: %v", a.p.ImportPath, err) 753 err = fmt.Errorf("go build %s: %v", a.p.ImportPath, err)
732 } 754 }
733 }() 755 }()
734 if buildN { 756 if buildN {
735 // In -n mode, print a banner between packages. 757 // In -n mode, print a banner between packages.
736 // The banner is five lines so that when changes to 758 // The banner is five lines so that when changes to
737 // different sections of the bootstrap script have to 759 // different sections of the bootstrap script have to
738 // be merged, the banners give patch something 760 // be merged, the banners give patch something
(...skipping 20 matching lines...) Expand all
759 dir, _ := filepath.Split(a.target) 781 dir, _ := filepath.Split(a.target)
760 if dir != "" { 782 if dir != "" {
761 if err := b.mkdir(dir); err != nil { 783 if err := b.mkdir(dir); err != nil {
762 return err 784 return err
763 } 785 }
764 } 786 }
765 787
766 var gofiles, cfiles, sfiles, objects, cgoObjects []string 788 var gofiles, cfiles, sfiles, objects, cgoObjects []string
767 gofiles = append(gofiles, a.p.GoFiles...) 789 gofiles = append(gofiles, a.p.GoFiles...)
768 cfiles = append(cfiles, a.p.CFiles...) 790 cfiles = append(cfiles, a.p.CFiles...)
769 cfiles = append(cfiles, a.p.CPPFiles...)
770 sfiles = append(sfiles, a.p.SFiles...) 791 sfiles = append(sfiles, a.p.SFiles...)
771 792
772 // Run cgo. 793 // Run cgo.
773 » if len(a.p.CgoFiles) > 0 { 794 » if a.p.usesCgo() {
774 // In a package using cgo, cgo compiles the C, C++ and assembly files with gcc. 795 // In a package using cgo, cgo compiles the C, C++ and assembly files with gcc.
775 // There is one exception: runtime/cgo's job is to bridge the 796 // There is one exception: runtime/cgo's job is to bridge the
776 // cgo and non-cgo worlds, so it necessarily has files in both. 797 // cgo and non-cgo worlds, so it necessarily has files in both.
777 // In that case gcc only gets the gcc_* files. 798 // In that case gcc only gets the gcc_* files.
778 var gccfiles []string 799 var gccfiles []string
779 if a.p.Standard && a.p.ImportPath == "runtime/cgo" { 800 if a.p.Standard && a.p.ImportPath == "runtime/cgo" {
780 filter := func(files, nongcc, gcc []string) ([]string, [ ]string) { 801 filter := func(files, nongcc, gcc []string) ([]string, [ ]string) {
781 for _, f := range files { 802 for _, f := range files {
782 if strings.HasPrefix(f, "gcc_") { 803 if strings.HasPrefix(f, "gcc_") {
783 gcc = append(gcc, f) 804 gcc = append(gcc, f)
784 } else { 805 } else {
785 nongcc = append(nongcc, f) 806 nongcc = append(nongcc, f)
786 } 807 }
787 } 808 }
788 return nongcc, gcc 809 return nongcc, gcc
789 } 810 }
790 cfiles, gccfiles = filter(cfiles, cfiles[:0], gccfiles) 811 cfiles, gccfiles = filter(cfiles, cfiles[:0], gccfiles)
791 sfiles, gccfiles = filter(sfiles, sfiles[:0], gccfiles) 812 sfiles, gccfiles = filter(sfiles, sfiles[:0], gccfiles)
792 } else { 813 } else {
793 gccfiles = append(cfiles, sfiles...) 814 gccfiles = append(cfiles, sfiles...)
794 cfiles = nil 815 cfiles = nil
795 sfiles = nil 816 sfiles = nil
796 } 817 }
797 818
798 cgoExe := tool("cgo") 819 cgoExe := tool("cgo")
799 if a.cgo != nil && a.cgo.target != "" { 820 if a.cgo != nil && a.cgo.target != "" {
800 cgoExe = a.cgo.target 821 cgoExe = a.cgo.target
801 } 822 }
802 » » outGo, outObj, err := b.cgo(a.p, cgoExe, obj, gccfiles) 823 » » outGo, outObj, err := b.cgo(a.p, cgoExe, obj, gccfiles, a.p.CXXF iles)
803 if err != nil { 824 if err != nil {
804 return err 825 return err
805 } 826 }
806 cgoObjects = append(cgoObjects, outObj...) 827 cgoObjects = append(cgoObjects, outObj...)
807 gofiles = append(gofiles, outGo...) 828 gofiles = append(gofiles, outGo...)
808 } 829 }
809 830
810 // Run SWIG. 831 // Run SWIG.
811 if a.p.usesSwig() { 832 if a.p.usesSwig() {
812 // In a package using SWIG, any .c or .s files are 833 // In a package using SWIG, any .c or .s files are
813 // compiled with gcc. 834 // compiled with gcc.
814 gccfiles := append(cfiles, sfiles...) 835 gccfiles := append(cfiles, sfiles...)
815 cfiles = nil 836 cfiles = nil
816 sfiles = nil 837 sfiles = nil
838 // TODO(hierro): Handle C++ files with SWIG
817 outGo, outObj, err := b.swig(a.p, obj, gccfiles) 839 outGo, outObj, err := b.swig(a.p, obj, gccfiles)
818 if err != nil { 840 if err != nil {
819 return err 841 return err
820 } 842 }
821 cgoObjects = append(cgoObjects, outObj...) 843 cgoObjects = append(cgoObjects, outObj...)
822 gofiles = append(gofiles, outGo...) 844 gofiles = append(gofiles, outGo...)
823 } 845 }
824 846
825 // Prepare Go import path list. 847 // Prepare Go import path list.
826 inc := b.includeArgs("-I", a.deps) 848 inc := b.includeArgs("-I", a.deps)
827 849
828 // Compile Go. 850 // Compile Go.
829 if len(gofiles) > 0 { 851 if len(gofiles) > 0 {
830 ofile, out, err := buildToolchain.gc(b, a.p, obj, inc, gofiles) 852 ofile, out, err := buildToolchain.gc(b, a.p, obj, inc, gofiles)
831 if len(out) > 0 { 853 if len(out) > 0 {
832 b.showOutput(a.p.Dir, a.p.ImportPath, b.processOutput(ou t)) 854 b.showOutput(a.p.Dir, a.p.ImportPath, b.processOutput(ou t))
833 if err != nil { 855 if err != nil {
834 return errPrintedOutput 856 return errPrintedOutput
835 } 857 }
836 } 858 }
837 if err != nil { 859 if err != nil {
838 return err 860 return err
839 } 861 }
840 objects = append(objects, ofile) 862 objects = append(objects, ofile)
841 } 863 }
842 864
843 // Copy .h files named for goos or goarch or goos_goarch 865 // Copy .h files named for goos or goarch or goos_goarch
844 // to names using GOOS and GOARCH. 866 // to names using GOOS and GOARCH.
845 // For example, defs_linux_amd64.h becomes defs_GOOS_GOARCH.h. 867 // For example, defs_linux_amd64.h becomes defs_GOOS_GOARCH.h.
846 » _goos_goarch := "_" + goos + "_" + goarch + ".h" 868 » _goos_goarch := "_" + goos + "_" + goarch
847 » _goos := "_" + goos + ".h" 869 » _goos := "_" + goos
848 » _goarch := "_" + goarch + ".h" 870 » _goarch := "_" + goarch
849 for _, file := range a.p.HFiles { 871 for _, file := range a.p.HFiles {
872 name, ext := fileExtSplit(file)
850 switch { 873 switch {
851 » » case strings.HasSuffix(file, _goos_goarch): 874 » » case strings.HasSuffix(name, _goos_goarch):
852 » » » targ := file[:len(file)-len(_goos_goarch)] + "_GOOS_GOAR CH.h" 875 » » » targ := file[:len(name)-len(_goos_goarch)] + "_GOOS_GOAR CH." + ext
853 if err := b.copyFile(a, obj+targ, filepath.Join(a.p.Dir, file), 0666); err != nil { 876 if err := b.copyFile(a, obj+targ, filepath.Join(a.p.Dir, file), 0666); err != nil {
854 return err 877 return err
855 } 878 }
856 » » case strings.HasSuffix(file, _goarch): 879 » » case strings.HasSuffix(name, _goarch):
857 » » » targ := file[:len(file)-len(_goarch)] + "_GOARCH.h" 880 » » » targ := file[:len(name)-len(_goarch)] + "_GOARCH." + ext
858 if err := b.copyFile(a, obj+targ, filepath.Join(a.p.Dir, file), 0666); err != nil { 881 if err := b.copyFile(a, obj+targ, filepath.Join(a.p.Dir, file), 0666); err != nil {
859 return err 882 return err
860 } 883 }
861 » » case strings.HasSuffix(file, _goos): 884 » » case strings.HasSuffix(name, _goos):
862 » » » targ := file[:len(file)-len(_goos)] + "_GOOS.h" 885 » » » targ := file[:len(name)-len(_goos)] + "_GOOS." + ext
863 if err := b.copyFile(a, obj+targ, filepath.Join(a.p.Dir, file), 0666); err != nil { 886 if err := b.copyFile(a, obj+targ, filepath.Join(a.p.Dir, file), 0666); err != nil {
864 return err 887 return err
865 } 888 }
866 } 889 }
867 } 890 }
868 891
869 objExt := archChar 892 objExt := archChar
870 if _, ok := buildToolchain.(gccgoToolchain); ok { 893 if _, ok := buildToolchain.(gccgoToolchain); ok {
871 objExt = "o" 894 objExt = "o"
872 } 895 }
873 896
874 for _, file := range cfiles { 897 for _, file := range cfiles {
875 » » out := file[:strings.LastIndex(file, ".")] + "." + objExt 898 » » out := file[:len(file)-len(".c")] + "." + objExt
876 if err := buildToolchain.cc(b, a.p, obj, obj+out, file); err != nil { 899 if err := buildToolchain.cc(b, a.p, obj, obj+out, file); err != nil {
877 return err 900 return err
878 } 901 }
879 objects = append(objects, out) 902 objects = append(objects, out)
880 } 903 }
881 904
882 // Assemble .s files. 905 // Assemble .s files.
883 for _, file := range sfiles { 906 for _, file := range sfiles {
884 out := file[:len(file)-len(".s")] + "." + objExt 907 out := file[:len(file)-len(".s")] + "." + objExt
885 if err := buildToolchain.asm(b, a.p, obj, obj+out, file); err != nil { 908 if err := buildToolchain.asm(b, a.p, obj, obj+out, file); err != nil {
(...skipping 308 matching lines...) Expand 10 before | Expand all | Expand 10 after
1194 // been printed, so there's no point showing 'exit status 1' or whatever 1217 // been printed, so there's no point showing 'exit status 1' or whatever
1195 // the wait status was. The main executor, builder.do, knows not to 1218 // the wait status was. The main executor, builder.do, knows not to
1196 // print this error. 1219 // print this error.
1197 var errPrintedOutput = errors.New("already printed output - no need to show erro r") 1220 var errPrintedOutput = errors.New("already printed output - no need to show erro r")
1198 1221
1199 var cgoLine = regexp.MustCompile(`\[[^\[\]]+\.cgo1\.go:[0-9]+\]`) 1222 var cgoLine = regexp.MustCompile(`\[[^\[\]]+\.cgo1\.go:[0-9]+\]`)
1200 1223
1201 // run runs the command given by cmdline in the directory dir. 1224 // run runs the command given by cmdline in the directory dir.
1202 // If the command fails, run prints information about the failure 1225 // If the command fails, run prints information about the failure
1203 // and returns a non-nil error. 1226 // and returns a non-nil error.
1204 func (b *builder) run(dir string, desc string, cmdargs ...interface{}) error { 1227 func (b *builder) run(dir string, desc string, env []string, cmdargs ...interfac e{}) error {
1205 » out, err := b.runOut(dir, desc, cmdargs...) 1228 » out, err := b.runOut(dir, desc, env, cmdargs...)
1206 if len(out) > 0 { 1229 if len(out) > 0 {
1207 if desc == "" { 1230 if desc == "" {
1208 desc = b.fmtcmd(dir, "%s", strings.Join(stringList(cmdar gs...), " ")) 1231 desc = b.fmtcmd(dir, "%s", strings.Join(stringList(cmdar gs...), " "))
1209 } 1232 }
1210 b.showOutput(dir, desc, b.processOutput(out)) 1233 b.showOutput(dir, desc, b.processOutput(out))
1211 if err != nil { 1234 if err != nil {
1212 err = errPrintedOutput 1235 err = errPrintedOutput
1213 } 1236 }
1214 } 1237 }
1215 return err 1238 return err
(...skipping 11 matching lines...) Expand all
1227 // If we're using -x, assume we're debugging and want the full dump, so disable the rewrite. 1250 // If we're using -x, assume we're debugging and want the full dump, so disable the rewrite.
1228 if !buildX && cgoLine.MatchString(messages) { 1251 if !buildX && cgoLine.MatchString(messages) {
1229 messages = cgoLine.ReplaceAllString(messages, "") 1252 messages = cgoLine.ReplaceAllString(messages, "")
1230 messages = strings.Replace(messages, "type _Ctype_", "type C.", -1) 1253 messages = strings.Replace(messages, "type _Ctype_", "type C.", -1)
1231 } 1254 }
1232 return messages 1255 return messages
1233 } 1256 }
1234 1257
1235 // runOut runs the command given by cmdline in the directory dir. 1258 // runOut runs the command given by cmdline in the directory dir.
1236 // It returns the command output and any errors that occurred. 1259 // It returns the command output and any errors that occurred.
1237 func (b *builder) runOut(dir string, desc string, cmdargs ...interface{}) ([]byt e, error) { 1260 func (b *builder) runOut(dir string, desc string, env []string, cmdargs ...inter face{}) ([]byte, error) {
1238 cmdline := stringList(cmdargs...) 1261 cmdline := stringList(cmdargs...)
1239 if buildN || buildX { 1262 if buildN || buildX {
1240 » » b.showcmd(dir, "%s", strings.Join(cmdline, " ")) 1263 » » b.showcmd(dir, "%s", joinUnambiguously(cmdline))
1241 if buildN { 1264 if buildN {
1242 return nil, nil 1265 return nil, nil
1243 } 1266 }
1244 } 1267 }
1245 1268
1246 nbusy := 0 1269 nbusy := 0
1247 for { 1270 for {
1248 var buf bytes.Buffer 1271 var buf bytes.Buffer
1249 cmd := exec.Command(cmdline[0], cmdline[1:]...) 1272 cmd := exec.Command(cmdline[0], cmdline[1:]...)
1250 cmd.Stdout = &buf 1273 cmd.Stdout = &buf
1251 cmd.Stderr = &buf 1274 cmd.Stderr = &buf
1252 cmd.Dir = dir 1275 cmd.Dir = dir
1253 » » cmd.Env = envForDir(cmd.Dir) 1276 » » cmd.Env = mergeEnvLists(env, envForDir(cmd.Dir))
1254 err := cmd.Run() 1277 err := cmd.Run()
1255 1278
1256 // cmd.Run will fail on Unix if some other process has the binar y 1279 // cmd.Run will fail on Unix if some other process has the binar y
1257 // we want to run open for writing. This can happen here becaus e 1280 // we want to run open for writing. This can happen here becaus e
1258 // we build and install the cgo command and then run it. 1281 // we build and install the cgo command and then run it.
1259 // If another command was kicked off while we were writing the 1282 // If another command was kicked off while we were writing the
1260 // cgo binary, the child process for that command may be holding 1283 // cgo binary, the child process for that command may be holding
1261 // a reference to the fd, keeping us from running exec. 1284 // a reference to the fd, keeping us from running exec.
1262 // 1285 //
1263 // But, you might reasonably wonder, how can this happen? 1286 // But, you might reasonably wonder, how can this happen?
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
1297 if err != nil && nbusy < 3 && strings.Contains(err.Error(), "tex t file busy") { 1320 if err != nil && nbusy < 3 && strings.Contains(err.Error(), "tex t file busy") {
1298 time.Sleep(100 * time.Millisecond << uint(nbusy)) 1321 time.Sleep(100 * time.Millisecond << uint(nbusy))
1299 nbusy++ 1322 nbusy++
1300 continue 1323 continue
1301 } 1324 }
1302 1325
1303 return buf.Bytes(), err 1326 return buf.Bytes(), err
1304 } 1327 }
1305 } 1328 }
1306 1329
1330 // joinUnambiguously prints the slice, quoting where necessary to make the
1331 // output unambiguous.
1332 // TODO: See issue 5279. The printing of commands needs a complete redo.
1333 func joinUnambiguously(a []string) string {
1334 var buf bytes.Buffer
1335 for i, s := range a {
1336 if i > 0 {
1337 buf.WriteByte(' ')
1338 }
1339 q := strconv.Quote(s)
1340 if s == "" || strings.Contains(s, " ") || len(q) > len(s)+2 {
1341 buf.WriteString(q)
1342 } else {
1343 buf.WriteString(s)
1344 }
1345 }
1346 return buf.String()
1347 }
1348
1307 // mkdir makes the named directory. 1349 // mkdir makes the named directory.
1308 func (b *builder) mkdir(dir string) error { 1350 func (b *builder) mkdir(dir string) error {
1309 b.exec.Lock() 1351 b.exec.Lock()
1310 defer b.exec.Unlock() 1352 defer b.exec.Unlock()
1311 // We can be a little aggressive about being 1353 // We can be a little aggressive about being
1312 // sure directories exist. Skip repeated calls. 1354 // sure directories exist. Skip repeated calls.
1313 if b.mkdirCache[dir] { 1355 if b.mkdirCache[dir] {
1314 return nil 1356 return nil
1315 } 1357 }
1316 b.mkdirCache[dir] = true 1358 b.mkdirCache[dir] = true
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after
1428 if p.Standard && p.ImportPath == "runtime" { 1470 if p.Standard && p.ImportPath == "runtime" {
1429 // runtime compiles with a special 6g flag to emit 1471 // runtime compiles with a special 6g flag to emit
1430 // additional reflect type data. 1472 // additional reflect type data.
1431 gcargs = append(gcargs, "-+") 1473 gcargs = append(gcargs, "-+")
1432 } 1474 }
1433 1475
1434 // If we're giving the compiler the entire package (no C etc files), tel l it that, 1476 // If we're giving the compiler the entire package (no C etc files), tel l it that,
1435 // so that it can give good error messages about forward declarations. 1477 // so that it can give good error messages about forward declarations.
1436 // Exceptions: a few standard packages have forward declarations for 1478 // Exceptions: a few standard packages have forward declarations for
1437 // pieces supplied behind-the-scenes by package runtime. 1479 // pieces supplied behind-the-scenes by package runtime.
1438 » extFiles := len(p.CgoFiles) + len(p.CFiles) + len(p.CPPFiles) + len(p.SF iles) + len(p.SysoFiles) + len(p.SwigFiles) + len(p.SwigCXXFiles) 1480 » extFiles := len(p.CgoFiles) + len(p.CFiles) + len(p.CXXFiles) + len(p.SF iles) + len(p.SysoFiles) + len(p.SwigFiles) + len(p.SwigCXXFiles)
1439 if p.Standard { 1481 if p.Standard {
1440 switch p.ImportPath { 1482 switch p.ImportPath {
1441 case "os", "runtime/pprof", "sync", "time": 1483 case "os", "runtime/pprof", "sync", "time":
1442 extFiles++ 1484 extFiles++
1443 } 1485 }
1444 } 1486 }
1445 if extFiles == 0 { 1487 if extFiles == 0 {
1446 gcargs = append(gcargs, "-complete") 1488 gcargs = append(gcargs, "-complete")
1447 } 1489 }
1448 1490
1449 args := stringList(tool(archChar+"g"), "-o", ofile, buildGcflags, gcargs , "-D", p.localPrefix, importArgs) 1491 args := stringList(tool(archChar+"g"), "-o", ofile, buildGcflags, gcargs , "-D", p.localPrefix, importArgs)
1450 for _, f := range gofiles { 1492 for _, f := range gofiles {
1451 args = append(args, mkAbs(p.Dir, f)) 1493 args = append(args, mkAbs(p.Dir, f))
1452 } 1494 }
1453 1495
1454 » output, err = b.runOut(p.Dir, p.ImportPath, args) 1496 » output, err = b.runOut(p.Dir, p.ImportPath, nil, args)
1455 return ofile, output, err 1497 return ofile, output, err
1456 } 1498 }
1457 1499
1458 func (gcToolchain) asm(b *builder, p *Package, obj, ofile, sfile string) error { 1500 func (gcToolchain) asm(b *builder, p *Package, obj, ofile, sfile string) error {
1459 sfile = mkAbs(p.Dir, sfile) 1501 sfile = mkAbs(p.Dir, sfile)
1460 » return b.run(p.Dir, p.ImportPath, tool(archChar+"a"), "-I", obj, "-o", o file, "-D", "GOOS_"+goos, "-D", "GOARCH_"+goarch, sfile) 1502 » return b.run(p.Dir, p.ImportPath, nil, tool(archChar+"a"), "-I", obj, "- o", ofile, "-D", "GOOS_"+goos, "-D", "GOARCH_"+goarch, sfile)
1461 } 1503 }
1462 1504
1463 func (gcToolchain) pkgpath(basedir string, p *Package) string { 1505 func (gcToolchain) pkgpath(basedir string, p *Package) string {
1464 end := filepath.FromSlash(p.ImportPath + ".a") 1506 end := filepath.FromSlash(p.ImportPath + ".a")
1465 return filepath.Join(basedir, end) 1507 return filepath.Join(basedir, end)
1466 } 1508 }
1467 1509
1468 func (gcToolchain) pack(b *builder, p *Package, objDir, afile string, ofiles []s tring) error { 1510 func (gcToolchain) pack(b *builder, p *Package, objDir, afile string, ofiles []s tring) error {
1469 var absOfiles []string 1511 var absOfiles []string
1470 for _, f := range ofiles { 1512 for _, f := range ofiles {
1471 absOfiles = append(absOfiles, mkAbs(objDir, f)) 1513 absOfiles = append(absOfiles, mkAbs(objDir, f))
1472 } 1514 }
1473 » return b.run(p.Dir, p.ImportPath, tool("pack"), "grcP", b.work, mkAbs(ob jDir, afile), absOfiles) 1515 » return b.run(p.Dir, p.ImportPath, nil, tool("pack"), "grcP", b.work, mkA bs(objDir, afile), absOfiles)
1474 } 1516 }
1475 1517
1476 func (gcToolchain) ld(b *builder, p *Package, out string, allactions []*action, mainpkg string, ofiles []string) error { 1518 func (gcToolchain) ld(b *builder, p *Package, out string, allactions []*action, mainpkg string, ofiles []string) error {
1477 importArgs := b.includeArgs("-L", allactions) 1519 importArgs := b.includeArgs("-L", allactions)
1478 swigDirs := make(map[string]bool) 1520 swigDirs := make(map[string]bool)
1479 swigArg := []string{} 1521 swigArg := []string{}
1480 for _, a := range allactions { 1522 for _, a := range allactions {
1481 if a.p != nil && a.p.usesSwig() { 1523 if a.p != nil && a.p.usesSwig() {
1482 sd := a.p.swigDir(&buildContext) 1524 sd := a.p.swigDir(&buildContext)
1483 if len(swigArg) == 0 { 1525 if len(swigArg) == 0 {
1484 swigArg = []string{"-r", sd} 1526 swigArg = []string{"-r", sd}
1485 } else if !swigDirs[sd] { 1527 } else if !swigDirs[sd] {
1486 swigArg[1] += ":" 1528 swigArg[1] += ":"
1487 swigArg[1] += sd 1529 swigArg[1] += sd
1488 } 1530 }
1489 swigDirs[sd] = true 1531 swigDirs[sd] = true
1490 } 1532 }
1491 } 1533 }
1492 » return b.run(".", p.ImportPath, tool(archChar+"l"), "-o", out, importArg s, swigArg, buildLdflags, mainpkg) 1534 » return b.run(".", p.ImportPath, nil, tool(archChar+"l"), "-o", out, impo rtArgs, swigArg, buildLdflags, mainpkg)
1493 } 1535 }
1494 1536
1495 func (gcToolchain) cc(b *builder, p *Package, objdir, ofile, cfile string) error { 1537 func (gcToolchain) cc(b *builder, p *Package, objdir, ofile, cfile string) error {
1496 inc := filepath.Join(goroot, "pkg", fmt.Sprintf("%s_%s", goos, goarch)) 1538 inc := filepath.Join(goroot, "pkg", fmt.Sprintf("%s_%s", goos, goarch))
1497 cfile = mkAbs(p.Dir, cfile) 1539 cfile = mkAbs(p.Dir, cfile)
1498 args := stringList(tool(archChar+"c"), "-F", "-V", "-w", "-I", objdir, " -I", inc, "-o", ofile, buildCcflags, "-D", "GOOS_"+goos, "-D", "GOARCH_"+goarch, cfile) 1540 args := stringList(tool(archChar+"c"), "-F", "-V", "-w", "-I", objdir, " -I", inc, "-o", ofile, buildCcflags, "-D", "GOOS_"+goos, "-D", "GOARCH_"+goarch, cfile)
1499 » return b.run(p.Dir, p.ImportPath, args) 1541 » return b.run(p.Dir, p.ImportPath, nil, args)
1500 } 1542 }
1501 1543
1502 // The Gccgo toolchain. 1544 // The Gccgo toolchain.
1503 type gccgoToolchain struct{} 1545 type gccgoToolchain struct{}
1504 1546
1505 var gccgoBin, _ = exec.LookPath("gccgo") 1547 var gccgoBin, _ = exec.LookPath("gccgo")
1506 1548
1507 func (gccgoToolchain) compiler() string { 1549 func (gccgoToolchain) compiler() string {
1508 return gccgoBin 1550 return gccgoBin
1509 } 1551 }
(...skipping 11 matching lines...) Expand all
1521 gcargs = append(gcargs, "-fgo-pkgpath="+pkgpath) 1563 gcargs = append(gcargs, "-fgo-pkgpath="+pkgpath)
1522 } 1564 }
1523 if p.localPrefix != "" { 1565 if p.localPrefix != "" {
1524 gcargs = append(gcargs, "-fgo-relative-import-path="+p.localPref ix) 1566 gcargs = append(gcargs, "-fgo-relative-import-path="+p.localPref ix)
1525 } 1567 }
1526 args := stringList("gccgo", importArgs, "-c", gcargs, "-o", ofile, build Gccgoflags) 1568 args := stringList("gccgo", importArgs, "-c", gcargs, "-o", ofile, build Gccgoflags)
1527 for _, f := range gofiles { 1569 for _, f := range gofiles {
1528 args = append(args, mkAbs(p.Dir, f)) 1570 args = append(args, mkAbs(p.Dir, f))
1529 } 1571 }
1530 1572
1531 » output, err = b.runOut(p.Dir, p.ImportPath, args) 1573 » output, err = b.runOut(p.Dir, p.ImportPath, nil, args)
1532 return ofile, output, err 1574 return ofile, output, err
1533 } 1575 }
1534 1576
1535 func (gccgoToolchain) asm(b *builder, p *Package, obj, ofile, sfile string) erro r { 1577 func (gccgoToolchain) asm(b *builder, p *Package, obj, ofile, sfile string) erro r {
1536 sfile = mkAbs(p.Dir, sfile) 1578 sfile = mkAbs(p.Dir, sfile)
1537 defs := []string{"-D", "GOOS_" + goos, "-D", "GOARCH_" + goarch} 1579 defs := []string{"-D", "GOOS_" + goos, "-D", "GOARCH_" + goarch}
1538 if pkgpath := gccgoCleanPkgpath(p); pkgpath != "" { 1580 if pkgpath := gccgoCleanPkgpath(p); pkgpath != "" {
1539 defs = append(defs, `-D`, `GOPKGPATH="`+pkgpath+`"`) 1581 defs = append(defs, `-D`, `GOPKGPATH="`+pkgpath+`"`)
1540 } 1582 }
1541 defs = append(defs, b.gccArchArgs()...) 1583 defs = append(defs, b.gccArchArgs()...)
1542 » return b.run(p.Dir, p.ImportPath, "gccgo", "-I", obj, "-o", ofile, defs, sfile) 1584 » return b.run(p.Dir, p.ImportPath, nil, "gccgo", "-I", obj, "-o", ofile, defs, sfile)
1543 } 1585 }
1544 1586
1545 func (gccgoToolchain) pkgpath(basedir string, p *Package) string { 1587 func (gccgoToolchain) pkgpath(basedir string, p *Package) string {
1546 end := filepath.FromSlash(p.ImportPath + ".a") 1588 end := filepath.FromSlash(p.ImportPath + ".a")
1547 afile := filepath.Join(basedir, end) 1589 afile := filepath.Join(basedir, end)
1548 // add "lib" to the final element 1590 // add "lib" to the final element
1549 return filepath.Join(filepath.Dir(afile), "lib"+filepath.Base(afile)) 1591 return filepath.Join(filepath.Dir(afile), "lib"+filepath.Base(afile))
1550 } 1592 }
1551 1593
1552 func (gccgoToolchain) pack(b *builder, p *Package, objDir, afile string, ofiles []string) error { 1594 func (gccgoToolchain) pack(b *builder, p *Package, objDir, afile string, ofiles []string) error {
1553 var absOfiles []string 1595 var absOfiles []string
1554 for _, f := range ofiles { 1596 for _, f := range ofiles {
1555 absOfiles = append(absOfiles, mkAbs(objDir, f)) 1597 absOfiles = append(absOfiles, mkAbs(objDir, f))
1556 } 1598 }
1557 » return b.run(p.Dir, p.ImportPath, "ar", "cru", mkAbs(objDir, afile), abs Ofiles) 1599 » return b.run(p.Dir, p.ImportPath, nil, "ar", "cru", mkAbs(objDir, afile) , absOfiles)
1558 } 1600 }
1559 1601
1560 func (tools gccgoToolchain) ld(b *builder, p *Package, out string, allactions [] *action, mainpkg string, ofiles []string) error { 1602 func (tools gccgoToolchain) ld(b *builder, p *Package, out string, allactions [] *action, mainpkg string, ofiles []string) error {
1561 // gccgo needs explicit linking with all package dependencies, 1603 // gccgo needs explicit linking with all package dependencies,
1562 // and all LDFLAGS from cgo dependencies. 1604 // and all LDFLAGS from cgo dependencies.
1563 afiles := make(map[*Package]string) 1605 afiles := make(map[*Package]string)
1564 sfiles := make(map[*Package][]string) 1606 sfiles := make(map[*Package][]string)
1565 ldflags := b.gccArchArgs() 1607 ldflags := b.gccArchArgs()
1566 cgoldflags := []string{} 1608 cgoldflags := []string{}
1567 usesCgo := false 1609 usesCgo := false
(...skipping 21 matching lines...) Expand all
1589 for _, afile := range afiles { 1631 for _, afile := range afiles {
1590 ldflags = append(ldflags, afile) 1632 ldflags = append(ldflags, afile)
1591 } 1633 }
1592 for _, sfiles := range sfiles { 1634 for _, sfiles := range sfiles {
1593 ldflags = append(ldflags, sfiles...) 1635 ldflags = append(ldflags, sfiles...)
1594 } 1636 }
1595 ldflags = append(ldflags, cgoldflags...) 1637 ldflags = append(ldflags, cgoldflags...)
1596 if usesCgo && goos == "linux" { 1638 if usesCgo && goos == "linux" {
1597 ldflags = append(ldflags, "-Wl,-E") 1639 ldflags = append(ldflags, "-Wl,-E")
1598 } 1640 }
1599 » return b.run(".", p.ImportPath, "gccgo", "-o", out, ofiles, "-Wl,-(", ld flags, "-Wl,-)", buildGccgoflags) 1641 » return b.run(".", p.ImportPath, nil, "gccgo", "-o", out, ofiles, "-Wl,-( ", ldflags, "-Wl,-)", buildGccgoflags)
1600 } 1642 }
1601 1643
1602 func (gccgoToolchain) cc(b *builder, p *Package, objdir, ofile, cfile string) er ror { 1644 func (gccgoToolchain) cc(b *builder, p *Package, objdir, ofile, cfile string) er ror {
1603 inc := filepath.Join(goroot, "pkg", fmt.Sprintf("%s_%s", goos, goarch)) 1645 inc := filepath.Join(goroot, "pkg", fmt.Sprintf("%s_%s", goos, goarch))
1604 cfile = mkAbs(p.Dir, cfile) 1646 cfile = mkAbs(p.Dir, cfile)
1605 defs := []string{"-D", "GOOS_" + goos, "-D", "GOARCH_" + goarch} 1647 defs := []string{"-D", "GOOS_" + goos, "-D", "GOARCH_" + goarch}
1606 defs = append(defs, b.gccArchArgs()...) 1648 defs = append(defs, b.gccArchArgs()...)
1607 if pkgpath := gccgoCleanPkgpath(p); pkgpath != "" { 1649 if pkgpath := gccgoCleanPkgpath(p); pkgpath != "" {
1608 defs = append(defs, `-D`, `GOPKGPATH="`+pkgpath+`"`) 1650 defs = append(defs, `-D`, `GOPKGPATH="`+pkgpath+`"`)
1609 } 1651 }
1610 // TODO: Support using clang here (during gccgo build)? 1652 // TODO: Support using clang here (during gccgo build)?
1611 » return b.run(p.Dir, p.ImportPath, "gcc", "-Wall", "-g", 1653 » return b.run(p.Dir, p.ImportPath, nil, "gcc", "-Wall", "-g",
1612 "-I", objdir, "-I", inc, "-o", ofile, defs, "-c", cfile) 1654 "-I", objdir, "-I", inc, "-o", ofile, defs, "-c", cfile)
1613 } 1655 }
1614 1656
1615 func gccgoPkgpath(p *Package) string { 1657 func gccgoPkgpath(p *Package) string {
1616 if p.build.IsCommand() && !p.forceLibrary { 1658 if p.build.IsCommand() && !p.forceLibrary {
1617 return "" 1659 return ""
1618 } 1660 }
1619 return p.ImportPath 1661 return p.ImportPath
1620 } 1662 }
1621 1663
(...skipping 19 matching lines...) Expand all
1641 prev := b.print 1683 prev := b.print
1642 if buildN { 1684 if buildN {
1643 // In -n mode we temporarily swap out the builder's 1685 // In -n mode we temporarily swap out the builder's
1644 // print function to capture the command-line. This 1686 // print function to capture the command-line. This
1645 // let's us assign it to $LIBGCC and produce a valid 1687 // let's us assign it to $LIBGCC and produce a valid
1646 // buildscript for cgo packages. 1688 // buildscript for cgo packages.
1647 b.print = func(a ...interface{}) (int, error) { 1689 b.print = func(a ...interface{}) (int, error) {
1648 return fmt.Fprint(&buf, a...) 1690 return fmt.Fprint(&buf, a...)
1649 } 1691 }
1650 } 1692 }
1651 » f, err := b.runOut(p.Dir, p.ImportPath, gccCmd, "-print-libgcc-file-name ") 1693 » f, err := b.runOut(p.Dir, p.ImportPath, nil, gccCmd, "-print-libgcc-file -name")
1652 if err != nil { 1694 if err != nil {
1653 return "", fmt.Errorf("gcc -print-libgcc-file-name: %v (%s)", er r, f) 1695 return "", fmt.Errorf("gcc -print-libgcc-file-name: %v (%s)", er r, f)
1654 } 1696 }
1655 if buildN { 1697 if buildN {
1656 s := fmt.Sprintf("LIBGCC=$(%s)\n", buf.Next(buf.Len()-1)) 1698 s := fmt.Sprintf("LIBGCC=$(%s)\n", buf.Next(buf.Len()-1))
1657 b.print = prev 1699 b.print = prev
1658 b.print(s) 1700 b.print(s)
1659 return "$LIBGCC", nil 1701 return "$LIBGCC", nil
1660 } 1702 }
1661 1703
1662 // clang might not be able to find libgcc, and in that case, 1704 // clang might not be able to find libgcc, and in that case,
1663 // it will simply return "libgcc.a", which is of no use to us. 1705 // it will simply return "libgcc.a", which is of no use to us.
1664 if strings.Contains(gccCmd[0], "clang") && !filepath.IsAbs(string(f)) { 1706 if strings.Contains(gccCmd[0], "clang") && !filepath.IsAbs(string(f)) {
1665 return "", nil 1707 return "", nil
1666 } 1708 }
1667 1709
1668 return strings.Trim(string(f), "\r\n"), nil 1710 return strings.Trim(string(f), "\r\n"), nil
1669 } 1711 }
1670 1712
1671 // gcc runs the gcc C compiler to create an object from a single C file. 1713 // gcc runs the gcc C compiler to create an object from a single C file.
1672 func (b *builder) gcc(p *Package, out string, flags []string, cfile string) erro r { 1714 func (b *builder) gcc(p *Package, out string, flags []string, cfile string) erro r {
1673 » cfile = mkAbs(p.Dir, cfile) 1715 » return b.ccompile(p, out, flags, cfile, b.gccCmd(p.Dir))
1674 » return b.run(p.Dir, p.ImportPath, b.gccCmd(p.Dir), flags, "-o", out, "-c ", cfile) 1716 }
1675 } 1717
1676 1718 // gxx runs the g++ C++ compiler to create an object from a single C++ file.
1677 // gccld runs the gcc linker to create an executable from a set of object files 1719 func (b *builder) gxx(p *Package, out string, flags []string, cxxfile string) er ror {
1720 » return b.ccompile(p, out, flags, cxxfile, b.gxxCmd(p.Dir))
1721 }
1722
1723 // ccompile runs the given C or C++ compiler and creates an object from a single source file.
1724 func (b *builder) ccompile(p *Package, out string, flags []string, file string, compiler []string) error {
1725 » file = mkAbs(p.Dir, file)
1726 » return b.run(p.Dir, p.ImportPath, nil, compiler, flags, "-o", out, "-c", file)
1727 }
1728
1729 // gccld runs the gcc linker to create an executable from a set of object files.
1678 func (b *builder) gccld(p *Package, out string, flags []string, obj []string) er ror { 1730 func (b *builder) gccld(p *Package, out string, flags []string, obj []string) er ror {
1679 » return b.run(p.Dir, p.ImportPath, b.gccCmd(p.Dir), "-o", out, obj, flags ) 1731 » var cmd []string
1732 » if len(p.CXXFiles) > 0 {
1733 » » cmd = b.gxxCmd(p.Dir)
1734 » } else {
1735 » » cmd = b.gccCmd(p.Dir)
1736 » }
1737 » return b.run(p.Dir, p.ImportPath, nil, cmd, "-o", out, obj, flags)
1680 } 1738 }
1681 1739
1682 // gccCmd returns a gcc command line prefix 1740 // gccCmd returns a gcc command line prefix
1683 func (b *builder) gccCmd(objdir string) []string { 1741 func (b *builder) gccCmd(objdir string) []string {
1742 return b.ccompilerCmd("CC", "gcc", objdir)
1743 }
1744
1745 // gxxCmd returns a g++ command line prefix
1746 func (b *builder) gxxCmd(objdir string) []string {
1747 return b.ccompilerCmd("CXX", "g++", objdir)
1748 }
1749
1750 // ccompilerCmd returns a command line prefix for the given environment
1751 // variable and using the default command when the variable is empty
1752 func (b *builder) ccompilerCmd(envvar, defcmd, objdir string) []string {
1684 // NOTE: env.go's mkEnv knows that the first three 1753 // NOTE: env.go's mkEnv knows that the first three
1685 // strings returned are "gcc", "-I", objdir (and cuts them off). 1754 // strings returned are "gcc", "-I", objdir (and cuts them off).
1686 1755
1687 » gcc := strings.Fields(os.Getenv("CC")) 1756 » compiler := strings.Fields(os.Getenv(envvar))
1688 » if len(gcc) == 0 { 1757 » if len(compiler) == 0 {
1689 » » gcc = append(gcc, "gcc") 1758 » » compiler = append(compiler, defcmd)
1690 » } 1759 » }
1691 » a := []string{gcc[0], "-I", objdir, "-g", "-O2"} 1760 » a := []string{compiler[0], "-I", objdir, "-g", "-O2"}
1692 » a = append(a, gcc[1:]...) 1761 » a = append(a, compiler[1:]...)
1693 1762
1694 // Definitely want -fPIC but on Windows gcc complains 1763 // Definitely want -fPIC but on Windows gcc complains
1695 // "-fPIC ignored for target (all code is position independent)" 1764 // "-fPIC ignored for target (all code is position independent)"
1696 if goos != "windows" { 1765 if goos != "windows" {
1697 a = append(a, "-fPIC") 1766 a = append(a, "-fPIC")
1698 } 1767 }
1699 a = append(a, b.gccArchArgs()...) 1768 a = append(a, b.gccArchArgs()...)
1700 // gcc-4.5 and beyond require explicit "-pthread" flag 1769 // gcc-4.5 and beyond require explicit "-pthread" flag
1701 // for multithreading with pthread library. 1770 // for multithreading with pthread library.
1702 if buildContext.CgoEnabled { 1771 if buildContext.CgoEnabled {
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
1741 } 1810 }
1742 1811
1743 var cgoRe = regexp.MustCompile(`[/\\:]`) 1812 var cgoRe = regexp.MustCompile(`[/\\:]`)
1744 1813
1745 var ( 1814 var (
1746 cgoLibGccFile string 1815 cgoLibGccFile string
1747 cgoLibGccErr error 1816 cgoLibGccErr error
1748 cgoLibGccFileOnce sync.Once 1817 cgoLibGccFileOnce sync.Once
1749 ) 1818 )
1750 1819
1751 func (b *builder) cgo(p *Package, cgoExe, obj string, gccfiles []string) (outGo, outObj []string, err error) { 1820 func (b *builder) cgo(p *Package, cgoExe, obj string, gccfiles []string, gxxfile s []string) (outGo, outObj []string, err error) {
1752 if goos != toolGOOS { 1821 if goos != toolGOOS {
1753 return nil, nil, errors.New("cannot use cgo when compiling for a different operating system") 1822 return nil, nil, errors.New("cannot use cgo when compiling for a different operating system")
1754 } 1823 }
1755 1824
1825 cgoCPPFLAGS := stringList(envList("CGO_CPPFLAGS"), p.CgoCPPFLAGS)
1756 cgoCFLAGS := stringList(envList("CGO_CFLAGS"), p.CgoCFLAGS) 1826 cgoCFLAGS := stringList(envList("CGO_CFLAGS"), p.CgoCFLAGS)
1827 cgoCXXFLAGS := stringList(envList("CGO_CXXFLAGS"), p.CgoCXXFLAGS)
1757 cgoLDFLAGS := stringList(envList("CGO_LDFLAGS"), p.CgoLDFLAGS) 1828 cgoLDFLAGS := stringList(envList("CGO_LDFLAGS"), p.CgoLDFLAGS)
1758 1829
1759 if pkgs := p.CgoPkgConfig; len(pkgs) > 0 { 1830 if pkgs := p.CgoPkgConfig; len(pkgs) > 0 {
1760 » » out, err := b.runOut(p.Dir, p.ImportPath, "pkg-config", "--cflag s", pkgs) 1831 » » out, err := b.runOut(p.Dir, p.ImportPath, nil, "pkg-config", "-- cflags", pkgs)
1761 if err != nil { 1832 if err != nil {
1762 b.showOutput(p.Dir, "pkg-config --cflags "+strings.Join( pkgs, " "), string(out)) 1833 b.showOutput(p.Dir, "pkg-config --cflags "+strings.Join( pkgs, " "), string(out))
1763 b.print(err.Error() + "\n") 1834 b.print(err.Error() + "\n")
1764 return nil, nil, errPrintedOutput 1835 return nil, nil, errPrintedOutput
1765 } 1836 }
1766 if len(out) > 0 { 1837 if len(out) > 0 {
1767 » » » cgoCFLAGS = append(cgoCFLAGS, strings.Fields(string(out) )...) 1838 » » » cgoCPPFLAGS = append(cgoCPPFLAGS, strings.Fields(string( out))...)
1768 » » } 1839 » » }
1769 » » out, err = b.runOut(p.Dir, p.ImportPath, "pkg-config", "--libs", pkgs) 1840 » » out, err = b.runOut(p.Dir, p.ImportPath, nil, "pkg-config", "--l ibs", pkgs)
1770 if err != nil { 1841 if err != nil {
1771 b.showOutput(p.Dir, "pkg-config --libs "+strings.Join(pk gs, " "), string(out)) 1842 b.showOutput(p.Dir, "pkg-config --libs "+strings.Join(pk gs, " "), string(out))
1772 b.print(err.Error() + "\n") 1843 b.print(err.Error() + "\n")
1773 return nil, nil, errPrintedOutput 1844 return nil, nil, errPrintedOutput
1774 } 1845 }
1775 if len(out) > 0 { 1846 if len(out) > 0 {
1776 cgoLDFLAGS = append(cgoLDFLAGS, strings.Fields(string(ou t))...) 1847 cgoLDFLAGS = append(cgoLDFLAGS, strings.Fields(string(ou t))...)
1777 } 1848 }
1778 } 1849 }
1779 1850
1780 // Allows including _cgo_export.h from .[ch] files in the package. 1851 // Allows including _cgo_export.h from .[ch] files in the package.
1781 » cgoCFLAGS = append(cgoCFLAGS, "-I", obj) 1852 » cgoCPPFLAGS = append(cgoCPPFLAGS, "-I", obj)
1782 1853
1783 // cgo 1854 // cgo
1784 // TODO: CGOPKGPATH, CGO_FLAGS? 1855 // TODO: CGOPKGPATH, CGO_FLAGS?
1785 gofiles := []string{obj + "_cgo_gotypes.go"} 1856 gofiles := []string{obj + "_cgo_gotypes.go"}
1786 cfiles := []string{"_cgo_main.c", "_cgo_export.c"} 1857 cfiles := []string{"_cgo_main.c", "_cgo_export.c"}
1787 for _, fn := range p.CgoFiles { 1858 for _, fn := range p.CgoFiles {
1788 f := cgoRe.ReplaceAllString(fn[:len(fn)-2], "_") 1859 f := cgoRe.ReplaceAllString(fn[:len(fn)-2], "_")
1789 gofiles = append(gofiles, obj+f+"cgo1.go") 1860 gofiles = append(gofiles, obj+f+"cgo1.go")
1790 cfiles = append(cfiles, f+"cgo2.c") 1861 cfiles = append(cfiles, f+"cgo2.c")
1791 } 1862 }
1792 defunC := obj + "_cgo_defun.c" 1863 defunC := obj + "_cgo_defun.c"
1793 1864
1794 cgoflags := []string{} 1865 cgoflags := []string{}
1795 // TODO: make cgo not depend on $GOARCH? 1866 // TODO: make cgo not depend on $GOARCH?
1796 1867
1797 objExt := archChar 1868 objExt := archChar
1798 1869
1799 if p.Standard && p.ImportPath == "runtime/cgo" { 1870 if p.Standard && p.ImportPath == "runtime/cgo" {
1800 cgoflags = append(cgoflags, "-import_runtime_cgo=false") 1871 cgoflags = append(cgoflags, "-import_runtime_cgo=false")
1801 } 1872 }
1802 if p.Standard && (p.ImportPath == "runtime/race" || p.ImportPath == "run time/cgo") { 1873 if p.Standard && (p.ImportPath == "runtime/race" || p.ImportPath == "run time/cgo") {
1803 cgoflags = append(cgoflags, "-import_syscall=false") 1874 cgoflags = append(cgoflags, "-import_syscall=false")
1804 } 1875 }
1805 1876
1877 // Update $CGO_LDFLAGS with p.CgoLDFLAGS.
1878 var cgoenv []string
1879 if len(cgoLDFLAGS) > 0 {
1880 flags := make([]string, len(cgoLDFLAGS))
1881 for i, f := range cgoLDFLAGS {
1882 flags[i] = strconv.Quote(f)
1883 }
1884 cgoenv = []string{"CGO_LDFLAGS=" + strings.Join(flags, " ")}
1885 }
1886
1806 if _, ok := buildToolchain.(gccgoToolchain); ok { 1887 if _, ok := buildToolchain.(gccgoToolchain); ok {
1807 cgoflags = append(cgoflags, "-gccgo") 1888 cgoflags = append(cgoflags, "-gccgo")
1808 if pkgpath := gccgoPkgpath(p); pkgpath != "" { 1889 if pkgpath := gccgoPkgpath(p); pkgpath != "" {
1809 cgoflags = append(cgoflags, "-gccgopkgpath="+pkgpath) 1890 cgoflags = append(cgoflags, "-gccgopkgpath="+pkgpath)
1810 } 1891 }
1811 objExt = "o" 1892 objExt = "o"
1812 } 1893 }
1813 » if err := b.run(p.Dir, p.ImportPath, cgoExe, "-objdir", obj, cgoflags, " --", cgoCFLAGS, p.CgoFiles); err != nil { 1894 » if err := b.run(p.Dir, p.ImportPath, cgoenv, cgoExe, "-objdir", obj, cgo flags, "--", cgoCPPFLAGS, cgoCFLAGS, p.CgoFiles); err != nil {
1814 return nil, nil, err 1895 return nil, nil, err
1815 } 1896 }
1816 outGo = append(outGo, gofiles...) 1897 outGo = append(outGo, gofiles...)
1817 1898
1818 // cc _cgo_defun.c 1899 // cc _cgo_defun.c
1819 defunObj := obj + "_cgo_defun." + objExt 1900 defunObj := obj + "_cgo_defun." + objExt
1820 if err := buildToolchain.cc(b, p, obj, defunObj, defunC); err != nil { 1901 if err := buildToolchain.cc(b, p, obj, defunObj, defunC); err != nil {
1821 return nil, nil, err 1902 return nil, nil, err
1822 } 1903 }
1823 outObj = append(outObj, defunObj) 1904 outObj = append(outObj, defunObj)
1824 1905
1825 // gcc 1906 // gcc
1826 var linkobj []string 1907 var linkobj []string
1827 1908
1828 var bareLDFLAGS []string 1909 var bareLDFLAGS []string
1829 » // filter out -lsomelib, and -framework X if on Darwin 1910 » // filter out -lsomelib, -l somelib, *.{so,dll,dylib}, and (on Darwin) - framework X
1830 for i := 0; i < len(cgoLDFLAGS); i++ { 1911 for i := 0; i < len(cgoLDFLAGS); i++ {
1831 f := cgoLDFLAGS[i] 1912 f := cgoLDFLAGS[i]
1832 » » if !strings.HasPrefix(f, "-l") { 1913 » » switch {
1833 » » » if goos == "darwin" && f == "-framework" { // skip the - framework X 1914 » » // skip "-lc" or "-l somelib"
1834 » » » » i += 1 1915 » » case strings.HasPrefix(f, "-l"):
1835 » » » » continue 1916 » » » if f == "-l" {
1917 » » » » i++
1836 } 1918 }
1919 // skip "-framework X" on Darwin
1920 case goos == "darwin" && f == "-framework":
1921 i++
1922 // skip "*.{dylib,so,dll}"
1923 case strings.HasSuffix(f, ".dylib"),
1924 strings.HasSuffix(f, ".so"),
1925 strings.HasSuffix(f, ".dll"):
1926 continue
1927 default:
1837 bareLDFLAGS = append(bareLDFLAGS, f) 1928 bareLDFLAGS = append(bareLDFLAGS, f)
1838 } 1929 }
1839 } 1930 }
1840 1931
1841 cgoLibGccFileOnce.Do(func() { 1932 cgoLibGccFileOnce.Do(func() {
1842 cgoLibGccFile, cgoLibGccErr = b.libgcc(p) 1933 cgoLibGccFile, cgoLibGccErr = b.libgcc(p)
1843 }) 1934 })
1844 if cgoLibGccFile == "" && cgoLibGccErr != nil { 1935 if cgoLibGccFile == "" && cgoLibGccErr != nil {
1845 return nil, nil, err 1936 return nil, nil, err
1846 } 1937 }
1847 1938
1848 var staticLibs []string 1939 var staticLibs []string
1849 if goos == "windows" { 1940 if goos == "windows" {
1850 // libmingw32 and libmingwex might also use libgcc, so libgcc mu st come last 1941 // libmingw32 and libmingwex might also use libgcc, so libgcc mu st come last
1851 staticLibs = []string{"-lmingwex", "-lmingw32"} 1942 staticLibs = []string{"-lmingwex", "-lmingw32"}
1852 } 1943 }
1853 if cgoLibGccFile != "" { 1944 if cgoLibGccFile != "" {
1854 staticLibs = append(staticLibs, cgoLibGccFile) 1945 staticLibs = append(staticLibs, cgoLibGccFile)
1855 } 1946 }
1856 1947
1948 cflags := stringList(cgoCPPFLAGS, cgoCFLAGS)
1857 for _, cfile := range cfiles { 1949 for _, cfile := range cfiles {
1858 ofile := obj + cfile[:len(cfile)-1] + "o" 1950 ofile := obj + cfile[:len(cfile)-1] + "o"
1859 » » if err := b.gcc(p, ofile, cgoCFLAGS, obj+cfile); err != nil { 1951 » » if err := b.gcc(p, ofile, cflags, obj+cfile); err != nil {
1860 return nil, nil, err 1952 return nil, nil, err
1861 } 1953 }
1862 linkobj = append(linkobj, ofile) 1954 linkobj = append(linkobj, ofile)
1863 if !strings.HasSuffix(ofile, "_cgo_main.o") { 1955 if !strings.HasSuffix(ofile, "_cgo_main.o") {
1864 outObj = append(outObj, ofile) 1956 outObj = append(outObj, ofile)
1865 } 1957 }
1866 } 1958 }
1959
1867 for _, file := range gccfiles { 1960 for _, file := range gccfiles {
1868 ofile := obj + cgoRe.ReplaceAllString(file[:len(file)-1], "_") + "o" 1961 ofile := obj + cgoRe.ReplaceAllString(file[:len(file)-1], "_") + "o"
1869 » » if err := b.gcc(p, ofile, cgoCFLAGS, file); err != nil { 1962 » » if err := b.gcc(p, ofile, cflags, file); err != nil {
1870 return nil, nil, err 1963 return nil, nil, err
1871 } 1964 }
1872 linkobj = append(linkobj, ofile) 1965 linkobj = append(linkobj, ofile)
1873 outObj = append(outObj, ofile) 1966 outObj = append(outObj, ofile)
1874 } 1967 }
1968
1969 cxxflags := stringList(cgoCPPFLAGS, cgoCXXFLAGS)
1970 for _, file := range gxxfiles {
1971 // Append .o to the file, just in case the pkg has file.c and fi le.cpp
1972 ofile := obj + cgoRe.ReplaceAllString(file, "_") + ".o"
1973 if err := b.gxx(p, ofile, cxxflags, file); err != nil {
1974 return nil, nil, err
1975 }
1976 linkobj = append(linkobj, ofile)
1977 outObj = append(outObj, ofile)
1978 }
1979
1875 linkobj = append(linkobj, p.SysoFiles...) 1980 linkobj = append(linkobj, p.SysoFiles...)
1876 dynobj := obj + "_cgo_.o" 1981 dynobj := obj + "_cgo_.o"
1877 if goarch == "arm" && goos == "linux" { // we need to use -pie for Linux /ARM to get accurate imported sym 1982 if goarch == "arm" && goos == "linux" { // we need to use -pie for Linux /ARM to get accurate imported sym
1878 cgoLDFLAGS = append(cgoLDFLAGS, "-pie") 1983 cgoLDFLAGS = append(cgoLDFLAGS, "-pie")
1879 } 1984 }
1880 if err := b.gccld(p, dynobj, cgoLDFLAGS, linkobj); err != nil { 1985 if err := b.gccld(p, dynobj, cgoLDFLAGS, linkobj); err != nil {
1881 return nil, nil, err 1986 return nil, nil, err
1882 } 1987 }
1883 if goarch == "arm" && goos == "linux" { // but we don't need -pie for no rmal cgo programs 1988 if goarch == "arm" && goos == "linux" { // but we don't need -pie for no rmal cgo programs
1884 cgoLDFLAGS = cgoLDFLAGS[0 : len(cgoLDFLAGS)-1] 1989 cgoLDFLAGS = cgoLDFLAGS[0 : len(cgoLDFLAGS)-1]
1885 } 1990 }
1886 1991
1887 if _, ok := buildToolchain.(gccgoToolchain); ok { 1992 if _, ok := buildToolchain.(gccgoToolchain); ok {
1888 // we don't use dynimport when using gccgo. 1993 // we don't use dynimport when using gccgo.
1889 return outGo, outObj, nil 1994 return outGo, outObj, nil
1890 } 1995 }
1891 1996
1892 // cgo -dynimport 1997 // cgo -dynimport
1893 importC := obj + "_cgo_import.c" 1998 importC := obj + "_cgo_import.c"
1894 cgoflags = []string{} 1999 cgoflags = []string{}
1895 if p.Standard && p.ImportPath == "runtime/cgo" { 2000 if p.Standard && p.ImportPath == "runtime/cgo" {
1896 cgoflags = append(cgoflags, "-dynlinker") // record path to dyna mic linker 2001 cgoflags = append(cgoflags, "-dynlinker") // record path to dyna mic linker
1897 } 2002 }
1898 » if err := b.run(p.Dir, p.ImportPath, cgoExe, "-objdir", obj, "-dynimport ", dynobj, "-dynout", importC, cgoflags); err != nil { 2003 » if err := b.run(p.Dir, p.ImportPath, nil, cgoExe, "-objdir", obj, "-dyni mport", dynobj, "-dynout", importC, cgoflags); err != nil {
1899 return nil, nil, err 2004 return nil, nil, err
1900 } 2005 }
1901 2006
1902 // cc _cgo_import.ARCH 2007 // cc _cgo_import.ARCH
1903 importObj := obj + "_cgo_import." + objExt 2008 importObj := obj + "_cgo_import." + objExt
1904 if err := buildToolchain.cc(b, p, obj, importObj, importC); err != nil { 2009 if err := buildToolchain.cc(b, p, obj, importObj, importC); err != nil {
1905 return nil, nil, err 2010 return nil, nil, err
1906 } 2011 }
1907 2012
1908 ofile := obj + "_all.o" 2013 ofile := obj + "_all.o"
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after
2011 "-o", obj + gccBase + gccExt, 2116 "-o", obj + gccBase + gccExt,
2012 "-outdir", obj, 2117 "-outdir", obj,
2013 } 2118 }
2014 if gccgo { 2119 if gccgo {
2015 args = append(args, "-gccgo") 2120 args = append(args, "-gccgo")
2016 } 2121 }
2017 if cxx { 2122 if cxx {
2018 args = append(args, "-c++") 2123 args = append(args, "-c++")
2019 } 2124 }
2020 2125
2021 » if out, err := b.runOut(p.Dir, p.ImportPath, "swig", args, file); err != nil { 2126 » if out, err := b.runOut(p.Dir, p.ImportPath, nil, "swig", args, file); e rr != nil {
2022 if len(out) > 0 { 2127 if len(out) > 0 {
2023 if bytes.Contains(out, []byte("Unrecognized option -intg osize")) { 2128 if bytes.Contains(out, []byte("Unrecognized option -intg osize")) {
2024 return "", "", errors.New("must have SWIG versio n >= 2.0.9\n") 2129 return "", "", errors.New("must have SWIG versio n >= 2.0.9\n")
2025 } 2130 }
2026 b.showOutput(p.Dir, p.ImportPath, b.processOutput(out)) 2131 b.showOutput(p.Dir, p.ImportPath, b.processOutput(out))
2027 return "", "", errPrintedOutput 2132 return "", "", errPrintedOutput
2028 } 2133 }
2029 return "", "", err 2134 return "", "", err
2030 } 2135 }
2031 2136
(...skipping 17 matching lines...) Expand all
2049 "darwin": {"-dynamiclib", "-Wl,-undefined,dynamic_lookup"}, 2154 "darwin": {"-dynamiclib", "-Wl,-undefined,dynamic_lookup"},
2050 "freebsd": {"-shared", "-lpthread", "-lm"}, 2155 "freebsd": {"-shared", "-lpthread", "-lm"},
2051 "linux": {"-shared", "-lpthread", "-lm"}, 2156 "linux": {"-shared", "-lpthread", "-lm"},
2052 "windows": {"-shared", "-lm", "-mthreads"}, 2157 "windows": {"-shared", "-lm", "-mthreads"},
2053 } 2158 }
2054 var cxxlib []string 2159 var cxxlib []string
2055 if cxx { 2160 if cxx {
2056 cxxlib = []string{"-lstdc++"} 2161 cxxlib = []string{"-lstdc++"}
2057 } 2162 }
2058 ldflags := stringList(osldflags[goos], cxxlib) 2163 ldflags := stringList(osldflags[goos], cxxlib)
2059 » b.run(p.Dir, p.ImportPath, b.gccCmd(p.Dir), "-o", soname, gccObj, ldflag s) 2164 » b.run(p.Dir, p.ImportPath, nil, b.gccCmd(p.Dir), "-o", soname, gccObj, l dflags)
2060 2165
2061 return obj + goFile, cObj, nil 2166 return obj + goFile, cObj, nil
2062 } 2167 }
2063 2168
2064 // An actionQueue is a priority queue of actions. 2169 // An actionQueue is a priority queue of actions.
2065 type actionQueue []*action 2170 type actionQueue []*action
2066 2171
2067 // Implement heap.Interface 2172 // Implement heap.Interface
2068 func (q *actionQueue) Len() int { return len(*q) } 2173 func (q *actionQueue) Len() int { return len(*q) }
2069 func (q *actionQueue) Swap(i, j int) { (*q)[i], (*q)[j] = (*q)[j], (*q)[i] } 2174 func (q *actionQueue) Swap(i, j int) { (*q)[i], (*q)[j] = (*q)[j], (*q)[i] }
(...skipping 24 matching lines...) Expand all
2094 } 2199 }
2095 buildGcflags = append(buildGcflags, "-race") 2200 buildGcflags = append(buildGcflags, "-race")
2096 buildLdflags = append(buildLdflags, "-race") 2201 buildLdflags = append(buildLdflags, "-race")
2097 buildCcflags = append(buildCcflags, "-D", "RACE") 2202 buildCcflags = append(buildCcflags, "-D", "RACE")
2098 if buildContext.InstallSuffix != "" { 2203 if buildContext.InstallSuffix != "" {
2099 buildContext.InstallSuffix += "_" 2204 buildContext.InstallSuffix += "_"
2100 } 2205 }
2101 buildContext.InstallSuffix += "race" 2206 buildContext.InstallSuffix += "race"
2102 buildContext.BuildTags = append(buildContext.BuildTags, "race") 2207 buildContext.BuildTags = append(buildContext.BuildTags, "race")
2103 } 2208 }
LEFTRIGHT

Powered by Google App Engine
RSS Feeds Recent Issues | This issue
This is Rietveld f62528b