Home | History | Annotate | Download | only in scripts
      1 # -*- coding: utf-8 -*-
      2 
      3 import os
      4 import re
      5 import sys
      6 import shutil
      7 import argparse
      8 
      9 import common
     10 
     11 def getStoreKeyPasswords (filename):
     12 	f			= open(filename)
     13 	storepass	= None
     14 	keypass		= None
     15 	for line in f:
     16 		m = re.search('([a-z]+)\s*\=\s*"([^"]+)"', line)
     17 		if m != None:
     18 			if m.group(1) == "storepass":
     19 				storepass = m.group(2)
     20 			elif m.group(1) == "keypass":
     21 				keypass = m.group(2)
     22 	f.close()
     23 	if storepass == None or keypass == None:
     24 		common.die("Could not read signing key passwords")
     25 	return (storepass, keypass)
     26 
     27 def getNativeBuildDir (buildRoot, nativeLib, buildType):
     28 	buildName = "%s-%d-%s" % (buildType.lower(), nativeLib.apiVersion, nativeLib.abiVersion)
     29 	return os.path.normpath(os.path.join(buildRoot, "native", buildName))
     30 
     31 def getAssetsDir (buildRoot, nativeLib, buildType):
     32 	return os.path.join(getNativeBuildDir(buildRoot, nativeLib, buildType), "assets")
     33 
     34 def getPrebuiltsDirName (abiName):
     35 	PREBUILT_DIRS = {
     36 			'x86':			'android-x86',
     37 			'armeabi-v7a':	'android-arm',
     38 			'arm64-v8a':	'android-arm64'
     39 		}
     40 
     41 	if not abiName in PREBUILT_DIRS:
     42 		raise Exception("Unknown ABI %s, don't know where prebuilts are" % abiName)
     43 
     44 	return PREBUILT_DIRS[abiName]
     45 
     46 def buildNative (buildRoot, libTargetDir, nativeLib, buildType):
     47 	deqpDir		= os.path.normpath(os.path.join(common.ANDROID_DIR, ".."))
     48 	buildDir	= getNativeBuildDir(buildRoot, nativeLib, buildType)
     49 	libsDir		= os.path.join(libTargetDir, nativeLib.abiVersion)
     50 	srcLibFile	= os.path.join(buildDir, common.NATIVE_LIB_NAME)
     51 	dstLibFile	= os.path.join(libsDir, common.NATIVE_LIB_NAME)
     52 
     53 	# Make build directory if necessary
     54 	if not os.path.exists(buildDir):
     55 		os.makedirs(buildDir)
     56 		os.chdir(buildDir)
     57 		toolchainFile = '%s/framework/delibs/cmake/toolchain-android-%s.cmake' % (deqpDir, common.ANDROID_NDK_TOOLCHAIN_VERSION)
     58 		common.execArgs([
     59 				'cmake',
     60 				'-G%s' % common.CMAKE_GENERATOR,
     61 				'-DCMAKE_TOOLCHAIN_FILE=%s' % toolchainFile,
     62 				'-DANDROID_NDK_HOST_OS=%s' % common.ANDROID_NDK_HOST_OS,
     63 				'-DANDROID_NDK_PATH=%s' % common.ANDROID_NDK_PATH,
     64 				'-DANDROID_ABI=%s' % nativeLib.abiVersion,
     65 				'-DDE_ANDROID_API=%s' % nativeLib.apiVersion,
     66 				'-DCMAKE_BUILD_TYPE=%s' % buildType,
     67 				'-DDEQP_TARGET=android',
     68 				deqpDir
     69 			])
     70 
     71 	os.chdir(buildDir)
     72 	common.execArgs(['cmake', '--build', '.'] + common.EXTRA_BUILD_ARGS)
     73 
     74 	if not os.path.exists(libsDir):
     75 		os.makedirs(libsDir)
     76 
     77 	shutil.copyfile(srcLibFile, dstLibFile)
     78 
     79 	# Copy gdbserver for debugging
     80 	if buildType.lower() == "debug":
     81 		srcGdbserverPath = os.path.join(common.ANDROID_NDK_PATH,
     82 										'prebuilt',
     83 										getPrebuiltsDirName(nativeLib.abiVersion),
     84 										'gdbserver',
     85 										'gdbserver')
     86 		dstGdbserverPath = os.path.join(libsDir, 'gdbserver')
     87 		shutil.copyfile(srcGdbserverPath, dstGdbserverPath)
     88 	else:
     89 		assert not os.path.exists(os.path.join(libsDir, "gdbserver"))
     90 
     91 def buildApp (buildRoot, isRelease):
     92 	appDir	= os.path.join(buildRoot, "package")
     93 
     94 	# Set up app
     95 	os.chdir(appDir)
     96 
     97 	manifestSrcPath = os.path.normpath(os.path.join(common.ANDROID_DIR, "package", "AndroidManifest.xml"))
     98 	manifestDstPath = os.path.normpath(os.path.join(appDir, "AndroidManifest.xml"))
     99 
    100 	# Build dir can be the Android dir, in which case the copy is not needed.
    101 	if manifestSrcPath != manifestDstPath:
    102 		shutil.copy(manifestSrcPath, manifestDstPath)
    103 
    104 	common.execArgs([
    105 			common.ANDROID_BIN,
    106 			'update', 'project',
    107 			'--name', 'dEQP',
    108 			'--path', '.',
    109 			'--target', str(common.ANDROID_JAVA_API),
    110 		])
    111 
    112 	# Build
    113 	common.execArgs([
    114 			common.ANT_BIN,
    115 			"release" if isRelease else "debug",
    116 			"-Dsource.dir=" + os.path.join(common.ANDROID_DIR, "package", "src"),
    117 			"-Dresource.absolute.dir=" + os.path.join(common.ANDROID_DIR, "package", "res")
    118 		])
    119 
    120 def signApp (keystore, keyname, storepass, keypass):
    121 	os.chdir(os.path.join(common.ANDROID_DIR, "package"))
    122 	common.execArgs([
    123 			common.JARSIGNER_BIN,
    124 			'-keystore', keystore,
    125 			'-storepass', storepass,
    126 			'-keypass', keypass,
    127 			'-sigfile', 'CERT',
    128 			'-digestalg', 'SHA1',
    129 			'-sigalg', 'MD5withRSA',
    130 			'-signedjar', 'bin/dEQP-unaligned.apk',
    131 			'bin/dEQP-release-unsigned.apk',
    132 			keyname
    133 		])
    134 	common.execArgs([
    135 			common.ZIPALIGN_BIN,
    136 			'-f', '4',
    137 			'bin/dEQP-unaligned.apk',
    138 			'bin/dEQP-release.apk'
    139 		])
    140 
    141 def build (buildRoot=common.ANDROID_DIR, isRelease=False, nativeBuildType="Release"):
    142 	curDir = os.getcwd()
    143 
    144 	try:
    145 		assetsSrcDir = getAssetsDir(buildRoot, common.NATIVE_LIBS[0], nativeBuildType)
    146 		assetsDstDir = os.path.join(buildRoot, "package", "assets")
    147 
    148 		# Remove assets from the first build dir where we copy assets from
    149 		# to avoid collecting cruft there.
    150 		if os.path.exists(assetsSrcDir):
    151 			shutil.rmtree(assetsSrcDir)
    152 		if os.path.exists(assetsDstDir):
    153 			shutil.rmtree(assetsDstDir)
    154 
    155 		# Remove old libs dir to avoid collecting out-of-date versions
    156 		# of libs for ABIs not built this time.
    157 		libTargetDir = os.path.join(buildRoot, "package", "libs")
    158 		if os.path.exists(libTargetDir):
    159 			shutil.rmtree(libTargetDir)
    160 
    161 		# Build native code
    162 		for lib in common.NATIVE_LIBS:
    163 			buildNative(buildRoot, libTargetDir, lib, nativeBuildType)
    164 
    165 		# Copy assets
    166 		if os.path.exists(assetsSrcDir):
    167 			shutil.copytree(assetsSrcDir, assetsDstDir)
    168 
    169 		# Build java code and .apk
    170 		buildApp(buildRoot, isRelease)
    171 
    172 	finally:
    173 		# Restore working dir
    174 		os.chdir(curDir)
    175 
    176 if __name__ == "__main__":
    177 	parser = argparse.ArgumentParser()
    178 	parser.add_argument('--is-release', dest='isRelease', type=bool, default=False, help="Build android project in release mode.")
    179 	parser.add_argument('--native-build-type', dest='nativeBuildType', default="Release", help="Build type passed cmake when building native code.")
    180 	parser.add_argument('--build-root', dest='buildRoot', default=common.ANDROID_DIR, help="Root directory for storing build results.")
    181 
    182 	args = parser.parse_args()
    183 
    184 	build(buildRoot=os.path.abspath(args.buildRoot), isRelease=args.isRelease, nativeBuildType=args.nativeBuildType)
    185