Commit 931f434a by Ian Lance Taylor

re PR go/66904 (cmd/go: "#cgo pkg-config:" comments do not work with gccgo)

	PR go/66904
    cmd/go: fix "#cgo pkg-config:" comments with gccgo
    
    Copy of https://golang.org/cl/18790 by Michael Hudson-Doyle.
    
    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.
    
    Update golang/go#11739.
    GCC PR 66904.

    Reviewed-on: https://go-review.googlesource.com/19431

From-SVN: r233290
parent e03dd765
4cec4c5db5b054c5536ec5c50ee7aebec83563bc 28a9dfbc3cda0bf7fd4f3fb1506c547f6cdf41a5
The first line of this file holds the git revision number of the last The first line of this file holds the git revision number of the last
merge done from the gofrontend repository. merge done from the gofrontend repository.
...@@ -1445,6 +1445,9 @@ func (b *builder) build(a *action) (err error) { ...@@ -1445,6 +1445,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...)
} }
...@@ -2620,12 +2623,64 @@ func (tools gccgoToolchain) ld(b *builder, root *action, out string, allactions ...@@ -2620,12 +2623,64 @@ func (tools gccgoToolchain) ld(b *builder, root *action, out string, allactions
cxx := len(root.p.CXXFiles) > 0 || len(root.p.SwigCXXFiles) > 0 cxx := len(root.p.CXXFiles) > 0 || len(root.p.SwigCXXFiles) > 0
objc := len(root.p.MFiles) > 0 objc := len(root.p.MFiles) > 0
readCgoFlags := func(flagsFile string) error {
flags, err := ioutil.ReadFile(flagsFile)
if err != nil {
return err
}
for _, line := range strings.Split(string(flags), "\n") {
if strings.HasPrefix(line, "_CGO_LDFLAGS=") {
cgoldflags = append(cgoldflags, strings.Fields(line[13:])...)
}
}
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
...@@ -2644,16 +2699,23 @@ func (tools gccgoToolchain) ld(b *builder, root *action, out string, allactions ...@@ -2644,16 +2699,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)
} }
} }
} }
...@@ -2663,10 +2725,16 @@ func (tools gccgoToolchain) ld(b *builder, root *action, out string, allactions ...@@ -2663,10 +2725,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...)
...@@ -2695,6 +2763,14 @@ func (tools gccgoToolchain) ld(b *builder, root *action, out string, allactions ...@@ -2695,6 +2763,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")
......
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