@ -1,28 +1,34 @@
#!/usr/bin/env python
#!/usr/bin/env python
import sys
import sys , os , platform , re , tempfile , glob , getpass , logging
import os
import platform
import re
import tempfile
import glob
import logging
import shutil
from subprocess import check_call , check_output , CalledProcessError , STDOUT
from subprocess import check_call , check_output , CalledProcessError , STDOUT
hostos = os . name # 'nt', 'posix'
hostmachine = platform . machine ( ) # 'x86', 'AMD64', 'x86_64'
def initLogger ( ) :
def initLogger ( ) :
l = logging . getLogger ( " run.py " )
logger = logging . getLogger ( " run.py " )
l . setLevel ( logging . DEBUG )
logger . setLevel ( logging . DEBUG )
ch = logging . StreamHandler ( sys . stderr )
ch = logging . StreamHandler ( sys . stderr )
ch . setFormatter ( logging . Formatter ( " %(message)s " ) )
ch . setFormatter ( logging . Formatter ( " %(message)s " ) )
l . addHandler ( ch )
logger . addHandler ( ch )
return l
return logger
log = initLogger ( )
log = initLogger ( )
hostos = os . name # 'nt', 'posix'
#===================================================================================================
class Err ( Exception ) :
class Err ( Exception ) :
def __init__ ( self , msg , * args ) :
def __init__ ( self , msg , * args ) :
self . msg = msg % args
self . msg = msg % args
def execute ( cmd , silent = False , cwd = " . " , env = None ) :
def execute ( cmd , silent = False , cwd = " . " , env = None ) :
try :
try :
log . debug ( " Run: %s " , cmd )
log . debug ( " Run: %s " , cmd )
if env is not None :
if env is not None :
@ -32,9 +38,9 @@ def execute(cmd, silent = False, cwd = ".", env = None):
new_env . update ( env )
new_env . update ( env )
env = new_env
env = new_env
if silent :
if silent :
return check_output ( cmd , stderr = STDOUT , cwd = cwd , env = env ) . decode ( " latin-1 " )
return check_output ( cmd , stderr = STDOUT , cwd = cwd , env = env ) . decode ( " latin-1 " )
else :
else :
return check_call ( cmd , cwd = cwd , env = env )
return check_call ( cmd , cwd = cwd , env = env )
except CalledProcessError as e :
except CalledProcessError as e :
if silent :
if silent :
log . debug ( " Process returned: %d " , e . returncode )
log . debug ( " Process returned: %d " , e . returncode )
@ -43,11 +49,11 @@ def execute(cmd, silent = False, cwd = ".", env = None):
log . error ( " Process returned: %d " , e . returncode )
log . error ( " Process returned: %d " , e . returncode )
return e . returncode
return e . returncode
def isColorEnabled ( args ) :
def isColorEnabled ( args ) :
usercolor = [ a for a in args if a . startswith ( " --gtest_color= " ) ]
usercolor = [ a for a in args if a . startswith ( " --gtest_color= " ) ]
return len ( usercolor ) == 0 and sys . stdout . isatty ( ) and hostos != " nt "
return len ( usercolor ) == 0 and sys . stdout . isatty ( ) and hostos != " nt "
#===================================================================================================
def getPlatformVersion ( ) :
def getPlatformVersion ( ) :
mv = platform . mac_ver ( )
mv = platform . mac_ver ( )
@ -63,130 +69,27 @@ def getPlatformVersion():
return lv [ 0 ] + lv [ 1 ]
return lv [ 0 ] + lv [ 1 ]
return None
return None
def readGitVersion ( git , path ) :
if not path or not git or not os . path . isdir ( os . path . join ( path , " .git " ) ) :
return None
try :
output = execute ( [ git , " -C " , path , " rev-parse " , " --short " , " HEAD " ] , silent = True )
return output . strip ( )
except OSError :
log . warning ( " Git version read failed " )
return None
SIMD_DETECTION_PROGRAM = """
#if __SSE5__
# error SSE5
#endif
#if __AVX2__
# error AVX2
#endif
#if __AVX__
# error AVX
#endif
#if __SSE4_2__
# error SSE4.2
#endif
#if __SSE4_1__
# error SSE4.1
#endif
#if __SSSE3__
# error SSSE3
#endif
#if __SSE3__
# error SSE3
#endif
#if __AES__
# error AES
#endif
#if __SSE2__
# error SSE2
#endif
#if __SSE__
# error SSE
#endif
#if __3dNOW__
# error 3dNOW
#endif
#if __MMX__
# error MMX
#endif
#if __ARM_NEON__
# error NEON
#endif
#error NOSIMD
"""
def testSIMD ( compiler , cxx_flags , compiler_arg = None ) :
if not compiler :
return None
compiler_output = " "
try :
_ , tmpfile = tempfile . mkstemp ( suffix = " .cpp " , text = True )
with open ( tmpfile , " w+ " ) as fd :
fd . write ( SIMD_DETECTION_PROGRAM )
options = [ compiler ]
if compiler_arg :
options . append ( compiler_arg )
prev_option = None
for opt in " " . join ( cxx_flags ) . split ( ) :
if opt . count ( ' \" ' ) % 2 == 1 :
if prev_option is None :
prev_option = opt
else :
options . append ( prev_option + " " + opt )
prev_option = None
elif prev_option is None :
options . append ( opt )
else :
prev_option = prev_option + " " + opt
options . append ( tmpfile )
compiler_output = execute ( options , silent = True )
os . remove ( tmpfile )
m = re . search ( " #error \ W+( \ w+) " , compiler_output )
if m :
return m . group ( 1 )
except OSError :
pass
log . debug ( " SIMD detection failed " )
return None
#==============================================================================
parse_patterns = (
parse_patterns = (
{ ' name ' : " cmake_home " , ' default ' : None , ' pattern ' : re . compile ( r " ^CMAKE_HOME_DIRECTORY:INTERNAL =(.+)$ " ) } ,
{ ' 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:STATIC =(.+)$ " ) } ,
{ ' 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:STATIC =(.+)$ " ) } ,
{ ' 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:PATH =(.+)$ " ) } ,
{ ' 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 ' : " build_type " , ' default ' : " Release " , ' pattern ' : re . compile ( r " ^CMAKE_BUILD_TYPE: \ w+=(.*)$ " ) } ,
{ ' name ' : " git_executable " , ' default ' : None , ' pattern ' : re . compile ( r " ^GIT_EXECUTABLE:FILEPATH=(.*)$ " ) } ,
{ ' name ' : " android_abi " , ' default ' : None , ' pattern ' : re . compile ( r " ^ANDROID_ABI: \ w+=(.*)$ " ) } ,
{ ' name ' : " cxx_flags " , ' default ' : " " , ' pattern ' : re . compile ( r " ^CMAKE_CXX_FLAGS:STRING=(.*)$ " ) } ,
{ ' name ' : " android_executable " , ' default ' : None , ' pattern ' : re . compile ( r " ^ANDROID_EXECUTABLE: \ w+=(.*android.*)$ " ) } ,
{ ' name ' : " cxx_flags_debug " , ' default ' : " " , ' pattern ' : re . compile ( r " ^CMAKE_CXX_FLAGS_DEBUG:STRING=(.*)$ " ) } ,
{ ' name ' : " ant_executable " , ' default ' : None , ' pattern ' : re . compile ( r " ^ANT_EXECUTABLE: \ w+=(.*ant.*)$ " ) } ,
{ ' name ' : " cxx_flags_release " , ' default ' : " " , ' pattern ' : re . compile ( r " ^CMAKE_CXX_FLAGS_RELEASE:STRING=(.*)$ " ) } ,
{ ' name ' : " opencv_cxx_flags " , ' default ' : " " , ' pattern ' : re . compile ( r " ^OPENCV_EXTRA_C_FLAGS:INTERNAL=(.*)$ " ) } ,
{ ' name ' : " cxx_flags_android " , ' default ' : None , ' pattern ' : re . compile ( r " ^ANDROID_CXX_FLAGS:INTERNAL=(.*)$ " ) } ,
{ ' name ' : " android_abi " , ' default ' : None , ' pattern ' : re . compile ( r " ^ANDROID_ABI:STRING=(.*)$ " ) } ,
{ ' name ' : " android_executable " , ' default ' : None , ' pattern ' : re . compile ( r " ^ANDROID_EXECUTABLE:FILEPATH=(.*android.*)$ " ) } ,
{ ' name ' : " ant_executable " , ' default ' : None , ' pattern ' : re . compile ( r " ^ANT_EXECUTABLE:FILEPATH=(.*ant.*)$ " ) } ,
{ ' name ' : " java_test_dir " , ' default ' : None , ' pattern ' : re . compile ( r " ^OPENCV_JAVA_TEST_DIR: \ w+=(.*)$ " ) } ,
{ ' 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:BOOL=(ON)$ " ) } , #ugly(
{ ' 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:INTERNAL=(.+)$ " ) } ,
{ ' name ' : " cmake_generator " , ' default ' : None , ' pattern ' : re . compile ( r " ^CMAKE_GENERATOR: \ w+=(.+)$ " ) } ,
{ ' name ' : " cxx_compiler " , ' default ' : None , ' pattern ' : re . compile ( r " ^CMAKE_CXX_COMPILER: \ w*PATH=(.+)$ " ) } ,
{ ' name ' : " python2 " , ' default ' : None , ' pattern ' : re . compile ( r " ^BUILD_opencv_python2: \ w+=(.*)$ " ) } ,
{ ' name ' : " cxx_compiler_arg1 " , ' default ' : None , ' pattern ' : re . compile ( r " ^CMAKE_CXX_COMPILER_ARG1:[A-Z]+=(.+)$ " ) } ,
{ ' name ' : " python3 " , ' default ' : None , ' pattern ' : re . compile ( r " ^BUILD_opencv_python3: \ w+=(.*)$ " ) } ,
{ ' name ' : " with_cuda " , ' default ' : " OFF " , ' pattern ' : re . compile ( r " ^WITH_CUDA:BOOL=(ON)$ " ) } ,
{ ' name ' : " cuda_library " , ' default ' : None , ' pattern ' : re . compile ( r " ^CUDA_CUDA_LIBRARY:FILEPATH=(.+)$ " ) } ,
{ ' name ' : " cuda_version " , ' default ' : None , ' pattern ' : re . compile ( r " ^CUDA_VERSION:STRING=(.+)$ " ) } ,
{ ' name ' : " core_dependencies " , ' default ' : None , ' pattern ' : re . compile ( r " ^opencv_core_LIB_DEPENDS:STATIC=(.+)$ " ) } ,
{ ' name ' : " python2 " , ' default ' : None , ' pattern ' : re . compile ( r " ^BUILD_opencv_python2:BOOL=(.*)$ " ) } ,
{ ' name ' : " python3 " , ' default ' : None , ' pattern ' : re . compile ( r " ^BUILD_opencv_python3:BOOL=(.*)$ " ) } ,
)
)
class CMakeCache :
class CMakeCache :
def __init__ ( self , cfg = None ) :
def __init__ ( self , cfg = None ) :
self . setDefaultAttrs ( )
self . setDefaultAttrs ( )
self . cmake_home_vcver = None
self . opencv_home_vcver = None
self . featuresSIMD = None
self . main_modules = [ ]
self . main_modules = [ ]
if cfg :
if cfg :
self . build_type = cfg
self . build_type = cfg
@ -196,7 +99,7 @@ class CMakeCache:
def read ( self , path , fname ) :
def read ( self , path , fname ) :
rx = re . compile ( r ' ^OPENCV_MODULE_opencv_( \ w+)_LOCATION:INTERNAL=(.*)$ ' )
rx = re . compile ( r ' ^OPENCV_MODULE_opencv_( \ w+)_LOCATION:INTERNAL=(.*)$ ' )
module_paths = { } # name -> path
module_paths = { } # name -> path
with open ( fname , " rt " ) as cachefile :
with open ( fname , " rt " ) as cachefile :
for l in cachefile . readlines ( ) :
for l in cachefile . readlines ( ) :
ll = l . strip ( )
ll = l . strip ( )
@ -225,31 +128,16 @@ class CMakeCache:
if " Visual Studio " in self . cmake_generator :
if " Visual Studio " in self . cmake_generator :
self . tests_dir = os . path . join ( self . tests_dir , self . build_type )
self . tests_dir = os . path . join ( self . tests_dir , self . build_type )
self . cmake_home_vcver = readGitVersion ( self . git_executable , self . cmake_home )
for module , path in module_paths . items ( ) :
if self . opencv_home == self . cmake_home :
self . opencv_home_vcver = self . cmake_home_vcver
else :
self . opencv_home_vcver = readGitVersion ( self . git_executable , self . opencv_home )
for module , path in module_paths . items ( ) :
rel = os . path . relpath ( path , self . opencv_home )
rel = os . path . relpath ( path , self . opencv_home )
if not " .. " in rel :
if " .. " not in rel :
self . main_modules . append ( module )
self . main_modules . append ( module )
self . flags = [
self . cxx_flags_android ,
self . cxx_flags ,
self . cxx_flags_release ,
self . opencv_cxx_flags ,
self . cxx_flags_release ]
self . flags = [ f for f in self . flags if f ]
self . featuresSIMD = testSIMD ( self . cxx_compiler , self . flags , self . cxx_compiler_arg1 )
def setDefaultAttrs ( self ) :
def setDefaultAttrs ( self ) :
for p in parse_patterns :
for p in parse_patterns :
setattr ( self , p [ " name " ] , p [ " default " ] )
setattr ( self , p [ " name " ] , p [ " default " ] )
def gatherTests ( self , mask , isGood = None ) :
def gatherTests ( self , mask , isGood = None ) :
if self . tests_dir and os . path . isdir ( self . tests_dir ) :
if self . tests_dir and os . path . isdir ( self . tests_dir ) :
d = os . path . abspath ( self . tests_dir )
d = os . path . abspath ( self . tests_dir )
files = glob . glob ( os . path . join ( d , mask ) )
files = glob . glob ( os . path . join ( d , mask ) )
@ -265,11 +153,8 @@ class CMakeCache:
def isMainModule ( self , name ) :
def isMainModule ( self , name ) :
return name in self . main_modules + [ ' python2 ' , ' python3 ' ]
return name in self . main_modules + [ ' python2 ' , ' python3 ' ]
def withCuda ( self ) :
return self . cuda_version and self . with_cuda == " ON " and self . cuda_library and not self . cuda_library . endswith ( " -NOTFOUND " )
def withJava ( self ) :
def withJava ( self ) :
return self . ant_executable and os . path . exists ( self . java_test_dir )
return self . ant_executable and self . java_test_dir and os . path . exists ( self . java_test_dir )
def withPython2 ( self ) :
def withPython2 ( self ) :
return self . python2 == ' ON '
return self . python2 == ' ON '
@ -277,164 +162,12 @@ class CMakeCache:
def withPython3 ( self ) :
def withPython3 ( self ) :
return self . python3 == ' ON '
return self . python3 == ' ON '
def getGitVersion ( self ) :
if self . cmake_home_vcver :
if self . cmake_home_vcver == self . opencv_home_vcver :
rev = self . cmake_home_vcver
elif self . opencv_home_vcver :
rev = self . cmake_home_vcver + " - " + self . opencv_home_vcver
else :
rev = self . cmake_home_vcver
else :
rev = None
if rev :
rev = rev . replace ( " : " , " to " )
else :
rev = " "
return rev
def getTestFullName ( self , shortname ) :
return os . path . join ( self . tests_dir , shortname )
def getSIMDFeatures ( self ) :
return self . featuresSIMD
def getOS ( self ) :
def getOS ( self ) :
if self . android_executable :
if self . android_executable :
return " android "
return " android "
else :
else :
return hostos
return hostos
def getArch ( self ) :
arch = " unknown "
if self . getOS ( ) == " android " :
if " armeabi-v7a " in self . android_abi :
arch = " armv7a "
elif " armeabi-v6 " in self . android_abi :
arch = " armv6 "
elif " armeabi " in self . android_abi :
arch = " armv5te "
elif " x86 " in self . android_abi :
arch = " x86 "
elif " mips " in self . android_abi :
arch = " mips "
else :
arch = " ARM "
elif self . is_x64 and hostmachine in [ " AMD64 " , " x86_64 " ] :
arch = " x64 "
elif hostmachine in [ " x86 " , " AMD64 " , " x86_64 " ] :
arch = " x86 "
return arch
def getDependencies ( self ) :
if self . core_dependencies :
candidates = [ " tbb " , " ippicv " , " ipp " , " pthreads " ]
return [ a for a in self . core_dependencies . split ( " ; " ) if a and a in candidates ]
return [ ]
#==============================================================================
def getRunningProcessExePathByName_win32 ( name ) :
from ctypes import windll , POINTER , pointer , Structure , sizeof
from ctypes import c_long , c_int , c_uint , c_char , c_ubyte , c_char_p , c_void_p
class PROCESSENTRY32 ( Structure ) :
_fields_ = [ ( ' dwSize ' , c_uint ) ,
( ' cntUsage ' , c_uint ) ,
( ' th32ProcessID ' , c_uint ) ,
( ' th32DefaultHeapID ' , c_uint ) ,
( ' th32ModuleID ' , c_uint ) ,
( ' cntThreads ' , c_uint ) ,
( ' th32ParentProcessID ' , c_uint ) ,
( ' pcPriClassBase ' , c_long ) ,
( ' dwFlags ' , c_uint ) ,
( ' szExeFile ' , c_char * 260 ) ,
( ' th32MemoryBase ' , c_long ) ,
( ' th32AccessKey ' , c_long ) ]
class MODULEENTRY32 ( Structure ) :
_fields_ = [ ( ' dwSize ' , c_long ) ,
( ' th32ModuleID ' , c_long ) ,
( ' th32ProcessID ' , c_long ) ,
( ' GlblcntUsage ' , c_long ) ,
( ' ProccntUsage ' , c_long ) ,
( ' modBaseAddr ' , c_long ) ,
( ' modBaseSize ' , c_long ) ,
( ' hModule ' , c_void_p ) ,
( ' szModule ' , c_char * 256 ) ,
( ' szExePath ' , c_char * 260 ) ]
TH32CS_SNAPPROCESS = 2
TH32CS_SNAPMODULE = 0x00000008
## CreateToolhelp32Snapshot
CreateToolhelp32Snapshot = windll . kernel32 . CreateToolhelp32Snapshot
CreateToolhelp32Snapshot . reltype = c_long
CreateToolhelp32Snapshot . argtypes = [ c_int , c_int ]
## Process32First
Process32First = windll . kernel32 . Process32First
Process32First . argtypes = [ c_void_p , POINTER ( PROCESSENTRY32 ) ]
Process32First . rettype = c_int
## Process32Next
Process32Next = windll . kernel32 . Process32Next
Process32Next . argtypes = [ c_void_p , POINTER ( PROCESSENTRY32 ) ]
Process32Next . rettype = c_int
## CloseHandle
CloseHandle = windll . kernel32 . CloseHandle
CloseHandle . argtypes = [ c_void_p ]
CloseHandle . rettype = c_int
## Module32First
Module32First = windll . kernel32 . Module32First
Module32First . argtypes = [ c_void_p , POINTER ( MODULEENTRY32 ) ]
Module32First . rettype = c_int
hProcessSnap = c_void_p ( 0 )
hProcessSnap = CreateToolhelp32Snapshot ( TH32CS_SNAPPROCESS , 0 )
pe32 = PROCESSENTRY32 ( )
pe32 . dwSize = sizeof ( PROCESSENTRY32 )
ret = Process32First ( hProcessSnap , pointer ( pe32 ) )
path = None
while ret :
if name + " .exe " == pe32 . szExeFile :
hModuleSnap = c_void_p ( 0 )
me32 = MODULEENTRY32 ( )
me32 . dwSize = sizeof ( MODULEENTRY32 )
hModuleSnap = CreateToolhelp32Snapshot ( TH32CS_SNAPMODULE , pe32 . th32ProcessID )
ret = Module32First ( hModuleSnap , pointer ( me32 ) )
path = me32 . szExePath
CloseHandle ( hModuleSnap )
if path :
break
ret = Process32Next ( hProcessSnap , pointer ( pe32 ) )
CloseHandle ( hProcessSnap )
return path
def getRunningProcessExePathByName_posix ( name ) :
pids = [ pid for pid in os . listdir ( ' /proc ' ) if pid . isdigit ( ) ]
for pid in pids :
try :
path = os . readlink ( os . path . join ( ' /proc ' , pid , ' exe ' ) )
if path and path . endswith ( name ) :
return path
except :
pass
def getRunningProcessExePathByName ( name ) :
try :
if hostos == " nt " :
return getRunningProcessExePathByName_win32 ( name )
elif hostos == " posix " :
return getRunningProcessExePathByName_posix ( name )
else :
return None
except :
return None
class TempEnvDir :
class TempEnvDir :
def __init__ ( self , envname , prefix ) :
def __init__ ( self , envname , prefix ) :
@ -458,7 +191,6 @@ class TempEnvDir:
except :
except :
pass
pass
#===================================================================================================
if __name__ == " __main__ " :
if __name__ == " __main__ " :
log . error ( " This is utility file, please execute run.py script " )
log . error ( " This is utility file, please execute run.py script " )