|
|
|
#!/usr/bin/env python
|
|
|
|
import sys
|
|
|
|
import os
|
|
|
|
import platform
|
|
|
|
import re
|
|
|
|
import tempfile
|
|
|
|
import glob
|
|
|
|
import logging
|
|
|
|
import shutil
|
|
|
|
from subprocess import check_call, check_output, CalledProcessError, STDOUT
|
|
|
|
|
|
|
|
|
|
|
|
def initLogger():
|
|
|
|
logger = logging.getLogger("run.py")
|
|
|
|
logger.setLevel(logging.DEBUG)
|
|
|
|
ch = logging.StreamHandler(sys.stderr)
|
|
|
|
ch.setFormatter(logging.Formatter("%(message)s"))
|
|
|
|
logger.addHandler(ch)
|
|
|
|
return logger
|
|
|
|
|
|
|
|
|
|
|
|
log = initLogger()
|
|
|
|
hostos = os.name # 'nt', 'posix'
|
|
|
|
|
|
|
|
|
|
|
|
class Err(Exception):
|
|
|
|
def __init__(self, msg, *args):
|
|
|
|
self.msg = msg % args
|
|
|
|
|
|
|
|
|
|
|
|
def execute(cmd, silent=False, cwd=".", env=None):
|
|
|
|
try:
|
|
|
|
log.debug("Run: %s", cmd)
|
|
|
|
if env is not None:
|
|
|
|
for k in env:
|
|
|
|
log.debug(" Environ: %s=%s", k, env[k])
|
|
|
|
new_env = os.environ.copy()
|
|
|
|
new_env.update(env)
|
|
|
|
env = new_env
|
|
|
|
|
|
|
|
if sys.platform == 'darwin': # https://github.com/opencv/opencv/issues/14351
|
|
|
|
if env is None:
|
|
|
|
env = os.environ.copy()
|
|
|
|
if 'DYLD_LIBRARY_PATH' in env:
|
|
|
|
env['OPENCV_SAVED_DYLD_LIBRARY_PATH'] = env['DYLD_LIBRARY_PATH']
|
|
|
|
|
|
|
|
if silent:
|
|
|
|
return check_output(cmd, stderr=STDOUT, cwd=cwd, env=env).decode("latin-1")
|
|
|
|
else:
|
|
|
|
return check_call(cmd, cwd=cwd, env=env)
|
|
|
|
except CalledProcessError as e:
|
|
|
|
if silent:
|
|
|
|
log.debug("Process returned: %d", e.returncode)
|
|
|
|
return e.output.decode("latin-1")
|
|
|
|
else:
|
|
|
|
log.error("Process returned: %d", e.returncode)
|
|
|
|
return e.returncode
|
|
|
|
|
|
|
|
|
|
|
|
def isColorEnabled(args):
|
|
|
|
usercolor = [a for a in args if a.startswith("--gtest_color=")]
|
|
|
|
return len(usercolor) == 0 and sys.stdout.isatty() and hostos != "nt"
|
|
|
|
|
|
|
|
|
|
|
|
def getPlatformVersion():
|
|
|
|
mv = platform.mac_ver()
|
|
|
|
if mv[0]:
|
|
|
|
return "Darwin" + mv[0]
|
|
|
|
else:
|
|
|
|
wv = platform.win32_ver()
|
|
|
|
if wv[0]:
|
|
|
|
return "Windows" + wv[0]
|
|
|
|
else:
|
|
|
|
lv = platform.linux_distribution()
|
|
|
|
if lv[0]:
|
|
|
|
return lv[0] + lv[1]
|
|
|
|
return None
|
|
|
|
|
|
|
|
|
|
|
|
parse_patterns = (
|
|
|
|
{'name': "cmake_home", 'default': None, 'pattern': re.compile(r"^CMAKE_HOME_DIRECTORY:\w+=(.+)$")},
|
|
|
|
{'name': "opencv_home", 'default': None, 'pattern': re.compile(r"^OpenCV_SOURCE_DIR:\w+=(.+)$")},
|
|
|
|
{'name': "opencv_build", 'default': None, 'pattern': re.compile(r"^OpenCV_BINARY_DIR:\w+=(.+)$")},
|
|
|
|
{'name': "tests_dir", 'default': None, 'pattern': re.compile(r"^EXECUTABLE_OUTPUT_PATH:\w+=(.+)$")},
|
|
|
|
{'name': "build_type", 'default': "Release", 'pattern': re.compile(r"^CMAKE_BUILD_TYPE:\w+=(.*)$")},
|
|
|
|
{'name': "android_abi", 'default': None, 'pattern': re.compile(r"^ANDROID_ABI:\w+=(.*)$")},
|
|
|
|
{'name': "android_executable", 'default': None, 'pattern': re.compile(r"^ANDROID_EXECUTABLE:\w+=(.*android.*)$")},
|
|
|
|
{'name': "ant_executable", 'default': None, 'pattern': re.compile(r"^ANT_EXECUTABLE:\w+=(.*ant.*)$")},
|
|
|
|
{'name': "java_test_dir", 'default': None, 'pattern': re.compile(r"^OPENCV_JAVA_TEST_DIR:\w+=(.*)$")},
|
|
|
|
{'name': "is_x64", 'default': "OFF", 'pattern': re.compile(r"^CUDA_64_BIT_DEVICE_CODE:\w+=(ON)$")},
|
|
|
|
{'name': "cmake_generator", 'default': None, 'pattern': re.compile(r"^CMAKE_GENERATOR:\w+=(.+)$")},
|
|
|
|
{'name': "python2", 'default': None, 'pattern': re.compile(r"^BUILD_opencv_python2:\w+=(.*)$")},
|
|
|
|
{'name': "python3", 'default': None, 'pattern': re.compile(r"^BUILD_opencv_python3:\w+=(.*)$")},
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
class CMakeCache:
|
|
|
|
def __init__(self, cfg=None):
|
|
|
|
self.setDefaultAttrs()
|
|
|
|
self.main_modules = []
|
|
|
|
if cfg:
|
|
|
|
self.build_type = cfg
|
|
|
|
|
|
|
|
def setDummy(self, path):
|
|
|
|
self.tests_dir = os.path.normpath(path)
|
|
|
|
|
|
|
|
def read(self, path, fname):
|
|
|
|
rx = re.compile(r'^OPENCV_MODULE_opencv_(\w+)_LOCATION:INTERNAL=(.*)$')
|
|
|
|
module_paths = {} # name -> path
|
|
|
|
with open(fname, "rt") as cachefile:
|
|
|
|
for l in cachefile.readlines():
|
|
|
|
ll = l.strip()
|
|
|
|
if not ll or ll.startswith("#"):
|
|
|
|
continue
|
|
|
|
for p in parse_patterns:
|
|
|
|
match = p["pattern"].match(ll)
|
|
|
|
if match:
|
|
|
|
value = match.groups()[0]
|
|
|
|
if value and not value.endswith("-NOTFOUND"):
|
|
|
|
setattr(self, p["name"], value)
|
|
|
|
# log.debug("cache value: %s = %s", p["name"], value)
|
|
|
|
|
|
|
|
match = rx.search(ll)
|
|
|
|
if match:
|
|
|
|
module_paths[match.group(1)] = match.group(2)
|
|
|
|
|
|
|
|
if not self.tests_dir:
|
|
|
|
self.tests_dir = path
|
|
|
|
else:
|
|
|
|
rel = os.path.relpath(self.tests_dir, self.opencv_build)
|
|
|
|
self.tests_dir = os.path.join(path, rel)
|
|
|
|
self.tests_dir = os.path.normpath(self.tests_dir)
|
|
|
|
|
|
|
|
# fix VS test binary path (add Debug or Release)
|
|
|
|
if "Visual Studio" in self.cmake_generator:
|
|
|
|
self.tests_dir = os.path.join(self.tests_dir, self.build_type)
|
|
|
|
|
|
|
|
for module, path in module_paths.items():
|
|
|
|
rel = os.path.relpath(path, self.opencv_home)
|
|
|
|
if ".." not in rel:
|
|
|
|
self.main_modules.append(module)
|
|
|
|
|
|
|
|
def setDefaultAttrs(self):
|
|
|
|
for p in parse_patterns:
|
|
|
|
setattr(self, p["name"], p["default"])
|
|
|
|
|
|
|
|
def gatherTests(self, mask, isGood=None):
|
|
|
|
if self.tests_dir and os.path.isdir(self.tests_dir):
|
|
|
|
d = os.path.abspath(self.tests_dir)
|
|
|
|
files = glob.glob(os.path.join(d, mask))
|
|
|
|
if not self.getOS() == "android" and self.withJava():
|
|
|
|
files.append("java")
|
|
|
|
if self.withPython2():
|
|
|
|
files.append("python2")
|
|
|
|
if self.withPython3():
|
|
|
|
files.append("python3")
|
|
|
|
return [f for f in files if isGood(f)]
|
|
|
|
return []
|
|
|
|
|
|
|
|
def isMainModule(self, name):
|
|
|
|
return name in self.main_modules + ['python2', 'python3']
|
|
|
|
|
|
|
|
def withJava(self):
|
|
|
|
return self.ant_executable and self.java_test_dir and os.path.exists(self.java_test_dir)
|
|
|
|
|
|
|
|
def withPython2(self):
|
|
|
|
return self.python2 == 'ON'
|
|
|
|
|
|
|
|
def withPython3(self):
|
|
|
|
return self.python3 == 'ON'
|
|
|
|
|
|
|
|
def getOS(self):
|
|
|
|
if self.android_executable:
|
|
|
|
return "android"
|
|
|
|
else:
|
|
|
|
return hostos
|
|
|
|
|
|
|
|
|
|
|
|
class TempEnvDir:
|
|
|
|
def __init__(self, envname, prefix):
|
|
|
|
self.envname = envname
|
|
|
|
self.prefix = prefix
|
|
|
|
self.saved_name = None
|
|
|
|
self.new_name = None
|
|
|
|
|
|
|
|
def init(self):
|
|
|
|
self.saved_name = os.environ.get(self.envname)
|
|
|
|
self.new_name = tempfile.mkdtemp(prefix=self.prefix, dir=self.saved_name or None)
|
|
|
|
os.environ[self.envname] = self.new_name
|
|
|
|
|
|
|
|
def clean(self):
|
|
|
|
if self.saved_name:
|
|
|
|
os.environ[self.envname] = self.saved_name
|
|
|
|
else:
|
|
|
|
del os.environ[self.envname]
|
|
|
|
try:
|
|
|
|
shutil.rmtree(self.new_name)
|
|
|
|
except:
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
|
|
if __name__ == "__main__":
|
|
|
|
log.error("This is utility file, please execute run.py script")
|