14 # GoVPP API generator generates Go bindings compatible with the local VPP
18 def get_go_version(go_root):
19 # Returns version of the installed Go
20 p = subprocess.Popen(["./go", "version"],
22 stdout=subprocess.PIPE,
23 universal_newlines=True, )
24 output, _ = p.communicate()
25 output_fmt = output.replace("go version go", "", 1)
27 return output_fmt.rstrip("\n")
30 # Returns version of the installed binary API generator
31 def get_binapi_gen_version(go_path):
32 p = subprocess.Popen(["./binapi-generator", "-version"],
34 stdout=subprocess.PIPE,
35 universal_newlines=True, )
36 output, _ = p.communicate()
37 output_fmt = output.replace("govpp", "", 1)
39 return output_fmt.rstrip("\n")
42 # Verifies local Go installation and installs the latest
44 def install_golang(go_root):
45 go_bin = go_root + "/bin/go"
47 if os.path.exists(go_bin) and os.path.isfile(go_bin):
48 print('Go ' + get_go_version(go_root) + ' is already installed')
51 filename = requests.get(
52 'https://golang.org/VERSION?m=text').text + ".linux-amd64.tar.gz"
53 url = "https://dl.google.com/go/" + filename
55 print("Go binary not found, installing the latest version...")
56 print("Download url = %s" % url)
57 print("Install directory = %s" % go_root)
58 text = input("[Y/n] ?")
60 if text.strip().lower() != "y" and text.strip().lower() != "yes":
64 go_folders = ['src', 'pkg', 'bin']
67 if not os.path.exists(os.path.join(go_root, f)):
68 os.makedirs(os.path.join(go_root, f))
70 with open("/tmp/" + filename, 'wb') as f:
73 go_tf = tarfile.open("/tmp/" + filename)
74 # Strip /go dir from the go_root path as it will
75 # be created while extracting the tar file
76 go_root_head, _ = os.path.split(go_root)
77 go_tf.extractall(path=go_root_head)
79 os.remove("/tmp/" + filename)
81 print('Go ' + get_go_version(go_root) + ' was installed')
84 # Installs latest binary API generator
85 def install_binapi_gen(c, go_root, go_path):
86 os.environ['GO111MODULE'] = "on"
87 if (os.path.exists(go_root + "/bin/go") and
88 os.path.isfile(go_root + "/bin/go")):
89 p = subprocess.Popen(["./go", "get",
90 "git.fd.io/govpp.git/cmd/binapi-generator@" + c],
92 stdout=subprocess.PIPE,
93 stderr=subprocess.PIPE,
94 universal_newlines=True, )
95 _, error = p.communicate()
97 print("binapi generator installation failed: %d %s" %
98 (p.returncode, error))
100 bg_ver = get_binapi_gen_version(go_path)
101 print('Installed binary API generator ' + bg_ver)
104 # Creates generated bindings using GoVPP binapigen to the target folder
105 def generate_api(output_dir, vpp_dir, api_list, import_prefix,
107 json_dir = vpp_dir + "/build-root/install-vpp-native/vpp/share/vpp/api"
109 if not os.path.exists(json_dir):
110 print("Missing JSON api definitions")
113 print("Generating API")
114 cmd = ["./binapi-generator", "--input-dir=" + json_dir]
116 cmd += ["--output-dir=" + output_dir]
118 print("Following API files were requested by 'GO_API_FILES': " +
120 print("Note that dependency requirements may generate "
121 "additional API files")
124 cmd.append("-import-prefix=" + import_prefix)
126 cmd.append("-no-source-path-info")
127 p = subprocess.Popen(cmd, cwd=go_path + "/bin",
128 stdout=subprocess.PIPE,
129 stderr=subprocess.PIPE,
130 universal_newlines=True, )
132 out = p.communicate()[1]
133 if p.returncode != 0:
134 print("go api generate failed: %d %s" % (p.returncode, out))
137 # Print nice output of the binapi generator
138 for msg in out.split():
144 print("Go API bindings were generated to " + output_dir)
148 # project root directory
149 root = pathlib.Path(os.path.dirname(os.path.abspath(__file__)))
150 vpp_dir = root.parent.parent.parent
152 parser = argparse.ArgumentParser()
153 parser.add_argument("-govpp-commit", "--govpp-commit",
154 help="GoVPP commit or branch "
155 "(defaults to v0.3.5-45-g671f16c)",
156 default="671f16c", # fixed GoVPP version
158 parser.add_argument("-output-dir", "--output-dir",
159 help="output target directory for generated bindings",
161 default=os.path.join(vpp_dir, "vppbinapi"))
162 parser.add_argument("-api-files", "--api-files",
163 help="api files to generate (without commas)",
167 parser.add_argument("-import-prefix", "--import-prefix",
168 help="prefix imports in the generated go code",
171 parser.add_argument("-no-source-path-info", "--no-source-path-info",
172 help="disable source path info in generated files",
176 args = parser.parse_args()
178 # go specific environment variables
179 if "GOROOT" in os.environ:
180 go_root = os.environ['GOROOT']
182 go_binary = shutil.which("go")
184 go_binary_dir, _ = os.path.split(go_binary)
185 go_root = os.path.join(go_binary_dir, "..")
187 go_root = os.environ['HOME'] + "/.go"
188 if "GOPATH" in os.environ:
189 go_path = os.environ['GOPATH']
191 go_path = os.environ['HOME'] + "/go"
193 install_golang(go_root)
194 install_binapi_gen(args.govpp_commit, go_root, go_path)
195 generate_api(args.output_dir, str(vpp_dir), args.api_files,
196 args.import_prefix, args.no_source_path_info, go_path)
199 if __name__ == "__main__":