Skip to content

Commit ddc41c9

Browse files
justinfxsbinet
authored andcommitted
bind: reduce shared library count from 2 to 1 and use ABI version tagged extension
This merge replaces the python extension linked against the go shared library with a single python extension module. The extension module is also named using the ABI version tagging reported by the python configuration to avoid clashes with other python minor version builds. Removes need/reference for LD_LIBRARY_PATH modification. Fixes #249
1 parent 50d04f7 commit ddc41c9

File tree

4 files changed

+66
-66
lines changed

4 files changed

+66
-66
lines changed

README.md

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -177,7 +177,6 @@ package hi exposes a few Go functions to be wrapped and used from Python.
177177
### From the command line
178178
179179
```sh
180-
$ export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:./
181180
$ gopy build -output=out -vm=`which python3` github.com/go-python/gopy/_examples/hi
182181
$ ls out
183182
Makefile __init__.py __pycache__/ _hi.so* build.py go.py hi.c hi.go hi.py hi_go.h hi_go.so patch-leaks.go

bind/utils.go

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -86,9 +86,10 @@ func isConstructor(sig *types.Signature) bool {
8686
}
8787

8888
type PyConfig struct {
89-
Version int
90-
CFlags string
91-
LdFlags string
89+
Version int
90+
CFlags string
91+
LdFlags string
92+
ExtSuffix string
9293
}
9394

9495
// AllFlags returns CFlags + " " + LdFlags
@@ -114,6 +115,7 @@ if "GOPY_INCLUDE" in os.environ and "GOPY_LIBDIR" in os.environ and "GOPY_PYLIB"
114115
"shlibs": ds.get_config_var("SHLIBS"),
115116
"syslibs": ds.get_config_var("SYSLIBS"),
116117
"shlinks": ds.get_config_var("LINKFORSHARED"),
118+
"extsuffix": ds.get_config_var("EXT_SUFFIX"),
117119
}))
118120
else:
119121
print(json.dumps({
@@ -124,6 +126,7 @@ else:
124126
"shlibs": ds.get_config_var("SHLIBS"),
125127
"syslibs": ds.get_config_var("SYSLIBS"),
126128
"shlinks": ds.get_config_var("LINKFORSHARED"),
129+
"extsuffix": ds.get_config_var("EXT_SUFFIX"),
127130
}))
128131
`
129132

@@ -144,12 +147,13 @@ else:
144147
}
145148

146149
var raw struct {
147-
Version int `json:"version"`
148-
IncDir string `json:"incdir"`
149-
LibDir string `json:"libdir"`
150-
LibPy string `json:"libpy"`
151-
ShLibs string `json:"shlibs"`
152-
SysLibs string `json:"syslibs"`
150+
Version int `json:"version"`
151+
IncDir string `json:"incdir"`
152+
LibDir string `json:"libdir"`
153+
LibPy string `json:"libpy"`
154+
ShLibs string `json:"shlibs"`
155+
SysLibs string `json:"syslibs"`
156+
ExtSuffix string `json:"extsuffix"`
153157
}
154158
err = json.NewDecoder(buf).Decode(&raw)
155159
if err != nil {
@@ -167,6 +171,7 @@ else:
167171
}
168172

169173
cfg.Version = raw.Version
174+
cfg.ExtSuffix = raw.ExtSuffix
170175
cfg.CFlags = strings.Join([]string{
171176
"-I" + raw.IncDir,
172177
}, " ")

cmd_build.go

Lines changed: 52 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,18 @@ func runBuild(mode bind.BuildMode, cfg *BuildCfg) error {
168168
}
169169

