gopy: proper handling of lang option

This CL introduces a split in handling of {py|py2|py3}{thon,}.
It also lifts up the bind.Package creation so the processing is done only once.

Change-Id: I946605fb24885df986baa77088f76df90ff4d168
This commit is contained in:
Sebastien Binet 2015-08-03 14:24:50 +02:00
parent 2f34f14535
commit 63c5bca8e1
4 changed files with 98 additions and 48 deletions

View File

@ -6,7 +6,6 @@ package main
import (
"fmt"
"go/build"
"io/ioutil"
"log"
"os"
@ -32,6 +31,7 @@ ex:
Flag: *flag.NewFlagSet("gopy-bind", flag.ExitOnError),
}
cmd.Flag.String("lang", "py2", "python version to use for bindings (python2|py2|python3|py3)")
cmd.Flag.String("output", "", "output directory for bindings")
return cmd
}
@ -47,6 +47,7 @@ func gopyRunCmdBind(cmdr *commander.Command, args []string) error {
}
odir := cmdr.Flag.Lookup("output").Value.Get().(string)
lang := cmdr.Flag.Lookup("lang").Value.Get().(string)
cwd, err := os.Getwd()
if err != nil {
@ -69,7 +70,7 @@ func gopyRunCmdBind(cmdr *commander.Command, args []string) error {
}
path := args[0]
pkg, err := build.Import(path, cwd, 0)
pkg, err := newPackage(path)
if err != nil {
return fmt.Errorf(
"gopy-bind: go/build.Inport failed with path=%q: %v\n",
@ -90,30 +91,12 @@ func gopyRunCmdBind(cmdr *commander.Command, args []string) error {
}
//defer os.RemoveAll(work)
cmd := exec.Command(
"gopy", "gen",
"-output", work,
"-lang=python", pkg.ImportPath,
)
cmd.Stdin = os.Stdin
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
err = cmd.Run()
err = genPkg(work, pkg, lang)
if err != nil {
return err
}
cmd = exec.Command(
"gopy", "gen",
"-output", work,
"-lang=go", pkg.ImportPath,
)
cmd.Stdin = os.Stdin
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
err = cmd.Run()
err = genPkg(work, pkg, "go")
if err != nil {
return err
}
@ -129,9 +112,9 @@ func gopyRunCmdBind(cmdr *commander.Command, args []string) error {
}
defer os.RemoveAll(wbind)
cmd = exec.Command(
cmd := exec.Command(
"go", "build", "-v", "-buildmode=c-shared",
"-o", filepath.Join(wbind, pkg.Name)+".so",
"-o", filepath.Join(wbind, pkg.Name())+".so",
// pkg.ImportPath,
".",
)
@ -146,8 +129,8 @@ func gopyRunCmdBind(cmdr *commander.Command, args []string) error {
cmd = exec.Command(
"/bin/cp",
filepath.Join(wbind, pkg.Name)+".so",
filepath.Join(odir, pkg.Name)+".so",
filepath.Join(wbind, pkg.Name())+".so",
filepath.Join(odir, pkg.Name())+".so",
)
cmd.Stdin = os.Stdin
cmd.Stdout = os.Stdout

View File

@ -6,7 +6,6 @@ package main
import (
"fmt"
"go/build"
"log"
"os"
"path/filepath"
@ -73,7 +72,7 @@ func gopyRunCmdGen(cmdr *commander.Command, args []string) error {
}
path := args[0]
pkg, err := build.Import(path, cwd, 0)
pkg, err := newPackage(path)
if err != nil {
return fmt.Errorf(
"gopy-gen: go/build.Inport failed with path=%q: %v\n",

63
gen.go
View File

@ -26,31 +26,22 @@ var (
fset = token.NewFileSet()
)
func genPkg(odir string, pkg *build.Package, lang string) error {
func genPkg(odir string, p *bind.Package, lang string) error {
var err error
var o *os.File
files, err := parseFiles(pkg.Dir, pkg.GoFiles)
if err != nil {
return err
}
conf := loader.Config{
Fset: fset,
}
conf.TypeChecker.Error = func(e error) {
log.Printf("%v\n", e)
err = e
}
p, err := newPackage(files, &conf, pkg)
if err != nil {
log.Printf("%v\n", err)
return err
switch lang {
case "python", "py":
lang, err = getPythonVersion()
if err != nil {
return err
}
default:
// no-op
}
switch lang {
case "python", "py":
case "python2", "py2":
o, err = os.Create(filepath.Join(odir, p.Name()+".c"))
if err != nil {
return err
@ -61,6 +52,9 @@ func genPkg(odir string, pkg *build.Package, lang string) error {
return err
}
case "python3", "py3":
return fmt.Errorf("gopy: python-3 support not yet implemented")
case "go":
o, err = os.Create(filepath.Join(odir, p.Name()+".go"))
if err != nil {
@ -147,7 +141,36 @@ func parseFiles(dir string, fnames []string) ([]*ast.File, error) {
return files, err
}
func newPackage(files []*ast.File, conf *loader.Config, pkg *build.Package) (*bind.Package, error) {
func newPackage(path string) (*bind.Package, error) {
cwd, err := os.Getwd()
if err != nil {
return nil, err
}
pkg, err := build.Import(path, cwd, 0)
files, err := parseFiles(pkg.Dir, pkg.GoFiles)
if err != nil {
return nil, err
}
conf := loader.Config{
Fset: fset,
}
conf.TypeChecker.Error = func(e error) {
log.Printf("%v\n", e)
err = e
}
p, err := newPackageFrom(files, &conf, pkg)
if err != nil {
log.Printf("%v\n", err)
return nil, err
}
return p, err
}
func newPackageFrom(files []*ast.File, conf *loader.Config, pkg *build.Package) (*bind.Package, error) {
conf.CreateFromFiles(pkg.ImportPath, files...)
program, err := conf.Load()

45
python.go Normal file
View File

@ -0,0 +1,45 @@
// 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.
package main
import (
"bytes"
"fmt"
"os/exec"
)
// getPythonVersion returns the python version available on this machine
func getPythonVersion() (string, error) {
py, err := exec.LookPath("python")
if err != nil {
return "", fmt.Errorf(
"gopy: could not locate 'python' executable (err: %v)",
err,
)
}
out, err := exec.Command(py, "--version").Output()
if err != nil {
return "", fmt.Errorf(
"gopy: error retrieving python version (err: %v)",
err,
)
}
vers := ""
switch {
case bytes.HasPrefix(out, []byte("Python 2")):
vers = "py2"
case bytes.HasPrefix(out, []byte("Python 3")):
vers = "py3"
default:
return "", fmt.Errorf(
"gopy: invalid python version (%s)",
string(out),
)
}
return vers, nil
}