gopy/gen.go

143 lines
3.1 KiB
Go
Raw Normal View History

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