1 // Copyright (c) 2020 Cisco and/or its affiliates.
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at:
7 // http://www.apache.org/licenses/LICENSE-2.0
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
26 "github.com/sirupsen/logrus"
28 "git.fd.io/govpp.git/binapigen/vppapi"
32 OutputDir string // output directory for generated files
33 ImportPrefix string // prefix for import paths
34 NoVersionInfo bool // disables generating version info
35 NoSourcePathInfo bool // disables the 'source: /path' comment
38 func Run(apiDir string, filesToGenerate []string, opts Options, f func(*Generator) error) {
39 if err := run(apiDir, filesToGenerate, opts, f); err != nil {
40 fmt.Fprintf(os.Stderr, "%s: %v\n", filepath.Base(os.Args[0]), err)
45 func run(apiDir string, filesToGenerate []string, opts Options, fn func(*Generator) error) error {
46 apiFiles, err := vppapi.ParseDir(apiDir)
51 if opts.ImportPrefix == "" {
52 opts.ImportPrefix, err = resolveImportPath(opts.OutputDir)
54 return fmt.Errorf("cannot resolve import path for output dir %s: %w", opts.OutputDir, err)
56 logrus.Infof("resolved import path prefix: %s", opts.ImportPrefix)
59 gen, err := New(opts, apiFiles, filesToGenerate)
64 gen.vppVersion = vppapi.ResolveVPPVersion(apiDir)
65 if gen.vppVersion == "" {
66 gen.vppVersion = "unknown"
72 if err := fn(gen); err != nil {
77 if err = gen.Generate(); err != nil {
84 func GenerateDefault(gen *Generator) {
85 for _, file := range gen.Files {
89 GenerateAPI(gen, file)
90 GenerateRPC(gen, file)
94 var Logger = logrus.New()
97 if debug := os.Getenv("DEBUG_GOVPP"); strings.Contains(debug, "binapigen") {
98 Logger.SetLevel(logrus.DebugLevel)
99 logrus.SetLevel(logrus.DebugLevel)
103 func logf(f string, v ...interface{}) {
104 Logger.Debugf(f, v...)
107 // resolveImportPath tries to resolve import path for a directory.
108 func resolveImportPath(dir string) (string, error) {
109 absPath, err := filepath.Abs(dir)
113 modRoot := findGoModuleRoot(absPath)
117 modPath, err := readModulePath(path.Join(modRoot, "go.mod"))
121 relDir, err := filepath.Rel(modRoot, absPath)
125 return filepath.Join(modPath, relDir), nil
128 // findGoModuleRoot looks for enclosing Go module.
129 func findGoModuleRoot(dir string) (root string) {
130 dir = filepath.Clean(dir)
132 if fi, err := os.Stat(filepath.Join(dir, "go.mod")); err == nil && !fi.IsDir() {
135 d := filepath.Dir(dir)
144 var modulePathRE = regexp.MustCompile(`module[ \t]+([^ \t\r\n]+)`)
146 // readModulePath reads module path from go.mod file.
147 func readModulePath(gomod string) (string, error) {
148 data, err := ioutil.ReadFile(gomod)
152 m := modulePathRE.FindSubmatch(data)
156 return string(m[1]), nil