Skip to content

Commit

Permalink
bind: discover pkgconfig package name
Browse files Browse the repository at this point in the history
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
  • Loading branch information
sbinet committed Aug 31, 2015
1 parent 6d80c41 commit daf017b
Show file tree
Hide file tree
Showing 4 changed files with 93 additions and 5 deletions.
3 changes: 2 additions & 1 deletion bind/bind.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
11 changes: 8 additions & 3 deletions bind/gengo.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ package bind
import (
"fmt"
"go/token"
"path/filepath"
"strings"

"golang.org/x/tools/go/types"
Expand All @@ -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>
Expand Down Expand Up @@ -134,6 +133,7 @@ type goGen struct {

fset *token.FileSet
pkg *Package
lang int // python's version API (2 or 3)
err ErrorList
}

Expand Down Expand Up @@ -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 {
Expand Down
70 changes: 70 additions & 0 deletions bind/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,13 @@
package bind

import (
"bufio"
"bytes"
"fmt"
"io"
"os/exec"
"regexp"
"sort"

"golang.org/x/tools/go/types"
)
Expand Down Expand Up @@ -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 changes: 13 additions & 1 deletion gen.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"))
Expand All @@ -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
}
Expand Down

0 comments on commit daf017b

Please sign in to comment.