diff options
author | ian <ian@138bc75d-0d04-0410-961f-82ee72b054a4> | 2016-02-10 18:30:27 +0000 |
---|---|---|
committer | ian <ian@138bc75d-0d04-0410-961f-82ee72b054a4> | 2016-02-10 18:30:27 +0000 |
commit | 1356bc7f3e4166e66877f755a8c20ae61d7a78c1 (patch) | |
tree | 386d8d63867ca51e9229c2f90dff88b83421574f | |
parent | ec4ec95a795fe6101372d1a53c9baab3757ba566 (diff) | |
download | gcc-1356bc7f3e4166e66877f755a8c20ae61d7a78c1.tar.gz |
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
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@233290 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r-- | gcc/go/gofrontend/MERGE | 2 | ||||
-rw-r--r-- | libgo/go/cmd/go/build.go | 82 |
2 files changed, 80 insertions, 4 deletions
diff --git a/gcc/go/gofrontend/MERGE b/gcc/go/gofrontend/MERGE index 23f1bfeaa9f..fee516838cb 100644 --- a/gcc/go/gofrontend/MERGE +++ b/gcc/go/gofrontend/MERGE @@ -1,4 +1,4 @@ -4cec4c5db5b054c5536ec5c50ee7aebec83563bc +28a9dfbc3cda0bf7fd4f3fb1506c547f6cdf41a5 The first line of this file holds the git revision number of the last merge done from the gofrontend repository. diff --git a/libgo/go/cmd/go/build.go b/libgo/go/cmd/go/build.go index 3dd9df40282..1b9a3e714d7 100644 --- a/libgo/go/cmd/go/build.go +++ b/libgo/go/cmd/go/build.go @@ -1445,6 +1445,9 @@ func (b *builder) build(a *action) (err error) { if err != nil { return err } + if _, ok := buildToolchain.(gccgoToolchain); ok { + cgoObjects = append(cgoObjects, filepath.Join(a.objdir, "_cgo_flags")) + } cgoObjects = append(cgoObjects, outObj...) gofiles = append(gofiles, outGo...) } @@ -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 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) // 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 // construction of the graph means that if any path to a node passes through // a shared library action, they all do). var walk func(a *action, seenShlib bool) + var err error walk = func(a *action, seenShlib bool) { if actionsSeen[a] { return @@ -2644,16 +2699,23 @@ func (tools gccgoToolchain) ld(b *builder, root *action, out string, allactions // doesn't work. if !apackagesSeen[a.p] { 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 { // external _tests, if present must come before // internal _tests. Store these on a separate list // and place them at the head after this loop. - xfiles = append(xfiles, a.target) + xfiles = append(xfiles, target) } else if a.p.fake { // move _test files to the top of the link order - afiles = append([]string{a.target}, afiles...) + afiles = append([]string{target}, afiles...) } 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 } for _, a1 := range a.deps { walk(a1, seenShlib) + if err != nil { + return + } } } for _, a1 := range root.deps { walk(a1, false) + if err != nil { + return err + } } afiles = append(xfiles, afiles...) @@ -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, afiles...) ldflags = append(ldflags, "-Wl,--no-whole-archive") |