# -*- 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 = list(map(lambda x: x.strip(), 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, minApi, nativeBuildType, gtfTarget, verbose, layers, angle):
		self.env				= env
		self.sourcePath			= DEQP_DIR
		self.buildPath			= buildPath
		self.abis				= abis
		self.nativeApi			= nativeApi
		self.javaApi			= 28
		self.minApi				= minApi
		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 not (self.minApi <= self.javaApi <= self.nativeApi):
			raise Exception("Requires: min-api (%d) <= java-api (%d) <= native-api (%d)" % (self.minApi, self.javaApi, self.nativeApi))

		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" % tool)

		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		= list(filter(os.path.exists, expandedInputs))
		existingOutputs		= list(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 clearCMakeCacheVariables(args):
	# New value, so clear the necessary cmake variables
	args.append('-UANGLE_LIBS')
	args.append('-UGLES1_LIBRARY')
	args.append('-UGLES2_LIBRARY')
	args.append('-UEGL_LIBRARY')

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_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 None:
			# Find any previous builds that may have embedded ANGLE libs and clear the CMake cache
			for abi in NDKEnv.getKnownAbis():
				cMakeCachePath = os.path.join(getNativeBuildPath(config, abi), "CMakeCache.txt")
				try:
					if 'ANGLE_LIBS' in open(cMakeCachePath).read():
						clearCMakeCacheVariables(args)
				except IOError:
					pass
		else:
			cMakeCachePath = os.path.join(getNativeBuildPath(config, abiName), "CMakeCache.txt")
			angleLibsDir = os.path.join(config.angle, abiName)
			# Check if the user changed where the ANGLE libs are being loaded from
			try:
				if angleLibsDir not in open(cMakeCachePath).read():
					clearCMakeCacheVariables(args)
			except IOError:
				pass
			args.append('-DANGLE_LIBS=%s' % angleLibsDir)

		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",
			"--min-sdk-version", str(config.minApi),
			"--target-sdk-version", str(config.javaApi),
			"-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)
		# Workaround for Windows.
		if os.path.sep == "\\":
			workQueue = [i.replace("\\", "/") for i in workQueue]

		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=28,
		help="Android API level to target in native code")
	parser.add_argument('--min-api',
		type=int,
		dest='minApi',
		default=22,
		help="Minimum Android API level for which the APK can be installed")
	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, minApi=args.minApi, 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)))
