vppapigen: fix make go-api for go1.18
[vpp.git] / src / tools / vppapigen / generate_go.py
index fa53bc3..4ed507b 100755 (executable)
@@ -14,33 +14,46 @@ import sys
 # GoVPP API generator generates Go bindings compatible with the local VPP
 #
 
+DefaultGoVppCommit = "16a47ef937b3a5ce6acf45885386062b323c8d25"
 
-def get_go_version(go_root):
-    # Returns version of the installed Go
+
+def version_geq(ver_a, ver_b):
+    major_a, minor_a, patch_a = ver_a.split(".")
+    major_b, minor_b, patch_b = ver_b.split(".")
+    if major_a > major_b:
+        return True
+    elif major_a == major_b and minor_a > minor_b:
+        return True
+    elif major_a == major_b and minor_a == minor_b and patch_a >= patch_b:
+        return True
+    return False
+
+
+def execute(cli, cwd=None):
     p = subprocess.Popen(
-        ["./go", "version"],
-        cwd=go_root + "/bin",
+        cli.split(),
+        cwd=cwd,
         stdout=subprocess.PIPE,
+        stderr=subprocess.PIPE,
         universal_newlines=True,
     )
-    output, _ = p.communicate()
-    output_fmt = output.replace("go version go", "", 1)
+    output, error = p.communicate()
+    if p.returncode != 0:
+        print("Command `%s` failed: %d %s" % (cli, p.returncode, error))
+        sys.exit(1)
+    return output, error
 
-    return output_fmt.rstrip("\n")
+
+def get_go_version(go_root):
+    # Returns version of the installed Go
+    output, _ = execute("./go version", cwd=go_root + "/bin")
+    return output.replace("go version go", "", 1).rstrip("\n")
 
 
 # Returns version of the installed binary API generator
 def get_binapi_gen_version(go_path):
-    p = subprocess.Popen(
-        ["./binapi-generator", "-version"],
-        cwd=go_path + "/bin",
-        stdout=subprocess.PIPE,
-        universal_newlines=True,
-    )
-    output, _ = p.communicate()
-    output_fmt = output.replace("govpp", "", 1)
-
-    return output_fmt.rstrip("\n")
+    output, _ = execute("./binapi-generator -version", cwd=go_path + "/bin")
+    return output.replace("govpp", "", 1).rstrip("\n")
 
 
 # Verifies local Go installation and installs the latest
@@ -88,19 +101,18 @@ def install_golang(go_root):
 
 # Installs latest binary API generator
 def install_binapi_gen(c, go_root, go_path):
-    os.environ["GO111MODULE"] = "on"
-    if os.path.exists(go_root + "/bin/go") and os.path.isfile(go_root + "/bin/go"):
-        p = subprocess.Popen(
-            ["./go", "get", "git.fd.io/govpp.git/cmd/binapi-generator@" + c],
+    go_version = get_go_version(go_root)
+    if version_geq(go_version, "1.18.0"):
+        execute(
+            "./go install git.fd.io/govpp.git/cmd/binapi-generator@" + c,
+            cwd=go_root + "/bin",
+        )
+    else:
+        os.environ["GO111MODULE"] = "on"
+        execute(
+            "./go get git.fd.io/govpp.git/cmd/binapi-generator@" + c,
             cwd=go_root + "/bin",
-            stdout=subprocess.PIPE,
-            stderr=subprocess.PIPE,
-            universal_newlines=True,
         )
-        _, error = p.communicate()
-        if p.returncode != 0:
-            print("binapi generator installation failed: %d %s" % (p.returncode, error))
-            sys.exit(1)
     bg_ver = get_binapi_gen_version(go_path)
     print("Installed binary API generator " + bg_ver)
 
@@ -119,25 +131,14 @@ def generate_api(output_dir, vpp_dir, api_list, import_prefix, no_source, go_pat
         cmd += ["--output-dir=" + output_dir]
     if len(api_list):
         print("Following API files were requested by 'GO_API_FILES': " + str(api_list))
-        print("Note that dependency requirements may generate " "additional API files")
+        print("Note that dependency requirements may generate additional API files")
         cmd.append(api_list)
     if import_prefix:
         cmd.append("-import-prefix=" + import_prefix)
     if no_source:
         cmd.append("-no-source-path-info")
-    p = subprocess.Popen(
-        cmd,
-        cwd=go_path + "/bin",
-        stdout=subprocess.PIPE,
-        stderr=subprocess.PIPE,
-        universal_newlines=True,
-    )
-
-    out = p.communicate()[1]
-    if p.returncode != 0:
-        print("go api generate failed: %d %s" % (p.returncode, out))
-        sys.exit(1)
 
+    _, out = execute(" ".join(cmd), cwd=go_path + "/bin")
     # Print nice output of the binapi generator
     for msg in out.split():
         if "=" in msg:
@@ -148,6 +149,25 @@ def generate_api(output_dir, vpp_dir, api_list, import_prefix, no_source, go_pat
     print("Go API bindings were generated to " + output_dir)
 
 
+def get_go_variables():
+    # go specific environment variables
+    if "GOROOT" in os.environ:
+        go_root = os.environ["GOROOT"]
+    else:
+        go_binary = shutil.which("go")
+        if go_binary != "":
+            go_binary_dir, _ = os.path.split(go_binary)
+            go_root = os.path.join(go_binary_dir, "..")
+        else:
+            go_root = os.environ["HOME"] + "/.go"
+    if "GOPATH" in os.environ:
+        go_path = os.environ["GOPATH"]
+    else:
+        go_path = os.environ["HOME"] + "/go"
+
+    return go_root, go_path
+
+
 def main():
     # project root directory
     root = pathlib.Path(os.path.dirname(os.path.abspath(__file__)))
@@ -157,8 +177,8 @@ def main():
     parser.add_argument(
         "-govpp-commit",
         "--govpp-commit",
-        help="GoVPP commit or branch " "(defaults to v0.3.5-45-g671f16c)",
-        default="671f16c",  # fixed GoVPP version
+        help="GoVPP commit or branch ",
+        default=DefaultGoVppCommit,
         type=str,
     )
     parser.add_argument(
@@ -193,22 +213,15 @@ def main():
     )
     args = parser.parse_args()
 
-    # go specific environment variables
-    if "GOROOT" in os.environ:
-        go_root = os.environ["GOROOT"]
-    else:
-        go_binary = shutil.which("go")
-        if go_binary != "":
-            go_binary_dir, _ = os.path.split(go_binary)
-            go_root = os.path.join(go_binary_dir, "..")
-        else:
-            go_root = os.environ["HOME"] + "/.go"
-    if "GOPATH" in os.environ:
-        go_path = os.environ["GOPATH"]
-    else:
-        go_path = os.environ["HOME"] + "/go"
-
+    go_root, go_path = get_go_variables()
     install_golang(go_root)
+
+    if not (
+        os.path.exists(go_root + "/bin/go") and os.path.isfile(go_root + "/bin/go")
+    ):
+        print(go_root + "/bin/go does not exist")
+        sys.exit(1)
+
     install_binapi_gen(args.govpp_commit, go_root, go_path)
     generate_api(
         args.output_dir,