• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# -*- coding: utf-8 -*-
2
3import os
4import re
5import sys
6import shutil
7import argparse
8
9import common
10
11def 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
27def 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
31def getAssetsDir (buildRoot, nativeLib, buildType):
32	return os.path.join(getNativeBuildDir(buildRoot, nativeLib, buildType), "assets")
33
34def 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
46def 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
91def 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
120def 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
141def 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
176if __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