mirror of
https://github.com/golang/go
synced 2024-11-26 16:57:14 -07:00
cmd/go: link SWIG objects directly rather than using a shared library
This change requires using SWIG version 3.0 or later. Earlier versions of SWIG do not generate the pragmas required to use the external linker. Fixes #7155. Fixes #7156. LGTM=rsc R=rsc CC=golang-codereviews https://golang.org/cl/97120046
This commit is contained in:
parent
f078711b41
commit
02cc45aded
@ -179,6 +179,15 @@ Finally, the go command now supports packages that import Objective-C
|
||||
files (suffixed <code>.m</code>) through cgo.
|
||||
</p>
|
||||
|
||||
<h3 id="swig">SWIG 3.0 required for programs that use SWIG</h3>
|
||||
|
||||
<p>
|
||||
For Go programs that use SWIG, SWIG version 3.0 is now required. The
|
||||
<a href="/cmd/go"><code>cmd/go</code></a> command will now link the
|
||||
SWIG generated object files directly into the binary, rather than
|
||||
building and linking with a shared library.
|
||||
</p>
|
||||
|
||||
<h3 id="gc_flag">Command-line flag parsing</h3>
|
||||
|
||||
<p>
|
||||
|
@ -1048,21 +1048,6 @@ func (b *builder) install(a *action) (err error) {
|
||||
defer os.Remove(a1.target)
|
||||
}
|
||||
|
||||
if a.p.usesSwig() {
|
||||
for _, f := range stringList(a.p.SwigFiles, a.p.SwigCXXFiles) {
|
||||
dir = a.p.swigDir(&buildContext)
|
||||
if err := b.mkdir(dir); err != nil {
|
||||
return err
|
||||
}
|
||||
soname := a.p.swigSoname(f)
|
||||
source := filepath.Join(a.objdir, soname)
|
||||
target := filepath.Join(dir, soname)
|
||||
if err = b.copyFile(a, target, source, perm); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return b.moveOrCopyFile(a, a.target, a1.target, perm)
|
||||
}
|
||||
|
||||
@ -1721,25 +1706,8 @@ func packInternal(b *builder, afile string, ofiles []string) error {
|
||||
|
||||
func (gcToolchain) ld(b *builder, p *Package, out string, allactions []*action, mainpkg string, ofiles []string) error {
|
||||
importArgs := b.includeArgs("-L", allactions)
|
||||
swigDirs := make(map[string]bool)
|
||||
swigArg := []string{}
|
||||
cxx := false
|
||||
for _, a := range allactions {
|
||||
if a.p != nil && a.p.usesSwig() {
|
||||
sd := a.p.swigDir(&buildContext)
|
||||
if len(swigArg) == 0 {
|
||||
swigArg = []string{"-r", sd}
|
||||
} else if !swigDirs[sd] {
|
||||
swigArg[1] += ":"
|
||||
swigArg[1] += sd
|
||||
}
|
||||
swigDirs[sd] = true
|
||||
if a.objdir != "" && !swigDirs[a.objdir] {
|
||||
swigArg[1] += ":"
|
||||
swigArg[1] += a.objdir
|
||||
swigDirs[a.objdir] = true
|
||||
}
|
||||
}
|
||||
if a.p != nil && len(a.p.CXXFiles) > 0 {
|
||||
cxx = true
|
||||
}
|
||||
@ -1792,7 +1760,7 @@ func (gcToolchain) ld(b *builder, p *Package, out string, allactions []*action,
|
||||
}
|
||||
}
|
||||
}
|
||||
return b.run(".", p.ImportPath, nil, tool(archChar+"l"), "-o", out, importArgs, swigArg, ldflags, mainpkg)
|
||||
return b.run(".", p.ImportPath, nil, tool(archChar+"l"), "-o", out, importArgs, ldflags, mainpkg)
|
||||
}
|
||||
|
||||
func (gcToolchain) cc(b *builder, p *Package, objdir, ofile, cfile string) error {
|
||||
@ -1865,7 +1833,6 @@ func (tools gccgoToolchain) ld(b *builder, p *Package, out string, allactions []
|
||||
// and all LDFLAGS from cgo dependencies.
|
||||
apackagesSeen := make(map[*Package]bool)
|
||||
afiles := []string{}
|
||||
sfiles := []string{}
|
||||
ldflags := b.gccArchArgs()
|
||||
cgoldflags := []string{}
|
||||
usesCgo := false
|
||||
@ -1898,14 +1865,6 @@ func (tools gccgoToolchain) ld(b *builder, p *Package, out string, allactions []
|
||||
usesCgo = true
|
||||
}
|
||||
if a.p.usesSwig() {
|
||||
sd := a.p.swigDir(&buildContext)
|
||||
if a.objdir != "" {
|
||||
sd = a.objdir
|
||||
}
|
||||
for _, f := range stringList(a.p.SwigFiles, a.p.SwigCXXFiles) {
|
||||
soname := a.p.swigSoname(f)
|
||||
sfiles = append(sfiles, filepath.Join(sd, soname))
|
||||
}
|
||||
usesCgo = true
|
||||
}
|
||||
if len(a.p.CXXFiles) > 0 {
|
||||
@ -1917,7 +1876,6 @@ func (tools gccgoToolchain) ld(b *builder, p *Package, out string, allactions []
|
||||
}
|
||||
}
|
||||
ldflags = append(ldflags, afiles...)
|
||||
ldflags = append(ldflags, sfiles...)
|
||||
ldflags = append(ldflags, cgoldflags...)
|
||||
ldflags = append(ldflags, p.CgoLDFLAGS...)
|
||||
if usesCgo && goos == "linux" {
|
||||
@ -2364,13 +2322,12 @@ func (b *builder) swig(p *Package, obj string, gccfiles, gxxfiles, mfiles []stri
|
||||
cflags := stringList(cgoCPPFLAGS, cgoCFLAGS)
|
||||
cxxflags := stringList(cgoCPPFLAGS, cgoCXXFLAGS)
|
||||
|
||||
var extraObj []string
|
||||
for _, file := range gccfiles {
|
||||
ofile := obj + cgoRe.ReplaceAllString(file[:len(file)-1], "_") + "o"
|
||||
if err := b.gcc(p, ofile, cflags, file); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
extraObj = append(extraObj, ofile)
|
||||
outObj = append(outObj, ofile)
|
||||
}
|
||||
|
||||
for _, file := range gxxfiles {
|
||||
@ -2379,7 +2336,7 @@ func (b *builder) swig(p *Package, obj string, gccfiles, gxxfiles, mfiles []stri
|
||||
if err := b.gxx(p, ofile, cxxflags, file); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
extraObj = append(extraObj, ofile)
|
||||
outObj = append(outObj, ofile)
|
||||
}
|
||||
|
||||
for _, file := range mfiles {
|
||||
@ -2388,7 +2345,7 @@ func (b *builder) swig(p *Package, obj string, gccfiles, gxxfiles, mfiles []stri
|
||||
if err := b.gcc(p, ofile, cflags, file); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
extraObj = append(extraObj, ofile)
|
||||
outObj = append(outObj, ofile)
|
||||
}
|
||||
|
||||
intgosize, err := b.swigIntSize(obj)
|
||||
@ -2397,7 +2354,7 @@ func (b *builder) swig(p *Package, obj string, gccfiles, gxxfiles, mfiles []stri
|
||||
}
|
||||
|
||||
for _, f := range p.SwigFiles {
|
||||
goFile, objFile, err := b.swigOne(p, f, obj, false, intgosize, extraObj)
|
||||
goFile, objFile, gccObjFile, err := b.swigOne(p, f, obj, false, intgosize)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
@ -2407,9 +2364,12 @@ func (b *builder) swig(p *Package, obj string, gccfiles, gxxfiles, mfiles []stri
|
||||
if objFile != "" {
|
||||
outObj = append(outObj, objFile)
|
||||
}
|
||||
if gccObjFile != "" {
|
||||
outObj = append(outObj, gccObjFile)
|
||||
}
|
||||
}
|
||||
for _, f := range p.SwigCXXFiles {
|
||||
goFile, objFile, err := b.swigOne(p, f, obj, true, intgosize, extraObj)
|
||||
goFile, objFile, gccObjFile, err := b.swigOne(p, f, obj, true, intgosize)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
@ -2419,6 +2379,9 @@ func (b *builder) swig(p *Package, obj string, gccfiles, gxxfiles, mfiles []stri
|
||||
if objFile != "" {
|
||||
outObj = append(outObj, objFile)
|
||||
}
|
||||
if gccObjFile != "" {
|
||||
outObj = append(outObj, gccObjFile)
|
||||
}
|
||||
}
|
||||
return outGo, outObj, nil
|
||||
}
|
||||
@ -2450,13 +2413,13 @@ func (b *builder) swigIntSize(obj string) (intsize string, err error) {
|
||||
}
|
||||
|
||||
// Run SWIG on one SWIG input file.
|
||||
func (b *builder) swigOne(p *Package, file, obj string, cxx bool, intgosize string, extraObj []string) (outGo, outObj string, err error) {
|
||||
cgoCPPFLAGS, cgoCFLAGS, cgoCXXFLAGS, cgoLDFLAGS := b.cflags(p, true)
|
||||
func (b *builder) swigOne(p *Package, file, obj string, cxx bool, intgosize string) (outGo, outObj, objGccObj string, err error) {
|
||||
cgoCPPFLAGS, cgoCFLAGS, cgoCXXFLAGS, _ := b.cflags(p, true)
|
||||
var cflags []string
|
||||
if cxx {
|
||||
cflags = stringList(cgoCPPFLAGS, cgoCXXFLAGS, "-fPIC")
|
||||
cflags = stringList(cgoCPPFLAGS, cgoCXXFLAGS)
|
||||
} else {
|
||||
cflags = stringList(cgoCPPFLAGS, cgoCFLAGS, "-fPIC")
|
||||
cflags = stringList(cgoCPPFLAGS, cgoCFLAGS)
|
||||
}
|
||||
|
||||
n := 5 // length of ".swig"
|
||||
@ -2471,7 +2434,6 @@ func (b *builder) swigOne(p *Package, file, obj string, cxx bool, intgosize stri
|
||||
if cxx {
|
||||
gccExt = "cxx"
|
||||
}
|
||||
soname := p.swigSoname(file)
|
||||
|
||||
_, gccgo := buildToolchain.(gccgoToolchain)
|
||||
|
||||
@ -2480,12 +2442,14 @@ func (b *builder) swigOne(p *Package, file, obj string, cxx bool, intgosize stri
|
||||
"-go",
|
||||
"-intgosize", intgosize,
|
||||
"-module", base,
|
||||
"-soname", soname,
|
||||
"-o", obj + gccBase + gccExt,
|
||||
"-outdir", obj,
|
||||
}
|
||||
if gccgo {
|
||||
args = append(args, "-gccgo")
|
||||
if pkgpath := gccgoPkgpath(p); pkgpath != "" {
|
||||
args = append(args, "-go-pkgpath", pkgpath)
|
||||
}
|
||||
}
|
||||
if cxx {
|
||||
args = append(args, "-c++")
|
||||
@ -2494,12 +2458,12 @@ func (b *builder) swigOne(p *Package, file, obj string, cxx bool, intgosize stri
|
||||
if out, err := b.runOut(p.Dir, p.ImportPath, nil, "swig", args, file); err != nil {
|
||||
if len(out) > 0 {
|
||||
if bytes.Contains(out, []byte("Unrecognized option -intgosize")) {
|
||||
return "", "", errors.New("must have SWIG version >= 2.0.9\n")
|
||||
return "", "", "", errors.New("must have SWIG version >= 3.0\n")
|
||||
}
|
||||
b.showOutput(p.Dir, p.ImportPath, b.processOutput(out))
|
||||
return "", "", errPrintedOutput
|
||||
return "", "", "", errPrintedOutput
|
||||
}
|
||||
return "", "", err
|
||||
return "", "", "", err
|
||||
}
|
||||
|
||||
var cObj string
|
||||
@ -2507,7 +2471,7 @@ func (b *builder) swigOne(p *Package, file, obj string, cxx bool, intgosize stri
|
||||
// cc
|
||||
cObj = obj + cBase + archChar
|
||||
if err := buildToolchain.cc(b, p, obj, cObj, obj+cBase+"c"); err != nil {
|
||||
return "", "", err
|
||||
return "", "", "", err
|
||||
}
|
||||
}
|
||||
|
||||
@ -2515,32 +2479,15 @@ func (b *builder) swigOne(p *Package, file, obj string, cxx bool, intgosize stri
|
||||
gccObj := obj + gccBase + "o"
|
||||
if !cxx {
|
||||
if err := b.gcc(p, gccObj, cflags, obj+gccBase+gccExt); err != nil {
|
||||
return "", "", err
|
||||
return "", "", "", err
|
||||
}
|
||||
} else {
|
||||
if err := b.gxx(p, gccObj, cflags, obj+gccBase+gccExt); err != nil {
|
||||
return "", "", err
|
||||
return "", "", "", err
|
||||
}
|
||||
}
|
||||
|
||||
// create shared library
|
||||
osldflags := map[string][]string{
|
||||
"darwin": {"-dynamiclib", "-Wl,-undefined,dynamic_lookup"},
|
||||
"freebsd": {"-shared", "-lpthread", "-lm"},
|
||||
"linux": {"-shared", "-lpthread", "-lm"},
|
||||
"windows": {"-shared", "-lm", "-mthreads"},
|
||||
}
|
||||
var cxxlib []string
|
||||
if cxx {
|
||||
cxxlib = []string{"-lstdc++"}
|
||||
}
|
||||
ldflags := stringList(osldflags[goos], cflags, cgoLDFLAGS, cxxlib)
|
||||
target := filepath.Join(obj, soname)
|
||||
if err := b.run(p.Dir, p.ImportPath, nil, b.gccCmd(p.Dir), "-o", target, gccObj, extraObj, ldflags); err != nil {
|
||||
return "", "", err
|
||||
}
|
||||
|
||||
return obj + goFile, cObj, nil
|
||||
return obj + goFile, cObj, gccObj, nil
|
||||
}
|
||||
|
||||
// An actionQueue is a priority queue of actions.
|
||||
|
@ -216,20 +216,6 @@ func clean(p *Package) {
|
||||
}
|
||||
}
|
||||
|
||||
if cleanI && p.usesSwig() {
|
||||
for _, f := range stringList(p.SwigFiles, p.SwigCXXFiles) {
|
||||
dir := p.swigDir(&buildContext)
|
||||
soname := p.swigSoname(f)
|
||||
target := filepath.Join(dir, soname)
|
||||
if buildN || buildX {
|
||||
b.showcmd("", "rm -f %s", target)
|
||||
}
|
||||
if !buildN {
|
||||
removeFile(target)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if cleanR {
|
||||
for _, p1 := range p.imports {
|
||||
clean(p1)
|
||||
|
@ -144,7 +144,6 @@ source directories corresponding to the import paths:
|
||||
DIR(.exe) from go build
|
||||
DIR.test(.exe) from go test -c
|
||||
MAINFILE(.exe) from go build MAINFILE.go
|
||||
*.so from SWIG
|
||||
|
||||
In the list, DIR represents the final path element of the
|
||||
directory, and MAINFILE is the base name of any Go source
|
||||
|
@ -560,24 +560,6 @@ func (p *Package) usesCgo() bool {
|
||||
return len(p.CgoFiles) > 0
|
||||
}
|
||||
|
||||
// swigSoname returns the name of the shared library we create for a
|
||||
// SWIG input file.
|
||||
func (p *Package) swigSoname(file string) string {
|
||||
return strings.Replace(p.ImportPath, "/", "-", -1) + "-" + strings.Replace(file, ".", "-", -1) + ".so"
|
||||
}
|
||||
|
||||
// swigDir returns the name of the shared SWIG directory for a
|
||||
// package.
|
||||
func (p *Package) swigDir(ctxt *build.Context) string {
|
||||
dir := p.build.PkgRoot
|
||||
if ctxt.Compiler == "gccgo" {
|
||||
dir = filepath.Join(dir, "gccgo_"+ctxt.GOOS+"_"+ctxt.GOARCH)
|
||||
} else {
|
||||
dir = filepath.Join(dir, ctxt.GOOS+"_"+ctxt.GOARCH)
|
||||
}
|
||||
return filepath.Join(dir, "swig")
|
||||
}
|
||||
|
||||
// packageList returns the list of packages in the dag rooted at roots
|
||||
// as visited in a depth-first post-order traversal.
|
||||
func packageList(roots []*Package) []*Package {
|
||||
|
Loading…
Reference in New Issue
Block a user