bind: discover pkgconfig package name

This CL enhances gengo with the ability to discover the latest python.pc
package name and adds it to the #cgo pkgconfig pragma.

Fixes #51.

Change-Id: If4d46d6fe90731df6b2cb4f9c39fb3ec967e7330
This commit is contained in:
Sebastien Binet 2015-08-31 10:23:57 +02:00
parent 6d80c41494
commit daf017bd41
4 changed files with 93 additions and 5 deletions

View File

@ -54,12 +54,13 @@ func GenCPython(w io.Writer, fset *token.FileSet, pkg *Package, lang int) error
}
// GenGo generates a cgo package from a Go package
func GenGo(w io.Writer, fset *token.FileSet, pkg *Package) error {
func GenGo(w io.Writer, fset *token.FileSet, pkg *Package, lang int) error {
buf := new(bytes.Buffer)
gen := &goGen{
printer: &printer{buf: buf, indentEach: []byte("\t")},
fset: fset,
pkg: pkg,
lang: lang,
}
err := gen.gen()
if err != nil {

View File

@ -7,7 +7,6 @@ package bind
import (
"fmt"
"go/token"
"path/filepath"
"strings"
"golang.org/x/tools/go/types"
@ -20,7 +19,7 @@ const (
// File is generated by gopy gen. Do not edit.
package main
//#cgo pkg-config: python2 --cflags --libs
//#cgo pkg-config: %[3]s --cflags --libs
//#include <stdlib.h>
//#include <string.h>
//#include <complex.h>
@ -134,6 +133,7 @@ type goGen struct {
fset *token.FileSet
pkg *Package
lang int // python's version API (2 or 3)
err ErrorList
}
@ -952,7 +952,12 @@ func (g *goGen) genPreamble() {
pkgimport = fmt.Sprintf("_ %q", g.pkg.pkg.Path())
}
g.Printf(goPreamble, n, pkgimport, filepath.Base(n))
pkgcfg, err := getPkgConfig(g.lang)
if err != nil {
panic(err)
}
g.Printf(goPreamble, n, pkgimport, pkgcfg)
}
func (g *goGen) tupleString(tuple []*Var) string {

View File

@ -5,7 +5,13 @@
package bind
import (
"bufio"
"bytes"
"fmt"
"io"
"os/exec"
"regexp"
"sort"
"golang.org/x/tools/go/types"
)
@ -79,3 +85,67 @@ func isConstructor(sig *types.Signature) bool {
//TODO(sbinet)
return false
}
// getPkgConfig returns the name of the pkg-config python's pc file
func getPkgConfig(vers int) (string, error) {
bin, err := exec.LookPath("pkg-config")
if err != nil {
return "", fmt.Errorf(
"gopy: could not locate 'pkg-config' executable (err: %v)",
err,
)
}
out, err := exec.Command(bin, "--list-all").Output()
if err != nil {
return "", fmt.Errorf(
"gopy: error retrieving the list of packages known to pkg-config (err: %v)",
err,
)
}
pkgs := []string{}
re := regexp.MustCompile(fmt.Sprintf(`^python(\s|-|\.|)%d.*?`, vers))
s := bufio.NewScanner(bytes.NewReader(out))
for s.Scan() {
err = s.Err()
if err != nil {
if err == io.EOF {
err = nil
}
break
}
line := s.Bytes()
if !bytes.HasPrefix(line, []byte("python")) {
continue
}
if !re.Match(line) {
continue
}
pkg := bytes.Split(line, []byte(" "))
pkgs = append(pkgs, string(pkg[0]))
}
if err != nil {
return "", fmt.Errorf(
"gopy: error scanning pkg-config output (err: %v)",
err,
)
}
if len(pkgs) <= 0 {
return "", fmt.Errorf(
"gopy: could not find pkg-config file (no python.pc installed?)",
)
}
sort.Strings(pkgs)
// FIXME(sbinet): make sure we take the latest version?
pkgcfg := pkgs[0]
return pkgcfg, nil
}

14
gen.go
View File

@ -40,6 +40,18 @@ func genPkg(odir string, p *bind.Package, lang string) error {
// no-op
}
pyvers := 2
switch lang {
case "python2", "py2":
pyvers = 2
case "python3", "py3":
pyvers = 3
}
if err != nil {
return err
}
switch lang {
case "python2", "py2":
o, err = os.Create(filepath.Join(odir, p.Name()+".c"))
@ -62,7 +74,7 @@ func genPkg(odir string, p *bind.Package, lang string) error {
}
defer o.Close()
err = bind.GenGo(o, fset, p)
err = bind.GenGo(o, fset, p, pyvers)
if err != nil {
return err
}