run_utils.py 7.2 KB

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