X-Git-Url: https://gerrit.fd.io/r/gitweb?a=blobdiff_plain;f=binapigen%2Frun.go;h=d632519b46e58232fa961d78c83f69d99a95e501;hb=833eaf3e97577cab97d6d5eedc5de29a5f862402;hp=441c43da2d16881384e16c45dc482b42a78bc20e;hpb=94620e85f0bdbb054af07ce3670fadc1f76cfdf0;p=govpp.git diff --git a/binapigen/run.go b/binapigen/run.go index 441c43d..d632519 100644 --- a/binapigen/run.go +++ b/binapigen/run.go @@ -16,74 +16,141 @@ package binapigen import ( "fmt" + "io/ioutil" "os" + "path" "path/filepath" + "regexp" + "strings" "github.com/sirupsen/logrus" "git.fd.io/govpp.git/binapigen/vppapi" ) -var debugMode = true +type Options struct { + OutputDir string // output directory for generated files + ImportPrefix string // prefix for import paths + NoVersionInfo bool // disables generating version info + NoSourcePathInfo bool // disables the 'source: /path' comment +} -func logf(f string, v ...interface{}) { - if debugMode { - logrus.Debugf(f, v...) +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 GenerateBinapiFile(gen *Generator, file *File, outputDir string) *GenFile { - packageDir := filepath.Join(outputDir, file.PackageName) - filename := filepath.Join(packageDir, file.PackageName+outputFileExt) - - g := gen.NewGenFile(filename) - g.file = file - g.packageDir = filepath.Join(outputDir, file.PackageName) +func run(apiDir string, filesToGenerate []string, opts Options, fn func(*Generator) error) error { + apiFiles, err := vppapi.ParseDir(apiDir) + if err != nil { + return err + } - generatePackage(g, &g.buf) + if opts.ImportPrefix == "" { + opts.ImportPrefix, err = resolveImportPath(opts.OutputDir) + if err != nil { + return fmt.Errorf("cannot resolve import path for output dir %s: %w", opts.OutputDir, err) + } + logrus.Debugf("resolved import path prefix: %s", opts.ImportPrefix) + } - return g -} + gen, err := New(opts, apiFiles, filesToGenerate) + if err != nil { + return err + } -func GenerateRPC(gen *Generator, file *File, outputDir string) *GenFile { - packageDir := filepath.Join(outputDir, file.PackageName) - filename := filepath.Join(packageDir, file.PackageName+rpcFileSuffix+outputFileExt) + gen.vppVersion = vppapi.ResolveVPPVersion(apiDir) + if gen.vppVersion == "" { + gen.vppVersion = "unknown" + } - g := gen.NewGenFile(filename) - g.file = file - g.packageDir = filepath.Join(outputDir, file.PackageName) + if fn == nil { + GenerateDefault(gen) + } else { + if err := fn(gen); err != nil { + return err + } + } + if err = gen.Generate(); err != nil { + return err + } - generatePackageRPC(g, &g.buf) + return nil +} - return g +func GenerateDefault(gen *Generator) { + for _, file := range gen.Files { + if !file.Generate { + continue + } + GenerateAPI(gen, file) + GenerateRPC(gen, file) + } } -func Run(apiDir string, opts Options, f func(*Generator) error) { - if err := run(apiDir, opts, f); err != nil { - fmt.Fprintf(os.Stderr, "%s: %v\n", filepath.Base(os.Args[0]), err) - os.Exit(1) +var Logger = logrus.New() + +func init() { + if debug := os.Getenv("DEBUG_GOVPP"); strings.Contains(debug, "binapigen") { + Logger.SetLevel(logrus.DebugLevel) + logrus.SetLevel(logrus.DebugLevel) } } -func run(apiDir string, opts Options, f func(*Generator) error) error { - // parse API files - apifiles, err := vppapi.ParseDir(apiDir) +func logf(f string, v ...interface{}) { + Logger.Debugf(f, v...) +} + +// resolveImportPath tries to resolve import path for a directory. +func resolveImportPath(dir string) (string, error) { + absPath, err := filepath.Abs(dir) if err != nil { - return err + return "", err } - - g, err := New(opts, apifiles) + modRoot := findGoModuleRoot(absPath) + if modRoot == "" { + return "", err + } + modPath, err := readModulePath(path.Join(modRoot, "go.mod")) if err != nil { - return err + return "", err } - - if err := f(g); err != nil { - return err + relDir, err := filepath.Rel(modRoot, absPath) + if err != nil { + return "", err } + return filepath.Join(modPath, relDir), nil +} - if err = g.Generate(); err != nil { - return err +// findGoModuleRoot looks for enclosing Go module. +func findGoModuleRoot(dir string) (root string) { + dir = filepath.Clean(dir) + 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 "" +} - return nil +var modulePathRE = regexp.MustCompile(`module[ \t]+([^ \t\r\n]+)`) + +// readModulePath reads module path from go.mod file. +func readModulePath(gomod string) (string, error) { + data, err := ioutil.ReadFile(gomod) + if err != nil { + return "", err + } + m := modulePathRE.FindSubmatch(data) + if m == nil { + return "", err + } + return string(m[1]), nil }