]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/link, cmd/go: delay linking of mingwex and mingw32 until very end
authorAlex Brainman <alex.brainman@gmail.com>
Wed, 10 Aug 2016 01:06:46 +0000 (11:06 +1000)
committerAlex Brainman <alex.brainman@gmail.com>
Wed, 31 Aug 2016 06:30:26 +0000 (06:30 +0000)
cmd/go links mingwex and mingw32 libraries to every package it builds.
This breaks when 2 different packages call same gcc standard library
function pow. gcc linker appends pow implementation to the compiled
package, and names that function "pow". But when these 2 compiled
packages are linked together into the final executable, linker
complains, because it finds two "pow" functions with the same name.

This CL stops linking of mingwex and mingw32 during package build -
that leaves pow function reference unresolved. pow reference gets
resolved as final executable is built, by having both internal and
external linker use mingwex and mingw32 libraries.

Fixes #8756

Change-Id: I50ddc79529ea5463c67118d668488345ecf069bc
Reviewed-on: https://go-review.googlesource.com/26670
Run-TryBot: Alex Brainman <alex.brainman@gmail.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
misc/cgo/test/cgo_test.go
misc/cgo/test/issue8756.go [new file with mode: 0644]
misc/cgo/test/issue8756/issue8756.go [new file with mode: 0644]
src/cmd/go/build.go
src/cmd/link/internal/ld/lib.go

index 8a95b02ac35fc93c7d4ac4b48d321d267b3673c4..64407472089b3d7a49c0e837b9f4b718de413d2d 100644 (file)
@@ -70,5 +70,6 @@ func Test12030(t *testing.T)                 { test12030(t) }
 func TestGCC68255(t *testing.T)              { testGCC68255(t) }
 func TestCallGoWithString(t *testing.T)      { testCallGoWithString(t) }
 func Test14838(t *testing.T)                 { test14838(t) }
+func Test8756(t *testing.T)                  { test8756(t) }
 
 func BenchmarkCgoCall(b *testing.B) { benchCgoCall(b) }