170170
} else {
171+
buildLib := buildname + libExt
172+
extext := libExt
173+
if runtime.GOOS == "windows" {
174+
extext = ".pyd"
175+
}
176+
if pycfg.ExtSuffix != "" {
177+
extext = pycfg.ExtSuffix
178+
}
179+
modlib := "_" + cfg.Name + extext
180+
181+
// build the go shared library upfront to generate the header
182+
// needed by our generated cpython code
171183
args := []string{"build", "-buildmode=c-shared"}
172184
if !cfg.Symbols {
173185
// These flags will omit the various symbol tables, thereby
@@ -176,15 +188,20 @@ func runBuild(mode bind.BuildMode, cfg *BuildCfg) error {
176188
// -w Omit the DWARF symbol table
177189
args = append(args, "-ldflags=-s -w")
178190
}
179-
args = append(args, "-o", buildname+libExt, ".")
191+
args = append(args, "-o", buildLib, ".")
180192
fmt.Printf("go %v\n", strings.Join(args, " "))
181193
cmd = exec.Command("go", args...)
182194
cmdout, err = cmd.CombinedOutput()
183195
if err != nil {
184196
fmt.Printf("cmd had error: %v output:\n%v\n", err, string(cmdout))
185197
return err
186198
}
199+
// update the output name to the one with the ABI extension
200+
args[len(args)-2] = modlib
201+
// we don't need this initial lib because we are going to relink
202+
os.Remove(buildLib)
187203

204+
// generate c code
188205
fmt.Printf("%v build.py\n", cfg.VM)
189206
cmd = exec.Command(cfg.VM, "build.py")
190207
cmdout, err = cmd.CombinedOutput()
@@ -193,77 +210,59 @@ func runBuild(mode bind.BuildMode, cfg *BuildCfg) error {
193210
return err
194211
}
195212

213+
// patch c code
196214
if err := patchLeaks(cfg.Name + ".c"); err != nil {
197215
return err
198216
}
199217

200-
fmt.Printf("go env CC\n")
201-
cmd = exec.Command("go", "env", "CC")
202-
cccmdb, err := cmd.CombinedOutput()
203-
if err != nil {
204-
fmt.Printf("cmd had error: %v output:\n%v\n", err, string(cccmdb))
205-
return err
206-
}
207-
cccmd := strings.TrimSpace(string(cccmdb))
208-
// var cflags, ldflags []byte
209-
// if runtime.GOOS != "windows" {
210-
// fmt.Printf("%v-config --cflags\n", vm)
211-
// cmd = exec.Command(vm+"-config", "--cflags") // TODO: need minor version!
212-
// cflags, err = cmd.CombinedOutput()
213-
// if err != nil {
214-
// fmt.Printf("cmd had error: %v output:\n%v\n", err, string(cflags))
215-
// return err
216-
// }
217-
//
218-
// fmt.Printf("%v-config --ldflags\n", vm)
219-
// cmd = exec.Command(vm+"-config", "--ldflags")
220-
// ldflags, err = cmd.CombinedOutput()
221-
// if err != nil {
222-
// fmt.Printf("cmd had error: %v output:\n%v\n", err, string(ldflags))
223-
// return err
224-
// }
225-
// fmt.Printf("build cmd: %s\nldflags: %s\n", cmd, ldflags)
226-
// }
227-
extext := libExt
228-
if runtime.GOOS == "windows" {
229-
extext = ".pyd"
218+
cflags := strings.Fields(strings.TrimSpace(pycfg.CFlags))
219+
cflags = append(cflags, "-fPIC", "-Ofast")
220+
if include, exists := os.LookupEnv("GOPY_INCLUDE"); exists {
221+
cflags = append(cflags, "-I"+filepath.ToSlash(include))
230222
}
231-
modlib := "_" + cfg.Name + extext
232-
gccargs := []string{cfg.Name + ".c", extraGccArgs, cfg.Name + "_go" + libExt, "-o", modlib}
233-
gccargs = append(gccargs, strings.Fields(pycfg.AllFlags())...)
234-
gccargs = append(gccargs, "-fPIC", "--shared", "-Ofast")
223+
224+
ldflags := strings.Fields(strings.TrimSpace(pycfg.LdFlags))
235225
if !cfg.Symbols {
236-
gccargs = append(gccargs, "-s")
226+
ldflags = append(ldflags, "-s")
237227
}
238-
include, exists := os.LookupEnv("GOPY_INCLUDE")
239-
if exists {
240-
gccargs = append(gccargs, "-I"+filepath.ToSlash(include))
228+
if lib, exists := os.LookupEnv("GOPY_LIBDIR"); exists {
229+
ldflags = append(ldflags, "-L"+filepath.ToSlash(lib))
241230
}
242-
lib, exists := os.LookupEnv("GOPY_LIBDIR")
243-
if exists {
244-
gccargs = append(gccargs, "-L"+filepath.ToSlash(lib))
245-
}
246-
libname, exists := os.LookupEnv("GOPY_PYLIB")
247-
if exists {
248-
gccargs = append(gccargs, "-l"+filepath.ToSlash(libname))
231+
if libname, exists := os.LookupEnv("GOPY_PYLIB"); exists {
232+
ldflags = append(ldflags, "-l"+filepath.ToSlash(libname))
249233
}
250234

251-
gccargs = func(vs []string) []string {
252-
o := make([]string, 0, len(gccargs))
253-
for _, v := range vs {
235+
removeEmpty := func(src []string) []string {
236+
o := make([]string, 0, len(src))
237+
for _, v := range src {
254238
if v == "" {
255239
continue
256240
}
257241
o = append(o, v)
258242
}
259243
return o
260-
}(gccargs)
244+
}
245+
246+
cflags = removeEmpty(cflags)
247+
ldflags = removeEmpty(ldflags)
261248

262-
fmt.Printf("%s %v\n", cccmd, strings.Join(gccargs, " "))
263-
cmd = exec.Command(cccmd, gccargs...)
249+
cflagsEnv := fmt.Sprintf("CGO_CFLAGS=%s", strings.Join(cflags, " "))
250+
ldflagsEnv := fmt.Sprintf("CGO_LDFLAGS=%s", strings.Join(ldflags, " "))
251+
252+
env := os.Environ()
253+
env = append(env, cflagsEnv)
254+
env = append(env, ldflagsEnv)
255+
256+
fmt.Println(cflagsEnv)
257+
fmt.Println(ldflagsEnv)
258+
259+
// build extension with go + c
260+
fmt.Printf("go %v\n", strings.Join(args, " "))
261+
cmd = exec.Command("go", args...)
262+
cmd.Env = env
264263
cmdout, err = cmd.CombinedOutput()
265264
if err != nil {
266-
fmt.Printf("cmd had error: %v\noutput: %v\n", err, string(cmdout))
265+
fmt.Printf("cmd had error: %v output:\n%v\n", err, string(cmdout))
267266
return err
268267
}
269268
}

main_unix_test.go

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
package main
88

99
import (
10-
"fmt"
1110
"log"
1211
"os"
1312
"os/exec"
@@ -16,8 +15,6 @@ import (
1615

1716
func init() {
1817

19-
// ld needs to look into the current directory to load the _go.so library
20-
os.Setenv("LD_LIBRARY_PATH", fmt.Sprintf("%s:.", os.Getenv("LD_LIBRARY_PATH")))
2118
testEnvironment = os.Environ()
2219

2320
var (

0 commit comments

Comments
 (0)