aboutsummaryrefslogtreecommitdiffstats
path: root/binapigen/run.go
diff options
context:
space:
mode:
authorOndrej Fabry <ofabry@cisco.com>2020-07-17 10:36:28 +0200
committerOndrej Fabry <ofabry@cisco.com>2020-07-17 11:43:41 +0200
commitd1f24d37bd447b64e402298bb8eb2479681facf9 (patch)
treea3fc21ba730a91d8a402c7a5bf9c614e3677c4fc /binapigen/run.go
parent1548c7e12531e3d055567d761c580a1c7ff0ac40 (diff)
Improve binapi generator
- simplified Size/Marshal/Unmarshal methods - replace struc in unions with custom marshal/unmarshal - fix imports in generated files - fix mock adapter - generate rpc service using low-level stream API (dumps generate control ping or stream msg..) - move examples/binapi to binapi and generate all API for latest release - add binapigen.Plugin for developing custom generator plugins - optionally generate HTTP handlers (REST API) for RPC services - add govpp program for browsing VPP API Change-Id: I092e9ed2b0c17972b3476463c3d4b14dd76ed42b Signed-off-by: Ondrej Fabry <ofabry@cisco.com>
Diffstat (limited to 'binapigen/run.go')
-rw-r--r--binapigen/run.go132
1 files changed, 104 insertions, 28 deletions
diff --git a/binapigen/run.go b/binapigen/run.go
index e6086ee..88e32b7 100644
--- a/binapigen/run.go
+++ b/binapigen/run.go
@@ -16,69 +16,145 @@ package binapigen
import (
"fmt"
+ "io/ioutil"
"os"
+ "path"
"path/filepath"
+ "regexp"
+ "strings"
+
+ "github.com/sirupsen/logrus"
"git.fd.io/govpp.git/binapigen/vppapi"
)
-const (
- outputFileExt = ".ba.go" // file extension of the Go generated files
- rpcFileSuffix = "_rpc" // file name suffix for the RPC services
-)
+type Options struct {
+ OutputDir string // output directory for generated files
+ ImportPrefix string // prefix for import paths
+ NoVersionInfo bool // disables generating version info
+}
-func Run(apiDir string, opts Options, f func(*Generator) error) {
- if err := run(apiDir, opts, f); err != nil {
+func Run(apiDir string, filesToGenerate []string, opts Options, f func(*Generator) error) {
+ if err := run(apiDir, filesToGenerate, opts, f); err != nil {
fmt.Fprintf(os.Stderr, "%s: %v\n", filepath.Base(os.Args[0]), err)
os.Exit(1)
}
}
-func run(apiDir string, opts Options, f func(*Generator) error) error {
- // parse API files
+func run(apiDir string, filesToGenerate []string, opts Options, fn func(*Generator) error) error {
apifiles, err := vppapi.ParseDir(apiDir)
if err != nil {
return err
}
- g, err := New(opts, apifiles)
+ if opts.ImportPrefix == "" {
+ opts.ImportPrefix = resolveImportPath(opts.OutputDir)
+ logrus.Debugf("resolved import prefix: %s", opts.ImportPrefix)
+ }
+
+ gen, err := New(opts, apifiles, filesToGenerate)
if err != nil {
return err
}
- if err := f(g); err != nil {
- return err
+ gen.vppVersion = vppapi.ResolveVPPVersion(apiDir)
+ if gen.vppVersion == "" {
+ gen.vppVersion = "unknown"
}
- if err = g.Generate(); err != nil {
+ if fn == nil {
+ GenerateDefault(gen)
+ } else {
+ if err := fn(gen); err != nil {
+ return err
+ }
+ }
+
+ if err = gen.Generate(); err != nil {
return err
}
return nil
}
-func GenerateBinapi(gen *Generator, file *File, outputDir string) *GenFile {
- packageDir := filepath.Join(outputDir, file.PackageName)
- filename := filepath.Join(packageDir, file.PackageName+outputFileExt)
+func GenerateDefault(gen *Generator) {
+ for _, file := range gen.Files {
+ if !file.Generate {
+ continue
+ }
+ GenerateAPI(gen, file)
+ GenerateRPC(gen, file)
+ }
+}
- g := gen.NewGenFile(filename)
- g.file = file
- g.outputDir = outputDir
+var Logger = logrus.New()
- generateFileBinapi(g, &g.buf)
+func init() {
+ if debug := os.Getenv("DEBUG_GOVPP"); strings.Contains(debug, "binapigen") {
+ Logger.SetLevel(logrus.DebugLevel)
+ logrus.SetLevel(logrus.DebugLevel)
+ } else if debug != "" {
+ Logger.SetLevel(logrus.InfoLevel)
+ } else {
+ Logger.SetLevel(logrus.WarnLevel)
+ }
+}
- return g
+func logf(f string, v ...interface{}) {
+ Logger.Debugf(f, v...)
}
-func GenerateRPC(gen *Generator, file *File, outputDir string) *GenFile {
- packageDir := filepath.Join(outputDir, file.PackageName)
- filename := filepath.Join(packageDir, file.PackageName+rpcFileSuffix+outputFileExt)
+func resolveImportPath(dir string) string {
+ absPath, err := filepath.Abs(dir)
+ if err != nil {
+ panic(err)
+ }
+ modRoot := findGoModuleRoot(absPath)
+ if modRoot == "" {
+ logrus.Fatalf("module root not found at: %s", absPath)
+ }
+ modPath := findModulePath(path.Join(modRoot, "go.mod"))
+ if modPath == "" {
+ logrus.Fatalf("module path not found")
+ }
+ relDir, err := filepath.Rel(modRoot, absPath)
+ if err != nil {
+ panic(err)
+ }
+ return filepath.Join(modPath, relDir)
+}
- g := gen.NewGenFile(filename)
- g.file = file
- g.outputDir = outputDir
+func findGoModuleRoot(dir string) (root string) {
+ if dir == "" {
+ panic("dir not set")
+ }
+ dir = filepath.Clean(dir)
+ // Look for enclosing go.mod.
+ for {
+ if fi, err := os.Stat(filepath.Join(dir, "go.mod")); err == nil && !fi.IsDir() {
+ return dir
+ }
+ d := filepath.Dir(dir)
+ if d == dir {
+ break
+ }
+ dir = d
+ }
+ return ""
+}
- generateFileRPC(g, &g.buf)
+var (
+ modulePathRE = regexp.MustCompile(`module[ \t]+([^ \t\r\n]+)`)
+)
- return g
+func findModulePath(file string) string {
+ data, err := ioutil.ReadFile(file)
+ if err != nil {
+ return ""
+ }
+ m := modulePathRE.FindSubmatch(data)
+ if m == nil {
+ return ""
+ }
+ return string(m[1])
}