Skip to content
This repository was archived by the owner on Jul 24, 2023. It is now read-only.

Commit b38845b

Browse files
committed
all: add Windows CI support
Fixes #32.
1 parent 53a27e0 commit b38845b

File tree

4 files changed

+177
-2
lines changed

4 files changed

+177
-2
lines changed

README.md

+1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ go-python
22
=========
33

44
[![Build Status](https://drone.io/github.com/sbinet/go-python/status.png)](https://drone.io/github.com/sbinet/go-python/latest)
5+
[![Build status](https://ci.appveyor.com/api/projects/status/n0ujg8no487a89vo/branch/master?svg=true)](https://ci.appveyor.com/project/sbinet/go-python/branch/master)
56

67
Naive `go` bindings towards the C-API of CPython-2.
78

appveyor.yml

+29
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
build: off
2+
3+
clone_folder: c:\gopath\src\github.com\sbinet\go-python
4+
5+
cache:
6+
- '%LocalAppData%\\go-build'
7+
- '%LocalAppData%\\pip'
8+
9+
branches:
10+
only:
11+
- master
12+
13+
environment:
14+
GOPATH: c:\gopath
15+
GOPY_APPVEYOR_CI: '1'
16+
GODEBUG: 'cgocheck=0'
17+
GOTRACEBACK: 'crash'
18+
PYTHONUNBUFFERED: "1"
19+
CPYTHON2DIR: "C:\\Python27-x64"
20+
PATH: '%GOPATH%\bin;%CPYTHON2DIR%;%CPYTHON2DIR%\\Scripts;C:\msys64\mingw64\bin;C:\msys64\usr\bin\;%PATH%'
21+
22+
stack: go 1.11
23+
24+
build_script:
25+
- "%CPYTHON2DIR%\\python --version"
26+
- go get -v -t ./...
27+
28+
test_script:
29+
- go test ./...

cgoflags_windows.go

+6-2
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,11 @@
22

33
package python
44

5-
// #cgo CFLAGS: -IC:/Python27/include
6-
// #cgo LDFLAGS: -LC:/Python27/libs -lpython27
5+
// #cgo 386 CFLAGS: -I C:/Python27/include
6+
// #cgo amd64 CFLAGS: -I C:/Python27-x64/include
7+
// #cgo amd64 CFLAGS: -D MS_WIN64
8+
// #cgo 386 LDFLAGS: -L C:/Python27/libs -lpython27
9+
// #cgo amd64 LDFLAGS: -L C:/Python27-x64/libs -lpython27
10+
//
711
// #include "go-python.h"
812
import "C"

gen-cgoflags.go

+141
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
// +build ignore
2+
3+
// simple command to generate CGOFLAGS for a given python VM
4+
package main
5+
6+
import (
7+
"bytes"
8+
"encoding/json"
9+
"flag"
10+
"fmt"
11+
"io/ioutil"
12+
"log"
13+
"os"
14+
"os/exec"
15+
"runtime"
16+
"strings"
17+
18+
"github.com/pkg/errors"
19+
)
20+
21+
func main() {
22+
vm := flag.String("vm", "python", "path to a python VM")
23+
flag.Parse()
24+
25+
if *vm == "" {
26+
log.Fatalf("need a python VM")
27+
}
28+
29+
cfg, err := getPythonConfig(*vm)
30+
if err != nil {
31+
log.Fatalf("could not infer python configuration: %v", err)
32+
}
33+
34+
oname := "cgoflags_unix.go"
35+
switch runtime.GOOS {
36+
case "windows":
37+
oname = "cgoflags_windows.go"
38+
}
39+
40+
err = ioutil.WriteFile(oname, []byte(fmt.Sprintf(tmpl,
41+
cfg.cflags,
42+
cfg.ldflags,
43+
runtime.GOOS,
44+
)), 0644)
45+
if err != nil {
46+
log.Fatalf("could not write %q: %v", oname, err)
47+
}
48+
}
49+
50+
// getPythonConfig returns the needed python configuration for the given
51+
// python VM (python, python2, python3, pypy, etc...)
52+
func getPythonConfig(vm string) (pyconfig, error) {
53+
code := `import sys
54+
import distutils.sysconfig as ds
55+
import json
56+
print(ds.get_config_vars())
57+
print(ds.get_python_lib())
58+
print(json.dumps({
59+
"version": sys.version_info.major,
60+
"prefix": ds.get_config_var("prefix"),
61+
"incdir": ds.get_python_inc(),
62+
"libdir": ds.get_config_var("LIBDIR"),
63+
"libdest": ds.get_config_var("LIBDEST"),
64+
"libpy": ds.get_config_var("LIBRARY"),
65+
"shlibs": ds.get_config_var("SHLIBS"),
66+
"syslibs": ds.get_config_var("SYSLIBS"),
67+
"shlinks": ds.get_config_var("LINKFORSHARED"),
68+
"DLLs": ds.get_config_var("DLLLIBRARY"),
69+
}))
70+
`
71+
72+
var cfg pyconfig
73+
bin, err := exec.LookPath(vm)
74+
if err != nil {
75+
return cfg, errors.Wrapf(err, "could not locate python vm %q", vm)
76+
}
77+
78+
buf := new(bytes.Buffer)
79+
cmd := exec.Command(bin, "-c", code)
80+
cmd.Stdin = os.Stdin
81+
cmd.Stdout = buf
82+
cmd.Stderr = os.Stderr
83+
err = cmd.Run()
84+
if err != nil {
85+
return cfg, errors.Wrap(err, "could not run python-config script")
86+
}
87+
88+
log.Printf("distutils:\n%s", buf.String())
89+
90+
var raw struct {
91+
Version int `json:"version"`
92+
IncDir string `json:"incdir"`
93+
LibDir string `json:"libdir"`
94+
LibPy string `json:"libpy"`
95+
ShLibs string `json:"shlibs"`
96+
SysLibs string `json:"syslibs"`
97+
}
98+
err = json.NewDecoder(buf).Decode(&raw)
99+
if err != nil {
100+
return cfg, errors.Wrapf(err, "could not decode JSON script output")
101+
}
102+
103+
if strings.HasSuffix(raw.LibPy, ".a") {
104+
raw.LibPy = raw.LibPy[:len(raw.LibPy)-len(".a")]
105+
}
106+
if strings.HasPrefix(raw.LibPy, "lib") {
107+
raw.LibPy = raw.LibPy[len("lib"):]
108+
}
109+
110+
cfg.version = raw.Version
111+
cfg.cflags = strings.Join([]string{
112+
"-I " + raw.IncDir,
113+
}, " ")
114+
cfg.ldflags = strings.Join([]string{
115+
"-L " + raw.LibDir,
116+
"-l " + raw.LibPy,
117+
raw.ShLibs,
118+
raw.SysLibs,
119+
}, " ")
120+
121+
return cfg, nil
122+
}
123+
124+
type pyconfig struct {
125+
version int
126+
cflags string
127+
ldflags string
128+
}
129+
130+
const tmpl = `// Automatically generated. Do not edit.
131+
132+
// +build %[3]s
133+
134+
package python
135+
136+
// #cgo %[3]s CFLAGS: %[1]s
137+
// #cgo %[3]s LDFLAGS: %[2]s
138+
//
139+
// #include "go-python.h"
140+
import "C"
141+
`

0 commit comments

Comments
 (0)