1# -*- coding: utf-8 -*- 2 3import os 4import re 5import sys 6import shlex 7import subprocess 8import multiprocessing 9 10class NativeLib: 11 def __init__ (self, apiVersion, abiVersion): 12 self.apiVersion = apiVersion 13 self.abiVersion = abiVersion 14 15def getPlatform (): 16 if sys.platform.startswith('linux'): 17 return 'linux' 18 else: 19 return sys.platform 20 21def selectByOS (variants): 22 platform = getPlatform() 23 if platform in variants: 24 return variants[platform] 25 elif 'other' in variants: 26 return variants['other'] 27 else: 28 raise Exception("No configuration for '%s'" % platform) 29 30def isExecutable (path): 31 return os.path.isfile(path) and os.access(path, os.X_OK) 32 33def which (binName): 34 for path in os.environ['PATH'].split(os.pathsep): 35 path = path.strip('"') 36 fullPath = os.path.join(path, binName) 37 if isExecutable(fullPath): 38 return fullPath 39 40 return None 41 42def isBinaryInPath (binName): 43 return which(binName) != None 44 45def selectFirstExistingBinary (filenames): 46 for filename in filenames: 47 if filename != None and isExecutable(filename): 48 return filename 49 50 return None 51 52def selectFirstExistingDir (paths): 53 for path in paths: 54 if path != None and os.path.isdir(path): 55 return path 56 57 return None 58 59def die (msg): 60 print msg 61 exit(-1) 62 63def shellquote(s): 64 return '"%s"' % s.replace('\\', '\\\\').replace('"', '\"').replace('$', '\$').replace('`', '\`') 65 66def execute (commandLine): 67 args = shlex.split(commandLine) 68 retcode = subprocess.call(args) 69 if retcode != 0: 70 raise Exception("Failed to execute '%s', got %d" % (commandLine, retcode)) 71 72def execArgs (args): 73 retcode = subprocess.call(args) 74 if retcode != 0: 75 raise Exception("Failed to execute '%s', got %d" % (str(args), retcode)) 76 77class Device: 78 def __init__(self, serial, product, model, device): 79 self.serial = serial 80 self.product = product 81 self.model = model 82 self.device = device 83 84 def __str__ (self): 85 return "%s: {product: %s, model: %s, device: %s}" % (self.serial, self.product, self.model, self.device) 86 87def getDevices (adb): 88 proc = subprocess.Popen([adb, 'devices', '-l'], stdout=subprocess.PIPE) 89 (stdout, stderr) = proc.communicate() 90 91 if proc.returncode != 0: 92 raise Exception("adb devices -l failed, got %d" % retcode) 93 94 ptrn = re.compile(r'^([a-zA-Z0-9]+)\s+.*product:([^\s]+)\s+model:([^\s]+)\s+device:([^\s]+)') 95 devices = [] 96 for line in stdout.splitlines()[1:]: 97 if len(line.strip()) == 0: 98 continue 99 100 m = ptrn.match(line) 101 if m == None: 102 print "WARNING: Failed to parse device info '%s'" % line 103 continue 104 105 devices.append(Device(m.group(1), m.group(2), m.group(3), m.group(4))) 106 107 return devices 108 109def getWin32Generator (): 110 if which("jom.exe") != None: 111 return "NMake Makefiles JOM" 112 else: 113 return "NMake Makefiles" 114 115def isNinjaSupported (): 116 return which("ninja") != None 117 118def getUnixGenerator (): 119 if isNinjaSupported(): 120 return "Ninja" 121 else: 122 return "Unix Makefiles" 123 124def getExtraBuildArgs (generator): 125 if generator == "Unix Makefiles": 126 return ["--", "-j%d" % multiprocessing.cpu_count()] 127 else: 128 return [] 129 130NDK_HOST_OS_NAMES = [ 131 "windows", 132 "windows_x86-64", 133 "darwin-x86", 134 "darwin-x86-64", 135 "linux-x86", 136 "linux-x86_64" 137] 138 139def getNDKHostOsName (ndkPath): 140 for name in NDK_HOST_OS_NAMES: 141 if os.path.exists(os.path.join(ndkPath, "prebuilt", name)): 142 return name 143 144 raise Exception("Couldn't determine NDK host OS") 145 146# deqp/android path 147ANDROID_DIR = os.path.realpath(os.path.join(os.path.dirname(os.path.abspath(__file__)), "..")) 148 149# Build configuration 150NATIVE_LIBS = [ 151 # API ABI 152 NativeLib(13, "armeabi-v7a"), # ARM v7a ABI 153 NativeLib(13, "x86"), # x86 154 NativeLib(21, "arm64-v8a"), # ARM64 v8a ABI 155 ] 156ANDROID_JAVA_API = "android-13" 157NATIVE_LIB_NAME = "libdeqp.so" 158 159# NDK paths 160ANDROID_NDK_PATH = selectFirstExistingDir([ 161 os.path.expanduser("~/android-ndk-r10c"), 162 "C:/android/android-ndk-r10c", 163 ]) 164ANDROID_NDK_HOST_OS = getNDKHostOsName(ANDROID_NDK_PATH) 165ANDROID_NDK_TOOLCHAIN_VERSION = "r10c" # Toolchain file is selected based on this 166 167# Native code build settings 168CMAKE_GENERATOR = selectByOS({ 169 'win32': getWin32Generator(), 170 'other': getUnixGenerator() 171 }) 172EXTRA_BUILD_ARGS = getExtraBuildArgs(CMAKE_GENERATOR) 173 174# SDK paths 175ANDROID_SDK_PATH = selectFirstExistingDir([ 176 os.path.expanduser("~/android-sdk-linux"), 177 os.path.expanduser("~/android-sdk-mac_x86"), 178 "C:/android/android-sdk-windows", 179 ]) 180ANDROID_BIN = selectFirstExistingBinary([ 181 os.path.join(ANDROID_SDK_PATH, "tools", "android"), 182 os.path.join(ANDROID_SDK_PATH, "tools", "android.bat"), 183 which('android'), 184 ]) 185ADB_BIN = selectFirstExistingBinary([ 186 which('adb'), # \note Prefer adb in path to avoid version issues on dev machines 187 os.path.join(ANDROID_SDK_PATH, "platform-tools", "adb"), 188 os.path.join(ANDROID_SDK_PATH, "platform-tools", "adb.exe"), 189 ]) 190ZIPALIGN_BIN = selectFirstExistingBinary([ 191 os.path.join(ANDROID_SDK_PATH, "tools", "zipalign"), 192 os.path.join(ANDROID_SDK_PATH, "tools", "zipalign.exe"), 193 which('zipalign'), 194 ]) 195JARSIGNER_BIN = which('jarsigner') 196 197# Apache ant 198ANT_BIN = selectFirstExistingBinary([ 199 which('ant'), 200 "C:/android/apache-ant-1.8.4/bin/ant.bat", 201 "C:/android/apache-ant-1.9.2/bin/ant.bat", 202 "C:/android/apache-ant-1.9.3/bin/ant.bat", 203 "C:/android/apache-ant-1.9.4/bin/ant.bat", 204 ]) 205