From: Jarkko Pöyry Date: Fri, 12 Dec 2014 02:22:05 +0000 (-0800) Subject: Support parallel build and install in on-device apk scripts. X-Git-Tag: upstream/0.1.0~2026 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=842a87c8cfd9eb5321eccd22c0f2def118d79b88;p=platform%2Fupstream%2FVK-GL-CTS.git Support parallel build and install in on-device apk scripts. Add -p flag to build.py to build native libs in parallel. Add -p flag to install.py to install to multiple devices in parallel. Change-Id: I042de5eae321e61455d330949c7f07577725ba15 --- diff --git a/android/scripts/build.py b/android/scripts/build.py index 3e42371..1fb54e8 100644 --- a/android/scripts/build.py +++ b/android/scripts/build.py @@ -53,9 +53,8 @@ def buildNative (buildRoot, libTargetDir, nativeLib, buildType): # Make build directory if necessary if not os.path.exists(buildDir): os.makedirs(buildDir) - os.chdir(buildDir) toolchainFile = '%s/framework/delibs/cmake/toolchain-android-%s.cmake' % (deqpDir, common.ANDROID_NDK_TOOLCHAIN_VERSION) - common.execArgs([ + common.execArgsInDirectory([ 'cmake', '-G%s' % common.CMAKE_GENERATOR, '-DCMAKE_TOOLCHAIN_FILE=%s' % toolchainFile, @@ -66,10 +65,9 @@ def buildNative (buildRoot, libTargetDir, nativeLib, buildType): '-DCMAKE_BUILD_TYPE=%s' % buildType, '-DDEQP_TARGET=android', deqpDir - ]) + ], buildDir) - os.chdir(buildDir) - common.execArgs(['cmake', '--build', '.'] + common.EXTRA_BUILD_ARGS) + common.execArgsInDirectory(['cmake', '--build', '.'] + common.EXTRA_BUILD_ARGS, buildDir) if not os.path.exists(libsDir): os.makedirs(libsDir) @@ -138,7 +136,7 @@ def signApp (keystore, keyname, storepass, keypass): 'bin/dEQP-release.apk' ]) -def build (buildRoot=common.ANDROID_DIR, isRelease=False, nativeBuildType="Release", javaApi=common.ANDROID_JAVA_API): +def build (buildRoot=common.ANDROID_DIR, isRelease=False, nativeBuildType="Release", javaApi=common.ANDROID_JAVA_API, doParallelBuild=False): curDir = os.getcwd() try: @@ -159,8 +157,11 @@ def build (buildRoot=common.ANDROID_DIR, isRelease=False, nativeBuildType="Relea shutil.rmtree(libTargetDir) # Build native code - for lib in common.NATIVE_LIBS: - buildNative(buildRoot, libTargetDir, lib, nativeBuildType) + nativeBuildArgs = [(buildRoot, libTargetDir, nativeLib, nativeBuildType) for nativeLib in common.NATIVE_LIBS] + if doParallelBuild: + common.parallelApply(buildNative, nativeBuildArgs) + else: + common.serialApply(buildNative, nativeBuildArgs) # Copy assets if os.path.exists(assetsSrcDir): @@ -186,10 +187,11 @@ if __name__ == "__main__": parser.add_argument('--build-root', dest='buildRoot', default=common.ANDROID_DIR, help="Root directory for storing build results.") parser.add_argument('--dump-config', dest='dumpConfig', action='store_true', help="Print out all configurations variables") parser.add_argument('--java-api', dest='javaApi', default=common.ANDROID_JAVA_API, help="Set the API signature for the java build.") + parser.add_argument('-p', '--parallel-build', dest='parallelBuild', action="store_true", help="Build native libraries in parallel.") args = parser.parse_args() if args.dumpConfig: dumpConfig() - build(buildRoot=os.path.abspath(args.buildRoot), isRelease=args.isRelease, nativeBuildType=args.nativeBuildType, javaApi=args.javaApi) + build(buildRoot=os.path.abspath(args.buildRoot), isRelease=args.isRelease, nativeBuildType=args.nativeBuildType, javaApi=args.javaApi, doParallelBuild=args.parallelBuild) diff --git a/android/scripts/common.py b/android/scripts/common.py index 674d818..d8e5b1b 100644 --- a/android/scripts/common.py +++ b/android/scripts/common.py @@ -8,6 +8,11 @@ import subprocess import multiprocessing import string +try: + import threading +except ImportError: + import dummy_threading as threading + class NativeLib: def __init__ (self, apiVersion, abiVersion): self.apiVersion = apiVersion @@ -82,7 +87,43 @@ def execArgs (args): sys.stdout.flush() retcode = subprocess.call(args) if retcode != 0: - raise Exception("Failed to execute '%s', got %d" % (str(args), retcode)) + raise Exception("Failed to execute '%s', got %d" % (str(args), retcode)) + +def execArgsInDirectory (args, cwd): + # Make sure previous stdout prints have been written out. + sys.stdout.flush() + process = subprocess.Popen(args, cwd=cwd) + retcode = process.wait() + if retcode != 0: + raise Exception("Failed to execute '%s', got %d" % (str(args), retcode)) + +def serialApply(f, argsList): + for args in argsList: + f(*args) + +def parallelApply(f, argsList): + class ErrorCode: + def __init__ (self): + self.error = None; + + def applyAndCaptureError (func, args, errorCode): + try: + func(*args) + except: + errorCode.error = sys.exc_info() + + errorCode = ErrorCode() + jobs = [] + for args in argsList: + job = threading.Thread(target=applyAndCaptureError, args=(f, args, errorCode)) + job.start() + jobs.append(job) + + for job in jobs: + job.join() + + if errorCode.error: + raise errorCode.error[0], errorCode.error[1], errorCode.error[2] class Device: def __init__(self, serial, product, model, device): @@ -99,7 +140,7 @@ def getDevices (adb): (stdout, stderr) = proc.communicate() if proc.returncode != 0: - raise Exception("adb devices -l failed, got %d" % retcode) + raise Exception("adb devices -l failed, got %d" % proc.returncode) ptrn = re.compile(r'^([a-zA-Z0-9]+)\s+.*product:([^\s]+)\s+model:([^\s]+)\s+device:([^\s]+)') devices = [] diff --git a/android/scripts/install.py b/android/scripts/install.py index 2ef02cd..317dd84 100644 --- a/android/scripts/install.py +++ b/android/scripts/install.py @@ -7,43 +7,39 @@ import string import common -def install (extraArgs = []): - curDir = os.getcwd() - try: - os.chdir(common.ANDROID_DIR) - - print "Removing old dEQP Package..." - common.execArgs([common.ADB_BIN] + extraArgs + [ - 'uninstall', - 'com.drawelements.deqp' - ]) - print "" - - print "Installing dEQP Package..." - common.execArgs([common.ADB_BIN] + extraArgs + [ - 'install', - '-r', - 'package/bin/dEQP-debug.apk' - ]) - print "" - - finally: - # Restore working dir - os.chdir(curDir) - -def installToDevice (device): - print "Installing to %s (%s)..." % (device.serial, device.model) - install(['-s', device.serial]) - -def installToAllDevices (): +def install (extraArgs = [], printPrefix=""): + print printPrefix + "Removing old dEQP Package...\n", + common.execArgsInDirectory([common.ADB_BIN] + extraArgs + [ + 'uninstall', + 'com.drawelements.deqp' + ], common.ANDROID_DIR) + print printPrefix + "Remove complete\n", + + print printPrefix + "Installing dEQP Package...\n", + common.execArgsInDirectory([common.ADB_BIN] + extraArgs + [ + 'install', + '-r', + 'package/bin/dEQP-debug.apk' + ], common.ANDROID_DIR) + print printPrefix + "Install complete\n", + +def installToDevice (device, printPrefix=""): + print printPrefix + "Installing to %s (%s)...\n" % (device.serial, device.model), + install(['-s', device.serial], printPrefix) + +def installToAllDevices (doParallel): devices = common.getDevices(common.ADB_BIN) - for device in devices: - installToDevice(device) + padLen = max([len(device.model) for device in devices])+1 + if doParallel: + common.parallelApply(installToDevice, [(device, ("(%s):%s" % (device.model, ' ' * (padLen - len(device.model))))) for device in devices]); + else: + common.serialApply(installToDevice, [(device, ) for device in devices]); if __name__ == "__main__": if len(sys.argv) > 1: if sys.argv[1] == '-a': - installToAllDevices() + doParallel = '-p' in sys.argv[1:] + installToAllDevices(doParallel) else: install(sys.argv[1:]) else: