diff options
author | Ondrej Fabry <ofabry@cisco.com> | 2020-07-17 10:36:28 +0200 |
---|---|---|
committer | Ondrej Fabry <ofabry@cisco.com> | 2020-07-17 11:43:41 +0200 |
commit | d1f24d37bd447b64e402298bb8eb2479681facf9 (patch) | |
tree | a3fc21ba730a91d8a402c7a5bf9c614e3677c4fc /binapigen/run.go | |
parent | 1548c7e12531e3d055567d761c580a1c7ff0ac40 (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.go | 132 |
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]) } |