2015-01-30 17:01:15 +00:00
|
|
|
// 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 (
|
|
|
|
"fmt"
|
|
|
|
"go/ast"
|
2015-02-02 09:32:52 +00:00
|
|
|
"go/doc"
|
2015-01-30 17:01:15 +00:00
|
|
|
"go/parser"
|
|
|
|
"go/token"
|
2015-07-24 14:16:31 +00:00
|
|
|
"log"
|
2015-01-30 17:01:15 +00:00
|
|
|
"os"
|
2015-07-24 14:16:31 +00:00
|
|
|
"os/exec"
|
2015-01-30 17:01:15 +00:00
|
|
|
"path/filepath"
|
2019-02-22 10:33:05 +00:00
|
|
|
"strings"
|
2015-01-30 17:01:15 +00:00
|
|
|
|
2019-02-23 07:13:27 +00:00
|
|
|
"golang.org/x/tools/go/packages"
|
|
|
|
|
2019-02-11 10:47:24 +00:00
|
|
|
"github.com/goki/gopy/bind"
|
2019-01-11 11:00:12 +00:00
|
|
|
"github.com/pkg/errors"
|
2015-01-30 17:01:15 +00:00
|
|
|
)
|
|
|
|
|
2019-02-22 10:33:05 +00:00
|
|
|
// argStr returns the full command args as a string, without path to exe
|
|
|
|
func argStr() string {
|
|
|
|
ma := make([]string, len(os.Args))
|
|
|
|
copy(ma, os.Args)
|
|
|
|
_, cmd := filepath.Split(ma[0])
|
|
|
|
ma[0] = cmd
|
2019-02-27 08:45:58 +00:00
|
|
|
for i := range ma {
|
|
|
|
if strings.HasPrefix(ma[i], "-main=") {
|
|
|
|
ma[i] = "-main=\"" + ma[i][6:] + "\""
|
|
|
|
}
|
|
|
|
}
|
2019-02-22 10:33:05 +00:00
|
|
|
return strings.Join(ma, " ")
|
|
|
|
}
|
2015-08-31 08:23:57 +00:00
|
|
|
|
2019-02-22 10:33:05 +00:00
|
|
|
// genOutDir makes the output directory and returns its absolute path
|
|
|
|
func genOutDir(odir string) (string, error) {
|
|
|
|
cwd, err := os.Getwd()
|
2015-08-31 08:23:57 +00:00
|
|
|
if err != nil {
|
2019-02-22 10:33:05 +00:00
|
|
|
log.Fatal(err)
|
2015-08-31 08:23:57 +00:00
|
|
|
}
|
|
|
|
|
2019-02-22 10:33:05 +00:00
|
|
|
if odir == "" {
|
|
|
|
odir = cwd
|
|
|
|
} else {
|
|
|
|
err = os.MkdirAll(odir, 0755)
|
|
|
|
if err != nil {
|
|
|
|
return odir, fmt.Errorf("gopy-gen: could not create output directory: %v", err)
|
|
|
|
}
|
2019-02-12 09:55:34 +00:00
|
|
|
}
|
2019-02-22 10:33:05 +00:00
|
|
|
odir, err = filepath.Abs(odir)
|
2019-02-12 09:55:34 +00:00
|
|
|
if err != nil {
|
2019-02-22 10:33:05 +00:00
|
|
|
return odir, fmt.Errorf("gopy-gen: could not infer absolute path to output directory: %v", err)
|
2019-02-12 09:55:34 +00:00
|
|
|
}
|
2019-02-22 10:33:05 +00:00
|
|
|
return odir, nil
|
|
|
|
}
|
2015-07-24 14:16:31 +00:00
|
|
|
|
2019-02-22 10:33:05 +00:00
|
|
|
// genPkg generates output for all the current packages that have been parsed,
|
|
|
|
// in the given output directory
|
2019-03-06 10:41:03 +00:00
|
|
|
// mode = gen, build, pkg, exe
|
|
|
|
func genPkg(mode string, odir, outname, cmdstr, vm, mainstr string) error {
|
2019-02-22 10:33:05 +00:00
|
|
|
var err error
|
|
|
|
odir, err = genOutDir(odir)
|
2019-02-20 11:09:23 +00:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2019-02-22 10:33:05 +00:00
|
|
|
if !filepath.IsAbs(vm) {
|
|
|
|
vm, err = exec.LookPath(vm)
|
|
|
|
if err != nil {
|
|
|
|
return errors.Wrapf(err, "could not locate absolute path to python VM")
|
|
|
|
}
|
|
|
|
}
|
2019-02-20 11:09:23 +00:00
|
|
|
|
2019-02-22 10:33:05 +00:00
|
|
|
pyvers, err := getPythonVersion(vm)
|
2019-02-12 09:55:34 +00:00
|
|
|
if err != nil {
|
|
|
|
return err
|
2015-01-30 17:01:15 +00:00
|
|
|
}
|
2019-03-06 10:41:03 +00:00
|
|
|
err = bind.GenPyBind(mode, odir, outname, cmdstr, vm, mainstr, libExt, pyvers)
|
2015-01-30 17:01:15 +00:00
|
|
|
if err != nil {
|
2019-02-22 10:33:05 +00:00
|
|
|
log.Println(err)
|
2015-01-30 17:01:15 +00:00
|
|
|
}
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2015-08-03 12:24:50 +00:00
|
|
|
func newPackage(path string) (*bind.Package, error) {
|
|
|
|
cwd, err := os.Getwd()
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
2015-11-16 12:00:54 +00:00
|
|
|
cmd := exec.Command("go", "install", path)
|
|
|
|
cmd.Stdin = os.Stdin
|
|
|
|
cmd.Stdout = os.Stdout
|
|
|
|
cmd.Stderr = os.Stderr
|
|
|
|
cmd.Dir = cwd
|
|
|
|
|
|
|
|
err = cmd.Run()
|
2015-08-03 12:24:50 +00:00
|
|
|
if err != nil {
|
2015-11-16 12:00:54 +00:00
|
|
|
log.Printf("error installing [%s]: %v\n",
|
|
|
|
path,
|
|
|
|
err,
|
|
|
|
)
|
2015-08-03 12:24:50 +00:00
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
2019-02-23 07:13:27 +00:00
|
|
|
// golang.org/x/tools/go/packages supports loading of std library packages too
|
|
|
|
bpkgs, err := packages.Load(&packages.Config{Mode: packages.LoadTypes}, path)
|
2015-11-16 12:00:54 +00:00
|
|
|
if err != nil {
|
|
|
|
log.Printf("error resolving import path [%s]: %v\n",
|
|
|
|
path,
|
|
|
|
err,
|
|
|
|
)
|
|
|
|
return nil, err
|
2015-08-03 12:24:50 +00:00
|
|
|
}
|
2015-11-16 12:00:54 +00:00
|
|
|
|
2019-02-23 07:13:27 +00:00
|
|
|
bpkg := bpkgs[0] // only ever have one at a time
|
|
|
|
dir, _ := filepath.Split(bpkg.GoFiles[0])
|
|
|
|
p := bpkg.Types
|
2015-08-03 12:24:50 +00:00
|
|
|
|
2019-02-23 07:13:27 +00:00
|
|
|
if bpkg.Name == "main" {
|
|
|
|
err = fmt.Errorf("gopy: skipping 'main' package %q", bpkg.PkgPath)
|
|
|
|
fmt.Println(err)
|
2015-08-03 12:24:50 +00:00
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
2019-02-23 07:13:27 +00:00
|
|
|
fset := token.NewFileSet()
|
2015-02-02 09:32:52 +00:00
|
|
|
var pkgast *ast.Package
|
2019-02-23 07:13:27 +00:00
|
|
|
pkgs, err := parser.ParseDir(fset, dir, nil, parser.ParseComments)
|
2015-02-02 09:32:52 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
pkgast = pkgs[p.Name()]
|
2015-08-10 07:12:51 +00:00
|
|
|
if pkgast == nil {
|
|
|
|
return nil, fmt.Errorf("gopy: could not find AST for package %q", p.Name())
|
|
|
|
}
|
2015-02-02 09:32:52 +00:00
|
|
|
|
2019-02-23 07:13:27 +00:00
|
|
|
pkgdoc := doc.New(pkgast, bpkg.PkgPath, 0)
|
2015-07-27 16:47:18 +00:00
|
|
|
return bind.NewPackage(p, pkgdoc)
|
2015-02-02 09:32:52 +00:00
|
|
|
}
|