LEFT | RIGHT |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 } |
LEFT | RIGHT |