cmd/link, cmd/go: delay linking of mingwex and mingw32 until very end

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>
This commit is contained in:
Alex Brainman 2016-08-10 11:06:46 +10:00
parent b040bc9c06
commit dfbbe06a20
5 changed files with 76 additions and 25 deletions

View 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) }

View file

@ -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)
}

View file

@ -0,0 +1,11 @@
package issue8756
/*
#cgo LDFLAGS: -lm
#include <math.h>
*/
import "C"
func Pow() {
C.pow(1, 2)
}

View 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")
}

View 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()...)
}