Merge lp:~mwhudson/ubuntu/utopic/gccgo-go/build-cgo into lp:ubuntu/utopic/gccgo-go

Proposed by Michael Hudson-Doyle on 2014-08-14
Status: Work in progress
Proposed branch: lp:~mwhudson/ubuntu/utopic/gccgo-go/build-cgo
Merge into: lp:ubuntu/utopic/gccgo-go
Diff against target: 1972 lines (+1870/-1)
12 files modified
.pc/applied-patches (+1/-0)
.pc/build-cgo.diff/src/cmd/cgo/gcc.go (+1633/-0)
.pc/build-cgo.diff/src/cmd/go/tool.go (+156/-0)
debian/changelog (+6/-0)
debian/install (+1/-0)
debian/lintian-overrides (+1/-0)
debian/patches/build-cgo.diff (+49/-0)
debian/patches/series (+1/-0)
debian/rules (+2/-0)
src/cmd/cgo/Makefile (+16/-0)
src/cmd/cgo/gcc.go (+1/-1)
src/cmd/go/tool.go (+3/-0)
To merge this branch: bzr merge lp:~mwhudson/ubuntu/utopic/gccgo-go/build-cgo
Reviewer Review Type Date Requested Status
James Page 2014-08-14 Pending
Review via email: mp+230739@code.launchpad.net

Description of the change

This branch builds and installs cgo. It also makes things so that "go tool cgo" works. It's probably all horrible but it's a start :)

To post a comment you must log in.
Michael Hudson-Doyle (mwhudson) wrote :

Bah the diff is certainly horrible. Here's a debdiff: http://paste.ubuntu.com/8041422/

Unmerged revisions

15. By Michael Hudson-Doyle <mwhudson@narsil> on 2014-08-14

lintian overrides

14. By Michael Hudson-Doyle <mwhudson@narsil> on 2014-08-14

install cgo

13. By Michael Hudson-Doyle <mwhudson@narsil> on 2014-08-14

updates

12. By Michael Hudson-Doyle <mwhudson@narsil> on 2014-08-14

quilt updates

11. By Michael Hudson-Doyle <mwhudson@narsil> on 2014-08-14

update version

10. By Michael Hudson-Doyle <mwhudson@narsil> on 2014-08-14

Build cgo too

9. By Michael Hudson-Doyle <mwhudson@narsil> on 2014-08-14

Add broken Makefile for cgo

8. By Michael Hudson-Doyle <mwhudson@narsil> on 2014-08-14

