Skip to content

Commit 21ebc8c

Browse files
authored
Merge pull request #284 from feast-dev/dynamic-linking
Add optional dynamic linking when building shared library
2 parents 0b356cb + 0b3020d commit 21ebc8c

File tree

7 files changed

+39
-12
lines changed

7 files changed

+39
-12
lines changed

bind/gen.go

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -434,14 +434,15 @@ var NoMake = false
434434
// and wrapper .py file(s) that are loaded as the interface to the package with shadow
435435
// python-side classes
436436
// mode = gen, build, pkg, exe
437-
func GenPyBind(mode BuildMode, libext, extragccargs string, lang int, cfg *BindCfg) error {
437+
func GenPyBind(mode BuildMode, libext, extragccargs string, lang int, dynamicLink bool, cfg *BindCfg) error {
438438
gen := &pyGen{
439439
mode: mode,
440440
pypkgname: cfg.Name,
441441
cfg: cfg,
442442
libext: libext,
443443
extraGccArgs: extragccargs,
444444
lang: lang,
445+
dynamicLink: dynamicLink,
445446
}
446447
gen.genPackageMap()
447448
thePyGen = gen
@@ -470,6 +471,7 @@ type pyGen struct {
470471
libext string
471472
extraGccArgs string
472473
lang int // c-python api version (2,3)
474+
dynamicLink bool
473475
}
474476

475477
func (g *pyGen) gen() error {
@@ -583,12 +585,18 @@ func (g *pyGen) genGoPreamble() {
583585
if err != nil {
584586
panic(err)
585587
}
588+
var ldflags string
589+
if g.mode == ModeExe || !g.dynamicLink {
590+
ldflags = pycfg.LdFlags
591+
} else {
592+
ldflags = pycfg.LdDynamicFlags
593+
}
586594
// this is critical to avoid pybindgen errors:
587595
exflags := " -Wno-error -Wno-implicit-function-declaration -Wno-int-conversion"
588596
pkgcfg := fmt.Sprintf(`
589597
#cgo CFLAGS: %s
590598
#cgo LDFLAGS: %s
591-
`, pycfg.CFlags+exflags, pycfg.LdFlags)
599+
`, pycfg.CFlags+exflags, ldflags)
592600

593601
return pkgcfg
594602
}()

bind/utils.go

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -87,10 +87,11 @@ func isConstructor(sig *types.Signature) bool {
8787
}
8888

8989
type PyConfig struct {
90-
Version int
91-
CFlags string
92-
LdFlags string
93-
ExtSuffix string
90+
Version int
91+
CFlags string
92+
LdFlags string
93+
LdDynamicFlags string
94+
ExtSuffix string
9495
}
9596

9697
// AllFlags returns CFlags + " " + LdFlags
@@ -107,6 +108,12 @@ import json
107108
import os
108109
version=sys.version_info.major
109110
111+
def clear_ld_flags(s):
112+
skip_first_word = s.split(' ', 1)[1] # skip compiler name
113+
skip_bundle = skip_first_word.replace('-bundle', '') # cgo already passes -dynamiclib
114+
return skip_bundle
115+
116+
110117
if "GOPY_INCLUDE" in os.environ and "GOPY_LIBDIR" in os.environ and "GOPY_PYLIB" in os.environ:
111118
print(json.dumps({
112119
"version": version,
@@ -117,6 +124,7 @@ if "GOPY_INCLUDE" in os.environ and "GOPY_LIBDIR" in os.environ and "GOPY_PYLIB"
117124
"shlibs": ds.get_config_var("SHLIBS"),
118125
"syslibs": ds.get_config_var("SYSLIBS"),
119126
"shlinks": ds.get_config_var("LINKFORSHARED"),
127+
"shflags": clear_ld_flags(ds.get_config_var("LDSHARED")),
120128
"extsuffix": ds.get_config_var("EXT_SUFFIX"),
121129
}))
122130
else:
@@ -129,6 +137,7 @@ else:
129137
"shlibs": ds.get_config_var("SHLIBS"),
130138
"syslibs": ds.get_config_var("SYSLIBS"),
131139
"shlinks": ds.get_config_var("LINKFORSHARED"),
140+
"shflags": clear_ld_flags(ds.get_config_var("LDSHARED")),
132141
"extsuffix": ds.get_config_var("EXT_SUFFIX"),
133142
}))
134143
`
@@ -158,6 +167,7 @@ else:
158167
ShLibs string `json:"shlibs"`
159168
SysLibs string `json:"syslibs"`
160169
ExtSuffix string `json:"extsuffix"`
170+
ShFlags string `json:"shflags"`
161171
}
162172
err = json.NewDecoder(buf).Decode(&raw)
163173
if err != nil {
@@ -199,6 +209,7 @@ else:
199209
raw.ShLibs,
200210
raw.SysLibs,
201211
}, " ")
212+
cfg.LdDynamicFlags = raw.ShFlags
202213

203214
return cfg, nil
204215
}

cmd_build.go

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ ex:
4444
cmd.Flag.Bool("symbols", true, "include symbols in output")
4545
cmd.Flag.Bool("no-warn", false, "suppress warning messages, which may be expected")
4646
cmd.Flag.Bool("no-make", false, "do not generate a Makefile, e.g., when called from Makefile")
47+
cmd.Flag.Bool("dynamic-link", false, "whether to link output shared library dynamically to Python")
4748
return cmd
4849
}
4950

