mirror of
https://github.com/golang/go
synced 2024-11-23 13:30:08 -07:00
cmd/go: fix "#cgo pkg-config:" comments with gccgo
The unique difficulty of #cgo pkg-config is that the linker flags are recorded when the package is compiled but (obviously) must be used when the package is linked into an executable -- so the flags need to be stored on disk somewhere. As it happens cgo already writes out a _cgo_flags file: nothing uses it currently, but this change adds it to the lib$pkg.a file when compiling a package, reads it out when linking (and passes a version of the .a file with _cgo_flags stripped out of it to the linker). It's all fairly ugly but it works and I can't really think of any way of reducing the essential level of ugliness. Fixes #11739 Change-Id: I35621878014e1e107eda77a5b0b23d0240ec5750 Reviewed-on: https://go-review.googlesource.com/18790 Run-TryBot: Michael Hudson-Doyle <michael.hudson@canonical.com> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Ian Lance Taylor <iant@golang.org>
This commit is contained in:
parent
096c900f9e
commit
e5463f5055
@ -1424,6 +1424,9 @@ func (b *builder) build(a *action) (err error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
if _, ok := buildToolchain.(gccgoToolchain); ok {
|
||||||
|
cgoObjects = append(cgoObjects, filepath.Join(a.objdir, "_cgo_flags"))
|
||||||
|
}
|
||||||
cgoObjects = append(cgoObjects, outObj...)
|
cgoObjects = append(cgoObjects, outObj...)
|
||||||
gofiles = append(gofiles, outGo...)
|
gofiles = append(gofiles, outGo...)
|
||||||
}
|
}
|
||||||
@ -2610,12 +2613,73 @@ func (tools gccgoToolchain) ld(b *builder, root *action, out string, allactions
|
|||||||
objc := len(root.p.MFiles) > 0
|
objc := len(root.p.MFiles) > 0
|
||||||
fortran := len(root.p.FFiles) > 0
|
fortran := len(root.p.FFiles) > 0
|
||||||
|
|
||||||
|
readCgoFlags := func(flagsFile string) error {
|
||||||
|
flags, err := ioutil.ReadFile(flagsFile)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
const ldflagsPrefix = "_CGO_LDFLAGS="
|
||||||
|
for _, line := range strings.Split(string(flags), "\n") {
|
||||||
|
if strings.HasPrefix(line, ldflagsPrefix) {
|
||||||
|
newFlags := strings.Fields(line[len(ldflagsPrefix):])
|
||||||
|
for _, flag := range newFlags {
|
||||||
|
// Every _cgo_flags file has -g and -O2 in _CGO_LDFLAGS
|
||||||
|
// but they don't mean anything to the linker so filter
|
||||||
|
// them out.
|
||||||
|
if flag != "-g" && !strings.HasPrefix(flag, "-O") {
|
||||||
|
cgoldflags = append(cgoldflags, flag)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
readAndRemoveCgoFlags := func(archive string) (string, error) {
|
||||||
|
newa, err := ioutil.TempFile(b.work, filepath.Base(archive))
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
olda, err := os.Open(archive)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
_, err = io.Copy(newa, olda)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
err = olda.Close()
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
err = newa.Close()
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
newarchive := newa.Name()
|
||||||
|
err = b.run(b.work, root.p.ImportPath, nil, "ar", "x", newarchive, "_cgo_flags")
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
err = b.run(".", root.p.ImportPath, nil, "ar", "d", newarchive, "_cgo_flags")
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
err = readCgoFlags(filepath.Join(b.work, "_cgo_flags"))
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
return newarchive, nil
|
||||||
|
}
|
||||||
|
|
||||||
actionsSeen := make(map[*action]bool)
|
actionsSeen := make(map[*action]bool)
|
||||||
// Make a pre-order depth-first traversal of the action graph, taking note of
|
// Make a pre-order depth-first traversal of the action graph, taking note of
|
||||||
// whether a shared library action has been seen on the way to an action (the
|
// whether a shared library action has been seen on the way to an action (the
|
||||||
// construction of the graph means that if any path to a node passes through
|
// construction of the graph means that if any path to a node passes through
|
||||||
// a shared library action, they all do).
|
// a shared library action, they all do).
|
||||||
var walk func(a *action, seenShlib bool)
|
var walk func(a *action, seenShlib bool)
|
||||||
|
var err error
|
||||||
walk = func(a *action, seenShlib bool) {
|
walk = func(a *action, seenShlib bool) {
|
||||||
if actionsSeen[a] {
|
if actionsSeen[a] {
|
||||||
return
|
return
|
||||||
@ -2634,16 +2698,23 @@ func (tools gccgoToolchain) ld(b *builder, root *action, out string, allactions
|
|||||||
// doesn't work.
|
// doesn't work.
|
||||||
if !apackagesSeen[a.p] {
|
if !apackagesSeen[a.p] {
|
||||||
apackagesSeen[a.p] = true
|
apackagesSeen[a.p] = true
|
||||||
|
target := a.target
|
||||||
|
if len(a.p.CgoFiles) > 0 {
|
||||||
|
target, err = readAndRemoveCgoFlags(target)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
if a.p.fake && a.p.external {
|
if a.p.fake && a.p.external {
|
||||||
// external _tests, if present must come before
|
// external _tests, if present must come before
|
||||||
// internal _tests. Store these on a separate list
|
// internal _tests. Store these on a separate list
|
||||||
// and place them at the head after this loop.
|
// and place them at the head after this loop.
|
||||||
xfiles = append(xfiles, a.target)
|
xfiles = append(xfiles, target)
|
||||||
} else if a.p.fake {
|
} else if a.p.fake {
|
||||||
// move _test files to the top of the link order
|
// move _test files to the top of the link order
|
||||||
afiles = append([]string{a.target}, afiles...)
|
afiles = append([]string{target}, afiles...)
|
||||||
} else {
|
} else {
|
||||||
afiles = append(afiles, a.target)
|
afiles = append(afiles, target)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2653,10 +2724,16 @@ func (tools gccgoToolchain) ld(b *builder, root *action, out string, allactions
|
|||||||
}
|
}
|
||||||
for _, a1 := range a.deps {
|
for _, a1 := range a.deps {
|
||||||
walk(a1, seenShlib)
|
walk(a1, seenShlib)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for _, a1 := range root.deps {
|
for _, a1 := range root.deps {
|
||||||
walk(a1, false)
|
walk(a1, false)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
afiles = append(xfiles, afiles...)
|
afiles = append(xfiles, afiles...)
|
||||||
|
|
||||||
@ -2688,6 +2765,14 @@ func (tools gccgoToolchain) ld(b *builder, root *action, out string, allactions
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for i, o := range ofiles {
|
||||||
|
if filepath.Base(o) == "_cgo_flags" {
|
||||||
|
readCgoFlags(o)
|
||||||
|
ofiles = append(ofiles[:i], ofiles[i+1:]...)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ldflags = append(ldflags, "-Wl,--whole-archive")
|
ldflags = append(ldflags, "-Wl,--whole-archive")
|
||||||
ldflags = append(ldflags, afiles...)
|
ldflags = append(ldflags, afiles...)
|
||||||
ldflags = append(ldflags, "-Wl,--no-whole-archive")
|
ldflags = append(ldflags, "-Wl,--no-whole-archive")
|
||||||
|
Loading…
Reference in New Issue
Block a user