mirror of https://github.com/go-python/gopy.git
finally got windows working -- fixed issues with library path by grabbing include dir which seems more reliable. adds an extra sed to fix generated .c file to do stupid windows __declspec(dllexport).. argh.
This commit is contained in:
parent
c428d23650
commit
d0c78b69e9
12
README.md
12
README.md
|
@ -33,6 +33,18 @@ To [install python modules](https://packaging.python.org/tutorials/packaging-pro
|
|||
python3 -m pip install --upgrade setuptools wheel
|
||||
```
|
||||
|
||||
### Windows
|
||||
|
||||
As of version 0.4.0, windows is now better supported, and is passing tests (on at least one developers machine). You may still need to set some environment variables depending on your python installation, but a vanilla standard install is working.
|
||||
|
||||
Install Python from the main Python distribution: https://www.python.org/downloads/windows/ -- *do not under any circumstances install from the Microsoft Store app!* while that is very convenient, it creates symbolic links to access the python executables, which is incompatible with go exec.Command to run it, despite too many hours of trying to get around that.
|
||||
|
||||
The standard python install does not create a `python3.exe` which gopy looks for -- follow instructions here:
|
||||
https://stackoverflow.com/questions/39910730/python3-is-not-recognized-as-an-internal-or-external-command-operable-program/41492852
|
||||
(just make a copy of python.exe to python3.exe in the relevant installed location).
|
||||
|
||||
If you get a bunch of errors during linking in the build process, set `LIBDIR` or `GOPY_LIBDIR` to path to python libraries, and `LIBRARY` or `GOPY_PYLIB` to name of python library (e.g., python39 for 3.9).
|
||||
|
||||
## Community
|
||||
|
||||
The `go-python` community can be reached out at [go-python@googlegroups.com](mailto:go-python@googlegroups.com) or via the web forum: [go-python group](https://groups.google.com/forum/#!forum/go-python).
|
||||
|
|
14
bind/gen.go
14
bind/gen.go
|
@ -33,6 +33,9 @@ const (
|
|||
ModePkg = "pkg"
|
||||
)
|
||||
|
||||
// set this to true if OS is windows
|
||||
var WindowsOS = false
|
||||
|
||||
// for all preambles: 1 = name of package (outname), 2 = cmdstr
|
||||
|
||||
// 3 = libcfg, 4 = GoHandle, 5 = CGoHandle, 6 = all imports, 7 = mainstr, 8 = exe pre C, 9 = exe pre go
|
||||
|
@ -332,7 +335,8 @@ def Init():
|
|||
|
||||
`
|
||||
|
||||
// 3 = gencmd, 4 = vm, 5 = libext 6 = extraGccArgs
|
||||
// 3 = gencmd, 4 = vm, 5 = libext 6 = extraGccArgs, 7 = CFLAGS, 8 = LDLFAGS,
|
||||
// 9 = windows special declspec hack
|
||||
MakefileTemplate = `# Makefile for python interface for package %[1]s.
|
||||
# File is generated by gopy. Do not edit.
|
||||
# %[2]s
|
||||
|
@ -366,6 +370,7 @@ build:
|
|||
$(PYTHON) build.py
|
||||
# build the _%[1]s$(LIBEXT) library that contains the cgo and CPython wrappers
|
||||
# generated %[1]s.py python wrapper imports this c-code package
|
||||
%[9]s
|
||||
$(GCC) %[1]s.c %[6]s %[1]s_go$(LIBEXT) -o _%[1]s$(LIBEXT) $(CFLAGS) $(LDFLAGS) -fPIC --shared -w
|
||||
|
||||
`
|
||||
|
@ -695,7 +700,12 @@ func (g *pyGen) genMakefile() {
|
|||
if g.mode == ModeExe {
|
||||
g.makefile.Printf(MakefileExeTemplate, g.cfg.Name, g.cfg.Cmd, gencmd, g.cfg.VM, g.libext, pycfg.CFlags, pycfg.LdFlags)
|
||||
} else {
|
||||
g.makefile.Printf(MakefileTemplate, g.cfg.Name, g.cfg.Cmd, gencmd, g.cfg.VM, g.libext, g.extraGccArgs, pycfg.CFlags, pycfg.LdFlags)
|
||||
winhack := ""
|
||||
if WindowsOS {
|
||||
winhack = fmt.Sprintf(`# windows-only sed hack here to fix pybindgen declaration of PyInit
|
||||
sed -i "s/ PyInit_/ __declspec(dllexport) PyInit_/g" %s.c`, g.cfg.Name)
|
||||
}
|
||||
g.makefile.Printf(MakefileTemplate, g.cfg.Name, g.cfg.Cmd, gencmd, g.cfg.VM, g.libext, g.extraGccArgs, pycfg.CFlags, pycfg.LdFlags, winhack)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -110,6 +110,7 @@ version=sys.version_info.major
|
|||
if "GOPY_INCLUDE" in os.environ and "GOPY_LIBDIR" in os.environ and "GOPY_PYLIB" in os.environ:
|
||||
print(json.dumps({
|
||||
"version": version,
|
||||
"minor": sys.version_info.minor,
|
||||
"incdir": os.environ["GOPY_INCLUDE"],
|
||||
"libdir": os.environ["GOPY_LIBDIR"],
|
||||
"libpy": os.environ["GOPY_PYLIB"],
|
||||
|
@ -121,6 +122,7 @@ if "GOPY_INCLUDE" in os.environ and "GOPY_LIBDIR" in os.environ and "GOPY_PYLIB"
|
|||
else:
|
||||
print(json.dumps({
|
||||
"version": sys.version_info.major,
|
||||
"minor": sys.version_info.minor,
|
||||
"incdir": ds.get_python_inc(),
|
||||
"libdir": ds.get_config_var("LIBDIR"),
|
||||
"libpy": ds.get_config_var("LIBRARY"),
|
||||
|
@ -149,6 +151,7 @@ else:
|
|||
|
||||
var raw struct {
|
||||
Version int `json:"version"`
|
||||
Minor int `json:"minor"`
|
||||
IncDir string `json:"incdir"`
|
||||
LibDir string `json:"libdir"`
|
||||
LibPy string `json:"libpy"`
|
||||
|
@ -164,6 +167,20 @@ else:
|
|||
raw.IncDir = filepath.ToSlash(raw.IncDir)
|
||||
raw.LibDir = filepath.ToSlash(raw.LibDir)
|
||||
|
||||
// on windows these can be empty -- use include dir which is usu good
|
||||
if raw.LibDir == "" && raw.IncDir != "" {
|
||||
raw.LibDir = raw.IncDir
|
||||
if strings.HasSuffix(raw.LibDir, "include") {
|
||||
raw.LibDir = raw.LibDir[:len(raw.LibDir)-len("include")] + "libs"
|
||||
}
|
||||
fmt.Printf("no LibDir -- copy from IncDir: %s\n", raw.LibDir)
|
||||
}
|
||||
|
||||
if raw.LibPy == "" {
|
||||
raw.LibPy = fmt.Sprintf("python%d%d", raw.Version, raw.Minor)
|
||||
fmt.Printf("no LibPy -- set to: %s\n", raw.LibPy)
|
||||
}
|
||||
|
||||
if strings.HasSuffix(raw.LibPy, ".a") {
|
||||
raw.LibPy = raw.LibPy[:len(raw.LibPy)-len(".a")]
|
||||
}
|
||||
|
|
10
cmd_build.go
10
cmd_build.go
|
@ -197,6 +197,16 @@ func runBuild(mode bind.BuildMode, cfg *BuildCfg) error {
|
|||
return err
|
||||
}
|
||||
|
||||
if bind.WindowsOS {
|
||||
fmt.Printf("Doing windows sed hack to fix declspec for PyInit\n")
|
||||
cmd = exec.Command("sed", "-i", "s/ PyInit_/ __declspec(dllexport) PyInit_/g", cfg.Name+".c")
|
||||
cmdout, err = cmd.CombinedOutput()
|
||||
if err != nil {
|
||||
fmt.Printf("cmd had error: %v output:\no%v\n", err, string(cmdout))
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
cflags := strings.Fields(strings.TrimSpace(pycfg.CFlags))
|
||||
cflags = append(cflags, "-fPIC", "-Ofast")
|
||||
if include, exists := os.LookupEnv("GOPY_INCLUDE"); exists {
|
||||
|
|
|
@ -937,7 +937,7 @@ func writeGoMod(t *testing.T, pkgDir, tstDir string) {
|
|||
module dummy
|
||||
|
||||
require github.com/go-python/gopy v0.0.0
|
||||
replace github.com/go-python/gopy => "%s"
|
||||
replace github.com/go-python/gopy => %s
|
||||
`
|
||||
contents := fmt.Sprintf(template, pkgDir)
|
||||
if err := ioutil.WriteFile(filepath.Join(tstDir, "go.mod"), []byte(contents), 0666); err != nil {
|
||||
|
|
|
@ -2,11 +2,18 @@
|
|||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build windows
|
||||
// +build windows
|
||||
|
||||
package main
|
||||
|
||||
import "github.com/go-python/gopy/bind"
|
||||
|
||||
const (
|
||||
libExt = ".dll"
|
||||
libExt = ".pyd"
|
||||
extraGccArgs = ""
|
||||
)
|
||||
|
||||
func init() {
|
||||
bind.WindowsOS = true
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// Copyright 2015 The go-python Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build windows
|
||||
// +build windows
|
||||
|
||||
package main
|
||||
|
@ -10,30 +10,22 @@ import (
|
|||
"log"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func init() {
|
||||
|
||||
testEnvironment = os.Environ()
|
||||
|
||||
var (
|
||||
py2 = "python2"
|
||||
py3 = "python3"
|
||||
pypy2 = "pypy"
|
||||
pypy3 = "pypy3"
|
||||
// py2 = "python2"
|
||||
py3 = "python3"
|
||||
// pypy2 = "pypy"
|
||||
// pypy3 = "pypy3"
|
||||
)
|
||||
|
||||
if os.Getenv("GOPY_APPVEYOR_CI") == "1" {
|
||||
log.Printf("Running in appveyor CI")
|
||||
var (
|
||||
cpy2dir = os.Getenv("CPYTHON2DIR")
|
||||
cpy3dir = os.Getenv("CPYTHON3DIR")
|
||||
pypy2dir = os.Getenv("PYPY2DIR")
|
||||
pypy3dir = os.Getenv("PYPY3DIR")
|
||||
)
|
||||
py2 = path.Join(cpy2dir, "python")
|
||||
py3 = path.Join(cpy3dir, "python")
|
||||
pypy2 = path.Join(pypy2dir, "pypy")
|
||||
pypy3 = path.Join(pypy3dir, "pypy")
|
||||
if os.Getenv("GOPY_TRAVIS_CI") == "1" {
|
||||
log.Printf("Running in travis CI")
|
||||
}
|
||||
|
||||
var (
|
||||
|
@ -46,23 +38,26 @@ func init() {
|
|||
module string
|
||||
mandatory bool
|
||||
}{
|
||||
// {"py2", py2, "", true},
|
||||
{"py2-cffi", py2, "cffi", true},
|
||||
// {"py3", py3, "", true},
|
||||
{"py3-cffi", py3, "cffi", true},
|
||||
{"pypy2-cffi", pypy2, "cffi", false},
|
||||
{"pypy3-cffi", pypy3, "cffi", false},
|
||||
{"py3", py3, "", true},
|
||||
// {"py2", py2, "", true},
|
||||
} {
|
||||
args := []string{"-c", ""}
|
||||
if be.module != "" {
|
||||
args[1] = "import " + be.module
|
||||
}
|
||||
log.Printf("checking testbackend: %q...", be.name)
|
||||
cmd := exec.Command(be.vm, args...)
|
||||
cmd.Stdin = os.Stdin
|
||||
cmd.Stdout = os.Stdout
|
||||
cmd.Stderr = os.Stderr
|
||||
err := cmd.Run()
|
||||
|
||||
py, err := exec.LookPath(be.vm)
|
||||
if err != nil {
|
||||
log.Printf("gopy: could not locate 'python' executable (err: %v)", err)
|
||||
} else {
|
||||
log.Printf("python executable found at: %s\n", py)
|
||||
cmd := exec.Command(py, args...)
|
||||
cmd.Stdin = os.Stdin
|
||||
cmd.Stdout = os.Stdout
|
||||
cmd.Stderr = os.Stderr
|
||||
err = cmd.Run()
|
||||
}
|
||||
if err != nil {
|
||||
log.Printf("disabling testbackend: %q, error: '%s'", be.name, err.Error())
|
||||
testBackends[be.name] = ""
|
||||
|
@ -79,8 +74,8 @@ func init() {
|
|||
if len(disabled) > 0 {
|
||||
log.Printf("The following test backends are not available: %s",
|
||||
strings.Join(disabled, ", "))
|
||||
if os.Getenv("GOPY_APPVEYOR_CI") == "1" && missing > 0 {
|
||||
log.Fatalf("Not all backends available in appveyor CI")
|
||||
if os.Getenv("GOPY_TRAVIS_CI") == "1" && missing > 0 {
|
||||
log.Fatalf("Not all backends available in travis CI")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue