# -*- coding: utf-8 -*-

#-------------------------------------------------------------------------
# drawElements Quality Program utilities
# --------------------------------------
#
# Copyright 2017 The Android Open Source Project
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
#-------------------------------------------------------------------------

# \todo [2017-04-10 pyry]
# * Use smarter asset copy in main build
#   * cmake -E copy_directory doesn't copy timestamps which will cause
#     assets to be always re-packaged
# * Consider adding an option for downloading SDK & NDK

import os
import re
import sys
import glob
import string
import shutil
import argparse
import tempfile
import xml.etree.ElementTree

# Import from <root>/scripts
sys.path.append(os.path.join(os.path.dirname(__file__), ".."))

from build.common import *
from build.config import *
from build.build import *

class SDKEnv:
	def __init__(self, path):
		self.path				= path
		self.buildToolsVersion	= SDKEnv.selectBuildToolsVersion(self.path)

	@staticmethod
	def getBuildToolsVersions (path):
		buildToolsPath	= os.path.join(path, "build-tools")
		versions		= []

		if os.path.exists(buildToolsPath):
			for item in os.listdir(buildToolsPath):
				m = re.match(r'^([0-9]+)\.([0-9]+)\.([0-9]+)$', item)
				if m != None:
					versions.append((int(m.group(1)), int(m.group(2)), int(m.group(3))))

		return versions

	@staticmethod
	def selectBuildToolsVersion (path):
		preferred	= [(25, 0, 2)]
		versions	= SDKEnv.getBuildToolsVersions(path)

		if len(versions) == 0:
			return (0,0,0)

		for candidate in preferred:
			if candidate in versions:
				return candidate

		# Pick newest
		versions.sort()
		return versions[-1]

	def getPlatformLibrary (self, apiVersion):
		return os.path.join(self.path, "platforms", "android-%d" % apiVersion, "android.jar")

	def getBuildToolsPath (self):
		return os.path.join(self.path, "build-tools", "%d.%d.%d" % self.buildToolsVersion)

class NDKEnv:
	def __init__(self, path):
		self.path		= path
		self.version	= NDKEnv.detectVersion(self.path)
		self.hostOsName	= NDKEnv.detectHostOsName(self.path)

	@staticmethod
	def getKnownAbis ():
		return ["armeabi-v7a", "arm64-v8a", "x86", "x86_64"]

	@staticmethod
	def getAbiPrebuiltsName (abiName):
		prebuilts = {
			"armeabi-v7a":	'android-arm',
			"arm64-v8a":	'android-arm64',
			"x86":			'android-x86',
			"x86_64":		'android-x86_64',
		}

		if not abiName in prebuilts:
			raise Exception("Unknown ABI: " + abiName)

		return prebuilts[abiName]

	@staticmethod
	def detectVersion (path):
		propFilePath = os.path.join(path, "source.properties")
		try:
			with open(propFilePath) as propFile:
				for line in propFile:
					keyValue = map(lambda x: string.strip(x), line.split("="))
					if keyValue[0] == "Pkg.Revision":
						versionParts = keyValue[1].split(".")
						return tuple(map(int, versionParts[0:2]))
		except Exception as e:
			raise Exception("Failed to read source prop file '%s': %s" % (propFilePath, str(e)))
		except:
			raise Exception("Failed to read source prop file '%s': unkown error")

		raise Exception("Failed to detect NDK version (does %s/source.properties have Pkg.Revision?)" % path)

	@staticmethod
	def isHostOsSupported (hostOsName):
		os			= HostInfo.getOs()
		bits		= HostInfo.getArchBits()
		hostOsParts	= hostOsName.split('-')

		if len(hostOsParts) > 1:
			assert(len(hostOsParts) == 2)
			assert(hostOsParts[1] == "x86_64")

			if bits != 64:
				return False

		if os == HostInfo.OS_WINDOWS:
			return hostOsParts[0] == 'windows'
		elif os == HostInfo.OS_LINUX:
			return hostOsParts[0] == 'linux'
		elif os == HostInfo.OS_OSX:
			return hostOsParts[0] == 'darwin'
		else:
			raise Exception("Unhandled HostInfo.getOs() '%d'" % os)

	@staticmethod
	def detectHostOsName (path):
		hostOsNames = [
			"windows",
			"windows-x86_64",
			"darwin-x86",
			"darwin-x86_64",
			"linux-x86",
			"linux-x86_64"
		]

		for name in hostOsNames:
			if os.path.exists(os.path.join(path, "prebuilt", name)):
				return name

		raise Exception("Failed to determine NDK host OS")

class Environment:
	def __init__(self, sdk, ndk):
		self.sdk		= sdk
		self.ndk		= ndk

class Configuration:
	def __init__(self, env, buildPath, abis, nativeApi, nativeBuildType, gtfTarget, verbose, layers, angle):
		self.env				= env
		self.sourcePath			= DEQP_DIR
		self.buildPath			= buildPath
		self.abis				= abis
		self.nativeApi			= nativeApi
		self.javaApi			= 22
		self.nativeBuildType	= nativeBuildType
		self.gtfTarget			= gtfTarget
		self.verbose			= verbose
		self.layers				= layers
		self.angle				= angle
		self.cmakeGenerator		= selectFirstAvailableGenerator([NINJA_GENERATOR, MAKEFILE_GENERATOR, NMAKE_GENERATOR])

	def check (self):
		if self.cmakeGenerator == None:
			raise Exception("Failed to find build tools for CMake")

		if not os.path.exists(self.env.ndk.path):
			raise Exception("Android NDK not found at %s" % self.env.ndk.path)

		if not NDKEnv.isHostOsSupported(self.env.ndk.hostOsName):
			raise Exception("NDK '%s' is not supported on this machine" % self.env.ndk.hostOsName)

		if self.env.ndk.version[0] < 15:
			raise Exception("Android NDK version %d is not supported; build requires NDK version >= 15" % (self.env.ndk.version[0]))

		if self.env.sdk.buildToolsVersion == (0,0,0):
			raise Exception("No build tools directory found at %s" % os.path.join(self.env.sdk.path, "build-tools"))

		androidBuildTools = ["aapt", "zipalign", "dx"]
		for tool in androidBuildTools:
			if which(tool, [self.env.sdk.getBuildToolsPath()]) == None:
				raise Exception("Missing Android build tool: %s" % toolPath)

		requiredToolsInPath = ["javac", "jar", "jarsigner", "keytool"]
		for tool in requiredToolsInPath:
			if which(tool) == None:
				raise Exception("%s not in PATH" % tool)

def log (config, msg):
	if config.verbose:
		print msg

def executeAndLog (config, args):
	if config.verbose:
		print " ".join(args)
	execute(args)

# Path components

class ResolvablePathComponent:
	def __init__ (self):
		pass

class SourceRoot (ResolvablePathComponent):
	def resolve (self, config):
		return config.sourcePath

class BuildRoot (ResolvablePathComponent):
	def resolve (self, config):
		return config.buildPath

class NativeBuildPath (ResolvablePathComponent):
	def __init__ (self, abiName):
		self.abiName = abiName

	def resolve (self, config):
		return getNativeBuildPath(config, self.abiName)

class GeneratedResSourcePath (ResolvablePathComponent):
	def __init__ (self, package):
		self.package = package

	def resolve (self, config):
		packageComps	= self.package.getPackageName(config).split('.')
		packageDir		= os.path.join(*packageComps)

		return os.path.join(config.buildPath, self.package.getAppDirName(), "src", packageDir, "R.java")

def resolvePath (config, path):
	resolvedComps = []

	for component in path:
		if isinstance(component, ResolvablePathComponent):
			resolvedComps.append(component.resolve(config))
		else:
			resolvedComps.append(str(component))

	return os.path.join(*resolvedComps)

def resolvePaths (config, paths):
	return list(map(lambda p: resolvePath(config, p), paths))

class BuildStep:
	def __init__ (self):
		pass

	def getInputs (self):
		return []

	def getOutputs (self):
		return []

	@staticmethod
	def expandPathsToFiles (paths):
		"""
		Expand mixed list of file and directory paths into a flattened list
		of files. Any non-existent input paths are preserved as is.
		"""

		def getFiles (dirPath):
			for root, dirs, files in os.walk(dirPath):
				for file in files:
					yield os.path.join(root, file)

		files = []
		for path in paths:
			if os.path.isdir(path):
				files += list(getFiles(path))
			else:
				files.append(path)

		return files

	def isUpToDate (self, config):
		inputs				= resolvePaths(config, self.getInputs())
		outputs				= resolvePaths(config, self.getOutputs())

		assert len(inputs) > 0 and len(outputs) > 0

		expandedInputs		= BuildStep.expandPathsToFiles(inputs)
		expandedOutputs		= BuildStep.expandPathsToFiles(outputs)

		existingInputs		= filter(os.path.exists, expandedInputs)
		existingOutputs		= filter(os.path.exists, expandedOutputs)

		if len(existingInputs) != len(expandedInputs):
			for file in expandedInputs:
				if file not in existingInputs:
					print "ERROR: Missing input file: %s" % file
			die("Missing input files")

		if len(existingOutputs) != len(expandedOutputs):
			return False # One or more output files are missing

		lastInputChange		= max(map(os.path.getmtime, existingInputs))
		firstOutputChange	= min(map(os.path.getmtime, existingOutputs))

		return lastInputChange <= firstOutputChange

	def update (config):
		die("BuildStep.update() not implemented")

def getNativeBuildPath (config, abiName):
	return os.path.join(config.buildPath, "%s-%s-%d" % (abiName, config.nativeBuildType, config.nativeApi))

def buildNativeLibrary (config, abiName):
	def makeNDKVersionString (version):
		minorVersionString = (chr(ord('a') + version[1]) if version[1] > 0 else "")
		return "r%d%s" % (version[0], minorVersionString)

	def getBuildArgs (config, abiName):
		args = ['-DDEQP_TARGET=android',
				'-DDEQP_TARGET_TOOLCHAIN=ndk-modern',
				'-DCMAKE_C_FLAGS=-Werror',
				'-DCMAKE_CXX_FLAGS=-Werror',
				'-DANDROID_NDK_HOST_OS=%s' % config.env.ndk.hostOsName,
				'-DANDROID_NDK_PATH=%s' % config.env.ndk.path,
				'-DANDROID_ABI=%s' % abiName,
				'-DDE_ANDROID_API=%s' % config.nativeApi,
				'-DGLCTS_GTF_TARGET=%s' % config.gtfTarget]

		if config.angle is not None:
			args.append('-DANGLE_LIBS=%s' % os.path.join(config.angle, abiName))

		return args

	nativeBuildPath	= getNativeBuildPath(config, abiName)
	buildConfig		= BuildConfig(nativeBuildPath, config.nativeBuildType, getBuildArgs(config, abiName))

	build(buildConfig, config.cmakeGenerator, ["deqp"])

def executeSteps (config, steps):
	for step in steps:
		if not step.isUpToDate(config):
			step.update(config)

def parsePackageName (manifestPath):
	tree = xml.etree.ElementTree.parse(manifestPath)

	if not 'package' in tree.getroot().attrib:
		raise Exception("'package' attribute missing from root element in %s" % manifestPath)

	return tree.getroot().attrib['package']

class PackageDescription:
	def __init__ (self, appDirName, appName, hasResources = True):
		self.appDirName		= appDirName
		self.appName		= appName
		self.hasResources	= hasResources

	def getAppName (self):
		return self.appName

	def getAppDirName (self):
		return self.appDirName

	def getPackageName (self, config):
		manifestPath	= resolvePath(config, self.getManifestPath())

		return parsePackageName(manifestPath)

	def getManifestPath (self):
		return [SourceRoot(), "android", self.appDirName, "AndroidManifest.xml"]

	def getResPath (self):
		return [SourceRoot(), "android", self.appDirName, "res"]

	def getSourcePaths (self):
		return [
				[SourceRoot(), "android", self.appDirName, "src"]
			]

	def getAssetsPath (self):
		return [BuildRoot(), self.appDirName, "assets"]

	def getClassesJarPath (self):
		return [BuildRoot(), self.appDirName, "bin", "classes.jar"]

	def getClassesDexPath (self):
		return [BuildRoot(), self.appDirName, "bin", "classes.dex"]

	def getAPKPath (self):
		return [BuildRoot(), self.appDirName, "bin", self.appName + ".apk"]

# Build step implementations

class BuildNativeLibrary (BuildStep):
	def __init__ (self, abi):
		self.abi = abi

	def isUpToDate (self, config):
		return False

	def update (self, config):
		log(config, "BuildNativeLibrary: %s" % self.abi)
		buildNativeLibrary(config, self.abi)

class GenResourcesSrc (BuildStep):
	def __init__ (self, package):
		self.package = package

	def getInputs (self):
		return [self.package.getResPath(), self.package.getManifestPath()]

	def getOutputs (self):
		return [[GeneratedResSourcePath(self.package)]]

	def update (self, config):
		aaptPath	= which("aapt", [config.env.sdk.getBuildToolsPath()])
		dstDir		= os.path.dirname(resolvePath(config, [GeneratedResSourcePath(self.package)]))

		if not os.path.exists(dstDir):
			os.makedirs(dstDir)

		executeAndLog(config, [
				aaptPath,
				"package",
				"-f",
				"-m",
				"-S", resolvePath(config, self.package.getResPath()),
				"-M", resolvePath(config, self.package.getManifestPath()),
				"-J", resolvePath(config, [BuildRoot(), self.package.getAppDirName(), "src"]),
				"-I", config.env.sdk.getPlatformLibrary(config.javaApi)
			])

# Builds classes.jar from *.java files
class BuildJavaSource (BuildStep):
	def __init__ (self, package, libraries = []):
		self.package	= package
		self.libraries	= libraries

	def getSourcePaths (self):
		srcPaths = self.package.getSourcePaths()

		if self.package.hasResources:
			srcPaths.append([BuildRoot(), self.package.getAppDirName(), "src"]) # Generated sources

		return srcPaths

	def getInputs (self):
		inputs = self.getSourcePaths()

		for lib in self.libraries:
			inputs.append(lib.getClassesJarPath())

		return inputs

	def getOutputs (self):
		return [self.package.getClassesJarPath()]

	def update (self, config):
		srcPaths	= resolvePaths(config, self.getSourcePaths())
		srcFiles	= BuildStep.expandPathsToFiles(srcPaths)
		jarPath		= resolvePath(config, self.package.getClassesJarPath())
		objPath		= resolvePath(config, [BuildRoot(), self.package.getAppDirName(), "obj"])
		classPaths	= [objPath] + [resolvePath(config, lib.getClassesJarPath()) for lib in self.libraries]
		pathSep		= ";" if HostInfo.getOs() == HostInfo.OS_WINDOWS else ":"

		if os.path.exists(objPath):
			shutil.rmtree(objPath)

		os.makedirs(objPath)

		for srcFile in srcFiles:
			executeAndLog(config, [
					"javac",
					"-source", "1.7",
					"-target", "1.7",
					"-d", objPath,
					"-bootclasspath", config.env.sdk.getPlatformLibrary(config.javaApi),
					"-classpath", pathSep.join(classPaths),
					"-sourcepath", pathSep.join(srcPaths),
					srcFile
				])

		if not os.path.exists(os.path.dirname(jarPath)):
			os.makedirs(os.path.dirname(jarPath))

		try:
			pushWorkingDir(objPath)
			executeAndLog(config, [
					"jar",
					"cf",
					jarPath,
					"."
				])
		finally:
			popWorkingDir()

class BuildDex (BuildStep):
	def __init__ (self, package, libraries):
		self.package	= package
		self.libraries	= libraries

	def getInputs (self):
		return [self.package.getClassesJarPath()] + [lib.getClassesJarPath() for lib in self.libraries]

	def getOutputs (self):
		return [self.package.getClassesDexPath()]

	def update (self, config):
		dxPath		= which("dx", [config.env.sdk.getBuildToolsPath()])
		srcPaths	= resolvePaths(config, self.getInputs())
		dexPath		= resolvePath(config, self.package.getClassesDexPath())
		jarPaths	= [resolvePath(config, self.package.getClassesJarPath())]

		for lib in self.libraries:
			jarPaths.append(resolvePath(config, lib.getClassesJarPath()))

		executeAndLog(config, [
				dxPath,
				"--dex",
				"--output", dexPath
			] + jarPaths)

class CreateKeystore (BuildStep):
	def __init__ (self):
		self.keystorePath	= [BuildRoot(), "debug.keystore"]

	def getOutputs (self):
		return [self.keystorePath]

	def isUpToDate (self, config):
		return os.path.exists(resolvePath(config, self.keystorePath))

	def update (self, config):
		executeAndLog(config, [
				"keytool",
				"-genkey",
				"-keystore", resolvePath(config, self.keystorePath),
				"-storepass", "android",
				"-alias", "androiddebugkey",
				"-keypass", "android",
				"-keyalg", "RSA",
				"-keysize", "2048",
				"-validity", "10000",
				"-dname", "CN=, OU=, O=, L=, S=, C=",
			])

# Builds APK without code
class BuildBaseAPK (BuildStep):
	def __init__ (self, package, libraries = []):
		self.package	= package
		self.libraries	= libraries
		self.dstPath	= [BuildRoot(), self.package.getAppDirName(), "tmp", "base.apk"]

	def getResPaths (self):
		paths = []
		for pkg in [self.package] + self.libraries:
			if pkg.hasResources:
				paths.append(pkg.getResPath())
		return paths

	def getInputs (self):
		return [self.package.getManifestPath()] + self.getResPaths()

	def getOutputs (self):
		return [self.dstPath]

	def update (self, config):
		aaptPath	= which("aapt", [config.env.sdk.getBuildToolsPath()])
		dstPath		= resolvePath(config, self.dstPath)

		if not os.path.exists(os.path.dirname(dstPath)):
			os.makedirs(os.path.dirname(dstPath))

		args = [
			aaptPath,
			"package",
			"-f",
			"-M", resolvePath(config, self.package.getManifestPath()),
			"-I", config.env.sdk.getPlatformLibrary(config.javaApi),
			"-F", dstPath,
		]

		for resPath in self.getResPaths():
			args += ["-S", resolvePath(config, resPath)]

		if config.verbose:
			args.append("-v")

		executeAndLog(config, args)

def addFilesToAPK (config, apkPath, baseDir, relFilePaths):
	aaptPath		= which("aapt", [config.env.sdk.getBuildToolsPath()])
	maxBatchSize	= 25

	pushWorkingDir(baseDir)
	try:
		workQueue = list(relFilePaths)

		while len(workQueue) > 0:
			batchSize	= min(len(workQueue), maxBatchSize)
			items		= workQueue[0:batchSize]

			executeAndLog(config, [
					aaptPath,
					"add",
					"-f", apkPath,
				] + items)

			del workQueue[0:batchSize]
	finally:
		popWorkingDir()

def addFileToAPK (config, apkPath, baseDir, relFilePath):
	addFilesToAPK(config, apkPath, baseDir, [relFilePath])

class AddJavaToAPK (BuildStep):
	def __init__ (self, package):
		self.package	= package
		self.srcPath	= BuildBaseAPK(self.package).getOutputs()[0]
		self.dstPath	= [BuildRoot(), self.package.getAppDirName(), "tmp", "with-java.apk"]

	def getInputs (self):
		return [
				self.srcPath,
				self.package.getClassesDexPath(),
			]

	def getOutputs (self):
		return [self.dstPath]

	def update (self, config):
		srcPath		= resolvePath(config, self.srcPath)
		dstPath		= resolvePath(config, self.getOutputs()[0])
		dexPath		= resolvePath(config, self.package.getClassesDexPath())

		shutil.copyfile(srcPath, dstPath)
		addFileToAPK(config, dstPath, os.path.dirname(dexPath), os.path.basename(dexPath))

class AddAssetsToAPK (BuildStep):
	def __init__ (self, package, abi):
		self.package	= package
		self.buildPath	= [NativeBuildPath(abi)]
		self.srcPath	= AddJavaToAPK(self.package).getOutputs()[0]
		self.dstPath	= [BuildRoot(), self.package.getAppDirName(), "tmp", "with-assets.apk"]

	def getInputs (self):
		return [
				self.srcPath,
				self.buildPath + ["assets"]
			]

	def getOutputs (self):
		return [self.dstPath]

	@staticmethod
	def getAssetFiles (buildPath):
		allFiles = BuildStep.expandPathsToFiles([os.path.join(buildPath, "assets")])
		return [os.path.relpath(p, buildPath) for p in allFiles]

	def update (self, config):
		srcPath		= resolvePath(config, self.srcPath)
		dstPath		= resolvePath(config, self.getOutputs()[0])
		buildPath	= resolvePath(config, self.buildPath)
		assetFiles	= AddAssetsToAPK.getAssetFiles(buildPath)

		shutil.copyfile(srcPath, dstPath)

		addFilesToAPK(config, dstPath, buildPath, assetFiles)

class AddNativeLibsToAPK (BuildStep):
	def __init__ (self, package, abis):
		self.package	= package
		self.abis		= abis
		self.srcPath	= AddAssetsToAPK(self.package, "").getOutputs()[0]
		self.dstPath	= [BuildRoot(), self.package.getAppDirName(), "tmp", "with-native-libs.apk"]

	def getInputs (self):
		paths = [self.srcPath]
		for abi in self.abis:
			paths.append([NativeBuildPath(abi), "libdeqp.so"])
		return paths

	def getOutputs (self):
		return [self.dstPath]

	def update (self, config):
		srcPath		= resolvePath(config, self.srcPath)
		dstPath		= resolvePath(config, self.getOutputs()[0])
		pkgPath		= resolvePath(config, [BuildRoot(), self.package.getAppDirName()])
		libFiles	= []

		# Create right directory structure first
		for abi in self.abis:
			libSrcPath	= resolvePath(config, [NativeBuildPath(abi), "libdeqp.so"])
			libRelPath	= os.path.join("lib", abi, "libdeqp.so")
			libAbsPath	= os.path.join(pkgPath, libRelPath)

			if not os.path.exists(os.path.dirname(libAbsPath)):
				os.makedirs(os.path.dirname(libAbsPath))

			shutil.copyfile(libSrcPath, libAbsPath)
			libFiles.append(libRelPath)

			if config.layers:
				layersGlob = os.path.join(config.layers, abi, "libVkLayer_*.so")
				libVkLayers = glob.glob(layersGlob)
				for layer in libVkLayers:
					layerFilename = os.path.basename(layer)
					layerRelPath = os.path.join("lib", abi, layerFilename)
					layerAbsPath = os.path.join(pkgPath, layerRelPath)
					shutil.copyfile(layer, layerAbsPath)
					libFiles.append(layerRelPath)
					print "Adding layer binary: %s" % (layer,)

			if config.angle:
				angleGlob = os.path.join(config.angle, abi, "lib*_angle.so")
				libAngle = glob.glob(angleGlob)
				for lib in libAngle:
					libFilename = os.path.basename(lib)
					libRelPath = os.path.join("lib", abi, libFilename)
					libAbsPath = os.path.join(pkgPath, libRelPath)
					shutil.copyfile(lib, libAbsPath)
					libFiles.append(libRelPath)
					print "Adding ANGLE binary: %s" % (lib,)

		shutil.copyfile(srcPath, dstPath)
		addFilesToAPK(config, dstPath, pkgPath, libFiles)

class SignAPK (BuildStep):
	def __init__ (self, package):
		self.package		= package
		self.srcPath		= AddNativeLibsToAPK(self.package, []).getOutputs()[0]
		self.dstPath		= [BuildRoot(), self.package.getAppDirName(), "tmp", "signed.apk"]
		self.keystorePath	= CreateKeystore().getOutputs()[0]

	def getInputs (self):
		return [self.srcPath, self.keystorePath]

	def getOutputs (self):
		return [self.dstPath]

	def update (self, config):
		srcPath		= resolvePath(config, self.srcPath)
		dstPath		= resolvePath(config, self.dstPath)

		executeAndLog(config, [
				"jarsigner",
				"-keystore", resolvePath(config, self.keystorePath),
				"-storepass", "android",
				"-keypass", "android",
				"-signedjar", dstPath,
				srcPath,
				"androiddebugkey"
			])

def getBuildRootRelativeAPKPath (package):
	return os.path.join(package.getAppDirName(), package.getAppName() + ".apk")

class FinalizeAPK (BuildStep):
	def __init__ (self, package):
		self.package		= package
		self.srcPath		= SignAPK(self.package).getOutputs()[0]
		self.dstPath		= [BuildRoot(), getBuildRootRelativeAPKPath(self.package)]
		self.keystorePath	= CreateKeystore().getOutputs()[0]

	def getInputs (self):
		return [self.srcPath]

	def getOutputs (self):
		return [self.dstPath]

	def update (self, config):
		srcPath			= resolvePath(config, self.srcPath)
		dstPath			= resolvePath(config, self.dstPath)
		zipalignPath	= os.path.join(config.env.sdk.getBuildToolsPath(), "zipalign")

		executeAndLog(config, [
				zipalignPath,
				"-f", "4",
				srcPath,
				dstPath
			])

def getBuildStepsForPackage (abis, package, libraries = []):
	steps = []

	assert len(abis) > 0

	# Build native code first
	for abi in abis:
		steps += [BuildNativeLibrary(abi)]

	# Build library packages
	for library in libraries:
		if library.hasResources:
			steps.append(GenResourcesSrc(library))
		steps.append(BuildJavaSource(library))

	# Build main package .java sources
	if package.hasResources:
		steps.append(GenResourcesSrc(package))
	steps.append(BuildJavaSource(package, libraries))
	steps.append(BuildDex(package, libraries))

	# Build base APK
	steps.append(BuildBaseAPK(package, libraries))
	steps.append(AddJavaToAPK(package))

	# Add assets from first ABI
	steps.append(AddAssetsToAPK(package, abis[0]))

	# Add native libs to APK
	steps.append(AddNativeLibsToAPK(package, abis))

	# Finalize APK
	steps.append(CreateKeystore())
	steps.append(SignAPK(package))
	steps.append(FinalizeAPK(package))

	return steps

def getPackageAndLibrariesForTarget (target):
	deqpPackage	= PackageDescription("package", "dEQP")
	ctsPackage	= PackageDescription("openglcts", "Khronos-CTS", hasResources = False)

	if target == 'deqp':
		return (deqpPackage, [])
	elif target == 'openglcts':
		return (ctsPackage, [deqpPackage])
	else:
		raise Exception("Uknown target '%s'" % target)

def findNDK ():
	ndkBuildPath = which('ndk-build')
	if ndkBuildPath != None:
		return os.path.dirname(ndkBuildPath)
	else:
		return None

def findSDK ():
	sdkBuildPath = which('android')
	if sdkBuildPath != None:
		return os.path.dirname(os.path.dirname(sdkBuildPath))
	else:
		return None