diff --git a/misc/cgo/test/issue8756.go b/misc/cgo/test/issue8756.go
new file mode 100644 (file)
index 0000000..d8ee3b8
--- /dev/null
@@ -0,0 +1,17 @@
+package cgotest
+
+/*
+#cgo LDFLAGS: -lm
+#include <math.h>
+*/
+import "C"
+import (
+       "testing"
+
+       "./issue8756"
+)
+
+func test8756(t *testing.T) {
+       issue8756.Pow()
+       C.pow(1, 2)
+}
diff --git a/misc/cgo/test/issue8756/issue8756.go b/misc/cgo/test/issue8756/issue8756.go
new file mode 100644 (file)
index 0000000..5f6b777
--- /dev/null
@@ -0,0 +1,11 @@
+package issue8756
+
+/*
+#cgo LDFLAGS: -lm
+#include <math.h>
+*/
+import "C"
+
+func Pow() {
+       C.pow(1, 2)
+}
index 6e7f54d99697fd1c5331ea56cbb4cb7085bbe5b6..3d0326b967760bccbf5896402089d5cadefa7fcd 100644 (file)
@@ -3268,7 +3268,6 @@ func (b *builder) cgo(p *Package, cgoExe, obj string, pcCFLAGS, pcLDFLAGS, cgofi
        outGo = append(outGo, gofiles...)
 
        // gcc
-
        cflags := stringList(cgoCPPFLAGS, cgoCFLAGS)
        for _, cfile := range cfiles {
                ofile := obj + cfile[:len(cfile)-1] + "o"
@@ -3421,12 +3420,6 @@ func (b *builder) collect(p *Package, obj, ofile string, cgoLDFLAGS, outObj []st
 
        ldflags = append(ldflags, "-Wl,-r", "-nostdlib")
 
-       if goos == "windows" {
-               // libmingw32 and libmingwex have some inter-dependencies,
-               // so must use linker groups.
-               ldflags = append(ldflags, "-Wl,--start-group", "-lmingwex", "-lmingw32", "-Wl,--end-group")
-       }
-
        if b.gccSupportsNoPie() {
                ldflags = append(ldflags, "-no-pie")
        }
index 9f906080e9b9118175d5e06b8e257104dec08554..0df49a7271e862e3061e9d45789cf3fba824c700 100644 (file)
@@ -372,6 +372,33 @@ func loadinternal(ctxt *Link, name string) {
        }
 }
 
+// findLibPathCmd uses cmd command to find gcc library libname.
+// It returns library full path if found, or "none" if not found.
+func (ctxt *Link) findLibPathCmd(cmd, libname string) string {
+       if *flagExtld == "" {
+               *flagExtld = "gcc"
+       }
+       args := hostlinkArchArgs()
+       args = append(args, cmd)
+       if ctxt.Debugvlog != 0 {
+               ctxt.Logf("%s %v\n", *flagExtld, args)
+       }
+       out, err := exec.Command(*flagExtld, args...).Output()
+       if err != nil {
+               if ctxt.Debugvlog != 0 {
+                       ctxt.Logf("not using a %s file because compiler failed\n%v\n%s\n", libname, err, out)
+               }
+               return "none"
+       }
+       return strings.TrimSpace(string(out))
+}
+
+// findLibPath searches for library libname.
+// It returns library full path if found, or "none" if not found.
+func (ctxt *Link) findLibPath(libname string) string {
+       return ctxt.findLibPathCmd("--print-file-name="+libname, libname)
+}
+
 func (ctxt *Link) loadlib() {
        switch Buildmode {
        case BuildmodeCShared:
@@ -573,28 +600,27 @@ func (ctxt *Link) loadlib() {
                }
                if any {
                        if *flagLibGCC == "" {
-                               if *flagExtld == "" {
-                                       *flagExtld = "gcc"
-                               }
-                               args := hostlinkArchArgs()
-                               args = append(args, "--print-libgcc-file-name")
-                               if ctxt.Debugvlog != 0 {
-                                       ctxt.Logf("%s %v\n", *flagExtld, args)
-                               }
-                               out, err := exec.Command(*flagExtld, args...).Output()
-                               if err != nil {
-                                       if ctxt.Debugvlog != 0 {
-                                               ctxt.Logf("not using a libgcc file because compiler failed\n%v\n%s\n", err, out)
-                                       }
-                                       *flagLibGCC = "none"
-                               } else {
-                                       *flagLibGCC = strings.TrimSpace(string(out))
-                               }
+                               *flagLibGCC = ctxt.findLibPathCmd("--print-libgcc-file-name", "libgcc")
                        }
-
                        if *flagLibGCC != "none" {
                                hostArchive(ctxt, *flagLibGCC)
                        }
+                       if HEADTYPE == obj.Hwindows {
+                               if p := ctxt.findLibPath("libmingwex.a"); p != "none" {
+                                       hostArchive(ctxt, p)
+                               }
+                               if p := ctxt.findLibPath("libmingw32.a"); p != "none" {
+                                       hostArchive(ctxt, p)
+                               }
+                               // TODO: maybe do something similar to peimporteddlls to collect all lib names
+                               // and try link them all to final exe just like libmingwex.a and libmingw32.a:
+                               /*
+                                       for:
+                                       #cgo windows LDFLAGS: -lmsvcrt -lm
+                                       import:
+                                       libmsvcrt.a libm.a
+                               */
+                       }
                }
        } else {
                hostlinksetup()
@@ -1145,6 +1171,9 @@ func (l *Link) hostlink() {
                }
        }
        if HEADTYPE == obj.Hwindows {
+               // libmingw32 and libmingwex have some inter-dependencies,
+               // so must use linker groups.
+               argv = append(argv, "-Wl,--start-group", "-lmingwex", "-lmingw32", "-Wl,--end-group")
                argv = append(argv, peimporteddlls()...)
        }