Commit dfbbe06a authored by Alex Brainman's avatar Alex Brainman

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: 's avatarIan Lance Taylor <iant@golang.org>
parent b040bc9c
......@@ -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) }
package cgotest
/*
#cgo LDFLAGS: -lm
#include <math.h>
*/
import "C"
import (
"testing"
"./issue8756"
)
func test8756(t *testing.T) {
issue8756.Pow()
C.pow(1, 2)
}
package issue8756
/*
#cgo LDFLAGS: -lm
#include <math.h>
*/
import "C"
func Pow() {
C.pow(1, 2)
}
......@@ -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")
}
......
......@@ -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()...)
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment