Jarkko Poyry | 3c82736 | 2014-09-02 11:48:52 +0300 | [diff] [blame] | 1 | # -*- coding: utf-8 -*- |
| 2 | |
Jarkko Pöyry | 3c77ed4 | 2015-01-06 12:54:34 -0800 | [diff] [blame] | 3 | #------------------------------------------------------------------------- |
| 4 | # drawElements Quality Program utilities |
| 5 | # -------------------------------------- |
| 6 | # |
| 7 | # Copyright 2015 The Android Open Source Project |
| 8 | # |
| 9 | # Licensed under the Apache License, Version 2.0 (the "License"); |
| 10 | # you may not use this file except in compliance with the License. |
| 11 | # You may obtain a copy of the License at |
| 12 | # |
| 13 | # http://www.apache.org/licenses/LICENSE-2.0 |
| 14 | # |
| 15 | # Unless required by applicable law or agreed to in writing, software |
| 16 | # distributed under the License is distributed on an "AS IS" BASIS, |
| 17 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 18 | # See the License for the specific language governing permissions and |
| 19 | # limitations under the License. |
| 20 | # |
| 21 | #------------------------------------------------------------------------- |
| 22 | |
Jarkko Poyry | 3c82736 | 2014-09-02 11:48:52 +0300 | [diff] [blame] | 23 | import os |
Pyry Haulos | 89e0405 | 2014-10-20 11:09:56 -0700 | [diff] [blame] | 24 | import re |
Jarkko Poyry | 3c82736 | 2014-09-02 11:48:52 +0300 | [diff] [blame] | 25 | import sys |
| 26 | import shlex |
| 27 | import subprocess |
Pyry Haulos | 89e0405 | 2014-10-20 11:09:56 -0700 | [diff] [blame] | 28 | import multiprocessing |
Kalle Raita | c9f7674 | 2014-11-13 13:00:08 -0800 | [diff] [blame] | 29 | import string |
Jarkko Poyry | 3c82736 | 2014-09-02 11:48:52 +0300 | [diff] [blame] | 30 | |
Jarkko Pöyry | 842a87c | 2014-12-11 18:22:05 -0800 | [diff] [blame] | 31 | try: |
| 32 | import threading |
| 33 | except ImportError: |
| 34 | import dummy_threading as threading |
| 35 | |
Jarkko Poyry | 3c82736 | 2014-09-02 11:48:52 +0300 | [diff] [blame] | 36 | class NativeLib: |
Jarkko Pöyry | b6d3233 | 2015-03-09 16:38:57 -0700 | [diff] [blame] | 37 | def __init__ (self, apiVersion, abiVersion, prebuiltDir): |
| 38 | self.apiVersion = apiVersion |
| 39 | self.abiVersion = abiVersion |
| 40 | self.prebuiltDir = prebuiltDir |
Jarkko Poyry | 3c82736 | 2014-09-02 11:48:52 +0300 | [diff] [blame] | 41 | |
Kalle Raita | c9f7674 | 2014-11-13 13:00:08 -0800 | [diff] [blame] | 42 | def __str__ (self): |
| 43 | return "(API: %s, ABI: %s)" % (self.apiVersion, self.abiVersion) |
| 44 | |
| 45 | def __repr__ (self): |
| 46 | return "(API: %s, ABI: %s)" % (self.apiVersion, self.abiVersion) |
| 47 | |
| 48 | |
Jarkko Poyry | 3c82736 | 2014-09-02 11:48:52 +0300 | [diff] [blame] | 49 | def getPlatform (): |
| 50 | if sys.platform.startswith('linux'): |
| 51 | return 'linux' |
| 52 | else: |
| 53 | return sys.platform |
| 54 | |
Pyry Haulos | 89e0405 | 2014-10-20 11:09:56 -0700 | [diff] [blame] | 55 | def selectByOS (variants): |
Jarkko Poyry | 3c82736 | 2014-09-02 11:48:52 +0300 | [diff] [blame] | 56 | platform = getPlatform() |
| 57 | if platform in variants: |
| 58 | return variants[platform] |
| 59 | elif 'other' in variants: |
| 60 | return variants['other'] |
| 61 | else: |
| 62 | raise Exception("No configuration for '%s'" % platform) |
| 63 | |
| 64 | def isExecutable (path): |
| 65 | return os.path.isfile(path) and os.access(path, os.X_OK) |
| 66 | |
| 67 | def which (binName): |
| 68 | for path in os.environ['PATH'].split(os.pathsep): |
| 69 | path = path.strip('"') |
| 70 | fullPath = os.path.join(path, binName) |
| 71 | if isExecutable(fullPath): |
| 72 | return fullPath |
| 73 | |
| 74 | return None |
| 75 | |
| 76 | def isBinaryInPath (binName): |
| 77 | return which(binName) != None |
| 78 | |
Pyry Haulos | 89e0405 | 2014-10-20 11:09:56 -0700 | [diff] [blame] | 79 | def selectFirstExistingBinary (filenames): |
| 80 | for filename in filenames: |
| 81 | if filename != None and isExecutable(filename): |
| 82 | return filename |
| 83 | |
| 84 | return None |
| 85 | |
| 86 | def selectFirstExistingDir (paths): |
| 87 | for path in paths: |
| 88 | if path != None and os.path.isdir(path): |
| 89 | return path |
| 90 | |
| 91 | return None |
Jarkko Poyry | 3c82736 | 2014-09-02 11:48:52 +0300 | [diff] [blame] | 92 | |
| 93 | def die (msg): |
| 94 | print msg |
| 95 | exit(-1) |
| 96 | |
| 97 | def shellquote(s): |
| 98 | return '"%s"' % s.replace('\\', '\\\\').replace('"', '\"').replace('$', '\$').replace('`', '\`') |
| 99 | |
| 100 | def execute (commandLine): |
| 101 | args = shlex.split(commandLine) |
| 102 | retcode = subprocess.call(args) |
| 103 | if retcode != 0: |
| 104 | raise Exception("Failed to execute '%s', got %d" % (commandLine, retcode)) |
| 105 | |
| 106 | def execArgs (args): |
Kalle Raita | c9f7674 | 2014-11-13 13:00:08 -0800 | [diff] [blame] | 107 | # Make sure previous stdout prints have been written out. |
| 108 | sys.stdout.flush() |
Jarkko Poyry | 3c82736 | 2014-09-02 11:48:52 +0300 | [diff] [blame] | 109 | retcode = subprocess.call(args) |
| 110 | if retcode != 0: |
Jarkko Pöyry | 842a87c | 2014-12-11 18:22:05 -0800 | [diff] [blame] | 111 | raise Exception("Failed to execute '%s', got %d" % (str(args), retcode)) |
| 112 | |
Jarkko Pöyry | d1ae94f | 2015-03-12 15:20:47 -0700 | [diff] [blame] | 113 | def execArgsInDirectory (args, cwd, linePrefix=""): |
| 114 | |
| 115 | def readApplyPrefixAndPrint (source, prefix, sink): |
| 116 | while True: |
| 117 | line = source.readline() |
| 118 | if len(line) == 0: # EOF |
| 119 | break; |
| 120 | sink.write(prefix + line) |
| 121 | |
| 122 | process = subprocess.Popen(args, cwd=cwd, stdout=subprocess.PIPE, stderr=subprocess.PIPE) |
| 123 | stdoutJob = threading.Thread(target=readApplyPrefixAndPrint, args=(process.stdout, linePrefix, sys.stdout)) |
Jarkko Pöyry | a31fb7a | 2015-05-19 11:12:01 -0700 | [diff] [blame] | 124 | stderrJob = threading.Thread(target=readApplyPrefixAndPrint, args=(process.stderr, linePrefix, sys.stderr)) |
Jarkko Pöyry | d1ae94f | 2015-03-12 15:20:47 -0700 | [diff] [blame] | 125 | stdoutJob.start() |
| 126 | stderrJob.start() |
Jarkko Pöyry | 842a87c | 2014-12-11 18:22:05 -0800 | [diff] [blame] | 127 | retcode = process.wait() |
| 128 | if retcode != 0: |
| 129 | raise Exception("Failed to execute '%s', got %d" % (str(args), retcode)) |
| 130 | |
| 131 | def serialApply(f, argsList): |
| 132 | for args in argsList: |
| 133 | f(*args) |
| 134 | |
| 135 | def parallelApply(f, argsList): |
| 136 | class ErrorCode: |
| 137 | def __init__ (self): |
| 138 | self.error = None; |
| 139 | |
| 140 | def applyAndCaptureError (func, args, errorCode): |
| 141 | try: |
| 142 | func(*args) |
| 143 | except: |
| 144 | errorCode.error = sys.exc_info() |
| 145 | |
| 146 | errorCode = ErrorCode() |
| 147 | jobs = [] |
| 148 | for args in argsList: |
| 149 | job = threading.Thread(target=applyAndCaptureError, args=(f, args, errorCode)) |
| 150 | job.start() |
| 151 | jobs.append(job) |
| 152 | |
| 153 | for job in jobs: |
| 154 | job.join() |
| 155 | |
| 156 | if errorCode.error: |
| 157 | raise errorCode.error[0], errorCode.error[1], errorCode.error[2] |
Jarkko Poyry | 3c82736 | 2014-09-02 11:48:52 +0300 | [diff] [blame] | 158 | |
Pyry Haulos | 89e0405 | 2014-10-20 11:09:56 -0700 | [diff] [blame] | 159 | class Device: |
| 160 | def __init__(self, serial, product, model, device): |
| 161 | self.serial = serial |
| 162 | self.product = product |
| 163 | self.model = model |
| 164 | self.device = device |
Jarkko Poyry | 3c82736 | 2014-09-02 11:48:52 +0300 | [diff] [blame] | 165 | |
Pyry Haulos | 89e0405 | 2014-10-20 11:09:56 -0700 | [diff] [blame] | 166 | def __str__ (self): |
| 167 | return "%s: {product: %s, model: %s, device: %s}" % (self.serial, self.product, self.model, self.device) |
Jarkko Poyry | 3c82736 | 2014-09-02 11:48:52 +0300 | [diff] [blame] | 168 | |
Pyry Haulos | 89e0405 | 2014-10-20 11:09:56 -0700 | [diff] [blame] | 169 | def getDevices (adb): |
| 170 | proc = subprocess.Popen([adb, 'devices', '-l'], stdout=subprocess.PIPE) |
| 171 | (stdout, stderr) = proc.communicate() |
| 172 | |
| 173 | if proc.returncode != 0: |
Jarkko Pöyry | 842a87c | 2014-12-11 18:22:05 -0800 | [diff] [blame] | 174 | raise Exception("adb devices -l failed, got %d" % proc.returncode) |
Pyry Haulos | 89e0405 | 2014-10-20 11:09:56 -0700 | [diff] [blame] | 175 | |
Nicolas Boichat | dbf9715 | 2016-11-30 12:14:52 +0800 | [diff] [blame] | 176 | ptrn = re.compile(r'^([a-zA-Z0-9\.:]+)\s+.*product:([^\s]+)\s+model:([^\s]+)\s+device:([^\s]+)') |
Pyry Haulos | 89e0405 | 2014-10-20 11:09:56 -0700 | [diff] [blame] | 177 | devices = [] |
| 178 | for line in stdout.splitlines()[1:]: |
| 179 | if len(line.strip()) == 0: |
| 180 | continue |
| 181 | |
| 182 | m = ptrn.match(line) |
| 183 | if m == None: |
Pyry Haulos | a78b661 | 2014-11-10 10:17:16 -0800 | [diff] [blame] | 184 | print "WARNING: Failed to parse device info '%s'" % line |
| 185 | continue |
Pyry Haulos | 89e0405 | 2014-10-20 11:09:56 -0700 | [diff] [blame] | 186 | |
| 187 | devices.append(Device(m.group(1), m.group(2), m.group(3), m.group(4))) |
| 188 | |
| 189 | return devices |
Jarkko Poyry | 3c82736 | 2014-09-02 11:48:52 +0300 | [diff] [blame] | 190 | |
| 191 | def getWin32Generator (): |
| 192 | if which("jom.exe") != None: |
| 193 | return "NMake Makefiles JOM" |
| 194 | else: |
| 195 | return "NMake Makefiles" |
| 196 | |
Pyry Haulos | 89e0405 | 2014-10-20 11:09:56 -0700 | [diff] [blame] | 197 | def isNinjaSupported (): |
| 198 | return which("ninja") != None |
| 199 | |
| 200 | def getUnixGenerator (): |
| 201 | if isNinjaSupported(): |
| 202 | return "Ninja" |
| 203 | else: |
| 204 | return "Unix Makefiles" |
| 205 | |
| 206 | def getExtraBuildArgs (generator): |
| 207 | if generator == "Unix Makefiles": |
| 208 | return ["--", "-j%d" % multiprocessing.cpu_count()] |
| 209 | else: |
| 210 | return [] |
| 211 | |
| 212 | NDK_HOST_OS_NAMES = [ |
| 213 | "windows", |
Maciej Jesionowski | 993a280 | 2016-01-04 10:45:10 +0100 | [diff] [blame] | 214 | "windows-x86_64", |
Pyry Haulos | 89e0405 | 2014-10-20 11:09:56 -0700 | [diff] [blame] | 215 | "darwin-x86", |
Jesse Hall | c198d02 | 2015-10-15 19:44:21 -0700 | [diff] [blame] | 216 | "darwin-x86_64", |
Pyry Haulos | 89e0405 | 2014-10-20 11:09:56 -0700 | [diff] [blame] | 217 | "linux-x86", |
| 218 | "linux-x86_64" |
| 219 | ] |
| 220 | |
| 221 | def getNDKHostOsName (ndkPath): |
| 222 | for name in NDK_HOST_OS_NAMES: |
| 223 | if os.path.exists(os.path.join(ndkPath, "prebuilt", name)): |
| 224 | return name |
| 225 | |
| 226 | raise Exception("Couldn't determine NDK host OS") |
| 227 | |
| 228 | # deqp/android path |
| 229 | ANDROID_DIR = os.path.realpath(os.path.join(os.path.dirname(os.path.abspath(__file__)), "..")) |
| 230 | |
| 231 | # Build configuration |
| 232 | NATIVE_LIBS = [ |
Jarkko Pöyry | b6d3233 | 2015-03-09 16:38:57 -0700 | [diff] [blame] | 233 | # API ABI prebuiltsDir |
| 234 | NativeLib(13, "armeabi-v7a", 'android-arm'), # ARM v7a ABI |
| 235 | NativeLib(13, "x86", 'android-x86'), # x86 |
| 236 | NativeLib(21, "arm64-v8a", 'android-arm64'), # ARM64 v8a ABI |
Pyry Haulos | 89e0405 | 2014-10-20 11:09:56 -0700 | [diff] [blame] | 237 | ] |
Jarkko Pöyry | b6d3233 | 2015-03-09 16:38:57 -0700 | [diff] [blame] | 238 | |
Daniel Koch | d290dcd | 2015-09-24 23:20:40 -0400 | [diff] [blame] | 239 | ANDROID_JAVA_API = "android-22" |
Pyry Haulos | 03700a8 | 2014-10-20 13:01:20 -0700 | [diff] [blame] | 240 | NATIVE_LIB_NAME = "libdeqp.so" |
Pyry Haulos | 89e0405 | 2014-10-20 11:09:56 -0700 | [diff] [blame] | 241 | |
Kalle Raita | c9f7674 | 2014-11-13 13:00:08 -0800 | [diff] [blame] | 242 | def selectNDKPath (): |
| 243 | candidates = [ |
Pyry Haulos | de7fb14 | 2016-03-15 13:47:53 -0700 | [diff] [blame] | 244 | os.path.expanduser("~/android-ndk-r11"), |
| 245 | "C:/android/android-ndk-r11", |
Kalle Raita | fee3a5f | 2014-11-17 10:40:26 -0800 | [diff] [blame] | 246 | os.environ.get("ANDROID_NDK_PATH", None), # If not defined, return None |
Kalle Raita | c9f7674 | 2014-11-13 13:00:08 -0800 | [diff] [blame] | 247 | ] |
| 248 | |
| 249 | ndkPath = selectFirstExistingDir(candidates) |
| 250 | |
| 251 | if ndkPath == None: |
| 252 | raise Exception("None of NDK directory candidates exist: %s. Check ANDROID_NDK_PATH in common.py" % candidates) |
| 253 | |
| 254 | return ndkPath |
| 255 | |
Kalle Raita | fee3a5f | 2014-11-17 10:40:26 -0800 | [diff] [blame] | 256 | def noneSafePathJoin (*components): |
| 257 | if None in components: |
| 258 | return None |
| 259 | return os.path.join(*components) |
| 260 | |
| 261 | |
Kalle Raita | c9f7674 | 2014-11-13 13:00:08 -0800 | [diff] [blame] | 262 | # NDK paths |
| 263 | ANDROID_NDK_PATH = selectNDKPath() |
Pyry Haulos | 89e0405 | 2014-10-20 11:09:56 -0700 | [diff] [blame] | 264 | ANDROID_NDK_HOST_OS = getNDKHostOsName(ANDROID_NDK_PATH) |
Pyry Haulos | de7fb14 | 2016-03-15 13:47:53 -0700 | [diff] [blame] | 265 | ANDROID_NDK_TOOLCHAIN_VERSION = "r11" # Toolchain file is selected based on this |
Pyry Haulos | 89e0405 | 2014-10-20 11:09:56 -0700 | [diff] [blame] | 266 | |
Jarkko Poyry | 3c82736 | 2014-09-02 11:48:52 +0300 | [diff] [blame] | 267 | # Native code build settings |
Pyry Haulos | 89e0405 | 2014-10-20 11:09:56 -0700 | [diff] [blame] | 268 | CMAKE_GENERATOR = selectByOS({ |
Jarkko Poyry | 3c82736 | 2014-09-02 11:48:52 +0300 | [diff] [blame] | 269 | 'win32': getWin32Generator(), |
Pyry Haulos | 89e0405 | 2014-10-20 11:09:56 -0700 | [diff] [blame] | 270 | 'other': getUnixGenerator() |
Jarkko Poyry | 3c82736 | 2014-09-02 11:48:52 +0300 | [diff] [blame] | 271 | }) |
Pyry Haulos | 89e0405 | 2014-10-20 11:09:56 -0700 | [diff] [blame] | 272 | EXTRA_BUILD_ARGS = getExtraBuildArgs(CMAKE_GENERATOR) |
Jarkko Poyry | 3c82736 | 2014-09-02 11:48:52 +0300 | [diff] [blame] | 273 | |
| 274 | # SDK paths |
Pyry Haulos | 89e0405 | 2014-10-20 11:09:56 -0700 | [diff] [blame] | 275 | ANDROID_SDK_PATH = selectFirstExistingDir([ |
Jesse Hall | c198d02 | 2015-10-15 19:44:21 -0700 | [diff] [blame] | 276 | os.environ.get("ANDROID_SDK_PATH", None), |
Pyry Haulos | 89e0405 | 2014-10-20 11:09:56 -0700 | [diff] [blame] | 277 | os.path.expanduser("~/android-sdk-linux"), |
| 278 | os.path.expanduser("~/android-sdk-mac_x86"), |
| 279 | "C:/android/android-sdk-windows", |
| 280 | ]) |
| 281 | ANDROID_BIN = selectFirstExistingBinary([ |
Kalle Raita | fee3a5f | 2014-11-17 10:40:26 -0800 | [diff] [blame] | 282 | noneSafePathJoin(ANDROID_SDK_PATH, "tools", "android"), |
| 283 | noneSafePathJoin(ANDROID_SDK_PATH, "tools", "android.bat"), |
Pyry Haulos | 89e0405 | 2014-10-20 11:09:56 -0700 | [diff] [blame] | 284 | which('android'), |
| 285 | ]) |
| 286 | ADB_BIN = selectFirstExistingBinary([ |
| 287 | which('adb'), # \note Prefer adb in path to avoid version issues on dev machines |
Kalle Raita | fee3a5f | 2014-11-17 10:40:26 -0800 | [diff] [blame] | 288 | noneSafePathJoin(ANDROID_SDK_PATH, "platform-tools", "adb"), |
| 289 | noneSafePathJoin(ANDROID_SDK_PATH, "platform-tools", "adb.exe"), |
Pyry Haulos | 89e0405 | 2014-10-20 11:09:56 -0700 | [diff] [blame] | 290 | ]) |
| 291 | ZIPALIGN_BIN = selectFirstExistingBinary([ |
Kalle Raita | fee3a5f | 2014-11-17 10:40:26 -0800 | [diff] [blame] | 292 | noneSafePathJoin(ANDROID_SDK_PATH, "tools", "zipalign"), |
| 293 | noneSafePathJoin(ANDROID_SDK_PATH, "tools", "zipalign.exe"), |
Pyry Haulos | 89e0405 | 2014-10-20 11:09:56 -0700 | [diff] [blame] | 294 | which('zipalign'), |
| 295 | ]) |
| 296 | JARSIGNER_BIN = which('jarsigner') |
Jarkko Poyry | 3c82736 | 2014-09-02 11:48:52 +0300 | [diff] [blame] | 297 | |
| 298 | # Apache ant |
Pyry Haulos | 89e0405 | 2014-10-20 11:09:56 -0700 | [diff] [blame] | 299 | ANT_BIN = selectFirstExistingBinary([ |
| 300 | which('ant'), |
| 301 | "C:/android/apache-ant-1.8.4/bin/ant.bat", |
| 302 | "C:/android/apache-ant-1.9.2/bin/ant.bat", |
| 303 | "C:/android/apache-ant-1.9.3/bin/ant.bat", |
| 304 | "C:/android/apache-ant-1.9.4/bin/ant.bat", |
| 305 | ]) |
Kalle Raita | c9f7674 | 2014-11-13 13:00:08 -0800 | [diff] [blame] | 306 | |
| 307 | def makeNameValueTuple (name): |
| 308 | return (name, str(eval(name))) |
| 309 | |
Pyry Haulos | 6b1f7dc | 2014-11-17 09:37:44 -0800 | [diff] [blame] | 310 | CONFIG_VAR_NAMES = [ |
| 311 | "ANDROID_DIR", |
| 312 | "NATIVE_LIBS", |
| 313 | "ANDROID_JAVA_API", |
| 314 | "NATIVE_LIB_NAME", |
| 315 | "ANDROID_NDK_PATH", |
| 316 | "ANDROID_NDK_HOST_OS", |
| 317 | "ANDROID_NDK_TOOLCHAIN_VERSION", |
| 318 | "CMAKE_GENERATOR", |
| 319 | "EXTRA_BUILD_ARGS", |
| 320 | "ANDROID_SDK_PATH", |
| 321 | "ANDROID_BIN", |
| 322 | "ADB_BIN", |
| 323 | "ZIPALIGN_BIN", |
| 324 | "JARSIGNER_BIN", |
| 325 | "ANT_BIN", |
Kalle Raita | c9f7674 | 2014-11-13 13:00:08 -0800 | [diff] [blame] | 326 | ] |
Pyry Haulos | 6b1f7dc | 2014-11-17 09:37:44 -0800 | [diff] [blame] | 327 | CONFIG_STRINGS = [makeNameValueTuple(x) for x in CONFIG_VAR_NAMES] |