@@ -64,6 +65,7 @@ func gopyRunCmdBuild(cmdr *commander.Command, args []string) error {
6465
cfg.Symbols = cmdr.Flag.Lookup("symbols").Value.Get().(bool)
6566
cfg.NoWarn = cmdr.Flag.Lookup("no-warn").Value.Get().(bool)
6667
cfg.NoMake = cmdr.Flag.Lookup("no-make").Value.Get().(bool)
68+
cfg.DynamicLinking = cmdr.Flag.Lookup("dynamic-link").Value.Get().(bool)
6769

6870
bind.NoWarn = cfg.NoWarn
6971
bind.NoMake = cfg.NoMake
@@ -212,8 +214,12 @@ func runBuild(mode bind.BuildMode, cfg *BuildCfg) error {
212214
if include, exists := os.LookupEnv("GOPY_INCLUDE"); exists {
213215
cflags = append(cflags, "-I"+filepath.ToSlash(include))
214216
}
215-
216-
ldflags := strings.Fields(strings.TrimSpace(pycfg.LdFlags))
217+
var ldflags []string
218+
if cfg.DynamicLinking {
219+
ldflags = strings.Fields(strings.TrimSpace(pycfg.LdDynamicFlags))
220+
} else {
221+
ldflags = strings.Fields(strings.TrimSpace(pycfg.LdFlags))
222+
}
217223
if !cfg.Symbols {
218224
ldflags = append(ldflags, "-s")
219225
}

gen.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ func genPkg(mode bind.BuildMode, cfg *BuildCfg) error {
7878
if err != nil {
7979
return err
8080
}
81-
err = bind.GenPyBind(mode, libExt, extraGccArgs, pyvers, &cfg.BindCfg)
81+
err = bind.GenPyBind(mode, libExt, extraGccArgs, pyvers, cfg.DynamicLinking, &cfg.BindCfg)
8282
if err != nil {
8383
log.Println(err)
8484
}

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ require (
1010
)
1111

1212
require (
13-
golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3 // indirect
13+
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 // indirect
1414
golang.org/x/sys v0.0.0-20211019181941-9d821ace8654 // indirect
1515
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect
1616
)

go.sum

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@ github.com/gonuts/flag v0.1.0 h1:fqMv/MZ+oNGu0i9gp0/IQ/ZaPIDoAZBOBaJoV7viCWM=
44
github.com/gonuts/flag v0.1.0/go.mod h1:ZTmTGtrSPejTo/SRNhCqwLTmiAgyBdCkLYhHrAoBdz4=
55
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
66
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
7-
golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3 h1:kQgndtyPBW/JIYERgdxfwMYh3AVStj88WQTlNDi2a+o=
8-
golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3/go.mod h1:3p9vT2HGsQu2K1YbXdKPJLVgG5VJdoTa1poYQBtP1AY=
7+
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 h1:6zppjxzCulZykYSLyVDYbneBfbaBIQPYMevg0bEwv2s=
8+
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
99
golang.org/x/sys v0.0.0-20211019181941-9d821ace8654 h1:id054HUawV2/6IGm2IV8KZQjqtwAOo2CYlOToYqa0d0=
1010
golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
1111
golang.org/x/tools v0.1.11-0.20220413170336-afc6aad76eb1 h1:Z3vE1sGlC7qiyFJkkDcZms8Y3+yV8+W7HmDSmuf71tM=

main.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@ type BuildCfg struct {
2828
NoWarn bool
2929
// do not generate a Makefile, e.g., when called from Makefile
3030
NoMake bool
31+
// link resulting library dynamically
32+
DynamicLinking bool
3133
}
3234

3335
// NewBuildCfg returns a newly constructed build config

0 commit comments

Comments
 (0)