def getDefaultBuildRoot ():
	return os.path.join(tempfile.gettempdir(), "deqp-android-build")

def parseArgs ():
	nativeBuildTypes	= ['Release', 'Debug', 'MinSizeRel', 'RelWithAsserts', 'RelWithDebInfo']
	defaultNDKPath		= findNDK()
	defaultSDKPath		= findSDK()
	defaultBuildRoot	= getDefaultBuildRoot()

	parser = argparse.ArgumentParser(os.path.basename(__file__),
		formatter_class=argparse.ArgumentDefaultsHelpFormatter)
	parser.add_argument('--native-build-type',
		dest='nativeBuildType',
		default="RelWithAsserts",
		choices=nativeBuildTypes,
		help="Native code build type")
	parser.add_argument('--build-root',
		dest='buildRoot',
		default=defaultBuildRoot,
		help="Root build directory")
	parser.add_argument('--abis',
		dest='abis',
		default=",".join(NDKEnv.getKnownAbis()),
		help="ABIs to build")
	parser.add_argument('--native-api',
		type=int,
		dest='nativeApi',
		default=21,
		help="Android API level to target in native code")
	parser.add_argument('--sdk',
		dest='sdkPath',
		default=defaultSDKPath,
		help="Android SDK path",
		required=(True if defaultSDKPath == None else False))
	parser.add_argument('--ndk',
		dest='ndkPath',
		default=defaultNDKPath,
		help="Android NDK path",
		required=(True if defaultNDKPath == None else False))
	parser.add_argument('-v', '--verbose',
		dest='verbose',
		help="Verbose output",
		default=False,
		action='store_true')
	parser.add_argument('--target',
		dest='target',
		help='Build target',
		choices=['deqp', 'openglcts'],
		default='deqp')
	parser.add_argument('--kc-cts-target',
		dest='gtfTarget',
		default='gles32',
		choices=['gles32', 'gles31', 'gles3', 'gles2', 'gl'],
		help="KC-CTS (GTF) target API (only used in openglcts target)")
	parser.add_argument('--layers-path',
		dest='layers',
		default=None,
		required=False)
	parser.add_argument('--angle-path',
		dest='angle',
		default=None,
		required=False)

	args = parser.parse_args()

	def parseAbis (abisStr):
		knownAbis	= set(NDKEnv.getKnownAbis())
		abis		= []

		for abi in abisStr.split(','):
			abi = abi.strip()
			if not abi in knownAbis:
				raise Exception("Unknown ABI: %s" % abi)
			abis.append(abi)

		return abis

	# Custom parsing & checks
	try:
		args.abis = parseAbis(args.abis)
		if len(args.abis) == 0:
			raise Exception("--abis can't be empty")
	except Exception as e:
		print "ERROR: %s" % str(e)
		parser.print_help()
		sys.exit(-1)

	return args

if __name__ == "__main__":
	args		= parseArgs()

	ndk			= NDKEnv(os.path.realpath(args.ndkPath))
	sdk			= SDKEnv(os.path.realpath(args.sdkPath))
	buildPath	= os.path.realpath(args.buildRoot)
	env			= Environment(sdk, ndk)
	config		= Configuration(env, buildPath, abis=args.abis, nativeApi=args.nativeApi, nativeBuildType=args.nativeBuildType, gtfTarget=args.gtfTarget, verbose=args.verbose,
						 layers=args.layers, angle=args.angle)

	try:
		config.check()
	except Exception as e:
		print "ERROR: %s" % str(e)
		print ""
		print "Please check your configuration:"
		print "  --sdk=%s" % args.sdkPath
		print "  --ndk=%s" % args.ndkPath
		sys.exit(-1)

	pkg, libs	= getPackageAndLibrariesForTarget(args.target)
	steps		= getBuildStepsForPackage(config.abis, pkg, libs)

	executeSteps(config, steps)

	print ""
	print "Built %s" % os.path.join(buildPath, getBuildRootRelativeAPKPath(pkg))