set ToolDir to something more sensible

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file '.pc/applied-patches'
2--- .pc/applied-patches 2014-03-26 10:50:18 +0000
3+++ .pc/applied-patches 2014-08-14 02:29:21 +0000
4@@ -5,3 +5,4 @@
5 issue28050043_60001_70001.diff
6 issue61970044_80001.diff
7 issue80300043_60001.diff
8+build-cgo.diff
9
10=== added directory '.pc/build-cgo.diff'
11=== added file '.pc/build-cgo.diff/.timestamp'
12=== added directory '.pc/build-cgo.diff/src'
13=== added directory '.pc/build-cgo.diff/src/cmd'
14=== added directory '.pc/build-cgo.diff/src/cmd/cgo'
15=== added file '.pc/build-cgo.diff/src/cmd/cgo/Makefile'
16=== added file '.pc/build-cgo.diff/src/cmd/cgo/gcc.go'
17--- .pc/build-cgo.diff/src/cmd/cgo/gcc.go 1970-01-01 00:00:00 +0000
18+++ .pc/build-cgo.diff/src/cmd/cgo/gcc.go 2014-08-14 02:29:21 +0000
19@@ -0,0 +1,1633 @@
20+// Copyright 2009 The Go Authors. All rights reserved.
21+// Use of this source code is governed by a BSD-style
22+// license that can be found in the LICENSE file.
23+
24+// Annotate Ref in Prog with C types by parsing gcc debug output.
25+// Conversion of debug output to Go types.
26+
27+package main
28+
29+import (
30+ "bytes"
31+ "debug/dwarf"
32+ "debug/elf"
33+ "debug/macho"
34+ "debug/pe"
35+ "encoding/binary"
36+ "errors"
37+ "flag"
38+ "fmt"
39+ "go/ast"
40+ "go/parser"
41+ "go/token"
42+ "os"
43+ "strconv"
44+ "strings"
45+ "unicode"
46+ "unicode/utf8"
47+)
48+
49+var debugDefine = flag.Bool("debug-define", false, "print relevant #defines")
50+var debugGcc = flag.Bool("debug-gcc", false, "print gcc invocations")
51+
52+var nameToC = map[string]string{
53+ "schar": "signed char",
54+ "uchar": "unsigned char",
55+ "ushort": "unsigned short",
56+ "uint": "unsigned int",
57+ "ulong": "unsigned long",
58+ "longlong": "long long",
59+ "ulonglong": "unsigned long long",
60+ "complexfloat": "float complex",
61+ "complexdouble": "double complex",
62+}
63+
64+// cname returns the C name to use for C.s.
65+// The expansions are listed in nameToC and also
66+// struct_foo becomes "struct foo", and similarly for
67+// union and enum.
68+func cname(s string) string {
69+ if t, ok := nameToC[s]; ok {
70+ return t
71+ }
72+
73+ if strings.HasPrefix(s, "struct_") {
74+ return "struct " + s[len("struct_"):]
75+ }
76+ if strings.HasPrefix(s, "union_") {
77+ return "union " + s[len("union_"):]
78+ }
79+ if strings.HasPrefix(s, "enum_") {
80+ return "enum " + s[len("enum_"):]
81+ }
82+ if strings.HasPrefix(s, "sizeof_") {
83+ return "sizeof(" + cname(s[len("sizeof_"):]) + ")"
84+ }
85+ return s
86+}
87+
88+// DiscardCgoDirectives processes the import C preamble, and discards
89+// all #cgo CFLAGS and LDFLAGS directives, so they don't make their
90+// way into _cgo_export.h.
91+func (f *File) DiscardCgoDirectives() {
92+ linesIn := strings.Split(f.Preamble, "\n")
93+ linesOut := make([]string, 0, len(linesIn))
94+ for _, line := range linesIn {
95+ l := strings.TrimSpace(line)
96+ if len(l) < 5 || l[:4] != "#cgo" || !unicode.IsSpace(rune(l[4])) {
97+ linesOut = append(linesOut, line)
98+ } else {
99+ linesOut = append(linesOut, "")
100+ }
101+ }
102+ f.Preamble = strings.Join(linesOut, "\n")
103+}
104+
105+// addToFlag appends args to flag. All flags are later written out onto the
106+// _cgo_flags file for the build system to use.
107+func (p *Package) addToFlag(flag string, args []string) {
108+ p.CgoFlags[flag] = append(p.CgoFlags[flag], args...)
109+ if flag == "CFLAGS" {
110+ // We'll also need these when preprocessing for dwarf information.
111+ p.GccOptions = append(p.GccOptions, args...)
112+ }
113+}
114+
115+// splitQuoted splits the string s around each instance of one or more consecutive
116+// white space characters while taking into account quotes and escaping, and
117+// returns an array of substrings of s or an empty list if s contains only white space.
118+// Single quotes and double quotes are recognized to prevent splitting within the
119+// quoted region, and are removed from the resulting substrings. If a quote in s
120+// isn't closed err will be set and r will have the unclosed argument as the
121+// last element. The backslash is used for escaping.
122+//
123+// For example, the following string:
124+//
125+// `a b:"c d" 'e''f' "g\""`
126+//
127+// Would be parsed as:
128+//
129+// []string{"a", "b:c d", "ef", `g"`}
130+//
131+func splitQuoted(s string) (r []string, err error) {
132+ var args []string
133+ arg := make([]rune, len(s))
134+ escaped := false
135+ quoted := false
136+ quote := '\x00'
137+ i := 0
138+ for _, r := range s {
139+ switch {
140+ case escaped:
141+ escaped = false
142+ case r == '\\':
143+ escaped = true
144+ continue
145+ case quote != 0:
146+ if r == quote {
147+ quote = 0
148+ continue
149+ }
150+ case r == '"' || r == '\'':
151+ quoted = true
152+ quote = r
153+ continue
154+ case unicode.IsSpace(r):
155+ if quoted || i > 0 {
156+ quoted = false
157+ args = append(args, string(arg[:i]))
158+ i = 0
159+ }
160+ continue
161+ }
162+ arg[i] = r
163+ i++
164+ }
165+ if quoted || i > 0 {
166+ args = append(args, string(arg[:i]))
167+ }
168+ if quote != 0 {
169+ err = errors.New("unclosed quote")
170+ } else if escaped {
171+ err = errors.New("unfinished escaping")
172+ }
173+ return args, err
174+}
175+
176+var safeBytes = []byte(`+-.,/0123456789:=ABCDEFGHIJKLMNOPQRSTUVWXYZ\_abcdefghijklmnopqrstuvwxyz`)
177+
178+func safeName(s string) bool {
179+ if s == "" {
180+ return false
181+ }
182+ for i := 0; i < len(s); i++ {
183+ if c := s[i]; c < 0x80 && bytes.IndexByte(safeBytes, c) < 0 {
184+ return false
185+ }
186+ }
187+ return true
188+}
189+
190+// Translate rewrites f.AST, the original Go input, to remove
191+// references to the imported package C, replacing them with
192+// references to the equivalent Go types, functions, and variables.
193+func (p *Package) Translate(f *File) {
194+ for _, cref := range f.Ref {
195+ // Convert C.ulong to C.unsigned long, etc.
196+ cref.Name.C = cname(cref.Name.Go)
197+ }
198+ p.loadDefines(f)
199+ needType := p.guessKinds(f)
200+ if len(needType) > 0 {
201+ p.loadDWARF(f, needType)
202+ }
203+ p.rewriteRef(f)
204+}
205+
206+// loadDefines coerces gcc into spitting out the #defines in use
207+// in the file f and saves relevant renamings in f.Name[name].Define.
208+func (p *Package) loadDefines(f *File) {
209+ var b bytes.Buffer
210+ b.WriteString(f.Preamble)
211+ b.WriteString(builtinProlog)
212+ stdout := p.gccDefines(b.Bytes())
213+
214+ for _, line := range strings.Split(stdout, "\n") {
215+ if len(line) < 9 || line[0:7] != "#define" {
216+ continue
217+ }
218+
219+ line = strings.TrimSpace(line[8:])
220+
221+ var key, val string
222+ spaceIndex := strings.Index(line, " ")
223+ tabIndex := strings.Index(line, "\t")
224+
225+ if spaceIndex == -1 && tabIndex == -1 {
226+ continue
227+ } else if tabIndex == -1 || (spaceIndex != -1 && spaceIndex < tabIndex) {
228+ key = line[0:spaceIndex]
229+ val = strings.TrimSpace(line[spaceIndex:])
230+ } else {
231+ key = line[0:tabIndex]
232+ val = strings.TrimSpace(line[tabIndex:])
233+ }
234+
235+ if n := f.Name[key]; n != nil {
236+ if *debugDefine {
237+ fmt.Fprintf(os.Stderr, "#define %s %s\n", key, val)
238+ }
239+ n.Define = val
240+ }
241+ }
242+}
243+
244+// guessKinds tricks gcc into revealing the kind of each
245+// name xxx for the references C.xxx in the Go input.
246+// The kind is either a constant, type, or variable.
247+func (p *Package) guessKinds(f *File) []*Name {
248+ // Determine kinds for names we already know about,
249+ // like #defines or 'struct foo', before bothering with gcc.
250+ var names, needType []*Name
251+ for _, n := range f.Name {
252+ // If we've already found this name as a #define
253+ // and we can translate it as a constant value, do so.
254+ if n.Define != "" {
255+ isConst := false
256+ if _, err := strconv.Atoi(n.Define); err == nil {
257+ isConst = true
258+ } else if n.Define[0] == '"' || n.Define[0] == '\'' {
259+ if _, err := parser.ParseExpr(n.Define); err == nil {
260+ isConst = true
261+ }
262+ }
263+ if isConst {
264+ n.Kind = "const"
265+ // Turn decimal into hex, just for consistency
266+ // with enum-derived constants. Otherwise
267+ // in the cgo -godefs output half the constants
268+ // are in hex and half are in whatever the #define used.
269+ i, err := strconv.ParseInt(n.Define, 0, 64)
270+ if err == nil {
271+ n.Const = fmt.Sprintf("%#x", i)
272+ } else {
273+ n.Const = n.Define
274+ }
275+ continue
276+ }
277+
278+ if isName(n.Define) {
279+ n.C = n.Define
280+ }
281+ }
282+
283+ needType = append(needType, n)
284+
285+ // If this is a struct, union, or enum type name, no need to guess the kind.
286+ if strings.HasPrefix(n.C, "struct ") || strings.HasPrefix(n.C, "union ") || strings.HasPrefix(n.C, "enum ") {
287+ n.Kind = "type"
288+ continue
289+ }
290+
291+ // Otherwise, we'll need to find out from gcc.
292+ names = append(names, n)
293+ }
294+
295+ // Bypass gcc if there's nothing left to find out.
296+ if len(names) == 0 {
297+ return needType
298+ }
299+
300+ // Coerce gcc into telling us whether each name is a type, a value, or undeclared.
301+ // For names, find out whether they are integer constants.
302+ // We used to look at specific warning or error messages here, but that tied the
303+ // behavior too closely to specific versions of the compilers.
304+ // Instead, arrange that we can infer what we need from only the presence or absence
305+ // of an error on a specific line.
306+ //
307+ // For each name, we generate these lines, where xxx is the index in toSniff plus one.
308+ //
309+ // #line xxx "not-declared"
310+ // void __cgo_f_xxx_1(void) { __typeof__(name) *__cgo_undefined__; }
311+ // #line xxx "not-type"
312+ // void __cgo_f_xxx_2(void) { name *__cgo_undefined__; }
313+ // #line xxx "not-const"
314+ // void __cgo_f_xxx_3(void) { enum { __cgo_undefined__ = (name)*1 }; }
315+ //
316+ // If we see an error at not-declared:xxx, the corresponding name is not declared.
317+ // If we see an error at not-type:xxx, the corresponding name is a type.
318+ // If we see an error at not-const:xxx, the corresponding name is not an integer constant.
319+ // If we see no errors, we assume the name is an expression but not a constant
320+ // (so a variable or a function).
321+ //
322+ // The specific input forms are chosen so that they are valid C syntax regardless of
323+ // whether name denotes a type or an expression.
324+
325+ var b bytes.Buffer
326+ b.WriteString(f.Preamble)
327+ b.WriteString(builtinProlog)
328+
329+ for i, n := range names {
330+ fmt.Fprintf(&b, "#line %d \"not-declared\"\n"+
331+ "void __cgo_f_%d_1(void) { __typeof__(%s) *__cgo_undefined__; }\n"+
332+ "#line %d \"not-type\"\n"+
333+ "void __cgo_f_%d_2(void) { %s *__cgo_undefined__; }\n"+
334+ "#line %d \"not-const\"\n"+
335+ "void __cgo_f_%d_3(void) { enum { __cgo__undefined__ = (%s)*1 }; }\n",
336+ i+1, i+1, n.C,
337+ i+1, i+1, n.C,
338+ i+1, i+1, n.C)
339+ }
340+ fmt.Fprintf(&b, "#line 1 \"completed\"\n"+
341+ "int __cgo__1 = __cgo__2;\n")
342+
343+ stderr := p.gccErrors(b.Bytes())
344+ if stderr == "" {
345+ fatalf("%s produced no output\non input:\n%s", p.gccBaseCmd()[0], b.Bytes())
346+ }
347+
348+ completed := false
349+ sniff := make([]int, len(names))
350+ const (
351+ notType = 1 << iota
352+ notConst
353+ )
354+ for _, line := range strings.Split(stderr, "\n") {
355+ if !strings.Contains(line, ": error:") {
356+ // we only care about errors.
357+ // we tried to turn off warnings on the command line, but one never knows.
358+ continue
359+ }
360+
361+ c1 := strings.Index(line, ":")
362+ if c1 < 0 {
363+ continue
364+ }
365+ c2 := strings.Index(line[c1+1:], ":")
366+ if c2 < 0 {
367+ continue
368+ }
369+ c2 += c1 + 1
370+
371+ filename := line[:c1]
372+ i, _ := strconv.Atoi(line[c1+1 : c2])
373+ i--
374+ if i < 0 || i >= len(names) {
375+ continue
376+ }
377+
378+ switch filename {
379+ case "completed":
380+ // Strictly speaking, there is no guarantee that seeing the error at completed:1
381+ // (at the end of the file) means we've seen all the errors from earlier in the file,
382+ // but usually it does. Certainly if we don't see the completed:1 error, we did
383+ // not get all the errors we expected.
384+ completed = true
385+
386+ case "not-declared":
387+ error_(token.NoPos, "%s", strings.TrimSpace(line[c2+1:]))
388+ case "not-type":
389+ sniff[i] |= notType
390+ case "not-const":
391+ sniff[i] |= notConst
392+ }
393+ }
394+
395+ if !completed {
396+ fatalf("%s did not produce error at completed:1\non input:\n%s", p.gccBaseCmd()[0], b.Bytes())
397+ }
398+
399+ for i, n := range names {
400+ switch sniff[i] {
401+ case 0:
402+ error_(token.NoPos, "could not determine kind of name for C.%s", fixGo(n.Go))
403+ case notType:
404+ n.Kind = "const"
405+ case notConst:
406+ n.Kind = "type"
407+ case notConst | notType:
408+ n.Kind = "not-type"
409+ }
410+ }
411+ if nerrors > 0 {
412+ fatalf("unresolved names")
413+ }
414+
415+ needType = append(needType, names...)
416+ return needType
417+}
418+
419+// loadDWARF parses the DWARF debug information generated
420+// by gcc to learn the details of the constants, variables, and types
421+// being referred to as C.xxx.
422+func (p *Package) loadDWARF(f *File, names []*Name) {
423+ // Extract the types from the DWARF section of an object
424+ // from a well-formed C program. Gcc only generates DWARF info
425+ // for symbols in the object file, so it is not enough to print the
426+ // preamble and hope the symbols we care about will be there.
427+ // Instead, emit
428+ // __typeof__(names[i]) *__cgo__i;
429+ // for each entry in names and then dereference the type we
430+ // learn for __cgo__i.
431+ var b bytes.Buffer
432+ b.WriteString(f.Preamble)
433+ b.WriteString(builtinProlog)
434+ for i, n := range names {
435+ fmt.Fprintf(&b, "__typeof__(%s) *__cgo__%d;\n", n.C, i)
436+ if n.Kind == "const" {
437+ fmt.Fprintf(&b, "enum { __cgo_enum__%d = %s };\n", i, n.C)
438+ }
439+ }
440+
441+ // Apple's LLVM-based gcc does not include the enumeration
442+ // names and values in its DWARF debug output. In case we're
443+ // using such a gcc, create a data block initialized with the values.
444+ // We can read them out of the object file.
445+ fmt.Fprintf(&b, "long long __cgodebug_data[] = {\n")
446+ for _, n := range names {
447+ if n.Kind == "const" {
448+ fmt.Fprintf(&b, "\t%s,\n", n.C)
449+ } else {
450+ fmt.Fprintf(&b, "\t0,\n")
451+ }
452+ }
453+ // for the last entry, we can not use 0, otherwise
454+ // in case all __cgodebug_data is zero initialized,
455+ // LLVM-based gcc will place the it in the __DATA.__common
456+ // zero-filled section (our debug/macho doesn't support
457+ // this)
458+ fmt.Fprintf(&b, "\t1\n")
459+ fmt.Fprintf(&b, "};\n")
460+
461+ d, bo, debugData := p.gccDebug(b.Bytes())
462+ enumVal := make([]int64, len(debugData)/8)
463+ for i := range enumVal {
464+ enumVal[i] = int64(bo.Uint64(debugData[i*8:]))
465+ }
466+
467+ // Scan DWARF info for top-level TagVariable entries with AttrName __cgo__i.
468+ types := make([]dwarf.Type, len(names))
469+ enums := make([]dwarf.Offset, len(names))
470+ nameToIndex := make(map[*Name]int)
471+ for i, n := range names {
472+ nameToIndex[n] = i
473+ }
474+ nameToRef := make(map[*Name]*Ref)
475+ for _, ref := range f.Ref {
476+ nameToRef[ref.Name] = ref
477+ }
478+ r := d.Reader()
479+ for {
480+ e, err := r.Next()
481+ if err != nil {
482+ fatalf("reading DWARF entry: %s", err)
483+ }
484+ if e == nil {
485+ break
486+ }
487+ switch e.Tag {
488+ case dwarf.TagEnumerationType:
489+ offset := e.Offset
490+ for {
491+ e, err := r.Next()
492+ if err != nil {
493+ fatalf("reading DWARF entry: %s", err)
494+ }
495+ if e.Tag == 0 {
496+ break
497+ }
498+ if e.Tag == dwarf.TagEnumerator {
499+ entryName := e.Val(dwarf.AttrName).(string)
500+ if strings.HasPrefix(entryName, "__cgo_enum__") {
501+ n, _ := strconv.Atoi(entryName[len("__cgo_enum__"):])
502+ if 0 <= n && n < len(names) {
503+ enums[n] = offset
504+ }
505+ }
506+ }
507+ }
508+ case dwarf.TagVariable:
509+ name, _ := e.Val(dwarf.AttrName).(string)
510+ typOff, _ := e.Val(dwarf.AttrType).(dwarf.Offset)
511+ if name == "" || typOff == 0 {
512+ fatalf("malformed DWARF TagVariable entry")
513+ }
514+ if !strings.HasPrefix(name, "__cgo__") {
515+ break
516+ }
517+ typ, err := d.Type(typOff)
518+ if err != nil {
519+ fatalf("loading DWARF type: %s", err)
520+ }
521+ t, ok := typ.(*dwarf.PtrType)
522+ if !ok || t == nil {
523+ fatalf("internal error: %s has non-pointer type", name)
524+ }
525+ i, err := strconv.Atoi(name[7:])
526+ if err != nil {
527+ fatalf("malformed __cgo__ name: %s", name)
528+ }
529+ if enums[i] != 0 {
530+ t, err := d.Type(enums[i])
531+ if err != nil {
532+ fatalf("loading DWARF type: %s", err)
533+ }
534+ types[i] = t
535+ } else {
536+ types[i] = t.Type
537+ }
538+ }
539+ if e.Tag != dwarf.TagCompileUnit {
540+ r.SkipChildren()
541+ }
542+ }
543+
544+ // Record types and typedef information.
545+ var conv typeConv
546+ conv.Init(p.PtrSize, p.IntSize)
547+ for i, n := range names {
548+ if types[i] == nil {
549+ continue
550+ }
551+ pos := token.NoPos
552+ if ref, ok := nameToRef[n]; ok {
553+ pos = ref.Pos()
554+ }
555+ f, fok := types[i].(*dwarf.FuncType)
556+ if n.Kind != "type" && fok {
557+ n.Kind = "func"
558+ n.FuncType = conv.FuncType(f, pos)
559+ } else {
560+ n.Type = conv.Type(types[i], pos)
561+ if enums[i] != 0 && n.Type.EnumValues != nil {
562+ k := fmt.Sprintf("__cgo_enum__%d", i)
563+ n.Kind = "const"
564+ n.Const = fmt.Sprintf("%#x", n.Type.EnumValues[k])
565+ // Remove injected enum to ensure the value will deep-compare
566+ // equally in future loads of the same constant.
567+ delete(n.Type.EnumValues, k)
568+ }
569+ // Prefer debug data over DWARF debug output, if we have it.
570+ if n.Kind == "const" && i < len(enumVal) {
571+ n.Const = fmt.Sprintf("%#x", enumVal[i])
572+ }
573+ }
574+ }
575+
576+}
577+
578+// mangleName does name mangling to translate names
579+// from the original Go source files to the names
580+// used in the final Go files generated by cgo.
581+func (p *Package) mangleName(n *Name) {
582+ // When using gccgo variables have to be
583+ // exported so that they become global symbols
584+ // that the C code can refer to.
585+ prefix := "_C"
586+ if *gccgo && n.IsVar() {
587+ prefix = "C"
588+ }
589+ n.Mangle = prefix + n.Kind + "_" + n.Go
590+}
591+
592+// rewriteRef rewrites all the C.xxx references in f.AST to refer to the
593+// Go equivalents, now that we have figured out the meaning of all
594+// the xxx. In *godefs or *cdefs mode, rewriteRef replaces the names
595+// with full definitions instead of mangled names.
596+func (p *Package) rewriteRef(f *File) {
597+ // Keep a list of all the functions, to remove the ones
598+ // only used as expressions and avoid generating bridge
599+ // code for them.
600+ functions := make(map[string]bool)
601+
602+ // Assign mangled names.
603+ for _, n := range f.Name {
604+ if n.Kind == "not-type" {
605+ n.Kind = "var"
606+ }
607+ if n.Mangle == "" {
608+ p.mangleName(n)
609+ }
610+ if n.Kind == "func" {
611+ functions[n.Go] = false
612+ }
613+ }
614+
615+ // Now that we have all the name types filled in,
616+ // scan through the Refs to identify the ones that
617+ // are trying to do a ,err call. Also check that
618+ // functions are only used in calls.
619+ for _, r := range f.Ref {
620+ if r.Name.Kind == "const" && r.Name.Const == "" {
621+ error_(r.Pos(), "unable to find value of constant C.%s", fixGo(r.Name.Go))
622+ }
623+ var expr ast.Expr = ast.NewIdent(r.Name.Mangle) // default
624+ switch r.Context {
625+ case "call", "call2":
626+ if r.Name.Kind != "func" {
627+ if r.Name.Kind == "type" {
628+ r.Context = "type"
629+ expr = r.Name.Type.Go
630+ break
631+ }
632+ error_(r.Pos(), "call of non-function C.%s", fixGo(r.Name.Go))
633+ break
634+ }
635+ functions[r.Name.Go] = true
636+ if r.Context == "call2" {
637+ if r.Name.Go == "_CMalloc" {
638+ error_(r.Pos(), "no two-result form for C.malloc")
639+ break
640+ }
641+ // Invent new Name for the two-result function.
642+ n := f.Name["2"+r.Name.Go]
643+ if n == nil {
644+ n = new(Name)
645+ *n = *r.Name
646+ n.AddError = true
647+ n.Mangle = "_C2func_" + n.Go
648+ f.Name["2"+r.Name.Go] = n
649+ }
650+ expr = ast.NewIdent(n.Mangle)
651+ r.Name = n
652+ break
653+ }
654+ case "expr":
655+ if r.Name.Kind == "func" {
656+ // Function is being used in an expression, to e.g. pass around a C function pointer.
657+ // Create a new Name for this Ref which causes the variable to be declared in Go land.
658+ fpName := "fp_" + r.Name.Go
659+ name := f.Name[fpName]
660+ if name == nil {
661+ name = &Name{
662+ Go: fpName,
663+ C: r.Name.C,
664+ Kind: "fpvar",
665+ Type: &Type{Size: p.PtrSize, Align: p.PtrSize, C: c("void*"), Go: ast.NewIdent("unsafe.Pointer")},
666+ }
667+ p.mangleName(name)
668+ f.Name[fpName] = name
669+ }
670+ r.Name = name
671+ expr = ast.NewIdent(name.Mangle)
672+ } else if r.Name.Kind == "type" {
673+ // Okay - might be new(T)
674+ expr = r.Name.Type.Go
675+ } else if r.Name.Kind == "var" {
676+ expr = &ast.StarExpr{Star: (*r.Expr).Pos(), X: expr}
677+ }
678+
679+ case "type":
680+ if r.Name.Kind != "type" {
681+ error_(r.Pos(), "expression C.%s used as type", fixGo(r.Name.Go))
682+ } else if r.Name.Type == nil {
683+ // Use of C.enum_x, C.struct_x or C.union_x without C definition.
684+ // GCC won't raise an error when using pointers to such unknown types.
685+ error_(r.Pos(), "type C.%s: undefined C type '%s'", fixGo(r.Name.Go), r.Name.C)
686+ } else {
687+ expr = r.Name.Type.Go
688+ }
689+ default:
690+ if r.Name.Kind == "func" {
691+ error_(r.Pos(), "must call C.%s", fixGo(r.Name.Go))
692+ }
693+ }
694+ if *godefs || *cdefs {
695+ // Substitute definition for mangled type name.
696+ if id, ok := expr.(*ast.Ident); ok {
697+ if t := typedef[id.Name]; t != nil {
698+ expr = t.Go
699+ }
700+ if id.Name == r.Name.Mangle && r.Name.Const != "" {
701+ expr = ast.NewIdent(r.Name.Const)
702+ }
703+ }
704+ }
705+
706+ // Copy position information from old expr into new expr,
707+ // in case expression being replaced is first on line.
708+ // See golang.org/issue/6563.
709+ pos := (*r.Expr).Pos()
710+ switch x := expr.(type) {
711+ case *ast.Ident:
712+ expr = &ast.Ident{NamePos: pos, Name: x.Name}
713+ }
714+
715+ *r.Expr = expr
716+ }
717+
718+ // Remove functions only used as expressions, so their respective
719+ // bridge functions are not generated.
720+ for name, used := range functions {
721+ if !used {
722+ delete(f.Name, name)
723+ }
724+ }
725+}
726+
727+// gccBaseCmd returns the start of the compiler command line.
728+// It uses $CC if set, or else $GCC, or else the compiler recorded
729+// during the initial build as defaultCC.
730+// defaultCC is defined in zdefaultcc.go, written by cmd/dist.
731+func (p *Package) gccBaseCmd() []string {
732+ // Use $CC if set, since that's what the build uses.
733+ if ret := strings.Fields(os.Getenv("CC")); len(ret) > 0 {
734+ return ret
735+ }
736+ // Try $GCC if set, since that's what we used to use.
737+ if ret := strings.Fields(os.Getenv("GCC")); len(ret) > 0 {
738+ return ret
739+ }
740+ return strings.Fields(defaultCC)
741+}
742+
743+// gccMachine returns the gcc -m flag to use, either "-m32", "-m64" or "-marm".
744+func (p *Package) gccMachine() []string {
745+ switch goarch {
746+ case "amd64":
747+ return []string{"-m64"}
748+ case "386":
749+ return []string{"-m32"}
750+ case "arm":
751+ return []string{"-marm"} // not thumb
752+ }
753+ return nil
754+}
755+
756+func gccTmp() string {
757+ return *objDir + "_cgo_.o"
758+}
759+
760+// gccCmd returns the gcc command line to use for compiling
761+// the input.
762+func (p *Package) gccCmd() []string {
763+ c := append(p.gccBaseCmd(),
764+ "-w", // no warnings
765+ "-Wno-error", // warnings are not errors
766+ "-o"+gccTmp(), // write object to tmp
767+ "-gdwarf-2", // generate DWARF v2 debugging symbols
768+ "-c", // do not link
769+ "-xc", // input language is C
770+ )
771+ if strings.Contains(c[0], "clang") {
772+ c = append(c,
773+ "-ferror-limit=0",
774+ // Apple clang version 1.7 (tags/Apple/clang-77) (based on LLVM 2.9svn)
775+ // doesn't have -Wno-unneeded-internal-declaration, so we need yet another
776+ // flag to disable the warning. Yes, really good diagnostics, clang.
777+ "-Wno-unknown-warning-option",
778+ "-Wno-unneeded-internal-declaration",
779+ "-Wno-unused-function",
780+ "-Qunused-arguments",
781+ // Clang embeds prototypes for some builtin functions,
782+ // like malloc and calloc, but all size_t parameters are
783+ // incorrectly typed unsigned long. We work around that
784+ // by disabling the builtin functions (this is safe as
785+ // it won't affect the actual compilation of the C code).
786+ // See: http://golang.org/issue/6506.
787+ "-fno-builtin",
788+ )
789+ }
790+
791+ c = append(c, p.GccOptions...)
792+ c = append(c, p.gccMachine()...)
793+ c = append(c, "-") //read input from standard input
794+ return c
795+}
796+
797+// gccDebug runs gcc -gdwarf-2 over the C program stdin and
798+// returns the corresponding DWARF data and, if present, debug data block.
799+func (p *Package) gccDebug(stdin []byte) (*dwarf.Data, binary.ByteOrder, []byte) {
800+ runGcc(stdin, p.gccCmd())
801+
802+ isDebugData := func(s string) bool {
803+ // Some systems use leading _ to denote non-assembly symbols.
804+ return s == "__cgodebug_data" || s == "___cgodebug_data"
805+ }
806+
807+ if f, err := macho.Open(gccTmp()); err == nil {
808+ defer f.Close()
809+ d, err := f.DWARF()
810+ if err != nil {
811+ fatalf("cannot load DWARF output from %s: %v", gccTmp(), err)
812+ }
813+ var data []byte
814+ if f.Symtab != nil {
815+ for i := range f.Symtab.Syms {
816+ s := &f.Symtab.Syms[i]
817+ if isDebugData(s.Name) {
818+ // Found it. Now find data section.
819+ if i := int(s.Sect) - 1; 0 <= i && i < len(f.Sections) {
820+ sect := f.Sections[i]
821+ if sect.Addr <= s.Value && s.Value < sect.Addr+sect.Size {
822+ if sdat, err := sect.Data(); err == nil {
823+ data = sdat[s.Value-sect.Addr:]
824+ }
825+ }
826+ }
827+ }
828+ }
829+ }
830+ return d, f.ByteOrder, data
831+ }
832+
833+ if f, err := elf.Open(gccTmp()); err == nil {
834+ defer f.Close()
835+ d, err := f.DWARF()
836+ if err != nil {
837+ fatalf("cannot load DWARF output from %s: %v", gccTmp(), err)
838+ }
839+ var data []byte
840+ symtab, err := f.Symbols()
841+ if err == nil {
842+ for i := range symtab {
843+ s := &symtab[i]
844+ if isDebugData(s.Name) {
845+ // Found it. Now find data section.
846+ if i := int(s.Section); 0 <= i && i < len(f.Sections) {
847+ sect := f.Sections[i]
848+ if sect.Addr <= s.Value && s.Value < sect.Addr+sect.Size {
849+ if sdat, err := sect.Data(); err == nil {
850+ data = sdat[s.Value-sect.Addr:]
851+ }
852+ }
853+ }
854+ }
855+ }
856+ }
857+ return d, f.ByteOrder, data
858+ }
859+
860+ if f, err := pe.Open(gccTmp()); err == nil {
861+ defer f.Close()
862+ d, err := f.DWARF()
863+ if err != nil {
864+ fatalf("cannot load DWARF output from %s: %v", gccTmp(), err)
865+ }
866+ var data []byte
867+ for _, s := range f.Symbols {
868+ if isDebugData(s.Name) {
869+ if i := int(s.SectionNumber) - 1; 0 <= i && i < len(f.Sections) {
870+ sect := f.Sections[i]
871+ if s.Value < sect.Size {
872+ if sdat, err := sect.Data(); err == nil {
873+ data = sdat[s.Value:]
874+ }
875+ }
876+ }
877+ }
878+ }
879+ return d, binary.LittleEndian, data
880+ }
881+
882+ fatalf("cannot parse gcc output %s as ELF, Mach-O, PE object", gccTmp())
883+ panic("not reached")
884+}
885+
886+// gccDefines runs gcc -E -dM -xc - over the C program stdin
887+// and returns the corresponding standard output, which is the
888+// #defines that gcc encountered while processing the input
889+// and its included files.
890+func (p *Package) gccDefines(stdin []byte) string {
891+ base := append(p.gccBaseCmd(), "-E", "-dM", "-xc")
892+ base = append(base, p.gccMachine()...)
893+ stdout, _ := runGcc(stdin, append(append(base, p.GccOptions...), "-"))
894+ return stdout
895+}
896+
897+// gccErrors runs gcc over the C program stdin and returns
898+// the errors that gcc prints. That is, this function expects
899+// gcc to fail.
900+func (p *Package) gccErrors(stdin []byte) string {
901+ // TODO(rsc): require failure
902+ args := p.gccCmd()
903+
904+ if *debugGcc {
905+ fmt.Fprintf(os.Stderr, "$ %s <<EOF\n", strings.Join(args, " "))
906+ os.Stderr.Write(stdin)
907+ fmt.Fprint(os.Stderr, "EOF\n")
908+ }
909+ stdout, stderr, _ := run(stdin, args)
910+ if *debugGcc {
911+ os.Stderr.Write(stdout)
912+ os.Stderr.Write(stderr)
913+ }
914+ return string(stderr)
915+}
916+
917+// runGcc runs the gcc command line args with stdin on standard input.
918+// If the command exits with a non-zero exit status, runGcc prints
919+// details about what was run and exits.
920+// Otherwise runGcc returns the data written to standard output and standard error.
921+// Note that for some of the uses we expect useful data back
922+// on standard error, but for those uses gcc must still exit 0.
923+func runGcc(stdin []byte, args []string) (string, string) {
924+ if *debugGcc {
925+ fmt.Fprintf(os.Stderr, "$ %s <<EOF\n", strings.Join(args, " "))
926+ os.Stderr.Write(stdin)
927+ fmt.Fprint(os.Stderr, "EOF\n")
928+ }
929+ stdout, stderr, ok := run(stdin, args)
930+ if *debugGcc {
931+ os.Stderr.Write(stdout)
932+ os.Stderr.Write(stderr)
933+ }
934+ if !ok {
935+ os.Stderr.Write(stderr)
936+ os.Exit(2)
937+ }
938+ return string(stdout), string(stderr)
939+}
940+
941+// A typeConv is a translator from dwarf types to Go types
942+// with equivalent memory layout.
943+type typeConv struct {
944+ // Cache of already-translated or in-progress types.
945+ m map[dwarf.Type]*Type
946+ typedef map[string]ast.Expr
947+
948+ // Predeclared types.
949+ bool ast.Expr
950+ byte ast.Expr // denotes padding
951+ int8, int16, int32, int64 ast.Expr
952+ uint8, uint16, uint32, uint64, uintptr ast.Expr
953+ float32, float64 ast.Expr
954+ complex64, complex128 ast.Expr
955+ void ast.Expr
956+ unsafePointer ast.Expr
957+ string ast.Expr
958+ goVoid ast.Expr // _Ctype_void, denotes C's void
959+
960+ ptrSize int64
961+ intSize int64
962+}
963+
964+var tagGen int
965+var typedef = make(map[string]*Type)
966+var goIdent = make(map[string]*ast.Ident)
967+
968+func (c *typeConv) Init(ptrSize, intSize int64) {
969+ c.ptrSize = ptrSize
970+ c.intSize = intSize
971+ c.m = make(map[dwarf.Type]*Type)
972+ c.bool = c.Ident("bool")
973+ c.byte = c.Ident("byte")
974+ c.int8 = c.Ident("int8")
975+ c.int16 = c.Ident("int16")
976+ c.int32 = c.Ident("int32")
977+ c.int64 = c.Ident("int64")
978+ c.uint8 = c.Ident("uint8")
979+ c.uint16 = c.Ident("uint16")
980+ c.uint32 = c.Ident("uint32")
981+ c.uint64 = c.Ident("uint64")
982+ c.uintptr = c.Ident("uintptr")
983+ c.float32 = c.Ident("float32")
984+ c.float64 = c.Ident("float64")
985+ c.complex64 = c.Ident("complex64")
986+ c.complex128 = c.Ident("complex128")
987+ c.unsafePointer = c.Ident("unsafe.Pointer")
988+ c.void = c.Ident("void")
989+ c.string = c.Ident("string")
990+ c.goVoid = c.Ident("_Ctype_void")
991+}
992+
993+// base strips away qualifiers and typedefs to get the underlying type
994+func base(dt dwarf.Type) dwarf.Type {
995+ for {
996+ if d, ok := dt.(*dwarf.QualType); ok {
997+ dt = d.Type
998+ continue
999+ }
1000+ if d, ok := dt.(*dwarf.TypedefType); ok {
1001+ dt = d.Type
1002+ continue
1003+ }
1004+ break
1005+ }
1006+ return dt
1007+}
1008+
1009+// Map from dwarf text names to aliases we use in package "C".
1010+var dwarfToName = map[string]string{
1011+ "long int": "long",
1012+ "long unsigned int": "ulong",
1013+ "unsigned int": "uint",
1014+ "short unsigned int": "ushort",
1015+ "short int": "short",
1016+ "long long int": "longlong",
1017+ "long long unsigned int": "ulonglong",
1018+ "signed char": "schar",
1019+ "float complex": "complexfloat",
1020+ "double complex": "complexdouble",
1021+}
1022+
1023+const signedDelta = 64
1024+
1025+// String returns the current type representation. Format arguments
1026+// are assembled within this method so that any changes in mutable
1027+// values are taken into account.
1028+func (tr *TypeRepr) String() string {
1029+ if len(tr.Repr) == 0 {
1030+ return ""
1031+ }
1032+ if len(tr.FormatArgs) == 0 {
1033+ return tr.Repr
1034+ }
1035+ return fmt.Sprintf(tr.Repr, tr.FormatArgs...)
1036+}
1037+
1038+// Empty returns true if the result of String would be "".
1039+func (tr *TypeRepr) Empty() bool {
1040+ return len(tr.Repr) == 0
1041+}
1042+
1043+// Set modifies the type representation.
1044+// If fargs are provided, repr is used as a format for fmt.Sprintf.
1045+// Otherwise, repr is used unprocessed as the type representation.
1046+func (tr *TypeRepr) Set(repr string, fargs ...interface{}) {
1047+ tr.Repr = repr
1048+ tr.FormatArgs = fargs
1049+}
1050+
1051+// Type returns a *Type with the same memory layout as
1052+// dtype when used as the type of a variable or a struct field.
1053+func (c *typeConv) Type(dtype dwarf.Type, pos token.Pos) *Type {
1054+ if t, ok := c.m[dtype]; ok {
1055+ if t.Go == nil {
1056+ fatalf("%s: type conversion loop at %s", lineno(pos), dtype)
1057+ }
1058+ return t
1059+ }
1060+
1061+ // clang won't generate DW_AT_byte_size for pointer types,
1062+ // so we have to fix it here.
1063+ if dt, ok := base(dtype).(*dwarf.PtrType); ok && dt.ByteSize == -1 {
1064+ dt.ByteSize = c.ptrSize
1065+ }
1066+
1067+ t := new(Type)
1068+ t.Size = dtype.Size() // note: wrong for array of pointers, corrected below
1069+ t.Align = -1
1070+ t.C = &TypeRepr{Repr: dtype.Common().Name}
1071+ c.m[dtype] = t
1072+
1073+ switch dt := dtype.(type) {
1074+ default:
1075+ fatalf("%s: unexpected type: %s", lineno(pos), dtype)
1076+
1077+ case *dwarf.AddrType:
1078+ if t.Size != c.ptrSize {
1079+ fatalf("%s: unexpected: %d-byte address type - %s", lineno(pos), t.Size, dtype)
1080+ }
1081+ t.Go = c.uintptr
1082+ t.Align = t.Size
1083+
1084+ case *dwarf.ArrayType:
1085+ if dt.StrideBitSize > 0 {
1086+ // Cannot represent bit-sized elements in Go.
1087+ t.Go = c.Opaque(t.Size)
1088+ break
1089+ }
1090+ gt := &ast.ArrayType{
1091+ Len: c.intExpr(dt.Count),
1092+ }
1093+ t.Go = gt // publish before recursive call
1094+ sub := c.Type(dt.Type, pos)
1095+ t.Align = sub.Align
1096+ gt.Elt = sub.Go
1097+ t.C.Set("__typeof__(%s[%d])", sub.C, dt.Count)
1098+
1099+ case *dwarf.BoolType:
1100+ t.Go = c.bool
1101+ t.Align = 1
1102+
1103+ case *dwarf.CharType:
1104+ if t.Size != 1 {
1105+ fatalf("%s: unexpected: %d-byte char type - %s", lineno(pos), t.Size, dtype)
1106+ }
1107+ t.Go = c.int8
1108+ t.Align = 1
1109+
1110+ case *dwarf.EnumType:
1111+ if t.Align = t.Size; t.Align >= c.ptrSize {
1112+ t.Align = c.ptrSize
1113+ }
1114+ t.C.Set("enum " + dt.EnumName)
1115+ signed := 0
1116+ t.EnumValues = make(map[string]int64)
1117+ for _, ev := range dt.Val {
1118+ t.EnumValues[ev.Name] = ev.Val
1119+ if ev.Val < 0 {
1120+ signed = signedDelta
1121+ }
1122+ }
1123+ switch t.Size + int64(signed) {
1124+ default:
1125+ fatalf("%s: unexpected: %d-byte enum type - %s", lineno(pos), t.Size, dtype)
1126+ case 1:
1127+ t.Go = c.uint8
1128+ case 2:
1129+ t.Go = c.uint16
1130+ case 4:
1131+ t.Go = c.uint32
1132+ case 8:
1133+ t.Go = c.uint64
1134+ case 1 + signedDelta:
1135+ t.Go = c.int8
1136+ case 2 + signedDelta:
1137+ t.Go = c.int16
1138+ case 4 + signedDelta:
1139+ t.Go = c.int32
1140+ case 8 + signedDelta:
1141+ t.Go = c.int64
1142+ }
1143+
1144+ case *dwarf.FloatType:
1145+ switch t.Size {
1146+ default:
1147+ fatalf("%s: unexpected: %d-byte float type - %s", lineno(pos), t.Size, dtype)
1148+ case 4:
1149+ t.Go = c.float32
1150+ case 8:
1151+ t.Go = c.float64
1152+ }
1153+ if t.Align = t.Size; t.Align >= c.ptrSize {
1154+ t.Align = c.ptrSize
1155+ }
1156+
1157+ case *dwarf.ComplexType:
1158+ switch t.Size {
1159+ default:
1160+ fatalf("%s: unexpected: %d-byte complex type - %s", lineno(pos), t.Size, dtype)
1161+ case 8:
1162+ t.Go = c.complex64
1163+ case 16:
1164+ t.Go = c.complex128
1165+ }
1166+ if t.Align = t.Size; t.Align >= c.ptrSize {
1167+ t.Align = c.ptrSize
1168+ }
1169+
1170+ case *dwarf.FuncType:
1171+ // No attempt at translation: would enable calls
1172+ // directly between worlds, but we need to moderate those.
1173+ t.Go = c.uintptr
1174+ t.Align = c.ptrSize
1175+
1176+ case *dwarf.IntType:
1177+ if dt.BitSize > 0 {
1178+ fatalf("%s: unexpected: %d-bit int type - %s", lineno(pos), dt.BitSize, dtype)
1179+ }
1180+ switch t.Size {
1181+ default:
1182+ fatalf("%s: unexpected: %d-byte int type - %s", lineno(pos), t.Size, dtype)
1183+ case 1:
1184+ t.Go = c.int8
1185+ case 2:
1186+ t.Go = c.int16
1187+ case 4:
1188+ t.Go = c.int32
1189+ case 8:
1190+ t.Go = c.int64
1191+ }
1192+ if t.Align = t.Size; t.Align >= c.ptrSize {
1193+ t.Align = c.ptrSize
1194+ }
1195+
1196+ case *dwarf.PtrType:
1197+ t.Align = c.ptrSize
1198+
1199+ // Translate void* as unsafe.Pointer
1200+ if _, ok := base(dt.Type).(*dwarf.VoidType); ok {
1201+ t.Go = c.unsafePointer
1202+ t.C.Set("void*")
1203+ break
1204+ }
1205+
1206+ gt := &ast.StarExpr{}
1207+ t.Go = gt // publish before recursive call
1208+ sub := c.Type(dt.Type, pos)
1209+ gt.X = sub.Go
1210+ t.C.Set("%s*", sub.C)
1211+
1212+ case *dwarf.QualType:
1213+ // Ignore qualifier.
1214+ t = c.Type(dt.Type, pos)
1215+ c.m[dtype] = t
1216+ return t
1217+
1218+ case *dwarf.StructType:
1219+ if dt.ByteSize < 0 { // opaque struct
1220+ break
1221+ }
1222+ // Convert to Go struct, being careful about alignment.
1223+ // Have to give it a name to simulate C "struct foo" references.
1224+ tag := dt.StructName
1225+ if tag == "" {
1226+ tag = "__" + strconv.Itoa(tagGen)
1227+ tagGen++
1228+ } else if t.C.Empty() {
1229+ t.C.Set(dt.Kind + " " + tag)
1230+ }
1231+ name := c.Ident("_Ctype_" + dt.Kind + "_" + tag)
1232+ t.Go = name // publish before recursive calls
1233+ goIdent[name.Name] = name
1234+ switch dt.Kind {
1235+ case "class", "union":
1236+ t.Go = c.Opaque(t.Size)
1237+ if t.C.Empty() {
1238+ t.C.Set("__typeof__(unsigned char[%d])", t.Size)
1239+ }
1240+ t.Align = 1 // TODO: should probably base this on field alignment.
1241+ typedef[name.Name] = t
1242+ case "struct":
1243+ g, csyntax, align := c.Struct(dt, pos)
1244+ if t.C.Empty() {
1245+ t.C.Set(csyntax)
1246+ }
1247+ t.Align = align
1248+ tt := *t
1249+ if tag != "" {
1250+ tt.C = &TypeRepr{"struct %s", []interface{}{tag}}
1251+ }
1252+ tt.Go = g
1253+ typedef[name.Name] = &tt
1254+ }
1255+
1256+ case *dwarf.TypedefType:
1257+ // Record typedef for printing.
1258+ if dt.Name == "_GoString_" {
1259+ // Special C name for Go string type.
1260+ // Knows string layout used by compilers: pointer plus length,
1261+ // which rounds up to 2 pointers after alignment.
1262+ t.Go = c.string
1263+ t.Size = c.ptrSize * 2
1264+ t.Align = c.ptrSize
1265+ break
1266+ }
1267+ if dt.Name == "_GoBytes_" {
1268+ // Special C name for Go []byte type.
1269+ // Knows slice layout used by compilers: pointer, length, cap.
1270+ t.Go = c.Ident("[]byte")
1271+ t.Size = c.ptrSize + 4 + 4
1272+ t.Align = c.ptrSize
1273+ break
1274+ }
1275+ name := c.Ident("_Ctype_" + dt.Name)
1276+ goIdent[name.Name] = name
1277+ t.Go = name // publish before recursive call
1278+ sub := c.Type(dt.Type, pos)
1279+ t.Size = sub.Size
1280+ t.Align = sub.Align
1281+ if _, ok := typedef[name.Name]; !ok {
1282+ tt := *t
1283+ tt.Go = sub.Go
1284+ typedef[name.Name] = &tt
1285+ }
1286+ if *godefs || *cdefs {
1287+ t.Go = sub.Go
1288+ }
1289+
1290+ case *dwarf.UcharType:
1291+ if t.Size != 1 {
1292+ fatalf("%s: unexpected: %d-byte uchar type - %s", lineno(pos), t.Size, dtype)
1293+ }
1294+ t.Go = c.uint8
1295+ t.Align = 1
1296+
1297+ case *dwarf.UintType:
1298+ if dt.BitSize > 0 {
1299+ fatalf("%s: unexpected: %d-bit uint type - %s", lineno(pos), dt.BitSize, dtype)
1300+ }
1301+ switch t.Size {
1302+ default:
1303+ fatalf("%s: unexpected: %d-byte uint type - %s", lineno(pos), t.Size, dtype)
1304+ case 1:
1305+ t.Go = c.uint8
1306+ case 2:
1307+ t.Go = c.uint16
1308+ case 4:
1309+ t.Go = c.uint32
1310+ case 8:
1311+ t.Go = c.uint64
1312+ }
1313+ if t.Align = t.Size; t.Align >= c.ptrSize {
1314+ t.Align = c.ptrSize
1315+ }
1316+
1317+ case *dwarf.VoidType:
1318+ t.Go = c.goVoid
1319+ t.C.Set("void")
1320+ t.Align = 1
1321+ }
1322+
1323+ switch dtype.(type) {
1324+ case *dwarf.AddrType, *dwarf.BoolType, *dwarf.CharType, *dwarf.IntType, *dwarf.FloatType, *dwarf.UcharType, *dwarf.UintType:
1325+ s := dtype.Common().Name
1326+ if s != "" {
1327+ if ss, ok := dwarfToName[s]; ok {
1328+ s = ss
1329+ }
1330+ s = strings.Join(strings.Split(s, " "), "") // strip spaces
1331+ name := c.Ident("_Ctype_" + s)
1332+ tt := *t
1333+ typedef[name.Name] = &tt
1334+ if !*godefs && !*cdefs {
1335+ t.Go = name
1336+ }
1337+ }
1338+ }
1339+
1340+ if t.Size <= 0 {
1341+ // Clang does not record the size of a pointer in its DWARF entry,
1342+ // so if dtype is an array, the call to dtype.Size at the top of the function
1343+ // computed the size as the array length * 0 = 0.
1344+ // The type switch called Type (this function) recursively on the pointer
1345+ // entry, and the code near the top of the function updated the size to
1346+ // be correct, so calling dtype.Size again will produce the correct value.
1347+ t.Size = dtype.Size()
1348+ if t.Size < 0 {
1349+ // Unsized types are [0]byte
1350+ t.Size = 0
1351+ t.Go = c.Opaque(0)
1352+ if t.C.Empty() {
1353+ t.C.Set("void")
1354+ }
1355+ return t
1356+ }
1357+ }
1358+
1359+ if t.C.Empty() {
1360+ fatalf("%s: internal error: did not create C name for %s", lineno(pos), dtype)
1361+ }
1362+
1363+ return t
1364+}
1365+
1366+// FuncArg returns a Go type with the same memory layout as
1367+// dtype when used as the type of a C function argument.
1368+func (c *typeConv) FuncArg(dtype dwarf.Type, pos token.Pos) *Type {
1369+ t := c.Type(dtype, pos)
1370+ switch dt := dtype.(type) {
1371+ case *dwarf.ArrayType:
1372+ // Arrays are passed implicitly as pointers in C.
1373+ // In Go, we must be explicit.
1374+ tr := &TypeRepr{}
1375+ tr.Set("%s*", t.C)
1376+ return &Type{
1377+ Size: c.ptrSize,
1378+ Align: c.ptrSize,
1379+ Go: &ast.StarExpr{X: t.Go},
1380+ C: tr,
1381+ }
1382+ case *dwarf.TypedefType:
1383+ // C has much more relaxed rules than Go for
1384+ // implicit type conversions. When the parameter
1385+ // is type T defined as *X, simulate a little of the
1386+ // laxness of C by making the argument *X instead of T.
1387+ if ptr, ok := base(dt.Type).(*dwarf.PtrType); ok {
1388+ // Unless the typedef happens to point to void* since
1389+ // Go has special rules around using unsafe.Pointer.
1390+ if _, void := base(ptr.Type).(*dwarf.VoidType); void {
1391+ break
1392+ }
1393+
1394+ t = c.Type(ptr, pos)
1395+ if t == nil {
1396+ return nil
1397+ }
1398+
1399+ // Remember the C spelling, in case the struct
1400+ // has __attribute__((unavailable)) on it. See issue 2888.
1401+ t.Typedef = dt.Name
1402+ }
1403+ }
1404+ return t
1405+}
1406+
1407+// FuncType returns the Go type analogous to dtype.
1408+// There is no guarantee about matching memory layout.
1409+func (c *typeConv) FuncType(dtype *dwarf.FuncType, pos token.Pos) *FuncType {
1410+ p := make([]*Type, len(dtype.ParamType))
1411+ gp := make([]*ast.Field, len(dtype.ParamType))
1412+ for i, f := range dtype.ParamType {
1413+ // gcc's DWARF generator outputs a single DotDotDotType parameter for
1414+ // function pointers that specify no parameters (e.g. void
1415+ // (*__cgo_0)()). Treat this special case as void. This case is
1416+ // invalid according to ISO C anyway (i.e. void (*__cgo_1)(...) is not
1417+ // legal).
1418+ if _, ok := f.(*dwarf.DotDotDotType); ok && i == 0 {
1419+ p, gp = nil, nil
1420+ break
1421+ }
1422+ p[i] = c.FuncArg(f, pos)
1423+ gp[i] = &ast.Field{Type: p[i].Go}
1424+ }
1425+ var r *Type
1426+ var gr []*ast.Field
1427+ if _, ok := dtype.ReturnType.(*dwarf.VoidType); ok {
1428+ gr = []*ast.Field{{Type: c.goVoid}}
1429+ } else if dtype.ReturnType != nil {
1430+ r = c.Type(dtype.ReturnType, pos)
1431+ gr = []*ast.Field{{Type: r.Go}}
1432+ }
1433+ return &FuncType{
1434+ Params: p,
1435+ Result: r,
1436+ Go: &ast.FuncType{
1437+ Params: &ast.FieldList{List: gp},
1438+ Results: &ast.FieldList{List: gr},
1439+ },
1440+ }
1441+}
1442+
1443+// Identifier
1444+func (c *typeConv) Ident(s string) *ast.Ident {
1445+ return ast.NewIdent(s)
1446+}
1447+
1448+// Opaque type of n bytes.
1449+func (c *typeConv) Opaque(n int64) ast.Expr {
1450+ return &ast.ArrayType{
1451+ Len: c.intExpr(n),
1452+ Elt: c.byte,
1453+ }
1454+}
1455+
1456+// Expr for integer n.
1457+func (c *typeConv) intExpr(n int64) ast.Expr {
1458+ return &ast.BasicLit{
1459+ Kind: token.INT,
1460+ Value: strconv.FormatInt(n, 10),
1461+ }
1462+}
1463+
1464+// Add padding of given size to fld.
1465+func (c *typeConv) pad(fld []*ast.Field, size int64) []*ast.Field {
1466+ n := len(fld)
1467+ fld = fld[0 : n+1]
1468+ fld[n] = &ast.Field{Names: []*ast.Ident{c.Ident("_")}, Type: c.Opaque(size)}
1469+ return fld
1470+}
1471+
1472+// Struct conversion: return Go and (6g) C syntax for type.
1473+func (c *typeConv) Struct(dt *dwarf.StructType, pos token.Pos) (expr *ast.StructType, csyntax string, align int64) {
1474+ var buf bytes.Buffer
1475+ buf.WriteString("struct {")
1476+ fld := make([]*ast.Field, 0, 2*len(dt.Field)+1) // enough for padding around every field
1477+ off := int64(0)
1478+
1479+ // Rename struct fields that happen to be named Go keywords into
1480+ // _{keyword}. Create a map from C ident -> Go ident. The Go ident will
1481+ // be mangled. Any existing identifier that already has the same name on
1482+ // the C-side will cause the Go-mangled version to be prefixed with _.
1483+ // (e.g. in a struct with fields '_type' and 'type', the latter would be
1484+ // rendered as '__type' in Go).
1485+ ident := make(map[string]string)
1486+ used := make(map[string]bool)
1487+ for _, f := range dt.Field {
1488+ ident[f.Name] = f.Name
1489+ used[f.Name] = true
1490+ }
1491+
1492+ if !*godefs && !*cdefs {
1493+ for cid, goid := range ident {
1494+ if token.Lookup(goid).IsKeyword() {
1495+ // Avoid keyword
1496+ goid = "_" + goid
1497+
1498+ // Also avoid existing fields
1499+ for _, exist := used[goid]; exist; _, exist = used[goid] {
1500+ goid = "_" + goid
1501+ }
1502+
1503+ used[goid] = true
1504+ ident[cid] = goid
1505+ }
1506+ }
1507+ }
1508+
1509+ anon := 0
1510+ for _, f := range dt.Field {
1511+ if f.ByteOffset > off {
1512+ fld = c.pad(fld, f.ByteOffset-off)
1513+ off = f.ByteOffset
1514+ }
1515+ t := c.Type(f.Type, pos)
1516+ tgo := t.Go
1517+ size := t.Size
1518+
1519+ if f.BitSize > 0 {
1520+ if f.BitSize%8 != 0 {
1521+ continue
1522+ }
1523+ size = f.BitSize / 8
1524+ name := tgo.(*ast.Ident).String()
1525+ if strings.HasPrefix(name, "int") {
1526+ name = "int"
1527+ } else {
1528+ name = "uint"
1529+ }
1530+ tgo = ast.NewIdent(name + fmt.Sprint(f.BitSize))
1531+ }
1532+
1533+ n := len(fld)
1534+ fld = fld[0 : n+1]
1535+ name := f.Name
1536+ if name == "" {
1537+ name = fmt.Sprintf("anon%d", anon)
1538+ anon++
1539+ ident[name] = name
1540+ }
1541+ fld[n] = &ast.Field{Names: []*ast.Ident{c.Ident(ident[name])}, Type: tgo}
1542+ off += size
1543+ buf.WriteString(t.C.String())
1544+ buf.WriteString(" ")
1545+ buf.WriteString(name)
1546+ buf.WriteString("; ")
1547+ if t.Align > align {
1548+ align = t.Align
1549+ }
1550+ }
1551+ if off < dt.ByteSize {
1552+ fld = c.pad(fld, dt.ByteSize-off)
1553+ off = dt.ByteSize
1554+ }
1555+ if off != dt.ByteSize {
1556+ fatalf("%s: struct size calculation error off=%d bytesize=%d", lineno(pos), off, dt.ByteSize)
1557+ }
1558+ buf.WriteString("}")
1559+ csyntax = buf.String()
1560+
1561+ if *godefs || *cdefs {
1562+ godefsFields(fld)
1563+ }
1564+ expr = &ast.StructType{Fields: &ast.FieldList{List: fld}}
1565+ return
1566+}
1567+
1568+func upper(s string) string {
1569+ if s == "" {
1570+ return ""
1571+ }
1572+ r, size := utf8.DecodeRuneInString(s)
1573+ if r == '_' {
1574+ return "X" + s
1575+ }
1576+ return string(unicode.ToUpper(r)) + s[size:]
1577+}
1578+
1579+// godefsFields rewrites field names for use in Go or C definitions.
1580+// It strips leading common prefixes (like tv_ in tv_sec, tv_usec)
1581+// converts names to upper case, and rewrites _ into Pad_godefs_n,
1582+// so that all fields are exported.
1583+func godefsFields(fld []*ast.Field) {
1584+ prefix := fieldPrefix(fld)
1585+ npad := 0
1586+ for _, f := range fld {
1587+ for _, n := range f.Names {
1588+ if n.Name != prefix {
1589+ n.Name = strings.TrimPrefix(n.Name, prefix)
1590+ }
1591+ if n.Name == "_" {
1592+ // Use exported name instead.
1593+ n.Name = "Pad_cgo_" + strconv.Itoa(npad)
1594+ npad++
1595+ }
1596+ if !*cdefs {
1597+ n.Name = upper(n.Name)
1598+ }
1599+ }
1600+ p := &f.Type
1601+ t := *p
1602+ if star, ok := t.(*ast.StarExpr); ok {
1603+ star = &ast.StarExpr{X: star.X}
1604+ *p = star
1605+ p = &star.X
1606+ t = *p
1607+ }
1608+ if id, ok := t.(*ast.Ident); ok {
1609+ if id.Name == "unsafe.Pointer" {
1610+ *p = ast.NewIdent("*byte")
1611+ }
1612+ }
1613+ }
1614+}
1615+
1616+// fieldPrefix returns the prefix that should be removed from all the
1617+// field names when generating the C or Go code. For generated
1618+// C, we leave the names as is (tv_sec, tv_usec), since that's what
1619+// people are used to seeing in C. For generated Go code, such as
1620+// package syscall's data structures, we drop a common prefix
1621+// (so sec, usec, which will get turned into Sec, Usec for exporting).
1622+func fieldPrefix(fld []*ast.Field) string {
1623+ if *cdefs {
1624+ return ""
1625+ }
1626+ prefix := ""
1627+ for _, f := range fld {
1628+ for _, n := range f.Names {
1629+ // Ignore field names that don't have the prefix we're
1630+ // looking for. It is common in C headers to have fields
1631+ // named, say, _pad in an otherwise prefixed header.
1632+ // If the struct has 3 fields tv_sec, tv_usec, _pad1, then we
1633+ // still want to remove the tv_ prefix.
1634+ // The check for "orig_" here handles orig_eax in the
1635+ // x86 ptrace register sets, which otherwise have all fields
1636+ // with reg_ prefixes.
1637+ if strings.HasPrefix(n.Name, "orig_") || strings.HasPrefix(n.Name, "_") {
1638+ continue
1639+ }
1640+ i := strings.Index(n.Name, "_")
1641+ if i < 0 {
1642+ continue
1643+ }
1644+ if prefix == "" {
1645+ prefix = n.Name[:i+1]
1646+ } else if prefix != n.Name[:i+1] {
1647+ return ""
1648+ }
1649+ }
1650+ }
1651+ return prefix
1652+}
1653
1654=== added directory '.pc/build-cgo.diff/src/cmd/go'
1655=== added file '.pc/build-cgo.diff/src/cmd/go/tool.go'
1656--- .pc/build-cgo.diff/src/cmd/go/tool.go 1970-01-01 00:00:00 +0000
1657+++ .pc/build-cgo.diff/src/cmd/go/tool.go 2014-08-14 02:29:21 +0000
1658@@ -0,0 +1,156 @@
1659+// Copyright 2011 The Go Authors. All rights reserved.
1660+// Use of this source code is governed by a BSD-style
1661+// license that can be found in the LICENSE file.
1662+
1663+package main
1664+
1665+import (
1666+ "fmt"
1667+ "go/build"
1668+ "os"
1669+ "os/exec"
1670+ "path/filepath"
1671+ "runtime"
1672+ "sort"
1673+ "strings"
1674+)
1675+
1676+var cmdTool = &Command{
1677+ Run: runTool,
1678+ UsageLine: "tool [-n] command [args...]",
1679+ Short: "run specified go tool",
1680+ Long: `
1681+Tool runs the go tool command identified by the arguments.
1682+With no arguments it prints the list of known tools.
1683+
1684+The -n flag causes tool to print the command that would be
1685+executed but not execute it.
1686+
1687+For more about each tool command, see 'go tool command -h'.
1688+`,
1689+}
1690+
1691+var (
1692+ toolGOOS = runtime.GOOS
1693+ toolGOARCH = runtime.GOARCH
1694+ toolIsWindows = toolGOOS == "windows"
1695+ toolDir = build.ToolDir
1696+
1697+ toolN bool
1698+)
1699+
1700+func init() {
1701+ cmdTool.Flag.BoolVar(&toolN, "n", false, "")
1702+}
1703+
1704+const toolWindowsExtension = ".exe"
1705+
1706+func tool(toolName string) string {
1707+ toolPath := filepath.Join(toolDir, toolName)
1708+ if toolIsWindows && toolName != "pprof" {
1709+ toolPath += toolWindowsExtension
1710+ }
1711+ // Give a nice message if there is no tool with that name.
1712+ if _, err := os.Stat(toolPath); err != nil {
1713+ if isInGoToolsRepo(toolName) {
1714+ fmt.Fprintf(os.Stderr, "go tool: no such tool %q; to install:\n\tgo get code.google.com/p/go.tools/cmd/%s\n", toolName, toolName)
1715+ } else {
1716+ fmt.Fprintf(os.Stderr, "go tool: no such tool %q\n", toolName)
1717+ }
1718+ setExitStatus(3)
1719+ exit()
1720+ }
1721+ return toolPath
1722+}
1723+
1724+func isInGoToolsRepo(toolName string) bool {
1725+ switch toolName {
1726+ case "cover", "vet":
1727+ return true
1728+ }
1729+ return false
1730+}
1731+
1732+func runTool(cmd *Command, args []string) {
1733+ if len(args) == 0 {
1734+ listTools()
1735+ return
1736+ }
1737+ toolName := args[0]
1738+ // The tool name must be lower-case letters, numbers or underscores.
1739+ for _, c := range toolName {
1740+ switch {
1741+ case 'a' <= c && c <= 'z', '0' <= c && c <= '9', c == '_':
1742+ default:
1743+ fmt.Fprintf(os.Stderr, "go tool: bad tool name %q\n", toolName)
1744+ setExitStatus(2)
1745+ return
1746+ }
1747+ }
1748+ toolPath := tool(toolName)
1749+ if toolPath == "" {
1750+ return
1751+ }
1752+ if toolIsWindows && toolName == "pprof" {
1753+ args = append([]string{"perl", toolPath}, args[1:]...)
1754+ var err error
1755+ toolPath, err = exec.LookPath("perl")
1756+ if err != nil {
1757+ fmt.Fprintf(os.Stderr, "go tool: perl not found\n")
1758+ setExitStatus(3)
1759+ return
1760+ }
1761+ }
1762+ if toolN {
1763+ fmt.Printf("%s %s\n", toolPath, strings.Join(args[1:], " "))
1764+ return
1765+ }
1766+ toolCmd := &exec.Cmd{
1767+ Path: toolPath,
1768+ Args: args,
1769+ Stdin: os.Stdin,
1770+ Stdout: os.Stdout,
1771+ Stderr: os.Stderr,
1772+ }
1773+ err := toolCmd.Run()
1774+ if err != nil {
1775+ // Only print about the exit status if the command
1776+ // didn't even run (not an ExitError) or it didn't exit cleanly
1777+ // or we're printing command lines too (-x mode).
1778+ // Assume if command exited cleanly (even with non-zero status)
1779+ // it printed any messages it wanted to print.
1780+ if e, ok := err.(*exec.ExitError); !ok || !e.Exited() || buildX {
1781+ fmt.Fprintf(os.Stderr, "go tool %s: %s\n", toolName, err)
1782+ }
1783+ setExitStatus(1)
1784+ return
1785+ }
1786+}
1787+
1788+// listTools prints a list of the available tools in the tools directory.
1789+func listTools() {
1790+ f, err := os.Open(toolDir)
1791+ if err != nil {
1792+ fmt.Fprintf(os.Stderr, "go tool: no tool directory: %s\n", err)
1793+ setExitStatus(2)
1794+ return
1795+ }
1796+ defer f.Close()
1797+ names, err := f.Readdirnames(-1)
1798+ if err != nil {
1799+ fmt.Fprintf(os.Stderr, "go tool: can't read directory: %s\n", err)
1800+ setExitStatus(2)
1801+ return
1802+ }
1803+
1804+ sort.Strings(names)
1805+ for _, name := range names {
1806+ // Unify presentation by going to lower case.
1807+ name = strings.ToLower(name)
1808+ // If it's windows, don't show the .exe suffix.
1809+ if toolIsWindows && strings.HasSuffix(name, toolWindowsExtension) {
1810+ name = name[:len(name)-len(toolWindowsExtension)]
1811+ }
1812+ fmt.Println(name)
1813+ }
1814+}
1815
1816=== modified file 'debian/changelog'
1817--- debian/changelog 2014-03-26 10:50:18 +0000
1818+++ debian/changelog 2014-08-14 02:29:21 +0000
1819@@ -1,3 +1,9 @@
1820+gccgo-go (1.2.1-0ubuntu2) UNRELEASED; urgency=medium
1821+
1822+ * Build and install cgo too.
1823+
1824+ -- Michael Hudson-Doyle <michael.hudson@linaro.org> Thu, 14 Aug 2014 14:01:51 +1200
1825+
1826 gccgo-go (1.2.1-0ubuntu1) trusty; urgency=medium
1827
1828 * New upstream point release.
1829
1830=== modified file 'debian/install'
1831--- debian/install 2014-01-28 12:32:46 +0000
1832+++ debian/install 2014-08-14 02:29:21 +0000
1833@@ -1,1 +1,2 @@
1834 src/cmd/go/gccgo-go /usr/bin
1835+src/cmd/cgo/cgo /usr/lib/gccgo/tool
1836\ No newline at end of file
1837
1838=== modified file 'debian/lintian-overrides'
1839--- debian/lintian-overrides 2014-01-27 09:18:55 +0000
1840+++ debian/lintian-overrides 2014-08-14 02:29:21 +0000
1841@@ -1,2 +1,3 @@
1842 # go binaries should never be stripped
1843 gccgo-go: unstripped-binary-or-object usr/bin/gccgo-go
1844+gccgo-go: unstripped-binary-or-object usr/lib/gccgo/tool/cgo
1845
1846=== added file 'debian/patches/build-cgo.diff'
1847--- debian/patches/build-cgo.diff 1970-01-01 00:00:00 +0000
1848+++ debian/patches/build-cgo.diff 2014-08-14 02:29:21 +0000
1849@@ -0,0 +1,49 @@
1850+=== added file 'src/cmd/cgo/Makefile'
1851+Index: gccgo-go/src/cmd/cgo/Makefile
1852+===================================================================
1853+--- /dev/null 1970-01-01 00:00:00.000000000 +0000
1854++++ gccgo-go/src/cmd/cgo/Makefile 2014-08-14 14:13:14.620783230 +1200
1855+@@ -0,0 +1,16 @@
1856++TARG=cgo
1857++GOFILES=\
1858++ ast.go\
1859++ doc.go\
1860++ gcc.go\
1861++ godefs.go\
1862++ main.go\
1863++ out.go\
1864++ util.go
1865++
1866++build:
1867++ gccgo -o _$(TARG)_ -c $(GOFLAGS) $(GOFILES)
1868++ gccgo -o $(TARG) _$(TARG)_ $(LDFLAGS)
1869++
1870++clean:
1871++ rm -f _$(TARG)_ $(TARG)
1872+Index: gccgo-go/src/cmd/go/tool.go
1873+===================================================================
1874+--- gccgo-go.orig/src/cmd/go/tool.go 2014-08-14 14:11:25.772787121 +1200
1875++++ gccgo-go/src/cmd/go/tool.go 2014-08-14 14:20:57.504766684 +1200
1876+@@ -41,6 +41,9 @@
1877+
1878+ func init() {
1879+ cmdTool.Flag.BoolVar(&toolN, "n", false, "")
1880++ if (runtime.Compiler == "gccgo") {
1881++ toolDir = filepath.Join(runtime.GOROOT(), "lib/gccgo/tool")
1882++ }
1883+ }
1884+
1885+ const toolWindowsExtension = ".exe"
1886+Index: gccgo-go/src/cmd/cgo/gcc.go
1887+===================================================================
1888+--- gccgo-go.orig/src/cmd/cgo/gcc.go 2014-08-12 15:34:03.612461000 +1200
1889++++ gccgo-go/src/cmd/cgo/gcc.go 2014-08-14 14:14:30.380780522 +1200
1890+@@ -718,7 +718,7 @@
1891+ if ret := strings.Fields(os.Getenv("GCC")); len(ret) > 0 {
1892+ return ret
1893+ }
1894+- return strings.Fields(defaultCC)
1895++ return strings.Fields("gcc")
1896+ }
1897+
1898+ // gccMachine returns the gcc -m flag to use, either "-m32", "-m64" or "-marm".
1899
1900=== modified file 'debian/patches/series'
1901--- debian/patches/series 2014-03-26 10:50:18 +0000
1902+++ debian/patches/series 2014-08-14 02:29:21 +0000
1903@@ -5,3 +5,4 @@
1904 issue28050043_60001_70001.diff
1905 issue61970044_80001.diff
1906 issue80300043_60001.diff
1907+build-cgo.diff
1908
1909=== modified file 'debian/rules'
1910--- debian/rules 2014-02-15 22:18:45 +0000
1911+++ debian/rules 2014-08-14 02:29:21 +0000
1912@@ -10,6 +10,7 @@
1913
1914 override_dh_auto_clean:
1915 dh_auto_clean -D src/cmd/go
1916+ dh_auto_clean -D src/cmd/cgo
1917
1918 override_dh_strip:
1919 # strip disabled as golang upstream doesn't support it and it makes go
1920@@ -20,3 +21,4 @@
1921
1922 override_dh_auto_build:
1923 dh_auto_build -D src/cmd/go
1924+ dh_auto_build -D src/cmd/cgo
1925
1926=== added file 'src/cmd/cgo/Makefile'
1927--- src/cmd/cgo/Makefile 1970-01-01 00:00:00 +0000
1928+++ src/cmd/cgo/Makefile 2014-08-14 02:29:21 +0000
1929@@ -0,0 +1,16 @@
1930+TARG=cgo
1931+GOFILES=\
1932+ ast.go\
1933+ doc.go\
1934+ gcc.go\
1935+ godefs.go\
1936+ main.go\
1937+ out.go\
1938+ util.go
1939+
1940+build:
1941+ gccgo -o _$(TARG)_ -c $(GOFLAGS) $(GOFILES)
1942+ gccgo -o $(TARG) _$(TARG)_ $(LDFLAGS)
1943+
1944+clean:
1945+ rm -f _$(TARG)_ $(TARG)
1946
1947=== modified file 'src/cmd/cgo/gcc.go'
1948--- src/cmd/cgo/gcc.go 2014-01-27 09:18:55 +0000
1949+++ src/cmd/cgo/gcc.go 2014-08-14 02:29:21 +0000
1950@@ -718,7 +718,7 @@
1951 if ret := strings.Fields(os.Getenv("GCC")); len(ret) > 0 {
1952 return ret
1953 }
1954- return strings.Fields(defaultCC)
1955+ return strings.Fields("gcc")
1956 }
1957
1958 // gccMachine returns the gcc -m flag to use, either "-m32", "-m64" or "-marm".
1959
1960=== modified file 'src/cmd/go/tool.go'
1961--- src/cmd/go/tool.go 2014-01-27 09:18:55 +0000
1962+++ src/cmd/go/tool.go 2014-08-14 02:29:21 +0000
1963@@ -41,6 +41,9 @@
1964
1965 func init() {
1966 cmdTool.Flag.BoolVar(&toolN, "n", false, "")
1967+ if (runtime.Compiler == "gccgo") {
1968+ toolDir = filepath.Join(runtime.GOROOT(), "lib/gccgo/tool")
1969+ }
1970 }
1971
1972 const toolWindowsExtension = ".exe"

Subscribers

People subscribed via source and target branches