14 # GoVPP API generator generates Go bindings compatible with the local VPP
17 DefaultGoVppCommit = "16a47ef937b3a5ce6acf45885386062b323c8d25"
20 def version_geq(ver_a, ver_b):
21 major_a, minor_a, patch_a = ver_a.split(".")
22 major_b, minor_b, patch_b = ver_b.split(".")
25 elif major_a == major_b and minor_a > minor_b:
27 elif major_a == major_b and minor_a == minor_b and patch_a >= patch_b:
32 def execute(cli, cwd=None):
36 stdout=subprocess.PIPE,
37 stderr=subprocess.PIPE,
38 universal_newlines=True,
40 output, error = p.communicate()
42 print("Command `%s` failed: %d %s" % (cli, p.returncode, error))
47 def get_go_version(go_root):
48 # Returns version of the installed Go
49 output, _ = execute("./go version", cwd=go_root + "/bin")
50 return output.replace("go version go", "", 1).rstrip("\n")
53 # Returns version of the installed binary API generator
54 def get_binapi_gen_version(go_path):
55 output, _ = execute("./binapi-generator -version", cwd=go_path + "/bin")
56 return output.replace("govpp", "", 1).rstrip("\n")
59 # Verifies local Go installation and installs the latest
61 def install_golang(go_root):
62 go_bin = go_root + "/bin/go"
64 if os.path.exists(go_bin) and os.path.isfile(go_bin):
65 print("Go " + get_go_version(go_root) + " is already installed")
69 requests.get("https://golang.org/VERSION?m=text").text + ".linux-amd64.tar.gz"
71 url = "https://dl.google.com/go/" + filename
73 print("Go binary not found, installing the latest version...")
74 print("Download url = %s" % url)
75 print("Install directory = %s" % go_root)
76 text = input("[Y/n] ?")
78 if text.strip().lower() != "y" and text.strip().lower() != "yes":
82 go_folders = ["src", "pkg", "bin"]
85 if not os.path.exists(os.path.join(go_root, f)):
86 os.makedirs(os.path.join(go_root, f))
88 with open("/tmp/" + filename, "wb") as f:
91 go_tf = tarfile.open("/tmp/" + filename)
92 # Strip /go dir from the go_root path as it will
93 # be created while extracting the tar file
94 go_root_head, _ = os.path.split(go_root)
95 go_tf.extractall(path=go_root_head)
97 os.remove("/tmp/" + filename)
99 print("Go " + get_go_version(go_root) + " was installed")
102 # Installs latest binary API generator
103 def install_binapi_gen(c, go_root, go_path):
104 go_version = get_go_version(go_root)
105 if version_geq(go_version, "1.18.0"):
107 "./go install git.fd.io/govpp.git/cmd/binapi-generator@" + c,
108 cwd=go_root + "/bin",
111 os.environ["GO111MODULE"] = "on"
113 "./go get git.fd.io/govpp.git/cmd/binapi-generator@" + c,
114 cwd=go_root + "/bin",
116 bg_ver = get_binapi_gen_version(go_path)
117 print("Installed binary API generator " + bg_ver)
120 # Creates generated bindings using GoVPP binapigen to the target folder
121 def generate_api(output_dir, vpp_dir, api_list, import_prefix, no_source, go_path):
122 json_dir = vpp_dir + "/build-root/install-vpp-native/vpp/share/vpp/api"
124 if not os.path.exists(json_dir):
125 print("Missing JSON api definitions")
128 print("Generating API")
129 cmd = ["./binapi-generator", "--input-dir=" + json_dir]
131 cmd += ["--output-dir=" + output_dir]
133 print("Following API files were requested by 'GO_API_FILES': " + str(api_list))
134 print("Note that dependency requirements may generate additional API files")
137 cmd.append("-import-prefix=" + import_prefix)
139 cmd.append("-no-source-path-info")
141 _, out = execute(" ".join(cmd), cwd=go_path + "/bin")
142 # Print nice output of the binapi generator
143 for msg in out.split():
149 print("Go API bindings were generated to " + output_dir)
152 def get_go_variables():
153 # go specific environment variables
154 if "GOROOT" in os.environ:
155 go_root = os.environ["GOROOT"]
157 go_binary = shutil.which("go")
159 go_binary_dir, _ = os.path.split(go_binary)
160 go_root = os.path.join(go_binary_dir, "..")
162 go_root = os.environ["HOME"] + "/.go"
163 if "GOPATH" in os.environ:
164 go_path = os.environ["GOPATH"]
166 go_path = os.environ["HOME"] + "/go"
168 return go_root, go_path
172 # project root directory
173 root = pathlib.Path(os.path.dirname(os.path.abspath(__file__)))
174 vpp_dir = root.parent.parent.parent
176 parser = argparse.ArgumentParser()
180 help="GoVPP commit or branch ",
181 default=DefaultGoVppCommit,
187 help="output target directory for generated bindings",
189 default=os.path.join(vpp_dir, "vppbinapi"),
194 help="api files to generate (without commas)",
202 help="prefix imports in the generated go code",
207 "-no-source-path-info",
208 "--no-source-path-info",
209 help="disable source path info in generated files",
214 args = parser.parse_args()
216 go_root, go_path = get_go_variables()
217 install_golang(go_root)
220 os.path.exists(go_root + "/bin/go") and os.path.isfile(go_root + "/bin/go")
222 print(go_root + "/bin/go does not exist")
225 install_binapi_gen(args.govpp_commit, go_root, go_path)
231 args.no_source_path_info,
236 if __name__ == "__main__":