1# -*- coding: utf-8 -*- 2 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 23import os 24import re 25import sys 26import shutil 27import argparse 28 29import common 30 31def getStoreKeyPasswords (filename): 32 f = open(filename) 33 storepass = None 34 keypass = None 35 for line in f: 36 m = re.search('([a-z]+)\s*\=\s*"([^"]+)"', line) 37 if m != None: 38 if m.group(1) == "storepass": 39 storepass = m.group(2) 40 elif m.group(1) == "keypass": 41 keypass = m.group(2) 42 f.close() 43 if storepass == None or keypass == None: 44 common.die("Could not read signing key passwords") 45 return (storepass, keypass) 46 47def getNativeBuildDir (buildRoot, nativeLib, buildType): 48 buildName = "%s-%d-%s" % (buildType.lower(), nativeLib.apiVersion, nativeLib.abiVersion) 49 return os.path.normpath(os.path.join(buildRoot, "native", buildName)) 50 51def getAssetsDir (buildRoot, nativeLib, buildType): 52 return os.path.join(getNativeBuildDir(buildRoot, nativeLib, buildType), "assets") 53 54def buildNative (buildRoot, libTargetDir, nativeLib, buildType): 55 deqpDir = os.path.normpath(os.path.join(common.ANDROID_DIR, "..")) 56 buildDir = getNativeBuildDir(buildRoot, nativeLib, buildType) 57 libsDir = os.path.join(libTargetDir, nativeLib.abiVersion) 58 srcLibFile = os.path.join(buildDir, common.NATIVE_LIB_NAME) 59 dstLibFile = os.path.join(libsDir, common.NATIVE_LIB_NAME) 60 61 # Make build directory if necessary 62 if not os.path.exists(buildDir): 63 os.makedirs(buildDir) 64 toolchainFile = '%s/framework/delibs/cmake/toolchain-android-%s.cmake' % (deqpDir, common.ANDROID_NDK_TOOLCHAIN_VERSION) 65 common.execArgsInDirectory([ 66 'cmake', 67 '-G%s' % common.CMAKE_GENERATOR, 68 '-DCMAKE_TOOLCHAIN_FILE=%s' % toolchainFile, 69 '-DANDROID_NDK_HOST_OS=%s' % common.ANDROID_NDK_HOST_OS, 70 '-DANDROID_NDK_PATH=%s' % common.ANDROID_NDK_PATH, 71 '-DANDROID_ABI=%s' % nativeLib.abiVersion, 72 '-DDE_ANDROID_API=%s' % nativeLib.apiVersion, 73 '-DCMAKE_BUILD_TYPE=%s' % buildType, 74 '-DDEQP_TARGET=android', 75 deqpDir 76 ], buildDir) 77 78 common.execArgsInDirectory(['cmake', '--build', '.'] + common.EXTRA_BUILD_ARGS, buildDir) 79 80 if not os.path.exists(libsDir): 81 os.makedirs(libsDir) 82 83 shutil.copyfile(srcLibFile, dstLibFile) 84 85 # Copy gdbserver for debugging 86 if buildType.lower() == "debug": 87 srcGdbserverPath = os.path.join(common.ANDROID_NDK_PATH, 88 'prebuilt', 89 nativeLib.prebuiltDir, 90 'gdbserver', 91 'gdbserver') 92 dstGdbserverPath = os.path.join(libsDir, 'gdbserver') 93 shutil.copyfile(srcGdbserverPath, dstGdbserverPath) 94 else: 95 assert not os.path.exists(os.path.join(libsDir, "gdbserver")) 96 97def buildApp (buildRoot, androidBuildType, javaApi): 98 appDir = os.path.join(buildRoot, "package") 99 100 # Set up app 101 os.chdir(appDir) 102 103 manifestSrcPath = os.path.normpath(os.path.join(common.ANDROID_DIR, "package", "AndroidManifest.xml")) 104 manifestDstPath = os.path.normpath(os.path.join(appDir, "AndroidManifest.xml")) 105 106 # Build dir can be the Android dir, in which case the copy is not needed. 107 if manifestSrcPath != manifestDstPath: 108 shutil.copy(manifestSrcPath, manifestDstPath) 109 110 common.execArgs([ 111 common.ANDROID_BIN, 112 'update', 'project', 113 '--name', 'dEQP', 114 '--path', '.', 115 '--target', javaApi, 116 ]) 117 118 # Build 119 common.execArgs([ 120 common.ANT_BIN, 121 androidBuildType, 122 "-Dsource.dir=" + os.path.join(common.ANDROID_DIR, "package", "src"), 123 "-Dresource.absolute.dir=" + os.path.join(common.ANDROID_DIR, "package", "res") 124 ]) 125 126def signApp (keystore, keyname, storepass, keypass): 127 os.chdir(os.path.join(common.ANDROID_DIR, "package")) 128 common.execArgs([ 129 common.JARSIGNER_BIN, 130 '-keystore', keystore, 131 '-storepass', storepass, 132 '-keypass', keypass, 133 '-sigfile', 'CERT', 134 '-digestalg', 'SHA1', 135 '-sigalg', 'MD5withRSA', 136 '-signedjar', 'bin/dEQP-unaligned.apk', 137 'bin/dEQP-release-unsigned.apk', 138 keyname 139 ]) 140 common.execArgs([ 141 common.ZIPALIGN_BIN, 142 '-f', '4', 143 'bin/dEQP-unaligned.apk', 144 'bin/dEQP-release.apk' 145 ]) 146 147def build (buildRoot=common.ANDROID_DIR, androidBuildType='debug', nativeBuildType="Release", javaApi=common.ANDROID_JAVA_API, doParallelBuild=False): 148 curDir = os.getcwd() 149 150 try: 151 assetsSrcDir = getAssetsDir(buildRoot, common.NATIVE_LIBS[0], nativeBuildType) 152 assetsDstDir = os.path.join(buildRoot, "package", "assets") 153 154 # Remove assets from the first build dir where we copy assets from 155 # to avoid collecting cruft there. 156 if os.path.exists(assetsSrcDir): 157 shutil.rmtree(assetsSrcDir) 158 if os.path.exists(assetsDstDir): 159 shutil.rmtree(assetsDstDir) 160 161 # Remove old libs dir to avoid collecting out-of-date versions 162 # of libs for ABIs not built this time. 163 libTargetDir = os.path.join(buildRoot, "package", "libs") 164 if os.path.exists(libTargetDir): 165 shutil.rmtree(libTargetDir) 166 167 # Build native code 168 nativeBuildArgs = [(buildRoot, libTargetDir, nativeLib, nativeBuildType) for nativeLib in common.NATIVE_LIBS] 169 if doParallelBuild: 170 common.parallelApply(buildNative, nativeBuildArgs) 171 else: 172 common.serialApply(buildNative, nativeBuildArgs) 173 174 # Copy assets 175 if os.path.exists(assetsSrcDir): 176 shutil.copytree(assetsSrcDir, assetsDstDir) 177 178 # Build java code and .apk 179 buildApp(buildRoot, androidBuildType, javaApi) 180 181 finally: 182 # Restore working dir 183 os.chdir(curDir) 184 185def dumpConfig (): 186 print " " 187 for entry in common.CONFIG_STRINGS: 188 print "%-30s : %s" % (entry[0], entry[1]) 189 print " " 190 191if __name__ == "__main__": 192 nativeBuildTypes = ['Release', 'Debug', 'MinSizeRel', 'RelWithAsserts', 'RelWithDebInfo'] 193 androidBuildTypes = ['debug', 'release'] 194 195 parser = argparse.ArgumentParser() 196 parser.add_argument('--android-build-type', dest='androidBuildType', choices=androidBuildTypes, default='debug', help="Build type for android project..") 197 parser.add_argument('--native-build-type', dest='nativeBuildType', default="RelWithAsserts", choices=nativeBuildTypes, help="Build type passed to cmake when building native code.") 198 parser.add_argument('--build-root', dest='buildRoot', default=common.ANDROID_DIR, help="Root directory for storing build results.") 199 parser.add_argument('--dump-config', dest='dumpConfig', action='store_true', help="Print out all configurations variables") 200 parser.add_argument('--java-api', dest='javaApi', default=common.ANDROID_JAVA_API, help="Set the API signature for the java build.") 201 parser.add_argument('-p', '--parallel-build', dest='parallelBuild', action="store_true", help="Build native libraries in parallel.") 202 203 args = parser.parse_args() 204 205 if args.dumpConfig: 206 dumpConfig() 207 208 build(buildRoot=os.path.abspath(args.buildRoot), androidBuildType=args.androidBuildType, nativeBuildType=args.nativeBuildType, javaApi=args.javaApi, doParallelBuild=args.parallelBuild) 209