run_utils.py 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206
  1. #!/usr/bin/env python
  2. """ Utility package for run.py
  3. """
  4. import sys
  5. import os
  6. import platform
  7. import re
  8. import tempfile
  9. import glob
  10. import logging
  11. import shutil
  12. from subprocess import check_call, check_output, CalledProcessError, STDOUT
  13. def initLogger():
  14. logger = logging.getLogger("run.py")
  15. logger.setLevel(logging.DEBUG)
  16. ch = logging.StreamHandler(sys.stderr)
  17. ch.setFormatter(logging.Formatter("%(message)s"))
  18. logger.addHandler(ch)
  19. return logger
  20. log = initLogger()
  21. hostos = os.name # 'nt', 'posix'
  22. class Err(Exception):
  23. def __init__(self, msg, *args):
  24. self.msg = msg % args
  25. def execute(cmd, silent=False, cwd=".", env=None):
  26. try:
  27. log.debug("Run: %s", cmd)
  28. if env is not None:
  29. for k in env:
  30. log.debug(" Environ: %s=%s", k, env[k])
  31. new_env = os.environ.copy()
  32. new_env.update(env)
  33. env = new_env
  34. if sys.platform == 'darwin': # https://github.com/opencv/opencv/issues/14351
  35. if env is None:
  36. env = os.environ.copy()
  37. if 'DYLD_LIBRARY_PATH' in env:
  38. env['OPENCV_SAVED_DYLD_LIBRARY_PATH'] = env['DYLD_LIBRARY_PATH']
  39. if silent:
  40. return check_output(cmd, stderr=STDOUT, cwd=cwd, env=env).decode("latin-1")
  41. else:
  42. return check_call(cmd, cwd=cwd, env=env)
  43. except CalledProcessError as e:
  44. if silent:
  45. log.debug("Process returned: %d", e.returncode)
  46. return e.output.decode("latin-1")
  47. else:
  48. log.error("Process returned: %d", e.returncode)
  49. return e.returncode
  50. def isColorEnabled(args):
  51. usercolor = [a for a in args if a.startswith("--gtest_color=")]
  52. return len(usercolor) == 0 and sys.stdout.isatty() and hostos != "nt"
  53. def getPlatformVersion():
  54. mv = platform.mac_ver()
  55. if mv[0]:
  56. return "Darwin" + mv[0]
  57. else:
  58. wv = platform.win32_ver()
  59. if wv[0]:
  60. return "Windows" + wv[0]
  61. else:
  62. lv = platform.linux_distribution()
  63. if lv[0]:
  64. return lv[0] + lv[1]
  65. return None
  66. parse_patterns = (
  67. {'name': "cmake_home", 'default': None, 'pattern': re.compile(r"^CMAKE_HOME_DIRECTORY:\w+=(.+)$")},
  68. {'name': "opencv_home", 'default': None, 'pattern': re.compile(r"^OpenCV_SOURCE_DIR:\w+=(.+)$")},
  69. {'name': "opencv_build", 'default': None, 'pattern': re.compile(r"^OpenCV_BINARY_DIR:\w+=(.+)$")},
  70. {'name': "tests_dir", 'default': None, 'pattern': re.compile(r"^EXECUTABLE_OUTPUT_PATH:\w+=(.+)$")},
  71. {'name': "build_type", 'default': "Release", 'pattern': re.compile(r"^CMAKE_BUILD_TYPE:\w+=(.*)$")},
  72. {'name': "android_abi", 'default': None, 'pattern': re.compile(r"^ANDROID_ABI:\w+=(.*)$")},
  73. {'name': "android_executable", 'default': None, 'pattern': re.compile(r"^ANDROID_EXECUTABLE:\w+=(.*android.*)$")},
  74. {'name': "ant_executable", 'default': None, 'pattern': re.compile(r"^ANT_EXECUTABLE:\w+=(.*ant.*)$")},
  75. {'name': "java_test_dir", 'default': None, 'pattern': re.compile(r"^OPENCV_JAVA_TEST_DIR:\w+=(.*)$")},
  76. {'name': "is_x64", 'default': "OFF", 'pattern': re.compile(r"^CUDA_64_BIT_DEVICE_CODE:\w+=(ON)$")},
  77. {'name': "cmake_generator", 'default': None, 'pattern': re.compile(r"^CMAKE_GENERATOR:\w+=(.+)$")},
  78. {'name': "python2", 'default': None, 'pattern': re.compile(r"^BUILD_opencv_python2:\w+=(.*)$")},
  79. {'name': "python3", 'default': None, 'pattern': re.compile(r"^BUILD_opencv_python3:\w+=(.*)$")},
  80. )
  81. class CMakeCache:
  82. def __init__(self, cfg=None):
  83. self.setDefaultAttrs()
  84. self.main_modules = []
  85. if cfg:
  86. self.build_type = cfg
  87. def setDummy(self, path):
  88. self.tests_dir = os.path.normpath(path)
  89. def read(self, path, fname):
  90. rx = re.compile(r'^OPENCV_MODULE_opencv_(\w+)_LOCATION:INTERNAL=(.*)$')
  91. module_paths = {} # name -> path
  92. with open(fname, "rt") as cachefile:
  93. for l in cachefile.readlines():
  94. ll = l.strip()
  95. if not ll or ll.startswith("#"):
  96. continue
  97. for p in parse_patterns:
  98. match = p["pattern"].match(ll)
  99. if match:
  100. value = match.groups()[0]
  101. if value and not value.endswith("-NOTFOUND"):
  102. setattr(self, p["name"], value)
  103. # log.debug("cache value: %s = %s", p["name"], value)
  104. match = rx.search(ll)
  105. if match:
  106. module_paths[match.group(1)] = match.group(2)
  107. if not self.tests_dir:
  108. self.tests_dir = path
  109. else:
  110. rel = os.path.relpath(self.tests_dir, self.opencv_build)
  111. self.tests_dir = os.path.join(path, rel)
  112. self.tests_dir = os.path.normpath(self.tests_dir)
  113. # fix VS test binary path (add Debug or Release)
  114. if "Visual Studio" in self.cmake_generator:
  115. self.tests_dir = os.path.join(self.tests_dir, self.build_type)
  116. for module, path in module_paths.items():
  117. rel = os.path.relpath(path, self.opencv_home)
  118. if ".." not in rel:
  119. self.main_modules.append(module)
  120. def setDefaultAttrs(self):
  121. for p in parse_patterns:
  122. setattr(self, p["name"], p["default"])
  123. def gatherTests(self, mask, isGood=None):
  124. if self.tests_dir and os.path.isdir(self.tests_dir):
  125. d = os.path.abspath(self.tests_dir)
  126. files = glob.glob(os.path.join(d, mask))
  127. if not self.getOS() == "android" and self.withJava():
  128. files.append("java")
  129. if self.withPython2():
  130. files.append("python2")
  131. if self.withPython3():
  132. files.append("python3")
  133. return [f for f in files if isGood(f)]
  134. return []
  135. def isMainModule(self, name):
  136. return name in self.main_modules + ['python2', 'python3']
  137. def withJava(self):
  138. return self.ant_executable and self.java_test_dir and os.path.exists(self.java_test_dir)
  139. def withPython2(self):
  140. return self.python2 == 'ON'
  141. def withPython3(self):
  142. return self.python3 == 'ON'
  143. def getOS(self):
  144. if self.android_executable:
  145. return "android"
  146. else:
  147. return hostos
  148. class TempEnvDir:
  149. def __init__(self, envname, prefix):
  150. self.envname = envname
  151. self.prefix = prefix
  152. self.saved_name = None
  153. self.new_name = None
  154. def init(self):
  155. self.saved_name = os.environ.get(self.envname)
  156. self.new_name = tempfile.mkdtemp(prefix=self.prefix, dir=self.saved_name or None)
  157. os.environ[self.envname] = self.new_name
  158. def clean(self):
  159. if self.saved_name:
  160. os.environ[self.envname] = self.saved_name
  161. else:
  162. del os.environ[self.envname]
  163. try:
  164. shutil.rmtree(self.new_name)
  165. except:
  166. pass
  167. if __name__ == "__main__":
  168. log.error("This is utility file, please execute run.py script")