golang.org/x/build@v0.0.0-20240506185731-218518f32b70/env/wasip1-wasm-wasmedge/install.py (about)

     1  #!/usr/bin/env python
     2  # -*- coding: utf-8 -*-
     3  
     4  from __future__ import (
     5      division,
     6      print_function,
     7      absolute_import,
     8      unicode_literals,
     9      with_statement,
    10  )
    11  from contextlib import contextmanager
    12  import shutil
    13  import sys
    14  import argparse
    15  from os.path import expanduser, join, dirname, abspath, exists, islink, lexists, isdir
    16  from os import (
    17      getenv,
    18      geteuid,
    19      listdir,
    20      makedirs,
    21      mkdir,
    22      readlink,
    23      remove,
    24      getpid,
    25      symlink,
    26  )
    27  import tempfile
    28  import tarfile
    29  import zipfile
    30  import platform
    31  import subprocess
    32  import re
    33  import logging
    34  
    35  download_url = None
    36  
    37  # Define version specific things
    38  if sys.version_info[0] == 3:
    39      import urllib.request
    40  
    41      download_url = urllib.request.urlretrieve
    42  
    43      def reraise(tp, value=None, tb=None):
    44          if value is None:
    45              value = tp
    46          if value.__traceback__ is not tb:
    47              raise value.with_traceback(tb)
    48          raise value
    49  
    50  else:
    51      exec("def reraise(tp, value=None, tb=None):\n    raise tp, value, tb\n")
    52  
    53      import urllib
    54  
    55      download_url = urllib.urlretrieve
    56  
    57  
    58  def show_progress(block_num, block_size, total_size):
    59      downloaded = block_num * block_size
    60  
    61      print(
    62          end=(
    63              "\r|%-60s|" % ("=" * int(60 * downloaded / (total_size)))
    64              + "%6.2f %%" % (downloaded / (total_size) * 100)
    65          )
    66      )
    67  
    68      if downloaded < total_size:
    69          pass
    70      else:
    71          print("Downloaded")
    72  
    73  
    74  @contextmanager
    75  def opened_w_error(filename, mode="r"):
    76      try:
    77          f = open(filename, mode)
    78      except IOError as err:
    79          logging.critical("Error opening file: %s error: %s", filename, err.strerror)
    80          yield None
    81      else:
    82          try:
    83              yield f
    84          finally:
    85              f.close()
    86  
    87  
    88  def _is_tarxz(filename):
    89      return filename.endswith(".tar.xz")
    90  
    91  
    92  def _is_tar(filename):
    93      return filename.endswith(".tar")
    94  
    95  
    96  def _is_targz(filename):
    97      return filename.endswith(".tar.gz")
    98  
    99  
   100  def _is_tgz(filename):
   101      return filename.endswith(".tgz")
   102  
   103  
   104  def _is_zip(filename):
   105      return filename.endswith(".zip")
   106  
   107  
   108  def extract_archive(
   109      from_path, ipath, to_path=None, remove_finished=False, env_file_path=None
   110  ):
   111      files_extracted = []
   112  
   113      if to_path is None:
   114          to_path = dirname(from_path)
   115  
   116      if _is_tar(from_path):
   117          with tarfile.open(from_path, "r") as tar:
   118              tar.extractall(path=to_path)
   119              files_extracted = tar.getnames()
   120      elif _is_targz(from_path) or _is_tgz(from_path):
   121          with tarfile.open(from_path, "r:gz") as tar:
   122              tar.extractall(path=to_path)
   123              files_extracted = tar.getnames()
   124      elif _is_tarxz(from_path):
   125          with tarfile.open(from_path, "r:xz") as tar:
   126              tar.extractall(path=to_path)
   127              files_extracted = tar.getnames()
   128      elif _is_zip(from_path):
   129          with zipfile.ZipFile(from_path, "r") as z:
   130              z.extractall(to_path)
   131              files_extracted = z.namelist()
   132      else:
   133          reraise(ValueError("Extraction of {} not supported".format(from_path)))
   134  
   135      logging.debug("Writing installed files to %s file", env_file_path)
   136      with opened_w_error(env_file_path, "a") as env_file:
   137          if env_file is not None:
   138              for filename in files_extracted:
   139                  fname = filename.replace(CONST_ipkg, ipath)
   140  
   141                  # Skip if it ends with "wasmedge" as it is going to be removed at a later stage
   142                  if fname.endswith("wasmedge") and not fname.endswith("bin/wasmedge"):
   143                      continue
   144  
   145                  # replace wasmedge folder name with include
   146                  if is_default_path(args):
   147                      fname = fname.replace("/lib64/", "/" + CONST_lib_dir + "/")
   148                  if fname.endswith("/lib64"):
   149                      fname = fname[:-5] + "lib"
   150                  if fname.startswith("/usr") and "lib64" in fname:
   151                      fname = fname.replace("lib64", "lib", 1)
   152                  if "Plugin" in fname:
   153                      if is_default_path(args):
   154                          fname = fname.replace(
   155                              join(ipath, CONST_lib_dir, "wasmedge/"), ""
   156                          )
   157  
   158                          fname = join(ipath, "plugin", fname)
   159                      else:
   160                          fname = join(ipath, CONST_lib_dir, "wasmedge", fname)
   161                  else:
   162                      if ipath not in fname:
   163                          fname = join(ipath, fname)
   164                  # replace GNUSparseFile.0 with nothing
   165                  fname = fname.replace("/GNUSparseFile.0", "")
   166                  # Don't append system directories
   167                  if (not is_default_path(args)) and isdir(fname):
   168                      continue
   169                  env_file.write("#" + fname + "\n")
   170                  logging.debug("Appending:%s", fname)
   171          else:
   172              logging.warning("Unable to write to env file")
   173  
   174      if remove_finished:
   175          remove(from_path)
   176  
   177  
   178  # https://stackoverflow.com/questions/1868714/
   179  # how-do-i-copy-an-entire-directory-of-files-
   180  # into-an-existing-directory-using-pyth
   181  def copytree(src, dst, symlinks=True, ignore=None):
   182      if not exists(dst):
   183          makedirs(dst)
   184          shutil.copystat(src, dst)
   185      lst = listdir(src)
   186      if ignore:
   187          excl = ignore(src, lst)
   188          lst = [x for x in lst if x not in excl]
   189      for item in lst:
   190          s = join(src, item)
   191          d = join(dst, item)
   192          if symlinks and islink(s):
   193              if lexists(d):
   194                  remove(d)
   195              symlink(readlink(s), d)
   196          elif isdir(s):
   197              copytree(s, d, symlinks, ignore)
   198          else:
   199              shutil.copy2(s, d)
   200  
   201  
   202  class VersionString:
   203      def __init__(self, version):
   204          self.version = version
   205  
   206      def __str__(self):
   207          return self.version
   208  
   209      def __repr__(self):
   210          return "VersionString:" + self.version
   211  
   212      def _preprocess(self, v, separator, ignorecase):
   213          if ignorecase:
   214              v = v.lower()
   215          return [
   216              int(x)
   217              if x.isdigit()
   218              else [int(y) if y.isdigit() else y for y in re.findall("\d+|[a-zA-Z]+", x)]
   219              for x in re.split(separator, v)
   220          ]
   221  
   222      def compare(self, version2, separator=". |-", ignorecase=True):
   223          # return 1 if self.version > version2
   224          # return 0 if self.version == version2
   225          # return -1 if self.version < version2
   226          # return False if not comparable
   227          if "rc" in self.version and not "rc" in version2:
   228              a = self._preprocess(
   229                  self.version.split("rc")[0].strip("-"), separator, ignorecase
   230              )
   231              b = b = self._preprocess(version2, separator, ignorecase)
   232              if ((a > b) - (a < b)) == 0:
   233                  return -1
   234              else:
   235                  return (a > b) - (a < b)
   236          else:
   237              a = self._preprocess(self.version, separator, ignorecase)
   238              b = self._preprocess(version2, separator, ignorecase)
   239              try:
   240                  return (a > b) - (a < b)
   241              except:
   242                  return False
   243  
   244  
   245  SUPPORTED_PLATFORM_MACHINE = {
   246      "Linux": ["x86_64", "amd64", "arm64", "armv8", "aarch64"],
   247      "Darwin": ["x86_64", "arm64", "arm"],
   248  }
   249  
   250  SUPPORTED_MIN_VERSION = {
   251      "Linux" + "x86_64": VersionString("0.9.0"),
   252      "Linux" + "amd64": VersionString("0.9.0"),
   253      "Linux" + "arm64": VersionString("0.9.0"),
   254      "Linux" + "armv8": VersionString("0.9.0"),
   255      "Linux" + "aarch64": VersionString("0.9.0"),
   256      "Darwin" + "x86_64": VersionString("0.9.0"),
   257      "Darwin" + "arm64": VersionString("0.9.0"),
   258      "Darwin" + "arm": VersionString("0.9.0"),
   259  }
   260  
   261  WASMEDGE = "WasmEdge"
   262  WASMEDGE_UNINSTALLER = "WasmEdge_Uninstaller"
   263  TENSORFLOW = "tensorflow"
   264  TENSORFLOW_LITE = "tensorflow_lite"
   265  TENSORFLOW_DEPS = "tensorflow_deps"
   266  TENSORFLOW_LITE_DEPS = "tensorflow_lite_deps"
   267  TENSORFLOW_TOOLS = "tensorflow_tools"
   268  IMAGE = "image"
   269  EXTENSIONS = [TENSORFLOW, IMAGE]
   270  
   271  SUPPORTED_EXTENSIONS = {
   272      "Linux" + "x86_64": EXTENSIONS,
   273      "Linux" + "amd64": EXTENSIONS,
   274      "Linux" + "arm64": EXTENSIONS,
   275      "Linux" + "armv8": EXTENSIONS,
   276      "Linux" + "aarch64": EXTENSIONS,
   277      "Darwin" + "x86_64": EXTENSIONS,
   278      "Darwin" + "arm64": [],
   279      "Darwin" + "arm": [],
   280  }
   281  
   282  SUPPORTED_EXTENSIONS_VERSION = {
   283      "Linux" + "x86_64" + TENSORFLOW: VersionString("0.9.0"),
   284      "Linux" + "x86_64" + IMAGE: VersionString("0.9.0"),
   285      "Linux" + "amd64" + TENSORFLOW: VersionString("0.9.0"),
   286      "Linux" + "amd64" + IMAGE: VersionString("0.9.0"),
   287      "Linux" + "arm64" + TENSORFLOW: VersionString("0.9.0"),
   288      "Linux" + "arm64" + IMAGE: VersionString("0.9.0"),
   289      "Linux" + "armv8" + TENSORFLOW: VersionString("0.9.0"),
   290      "Linux" + "armv8" + IMAGE: VersionString("0.9.0"),
   291      "Linux" + "aarch64" + TENSORFLOW: VersionString("0.9.1-beta.1"),
   292      "Linux" + "aarch64" + IMAGE: VersionString("0.9.1-beta.1"),
   293      "Darwin" + "x86_64" + TENSORFLOW: VersionString("0.10.0-alpha.1"),
   294      "Darwin" + "x86_64" + IMAGE: VersionString("0.10.0-alpha.1"),
   295      "Darwin" + "arm64" + TENSORFLOW: VersionString("0.10.0-alpha.1"),
   296      "Darwin" + "arm" + TENSORFLOW: VersionString("0.10.0-alpha.1"),
   297  }
   298  
   299  WASI_NN_OPENVINO = "wasi_nn-openvino"
   300  WASI_CRYPTO = "wasi_crypto"
   301  WASI_NN_PYTORCH = "wasi_nn-pytorch"
   302  WASI_NN_TENSORFLOW_LITE = "wasi_nn-tensorflowlite"
   303  WASMEDGE_HTTPSREQ = "wasmedge_httpsreq"
   304  PLUGINS_AVAILABLE = [
   305      WASI_NN_OPENVINO,
   306      WASI_CRYPTO,
   307      WASI_NN_PYTORCH,
   308      WASI_NN_TENSORFLOW_LITE,
   309      WASMEDGE_HTTPSREQ,
   310  ]
   311  
   312  SUPPORTTED_PLUGINS = {
   313      "ubuntu20.04" + "x86_64" + WASI_CRYPTO: VersionString("0.10.1-rc.1"),
   314      "manylinux2014" + "x86_64" + WASI_CRYPTO: VersionString("0.10.1-rc.1"),
   315      "manylinux2014" + "aarch64" + WASI_CRYPTO: VersionString("0.10.1-rc.1"),
   316      "manylinux2014" + "arm64" + WASI_CRYPTO: VersionString("0.10.1-rc.1"),
   317      "ubuntu20.04" + "x86_64" + WASI_NN_OPENVINO: VersionString("0.10.1-alpha.1"),
   318      "ubuntu20.04" + "x86_64" + WASI_NN_PYTORCH: VersionString("0.11.1-alpha.1"),
   319      "manylinux2014" + "x86_64" + WASI_NN_PYTORCH: VersionString("0.11.2-alpha.1"),
   320      "manylinux2014"
   321      + "x86_64"
   322      + WASI_NN_TENSORFLOW_LITE: VersionString("0.11.2-alpha.1"),
   323      "manylinux2014"
   324      + "aarch64"
   325      + WASI_NN_TENSORFLOW_LITE: VersionString("0.11.2-alpha.1"),
   326      "ubuntu20.04" + "x86_64" + WASI_NN_TENSORFLOW_LITE: VersionString("0.11.2-rc.1"),
   327      "ubuntu20.04" + "x86_64" + WASMEDGE_HTTPSREQ: VersionString("0.11.1"),
   328      "manylinux2014" + "x86_64" + WASMEDGE_HTTPSREQ: VersionString("0.11.1"),
   329      "manylinux2014" + "aarch64" + WASMEDGE_HTTPSREQ: VersionString("0.11.1"),
   330  }
   331  
   332  HOME = expanduser("~")
   333  PATH = join(HOME, ".wasmedge")
   334  SHELL = getenv("SHELL", "bash").split("/")[-1]
   335  TEMP_PATH = join(tempfile.gettempdir(), "wasmedge." + str(getpid()))
   336  CONST_shell_config = None
   337  CONST_shell_profile = None
   338  CONST_env = None
   339  CONST_urls = None
   340  CONST_release_pkg = None
   341  CONST_ipkg = None
   342  CONST_lib_ext = None
   343  CONST_env_path = None
   344  CONST_lib_dir = "lib"
   345  
   346  try:
   347      mkdir(TEMP_PATH)
   348  except:
   349      pass
   350  
   351  
   352  def set_env(args, compat):
   353      global CONST_env, CONST_env_path, CONST_lib_dir
   354  
   355      CONST_env = """#!/bin/sh
   356  # wasmedge shell setup
   357  # affix colons on either side of $PATH to simplify matching
   358  case :"${1}": in
   359      *:"{0}/bin":*)
   360          ;;
   361      *)
   362          # Prepending path in case a system-installed wasmedge needs to be overridden
   363          if [ -n "${1}" ]; then
   364              export PATH="{0}/bin":$PATH
   365          else
   366              export PATH="{0}/bin"
   367          fi
   368          ;;
   369  esac
   370  case :"${2}": in
   371      *:"{0}/{6}":*)
   372          ;;
   373      *)
   374          # Prepending path in case a system-installed wasmedge libs needs to be overridden
   375          if [ -n "${2}" ]; then
   376              export {2}="{0}/{6}":${2}
   377          else
   378              export {2}="{0}/{6}"
   379          fi
   380          ;;
   381  esac
   382  case :"${3}": in
   383      *:"{0}/{6}":*)
   384          ;;
   385      *)
   386          if [ -n "${3}" ]; then
   387              export LIBRARY_PATH="{0}/{6}":$LIBRARY_PATH
   388          else
   389              export LIBRARY_PATH="{0}/{6}"
   390          fi
   391          ;;
   392  esac
   393  case :"${4}": in
   394      *:"{0}/include":*)
   395          ;;
   396      *)
   397          if [ -n "${4}" ]; then
   398              export C_INCLUDE_PATH="{0}/include":$C_INCLUDE_PATH
   399          else
   400              export C_INCLUDE_PATH="{0}/include"
   401          fi
   402          ;;
   403  esac
   404  case :"${5}": in
   405      *:"{0}/include":*)
   406          ;;
   407      *)
   408          if [ -n "${5}" ]; then
   409              export CPLUS_INCLUDE_PATH="{0}/include":$CPLUS_INCLUDE_PATH
   410          else
   411              export CPLUS_INCLUDE_PATH="{0}/include"
   412          fi
   413          ;;
   414  esac
   415  if [ -z ${{WASMEDGE_LIB_DIR+x}} ]; then
   416      export WASMEDGE_LIB_DIR="{0}/{6}"
   417  fi
   418  # Please do not edit comments below this for uninstallation purpose
   419  """.format(
   420          args.path,
   421          "PATH",
   422          compat.ld_library_path,
   423          "LIBRARY_PATH",
   424          "C_INCLUDE_PATH",
   425          "CPLUS_INCLUDE_PATH",
   426          CONST_lib_dir,
   427      )
   428  
   429      try:
   430          mkdir(args.path)
   431          if is_default_path(args):
   432              mkdir(join(args.path, "plugin"))
   433      except:
   434          pass
   435      CONST_env_path = join(args.path, "env")
   436      mode = "w+" if not exists(CONST_env_path) else "w"
   437      with opened_w_error(CONST_env_path, mode) as env:
   438          if env is not None:
   439              env.write(CONST_env)
   440          else:
   441              logging.error("Not able to write to env file")
   442  
   443  
   444  def shell_configure(args, compat):
   445      global CONST_shell_profile, CONST_shell_config
   446  
   447      source_string = '\n. "{0}"\n'.format(join(args.path, "env"))
   448  
   449      if ("bash" in SHELL) or ("zsh" in SHELL):
   450          CONST_shell_config = join(HOME, "." + SHELL + "rc")
   451  
   452          if "zsh" in SHELL:
   453              CONST_shell_profile = join(HOME, "." + "zprofile")
   454          else:
   455              CONST_shell_profile = join(HOME, "." + SHELL + "_profile")
   456  
   457          # On Darwin: Create shell config only if shell_profile does not exist
   458          # On Linux: Create shell config anyway
   459          if not exists(CONST_shell_config) and compat.platform != "Darwin":
   460              open(CONST_shell_config, "a").close()
   461  
   462          write_shell = False
   463          if compat.platform != "Darwin":
   464              with opened_w_error(CONST_shell_config, "r") as shell_config:
   465                  if shell_config is not None:
   466                      if source_string not in shell_config.read():
   467                          write_shell = True
   468  
   469          # On Darwin: Append to shell config only if shell_profile does not exist
   470          # On Linux: Append to shell config anyway
   471          if write_shell and compat.platform != "Darwin":
   472              with opened_w_error(CONST_shell_config, "a") as shell_config:
   473                  if shell_config is not None:
   474                      shell_config.write(source_string)
   475              write_shell = False
   476  
   477          if exists(CONST_shell_profile):
   478              with opened_w_error(CONST_shell_profile, "r") as shell_profile:
   479                  if shell_profile is not None:
   480                      if source_string not in shell_profile.read():
   481                          write_shell = True
   482              if write_shell:
   483                  with opened_w_error(CONST_shell_profile, "a") as shell_profile:
   484                      if shell_profile is not None:
   485                          shell_profile.write(source_string)
   486                  write_shell = False
   487      else:
   488          logging.error("Unknown shell found")
   489          return -1
   490  
   491      print("shell configuration updated")
   492      return 0
   493  
   494  
   495  def fix_gnu_sparse(args):
   496      # Fix GNUSparseFile.0 folder in macOS if exists
   497      global CONST_lib_ext, CONST_lib_dir
   498  
   499      for dir in listdir(args.path):
   500          if not isdir(join(args.path, dir)):
   501              continue
   502          if "GNUSparseFile" in dir:
   503              for file in listdir(join(args.path, dir)):
   504                  if file.endswith(CONST_lib_ext):
   505                      if isdir(join(args.path, CONST_lib_dir)):
   506                          shutil.move(
   507                              join(args.path, dir, file), join(args.path, CONST_lib_dir)
   508                          )
   509                      else:
   510                          logging.error(
   511                              "%s directory not found", join(args.path, CONST_lib_dir)
   512                          )
   513                          try:
   514                              mkdir(join(args.path, CONST_lib_dir))
   515                              shutil.move(
   516                                  join(args.path, dir, file),
   517                                  join(args.path, CONST_lib_dir),
   518                              )
   519                          except:
   520                              pass
   521                  elif (
   522                      file.endswith(".h")
   523                      or file.endswith(".hpp")
   524                      or file.endswith(".inc")
   525                  ):
   526                      shutil.move(join(args.path, dir, file), join(args.path, "include"))
   527                  else:
   528                      shutil.move(join(args.path, dir, file), join(args.path, "bin"))
   529          for sub_dir in listdir(join(args.path, dir)):
   530              if not isdir(join(args.path, dir, sub_dir)):
   531                  continue
   532              if "GNUSparseFile" in sub_dir:
   533                  for file in listdir(join(args.path, dir, sub_dir)):
   534                      shutil.move(
   535                          join(args.path, dir, sub_dir, file), join(args.path, dir)
   536                      )
   537                  if len(listdir(join(args.path, dir, sub_dir))) == 0:
   538                      shutil.rmtree(join(args.path, dir, sub_dir))
   539  
   540  
   541  def ldconfig(args, compat):
   542      if geteuid() == 0:
   543          # Only run ldconfig or update_dyld_shared_cache when user is root/sudoer
   544          if compat.platform == "Linux":
   545              cmd = "ldconfig {0}".format(join(args.path, CONST_lib_dir))
   546              output = run_shell_command(cmd)
   547              logging.debug("%s: %s", cmd, output)
   548          elif compat.platform == "Darwin":
   549              cmd = "update_dyld_shared_cache {0}".format(join(args.path, CONST_lib_dir))
   550              output = run_shell_command(cmd)
   551              logging.debug("%s: %s", cmd, output)
   552          else:
   553              logging.warning("Help adding ldconfig for your platform")
   554      else:
   555          logging.debug("Not root or sudoer, skip ldconfig")
   556  
   557  
   558  def is_default_path(args):
   559      global PATH
   560      return args.path == abspath(PATH) or args.path[:4] != "/usr"
   561  
   562  
   563  def install_image_extension(args, compat):
   564      global CONST_release_pkg, CONST_lib_dir
   565  
   566      if not get_remote_version_availability(
   567          "second-state/WasmEdge-image", args.image_version
   568      ):
   569          logging.error(
   570              "Image extension version incorrect: {0}".format(args.image_version)
   571          )
   572          return -1
   573      if compat.prefix() + IMAGE not in SUPPORTED_EXTENSIONS_VERSION:
   574          logging.error("Image extensions not compatible: {0}".format(compat.prefix()))
   575          return -1
   576      elif (
   577          SUPPORTED_EXTENSIONS_VERSION[compat.prefix() + IMAGE].compare(
   578              args.image_version
   579          )
   580          > 0
   581      ):
   582          logging.error(
   583              "Min image extensions version: {0}".format(
   584                  SUPPORTED_EXTENSIONS_VERSION[compat.prefix() + IMAGE],
   585              )
   586          )
   587          return -1
   588  
   589      print("Downloading image extension")
   590  
   591      local_release_package = CONST_release_pkg
   592  
   593      # From WasmEdge 0.11.1, we have the Ubuntu release.
   594      # Installation of ubuntu version extensions when the ubuntu version of WasmEdge selected.
   595      if VersionString(args.image_version).compare("0.11.1") >= 0:
   596          local_release_package = compat.release_package_wasmedge
   597          logging.debug("Downloading dist package: {0}".format(local_release_package))
   598  
   599      image_pkg = "WasmEdge-image-" + args.image_version + "-" + local_release_package
   600  
   601      download_url(CONST_urls[IMAGE], join(TEMP_PATH, image_pkg), show_progress)
   602  
   603      # Extract archive
   604      extract_archive(
   605          join(TEMP_PATH, image_pkg),
   606          args.path,
   607          join(TEMP_PATH, "WasmEdge-image"),
   608          env_file_path=CONST_env_path,
   609          remove_finished=True,
   610      )
   611  
   612      wasmedge_image_temp = join(TEMP_PATH, "WasmEdge-image")
   613      for dir in listdir(wasmedge_image_temp):
   614          wasmedge_image_temp_dir = join(wasmedge_image_temp, dir)
   615          for file in listdir(wasmedge_image_temp_dir):
   616              if isdir(join(wasmedge_image_temp_dir, file)) and "wasmedge" == file:
   617                  copytree(
   618                      join(wasmedge_image_temp_dir, file),
   619                      join(args.path, "include", "wasmedge"),
   620                  )
   621              elif CONST_lib_ext in file:
   622                  if isdir(join(args.path, CONST_lib_dir)):
   623                      shutil.move(
   624                          join(wasmedge_image_temp_dir, file),
   625                          join(args.path, CONST_lib_dir, file),
   626                      )
   627                  else:
   628                      logging.error(
   629                          "%s directory not found", join(args.path, CONST_lib_dir)
   630                      )
   631                      try:
   632                          mkdir(join(args.path, CONST_lib_dir))
   633                          shutil.move(
   634                              join(wasmedge_image_temp_dir, file),
   635                              join(args.path, "lib", file),
   636                          )
   637                      except:
   638                          pass
   639              elif isdir(join(wasmedge_image_temp_dir, file)):
   640                  copytree(
   641                      join(wasmedge_image_temp_dir, file),
   642                      join(args.path, file),
   643                  )
   644              else:
   645                  shutil.move(
   646                      join(wasmedge_image_temp_dir, file),
   647                      join(args.path, "bin", file),
   648                  )
   649  
   650      fix_gnu_sparse(args)
   651  
   652      return 0
   653  
   654  
   655  def install_tensorflow_extension(args, compat):
   656      global CONST_release_pkg, CONST_lib_ext, CONST_lib_dir, CONST_env_path
   657  
   658      if not get_remote_version_availability(
   659          "second-state/WasmEdge-tensorflow", args.tf_version
   660      ):
   661          logging.error(
   662              "Tensorflow extension version incorrect: {0}".format(args.tf_version)
   663          )
   664          return -1
   665      elif not get_remote_version_availability(
   666          "second-state/WasmEdge-tensorflow-deps", args.tf_deps_version
   667      ):
   668          logging.error(
   669              "Tensorflow Deps extension version incorrect: {0}".format(
   670                  args.tf_deps_version
   671              )
   672          )
   673          return -1
   674      elif not get_remote_version_availability(
   675          "second-state/WasmEdge-tensorflow", args.tf_tools_version
   676      ):
   677          logging.error(
   678              "Tensorflow Tools version incorrect: {0}".format(args.tf_tools_version)
   679          )
   680          return -1
   681  
   682      if compat.prefix() + TENSORFLOW not in SUPPORTED_EXTENSIONS_VERSION:
   683          logging.error(
   684              "Tensorflow extensions not compatible: {0}".format(compat.prefix())
   685          )
   686          return -1
   687      elif (
   688          SUPPORTED_EXTENSIONS_VERSION[compat.prefix() + TENSORFLOW].compare(
   689              args.tf_version
   690          )
   691          > 0
   692      ):
   693          logging.error(
   694              "Min tensorflow extensions version: {0}".format(
   695                  SUPPORTED_EXTENSIONS_VERSION[compat.prefix() + TENSORFLOW],
   696              )
   697          )
   698          return -1
   699  
   700      download_tf = True
   701      download_tf_lite = True
   702  
   703      if compat.machine == "aarch64":
   704          download_tf = False
   705  
   706      local_release_package = CONST_release_pkg
   707  
   708      # From WasmEdge 0.11.1, we have the Ubuntu release.
   709      # Installation of ubuntu version extensions when the ubuntu version of WasmEdge selected.
   710      if VersionString(args.tf_version).compare("0.11.1") >= 0:
   711          local_release_package = compat.release_package_wasmedge
   712          logging.debug("Downloading dist package: {0}".format(local_release_package))
   713  
   714      if download_tf:
   715          tf_pkg = "WasmEdge-tensorflow-" + args.tf_version + "-" + local_release_package
   716          tf_deps_pkg = (
   717              "WasmEdge-tensorflow-deps-TF-"
   718              + args.tf_deps_version
   719              + "-"
   720              + CONST_release_pkg
   721          )
   722  
   723          print("Downloading tensorflow extension")
   724          download_url(CONST_urls[TENSORFLOW], join(TEMP_PATH, tf_pkg), show_progress)
   725  
   726          print("Downloading tensorflow-deps")
   727          download_url(
   728              CONST_urls[TENSORFLOW_DEPS], join(TEMP_PATH, tf_deps_pkg), show_progress
   729          )
   730  
   731          # Extract archive
   732          extract_archive(
   733              join(TEMP_PATH, tf_pkg),
   734              args.path,
   735              join(TEMP_PATH, "WasmEdge-tensorflow"),
   736              env_file_path=CONST_env_path,
   737              remove_finished=True,
   738          )
   739  
   740          # Extract archive
   741          extract_archive(
   742              join(TEMP_PATH, tf_deps_pkg),
   743              join(args.path, CONST_lib_dir),
   744              join(TEMP_PATH, "WasmEdge-tensorflow-deps", CONST_lib_dir),
   745              env_file_path=CONST_env_path,
   746              remove_finished=True,
   747          )
   748  
   749          copytree(join(TEMP_PATH, "WasmEdge-tensorflow"), args.path)
   750          copytree(join(TEMP_PATH, "WasmEdge-tensorflow-deps"), args.path)
   751  
   752      if download_tf_lite:
   753          tf_lite_pkg = (
   754              "WasmEdge-tensorflowlite-" + args.tf_version + "-" + local_release_package
   755          )
   756          tf_deps_lite_pkg = (
   757              "WasmEdge-tensorflow-deps-TFLite-"
   758              + args.tf_deps_version
   759              + "-"
   760              + CONST_release_pkg
   761          )
   762  
   763          print("Downloading tensorflow-lite extension")
   764          download_url(
   765              CONST_urls[TENSORFLOW_LITE], join(TEMP_PATH, tf_lite_pkg), show_progress
   766          )
   767  
   768          print("Downloading tensorflow-lite-deps")
   769          download_url(
   770              CONST_urls[TENSORFLOW_LITE_DEPS],
   771              join(TEMP_PATH, tf_deps_lite_pkg),
   772              show_progress,
   773          )
   774  
   775          # Extract archive
   776          extract_archive(
   777              join(TEMP_PATH, tf_lite_pkg),
   778              args.path,
   779              join(TEMP_PATH, "WasmEdge-tensorflow-lite"),
   780              env_file_path=CONST_env_path,
   781              remove_finished=True,
   782          )
   783  
   784          # Extract archive
   785          extract_archive(
   786              join(TEMP_PATH, tf_deps_lite_pkg),
   787              join(args.path, CONST_lib_dir),
   788              join(TEMP_PATH, "WasmEdge-tensorflow-lite-deps", CONST_lib_dir),
   789              env_file_path=CONST_env_path,
   790              remove_finished=True,
   791          )
   792  
   793          copytree(join(TEMP_PATH, "WasmEdge-tensorflow-lite"), args.path)
   794          copytree(join(TEMP_PATH, "WasmEdge-tensorflow-lite-deps"), args.path)
   795  
   796      tf_tools_pkg = (
   797          "WasmEdge-tensorflow-tools-" + args.tf_tools_version + "-" + CONST_release_pkg
   798      )
   799  
   800      print("Downloading tensorflow-tools extension")
   801      download_url(
   802          CONST_urls[TENSORFLOW_TOOLS], join(TEMP_PATH, tf_tools_pkg), show_progress
   803      )
   804  
   805      # Extract archive
   806      extract_archive(
   807          join(TEMP_PATH, tf_tools_pkg),
   808          join(args.path, "bin"),
   809          join(TEMP_PATH, "WasmEdge-tensorflow-tools", "bin"),
   810          env_file_path=CONST_env_path,
   811          remove_finished=True,
   812      )
   813  
   814      copytree(join(TEMP_PATH, "WasmEdge-tensorflow-tools"), args.path)
   815  
   816      fix_gnu_sparse(args)
   817  
   818      all_files = run_shell_command("ls -R {0}".format(TEMP_PATH))
   819  
   820      if not isdir(join(args.path, CONST_lib_dir)):
   821          logging.error("Strange: No %s directory found", CONST_lib_dir)
   822  
   823      for file in listdir(join(args.path, CONST_lib_dir)):
   824          if CONST_lib_ext not in file:
   825              # ignore files that are not libraries
   826              continue
   827          if file not in all_files:
   828              # ignore files that are not downloaded by this script
   829              continue
   830          if "tensorflow" not in file:
   831              continue
   832          # check if it contains any digits
   833          if not any(i.isdigit() for i in file):
   834              continue
   835          if compat.platform == "Linux":
   836              name, version = file.split(CONST_lib_ext, 1)
   837              if version[0] == ".":
   838                  version = version[1:]
   839              if version != "" and version.count(".") >= 2:
   840                  no_v_name = name + CONST_lib_ext
   841                  single_v_name = name + CONST_lib_ext + "." + version.split(".")[0]
   842                  dual_v_name = (
   843                      name
   844                      + CONST_lib_ext
   845                      + "."
   846                      + version.split(".")[0]
   847                      + "."
   848                      + version.split(".")[1]
   849                  )
   850                  file_path = join(args.path, CONST_lib_dir, file)
   851                  single_v_file_path = join(args.path, CONST_lib_dir, single_v_name)
   852                  dual_v_file_path = join(args.path, CONST_lib_dir, dual_v_name)
   853                  no_v_file_path = join(args.path, CONST_lib_dir, no_v_name)
   854                  try:
   855                      symlink(file_path, single_v_file_path)
   856                      symlink(file_path, dual_v_file_path)
   857                      symlink(file_path, no_v_file_path)
   858                  except Exception as e:
   859                      logging.debug(e)
   860              else:
   861                  continue
   862          elif compat.platform == "Darwin":
   863              name, version = file.split(CONST_lib_ext, 1)[0].split(".", 1)
   864              if version != "" and version.count(".") >= 2:
   865                  no_v_name = name + CONST_lib_ext
   866                  single_v_name = name + "." + version.split(".")[0] + CONST_lib_ext
   867                  dual_v_name = (
   868                      name
   869                      + "."
   870                      + version.split(".")[0]
   871                      + "."
   872                      + version.split(".")[1]
   873                      + CONST_lib_ext
   874                  )
   875                  file_path = join(args.path, CONST_lib_dir, file)
   876                  single_v_file_path = join(args.path, CONST_lib_dir, single_v_name)
   877                  dual_v_file_path = join(args.path, CONST_lib_dir, dual_v_name)
   878                  no_v_file_path = join(args.path, CONST_lib_dir, no_v_name)
   879                  try:
   880                      symlink(file_path, single_v_file_path)
   881                      symlink(file_path, dual_v_file_path)
   882                      symlink(file_path, no_v_file_path)
   883                  except Exception as e:
   884                      logging.debug(e)
   885              else:
   886                  continue
   887          else:
   888              reraise(Exception("Not implemented for {0}".format(compat.platform)))
   889          with opened_w_error(CONST_env_path, "a") as env_file:
   890              if env_file is not None:
   891                  env_file.write("#" + single_v_file_path + "\n")
   892                  logging.debug("Appending:%s", single_v_file_path)
   893                  env_file.write("#" + dual_v_file_path + "\n")
   894                  logging.debug("Appending:%s", dual_v_file_path)
   895                  env_file.write("#" + no_v_file_path + "\n")
   896                  logging.debug("Appending:%s", no_v_file_path)
   897              else:
   898                  logging.error("Not able to append installed files to env file")
   899  
   900      for main_dir in ["WasmEdge-tensorflow", "WasmEdge-tensorflow-lite"]:
   901          if not isdir(join(TEMP_PATH, main_dir)):
   902              continue
   903          for directory_file in listdir(join(TEMP_PATH, main_dir)):
   904              if isdir(directory_file):
   905                  wasmedge_tf_folder = join(TEMP_PATH, main_dir, directory_file)
   906                  for _file in listdir(wasmedge_tf_folder):
   907                      if (
   908                          _file == "wasmedge"
   909                          and isdir(join(wasmedge_tf_folder, _file))
   910                          and is_default_path(args)
   911                      ):
   912                          copytree(
   913                              join(wasmedge_tf_folder, _file),
   914                              join(args.path, "include", "wasmedge"),
   915                          )
   916                      elif CONST_lib_ext in _file:
   917                          if isdir(join(args.path, CONST_lib_dir)):
   918                              shutil.move(
   919                                  join(wasmedge_tf_folder, _file),
   920                                  join(args.path, CONST_lib_dir, _file),
   921                              )
   922                          else:
   923                              logging.error(
   924                                  "%s is not a directory", join(args.path, CONST_lib_dir)
   925                              )
   926                              try:
   927                                  mkdir(join(args.path, CONST_lib_dir))
   928                                  shutil.move(
   929                                      join(wasmedge_tf_folder, _file),
   930                                      join(args.path, CONST_lib_dir, _file),
   931                                  )
   932                              except:
   933                                  pass
   934  
   935                      elif isdir(join(wasmedge_tf_folder, _file)):
   936                          copytree(
   937                              join(wasmedge_tf_folder, _file),
   938                              join(args.path, _file),
   939                          )
   940                      else:
   941                          shutil.move(
   942                              join(wasmedge_tf_folder, _file),
   943                              join(args.path, "bin", _file),
   944                          )
   945  
   946      if download_tf:
   947          # Check if wasmedge binary works
   948          wasmedge_tf_output = run_shell_command(
   949              ". {0}/env &&{0}/bin/wasmedge-tensorflow --version".format(args.path)
   950          )
   951  
   952          if args.tf_version in wasmedge_tf_output:
   953              print("WasmEdge Successfully installed")
   954          else:
   955              logging.critical(
   956                  "WasmEdge Tensorflow installation incorrect: {0}".format(
   957                      wasmedge_tf_output
   958                  )
   959              )
   960  
   961      if download_tf_lite:
   962          # Check if wasmedge binary works
   963          wasmedge_tf_lite_output = run_shell_command(
   964              ". {0}/env && {0}/bin/wasmedge-tensorflow-lite --version".format(args.path)
   965          )
   966  
   967          if args.tf_version in wasmedge_tf_lite_output:
   968              print("WasmEdge Tensorflow Lite Successfully installed")
   969          else:
   970              logging.critical(
   971                  "WasmEdge Tensorflow installation incorrect: {0}".format(
   972                      wasmedge_tf_lite_output
   973                  )
   974              )
   975  
   976      return 0
   977  
   978  
   979  def install_plugins(args, compat):
   980      global CONST_lib_dir
   981      url_root = "https://github.com/WasmEdge/WasmEdge/releases/download/"
   982      url_root += "$VERSION$/WasmEdge-plugin-$PLUGIN_NAME$-$VERSION$-$DIST$_$ARCH$.tar.gz"
   983  
   984      if len(args.plugins) >= 1:
   985          for plugin_name in args.plugins:
   986              plugin_version_supplied = None
   987              if plugin_name.find(":") != -1:
   988                  plugin_name, plugin_version_supplied = plugin_name.split(":")
   989  
   990              if plugin_name not in PLUGINS_AVAILABLE:
   991                  logging.error(
   992                      "%s plugin not found, available names - %s",
   993                      plugin_name,
   994                      PLUGINS_AVAILABLE,
   995                  )
   996                  continue
   997  
   998              if compat.dist + compat.machine + plugin_name not in SUPPORTTED_PLUGINS:
   999                  logging.error(
  1000                      "Plugin not compatible: %s",
  1001                      compat.dist + compat.machine + plugin_name,
  1002                  )
  1003                  logging.debug("Supported: %s", SUPPORTTED_PLUGINS)
  1004                  continue
  1005              else:
  1006                  if plugin_version_supplied is None:
  1007                      plugin_version_supplied = args.version
  1008                  elif (
  1009                      SUPPORTTED_PLUGINS[
  1010                          compat.dist + compat.machine + plugin_name
  1011                      ].compare(plugin_version_supplied)
  1012                      > 0
  1013                  ):
  1014                      logging.error(
  1015                          "Plugin not compatible: %s %s",
  1016                          plugin_name,
  1017                          plugin_version_supplied,
  1018                      )
  1019                      continue
  1020  
  1021                  plugin_url = (
  1022                      url_root.replace("$PLUGIN_NAME$", plugin_name)
  1023                      .replace("$VERSION$", plugin_version_supplied)
  1024                      .replace("$DIST$", compat.dist)
  1025                      .replace("$ARCH$", compat.machine)
  1026                  )
  1027                  logging.debug("Plugin URL: %s", plugin_url)
  1028  
  1029                  print("Downloading Plugin: " + plugin_name)
  1030                  download_url(
  1031                      plugin_url,
  1032                      join(TEMP_PATH, "Plugin" + plugin_name) + ".tar.gz",
  1033                      show_progress,
  1034                  )
  1035                  extract_archive(
  1036                      join(TEMP_PATH, "Plugin" + plugin_name + ".tar.gz"),
  1037                      join(args.path),
  1038                      join(TEMP_PATH, "Plugins"),
  1039                      env_file_path=CONST_env_path,
  1040                      remove_finished=True,
  1041                  )
  1042  
  1043          if isdir(join(TEMP_PATH, "Plugins")):
  1044              if is_default_path(args):
  1045                  copytree(join(TEMP_PATH, "Plugins"), join(args.path, "plugin"))
  1046              else:
  1047                  copytree(
  1048                      join(TEMP_PATH, "Plugins"),
  1049                      join(args.path, CONST_lib_dir, "wasmedge"),
  1050                  )
  1051  
  1052  
  1053  def set_consts(args, compat):
  1054      global CONST_release_pkg, CONST_ipkg, CONST_lib_ext, CONST_urls, CONST_lib_dir, CONST_env_path
  1055      CONST_release_pkg = compat.release_package
  1056      CONST_ipkg = compat.install_package_name
  1057      CONST_lib_ext = compat.lib_extension
  1058  
  1059      local_release_package_tf = CONST_release_pkg
  1060  
  1061      # From WasmEdge 0.11.1, we have the Ubuntu release.
  1062      # Installation of ubuntu version extensions when the ubuntu version of WasmEdge selected.
  1063      if VersionString(args.tf_version).compare("0.11.1") >= 0:
  1064          local_release_package_tf = compat.release_package_wasmedge
  1065          logging.debug("Tensorflow release pkg: {0}".format(local_release_package_tf))
  1066  
  1067      local_release_package_im = CONST_release_pkg
  1068  
  1069      # From WasmEdge 0.11.1, we have the Ubuntu release.
  1070      # Installation of ubuntu version extensions when the ubuntu version of WasmEdge selected.
  1071      if VersionString(args.image_version).compare("0.11.1") >= 0:
  1072          local_release_package_im = compat.release_package_wasmedge
  1073          logging.debug("Image release pkg: {0}".format(local_release_package_im))
  1074  
  1075      CONST_urls = {
  1076          WASMEDGE: "https://github.com/WasmEdge/WasmEdge/releases/download/{0}/WasmEdge-{0}-{1}".format(
  1077              args.version, compat.release_package_wasmedge
  1078          ),
  1079          WASMEDGE_UNINSTALLER: "https://raw.githubusercontent.com/WasmEdge/WasmEdge/{0}/utils/uninstall.sh".format(
  1080              args.uninstall_script_tag
  1081          ),
  1082          IMAGE: "https://github.com/second-state/WasmEdge-image/releases/download/{0}/WasmEdge-image-{0}-{1}".format(
  1083              args.image_version, local_release_package_im
  1084          ),
  1085          TENSORFLOW_DEPS: "https://github.com/second-state/WasmEdge-tensorflow-deps/releases/download/{0}/WasmEdge-tensorflow-deps-TF-{0}-{1}".format(
  1086              args.tf_deps_version, CONST_release_pkg
  1087          ),
  1088          TENSORFLOW_LITE_DEPS: "https://github.com/second-state/WasmEdge-tensorflow-deps/releases/download/{0}/WasmEdge-tensorflow-deps-TFLite-{0}-{1}".format(
  1089              args.tf_deps_version, CONST_release_pkg
  1090          ),
  1091          TENSORFLOW: "https://github.com/second-state/WasmEdge-tensorflow/releases/download/{0}/WasmEdge-tensorflow-{0}-{1}".format(
  1092              args.tf_version, local_release_package_tf
  1093          ),
  1094          TENSORFLOW_LITE: "https://github.com/second-state/WasmEdge-tensorflow/releases/download/{0}/WasmEdge-tensorflowlite-{0}-{1}".format(
  1095              args.tf_version, local_release_package_tf
  1096          ),
  1097          TENSORFLOW_TOOLS: "https://github.com/second-state/WasmEdge-tensorflow-tools/releases/download/{0}/WasmEdge-tensorflow-tools-{0}-{1}".format(
  1098              args.tf_tools_version, CONST_release_pkg
  1099          ),
  1100      }
  1101  
  1102  
  1103  def run_shell_command(cmd):
  1104      try:
  1105          output = subprocess.check_output([cmd], shell=True)
  1106          return output.decode("utf8").strip()
  1107      except subprocess.CalledProcessError as e:
  1108          if "Cannot detect installation path" in str(e.output):
  1109              logging.warning("Uninstaller did not find previous installation")
  1110          else:
  1111              print("Exception on process, rc=", e.returncode, "output=", e.output, e.cmd)
  1112  
  1113      return ""
  1114  
  1115  
  1116  def get_latest_github_release(repo):
  1117      return run_shell_command(
  1118          """git ls-remote --refs --tags "https://github.com/{0}.git" |
  1119          cut -d '/' -f 3 |
  1120          awk {1} | sort --version-sort | sed 's/_$//' |
  1121          grep -e '^[0-9]\+.[0-9]\+.[0-9]\+$' |
  1122          tail -1""".format(
  1123              repo,
  1124              "'{ if ($1 ~ /-/) print; else print $0\"_\" ;}'",
  1125          )
  1126      )
  1127  
  1128  
  1129  def get_remote_version_availability(repo, version):
  1130      output = run_shell_command(
  1131          """git ls-remote --refs --tags "https://github.com/{0}.git" |
  1132          cut -d '/' -f 3 |
  1133          awk {1} | sort --version-sort | sed 's/_$//'""".format(
  1134              repo,
  1135              "'{ if ($1 ~ /-/) print; else print $0\"_\" ;}'",
  1136          )
  1137      )
  1138      if version in output:
  1139          return True
  1140      return False
  1141  
  1142  
  1143  class Compat:
  1144      def __init__(
  1145          self,
  1146          platform_=platform.system(),
  1147          machine=platform.machine(),
  1148          dist_=None,
  1149          version=None,
  1150          extensions=None,
  1151      ):
  1152          self.platform = platform_  # Linux, Darwin
  1153          self.machine = machine  # x86_64, arm
  1154          self.version = VersionString(version)
  1155          self.extensions = extensions
  1156          self.release_package = None
  1157          self.install_package_name = None
  1158          self.lib_extension = None
  1159          self.ld_library_path = None
  1160          self.dist = dist_
  1161          self.release_package_wasmedge = None
  1162  
  1163          if self.platform == "Linux":
  1164              self.install_package_name = "WasmEdge-{0}-Linux".format(self.version)
  1165              self.lib_extension = ".so"
  1166              self.ld_library_path = "LD_LIBRARY_PATH"
  1167  
  1168              if self.machine in ["arm64", "armv8", "aarch64"]:
  1169                  self.release_package = "manylinux2014_aarch64.tar.gz"
  1170              elif self.machine in ["x86_64", "amd64"]:
  1171                  self.release_package = "manylinux2014_x86_64.tar.gz"
  1172              else:
  1173                  reraise(Exception("Unsupported arch: {0}".format(self.machine)))
  1174  
  1175              self.release_package_wasmedge = self.release_package
  1176  
  1177              if self.dist is None:
  1178                  if sys.version_info[0] == 2:
  1179                      if (
  1180                          "Ubuntu" in platform.dist() and "20.04" in platform.dist()
  1181                      ) or "Ubuntu 20.04" in run_shell_command(
  1182                          "lsb_release -d | awk -F'\t' '{print $2}'"
  1183                      ):
  1184                          self.dist = "ubuntu20.04"
  1185                      else:
  1186                          self.dist = "manylinux2014"
  1187                  elif sys.version_info[0] == 3:
  1188                      __lsb_rel = run_shell_command(
  1189                          "cat /etc/lsb-release | grep RELEASE"
  1190                      )[-5:]
  1191                      if "20.04" == __lsb_rel or "Ubuntu 20.04" in run_shell_command(
  1192                          "lsb_release -d | awk -F'\t' '{print $2}'"
  1193                      ):
  1194                          self.dist = "ubuntu20.04"
  1195                      else:
  1196                          self.dist = "manylinux2014"
  1197  
  1198              # Below version 0.11.1 different distributions for wasmedge binary do not exist
  1199              if self.version.compare("0.11.1") != -1:
  1200                  if self.machine in ["arm64", "armv8", "aarch64"]:
  1201                      self.release_package_wasmedge = self.dist + "_aarch64.tar.gz"
  1202                  elif self.machine in ["x86_64", "amd64"]:
  1203                      self.release_package_wasmedge = self.dist + "_x86_64.tar.gz"
  1204                  else:
  1205                      reraise(Exception("Unsupported arch: {0}".format(self.machine)))
  1206  
  1207          elif self.platform == "Darwin":
  1208              self.ld_library_path = "DYLD_LIBRARY_PATH"
  1209              self.install_package_name = "WasmEdge-{0}-Darwin".format(self.version)
  1210              self.release_package = "darwin_{0}.tar.gz".format(self.machine)
  1211              self.release_package_wasmedge = self.release_package
  1212              self.lib_extension = ".dylib"
  1213              if self.dist is None:
  1214                  self.dist = "darwin"
  1215  
  1216      def __str__(self):
  1217          return (
  1218              "Platform:{0}\nMachine:{1}\nVersion:{2}\nExtensions:{3}\nDist:{4}\n".format(
  1219                  self.platform, self.machine, self.version, self.extensions, self.dist
  1220              )
  1221          )
  1222  
  1223      if sys.version_info[0] == 2:
  1224  
  1225          def __nonzero__(self):
  1226              return self.bool_overload()
  1227  
  1228      elif sys.version_info[0] == 3:
  1229  
  1230          def __bool__(self):
  1231              return self.bool_overload()
  1232  
  1233      def bool_overload(self):
  1234          if self.platform not in SUPPORTED_PLATFORM_MACHINE:
  1235              reraise(Exception("Unsupported platform: {0}".format(self.platform)))
  1236          if self.machine not in SUPPORTED_PLATFORM_MACHINE[self.platform]:
  1237              reraise(Exception("Unsupported machine: {0}".format(self.machine)))
  1238          if self.extensions is not None and len(self.extensions) > 0:
  1239              if not (
  1240                  set(self.extensions)
  1241                  <= set(SUPPORTED_EXTENSIONS[self.platform + self.machine])
  1242              ):
  1243                  reraise(
  1244                      Exception(
  1245                          "Extensions not supported: {0}. Supported extensions: {1}".format(
  1246                              self.extensions,
  1247                              SUPPORTED_EXTENSIONS[self.platform + self.machine],
  1248                          )
  1249                      )
  1250                  )
  1251          if (
  1252              self.version.compare(
  1253                  version2=SUPPORTED_MIN_VERSION[self.platform + self.machine].version
  1254              )
  1255              < 0
  1256          ):
  1257              reraise(
  1258                  Exception(
  1259                      "Version not supported. Min Version: {0}".format(
  1260                          SUPPORTED_MIN_VERSION[self.platform + self.machine].version
  1261                      )
  1262                  )
  1263              )
  1264  
  1265          if not get_remote_version_availability(
  1266              "WasmEdge/WasmEdge", self.version.version
  1267          ):
  1268              reraise(
  1269                  Exception(
  1270                      "Version {0} does not exist in remote repository of WasmEdge".format(
  1271                          self.version.version
  1272                      )
  1273                  )
  1274              )
  1275          return True
  1276  
  1277      def prefix(self):
  1278          return self.platform + self.machine
  1279  
  1280  
  1281  def main(args):
  1282      global CONST_env_path, CONST_release_pkg, CONST_ipkg, CONST_shell_config, CONST_shell_profile, CONST_lib_dir
  1283  
  1284      compat = Compat(
  1285          version=args.version,
  1286          extensions=args.extensions,
  1287          platform_=args.platform,
  1288          machine=args.machine,
  1289          dist_=args.dist,
  1290      )
  1291  
  1292      logging.debug("Compat object: %s", compat)
  1293      logging.debug("Temp path: %s", TEMP_PATH)
  1294      logging.debug("CLI Args:")
  1295      logging.debug(args)
  1296  
  1297      if len(args.plugins) >= 1:
  1298          logging.warning("Experimental Option Selected: plugins")
  1299          logging.warning("plugins option may change later")
  1300  
  1301      if compat:
  1302          print("Compatible with current configuration")
  1303  
  1304          set_consts(args, compat)
  1305  
  1306          # Run uninstaller
  1307          uninstaller_path = join(TEMP_PATH, "uninstall.sh")
  1308          download_url(CONST_urls[WASMEDGE_UNINSTALLER], uninstaller_path)
  1309  
  1310          print("Running Uninstaller")
  1311  
  1312          logging.debug(
  1313              run_shell_command("bash {0}  -p {1} -q".format(uninstaller_path, args.path))
  1314          )
  1315          remove(uninstaller_path)
  1316  
  1317          # If args.path is default then remove it initially
  1318          if PATH in args.path and exists(args.path):
  1319              shutil.rmtree(args.path)
  1320  
  1321          set_env(args, compat)
  1322  
  1323          logging.debug("CONST_env_path: %s", CONST_env_path)
  1324          logging.debug("CONST_release_pkg: %s", CONST_release_pkg)
  1325          logging.debug("CONST_ipkg: %s", CONST_ipkg)
  1326          logging.debug("CONST_lib_ext: %s", CONST_lib_ext)
  1327          logging.debug("CONST_urls: %s", CONST_urls)
  1328          logging.debug("CONST_lib_dir: %s", CONST_lib_dir)
  1329  
  1330          if getenv("SHELL") != SHELL:
  1331              logging.warning("SHELL variable not found. Using %s as SHELL", SHELL)
  1332  
  1333          if shell_configure(args, compat) != 0:
  1334              logging.error("Error in configuring shell")
  1335  
  1336          logging.debug("CONST_shell_profile: %s", CONST_shell_profile)
  1337          logging.debug("CONST_shell_config: %s", CONST_shell_config)
  1338  
  1339          print("Downloading WasmEdge")
  1340  
  1341          # Download WasmEdge
  1342          download_url(
  1343              CONST_urls[WASMEDGE], join(TEMP_PATH, CONST_release_pkg), show_progress
  1344          )
  1345  
  1346          # Extract archive
  1347          extract_archive(
  1348              join(TEMP_PATH, CONST_release_pkg),
  1349              args.path,
  1350              join(TEMP_PATH),
  1351              env_file_path=CONST_env_path,
  1352              remove_finished=True,
  1353          )
  1354  
  1355          print("Installing WasmEdge")
  1356          # Copy the tree
  1357          for sub_dir in listdir(join(TEMP_PATH, CONST_ipkg)):
  1358              if sub_dir == "lib64":
  1359                  copytree(join(TEMP_PATH, CONST_ipkg, sub_dir), join(args.path, "lib"))
  1360              else:
  1361                  copytree(join(TEMP_PATH, CONST_ipkg, sub_dir), join(args.path, sub_dir))
  1362  
  1363          if is_default_path(args):
  1364              # perform actions if default path
  1365              for dir in listdir(args.path):
  1366                  path = join(args.path, dir)
  1367                  if not isdir(path):
  1368                      continue
  1369                  for subdir in listdir(path):
  1370                      sub_folder = join(path, subdir)
  1371                      if isdir(sub_folder):
  1372                          if any("Plugin" in s for s in listdir(sub_folder)):
  1373                              # Handle plugins
  1374                              copytree(sub_folder, join(args.path, "plugin"), True)
  1375                              shutil.rmtree(sub_folder)
  1376  
  1377          # Check if wasmedge binary works
  1378          wasmedge_output = run_shell_command(
  1379              ". {0}/env && {0}/bin/wasmedge --version".format(args.path)
  1380          )
  1381  
  1382          if args.version in wasmedge_output:
  1383              print("WasmEdge Successfully installed")
  1384          else:
  1385              logging.critical(
  1386                  "WasmEdge installation incorrect: {0}".format(wasmedge_output)
  1387              )
  1388  
  1389          if IMAGE in args.extensions or "all" in args.extensions:
  1390              if install_image_extension(args, compat) != 0:
  1391                  logging.error("Error in installing image extensions")
  1392              else:
  1393                  print("Image extension installed")
  1394  
  1395          if TENSORFLOW in args.extensions or "all" in args.extensions:
  1396              if install_tensorflow_extension(args, compat) != 0:
  1397                  logging.error("Error in installing tensorflow extensions")
  1398              else:
  1399                  print("Tensorflow extension installed")
  1400  
  1401          install_plugins(args, compat)
  1402  
  1403          ldconfig(args, compat)
  1404  
  1405          # Cleanup
  1406          shutil.rmtree(TEMP_PATH)
  1407  
  1408          if compat.platform != "Darwin":
  1409              print("Run:\nsource {0}".format(CONST_shell_config))
  1410          else:
  1411              print("Run:\nsource {0}".format(CONST_shell_profile))
  1412      else:
  1413          reraise(Exception("Incompatible with your machine\n{0}".format(compat)))
  1414  
  1415  
  1416  if __name__ == "__main__":
  1417      parser = argparse.ArgumentParser(
  1418          description="WasmEdge installation, uninstallation and extensions install"
  1419      )
  1420      parser.add_argument(
  1421          "-e",
  1422          "--extension",
  1423          dest="extensions",
  1424          choices=EXTENSIONS.append("all"),
  1425          required=False,
  1426          default=[],
  1427          nargs="*",
  1428          help="Supported Extensions - {0}".format(EXTENSIONS),
  1429      )
  1430      parser.add_argument(
  1431          "-v",
  1432          "--version",
  1433          dest="version",
  1434          default=get_latest_github_release("WasmEdge/WasmEdge"),
  1435          required=False,
  1436          help="Version for WasmEdge",
  1437      )
  1438      parser.add_argument(
  1439          "-D",
  1440          "--debug",
  1441          dest="loglevel",
  1442          required=False,
  1443          action="store_const",
  1444          const=logging.DEBUG,
  1445          help="Verbosity debug",
  1446      )
  1447      parser.add_argument(
  1448          "-p",
  1449          "--path",
  1450          dest="path",
  1451          required=False,
  1452          default=PATH,
  1453          help="Installation path for WasmEdge",
  1454      )
  1455      parser.add_argument(
  1456          "-r",
  1457          "--remove-old",
  1458          dest="remove_old",
  1459          required=False,
  1460          choices=["yes", "no"],
  1461          help="Run uninstaller script before installing",
  1462      )
  1463      parser.add_argument(
  1464          "-u",
  1465          "--uninstall-script-tag",
  1466          dest="uninstall_script_tag",
  1467          required=False,
  1468          default=get_latest_github_release("WasmEdge/WasmEdge"),
  1469          help="GitHub tag for uninstall script",
  1470      )
  1471      parser.add_argument(
  1472          "--plugins",
  1473          dest="plugins",
  1474          required=False,
  1475          default=[],
  1476          nargs="*",
  1477          help="(experimental option)Supported Plugins. Example\n"
  1478          + "--plugins wasi_crypto:0.11.0\n"
  1479          + "--plugins wasi_crypto",
  1480      )
  1481      parser.add_argument(
  1482          "--tf-version",
  1483          dest="tf_version",
  1484          required=False,
  1485          default=None,
  1486          help="Tensorflow and tensorflow lite version",
  1487      )
  1488      parser.add_argument(
  1489          "--tf-deps-version",
  1490          dest="tf_deps_version",
  1491          required=False,
  1492          default=None,
  1493          help="Tensorflow and tensorflow lite deps version",
  1494      )
  1495      parser.add_argument(
  1496          "--tf-tools-version",
  1497          dest="tf_tools_version",
  1498          required=False,
  1499          default=None,
  1500          help="Tensorflow and tensorflow lite tools version",
  1501      )
  1502      parser.add_argument(
  1503          "--image-version",
  1504          dest="image_version",
  1505          required=False,
  1506          default=None,
  1507          help="Image extension version",
  1508      )
  1509      parser.add_argument(
  1510          "--platform",
  1511          "--os",
  1512          dest="platform",
  1513          required=False,
  1514          default=platform.system(),
  1515          choices=["Linux", "Darwin"],
  1516          type=lambda s: s.title(),
  1517          help="Platform ex- Linux, Darwin, Windows",
  1518      )
  1519      parser.add_argument(
  1520          "--machine",
  1521          "--arch",
  1522          dest="machine",
  1523          required=False,
  1524          default=platform.machine(),
  1525          choices=["x86_64", "aarch64", "arm", "arm64"],
  1526          type=lambda s: s.lower(),
  1527          help="Machine ex- x86_64, aarch64",
  1528      )
  1529      parser.add_argument(
  1530          "--dist",
  1531          dest="dist",
  1532          required=False,
  1533          default=None,
  1534          choices=["ubuntu20.04", "manylinux2014"],
  1535          type=lambda s: s.lower(),
  1536          help="Dist ex- ubuntu20.04,manylinux2014",
  1537      )
  1538      args = parser.parse_args()
  1539  
  1540      logging.basicConfig(format="%(levelname)-8s- %(message)s", level=args.loglevel)
  1541  
  1542      args.path = abspath(args.path)
  1543  
  1544      if args.tf_version is None:
  1545          args.tf_version = args.version
  1546  
  1547      if args.tf_deps_version is None:
  1548          args.tf_deps_version = args.version
  1549  
  1550      if args.tf_tools_version is None:
  1551          args.tf_tools_version = args.version
  1552  
  1553      if args.image_version is None:
  1554          args.image_version = args.version
  1555  
  1556      logging.debug("Python Version: %s", sys.version_info)
  1557      main(args)