Improve check_build_sanity.py

 * All steps now respect --tmp-dir argument. This required adding
--build-dir and other args to mustpass scripts.

 * --recipe command line argument allows running only a specific build
check recipe.

 * --dump-recipes option allows printing out all recipes that are
supported in the current environment.

Components: Vulkan, Framework, AOSP

Change-Id: I6ba4f1369def14dc4ea6b398f367366549eecdc5
(cherry picked from commit 8849259035284f5506802f54f09f99f2b146e0b0)
diff --git a/external/vulkancts/scripts/build_mustpass.py b/external/vulkancts/scripts/build_mustpass.py
index b5bc747..12ff7cf 100644
--- a/external/vulkancts/scripts/build_mustpass.py
+++ b/external/vulkancts/scripts/build_mustpass.py
@@ -28,7 +28,7 @@
 from build.common import DEQP_DIR
 from build.config import ANY_GENERATOR
 from build_caselists import Module, getModuleByName, getBuildConfig, DEFAULT_BUILD_DIR, DEFAULT_TARGET
-from mustpass import Project, Package, Mustpass, Configuration, include, exclude, genMustpassLists
+from mustpass import Project, Package, Mustpass, Configuration, include, exclude, genMustpassLists, parseBuildConfigFromCmdLineArgs
 
 COPYRIGHT_DECLARATION = """
 	 Licensed under the Apache License, Version 2.0 (the "License");
@@ -83,4 +83,4 @@
 	]
 
 if __name__ == "__main__":
-	genMustpassLists(MUSTPASS_LISTS, ANY_GENERATOR, BUILD_CONFIG)
+	genMustpassLists(MUSTPASS_LISTS, ANY_GENERATOR, parseBuildConfigFromCmdLineArgs())
diff --git a/scripts/build_android_mustpass.py b/scripts/build_android_mustpass.py
index de28b32..ddbd5ed 100644
--- a/scripts/build_android_mustpass.py
+++ b/scripts/build_android_mustpass.py
@@ -23,7 +23,7 @@
 from build.common import DEQP_DIR
 from build.config import ANY_GENERATOR
 from build_caselists import Module, getModuleByName, getBuildConfig, DEFAULT_BUILD_DIR, DEFAULT_TARGET
-from mustpass import Project, Package, Mustpass, Configuration, include, exclude, genMustpassLists
+from mustpass import Project, Package, Mustpass, Configuration, include, exclude, genMustpassLists, parseBuildConfigFromCmdLineArgs
 
 import os
 
@@ -514,7 +514,5 @@
 		Mustpass(project = CTS_PROJECT, version = "master",		packages = [MASTER_EGL_PKG, MASTER_GLES2_PKG, MASTER_GLES3_PKG, MASTER_GLES31_PKG, MASTER_VULKAN_PKG])
 	]
 
-BUILD_CONFIG				= getBuildConfig(DEFAULT_BUILD_DIR, DEFAULT_TARGET, "Debug")
-
 if __name__ == "__main__":
-	genMustpassLists(MUSTPASS_LISTS, ANY_GENERATOR, BUILD_CONFIG)
+	genMustpassLists(MUSTPASS_LISTS, ANY_GENERATOR, parseBuildConfigFromCmdLineArgs())
diff --git a/scripts/check_build_sanity.py b/scripts/check_build_sanity.py
index fae53a2..88500a4 100644
--- a/scripts/check_build_sanity.py
+++ b/scripts/check_build_sanity.py
@@ -43,14 +43,20 @@
 		raise Exception("Not implemented")
 
 class RunScript(BuildTestStep):
-	def __init__ (self, scriptPath):
-		self.scriptPath = scriptPath
+	def __init__ (self, scriptPath, getExtraArgs = None):
+		self.scriptPath		= scriptPath
+		self.getExtraArgs	= getExtraArgs
 
 	def getName (self):
 		return self.scriptPath
 
 	def run (self, env):
-		execute(["python", os.path.join(env.srcDir, self.scriptPath)])
+		args = ["python", os.path.join(env.srcDir, self.scriptPath)]
+
+		if self.getExtraArgs != None:
+			args += self.getExtraArgs(env)
+
+		execute(args)
 
 def makeCflagsArgs (cflags):
 	cflagsStr = " ".join(cflags)
@@ -121,6 +127,18 @@
 			return "-" + version
 	return ""
 
+def runSteps (steps):
+	for step in steps:
+		if step.isAvailable(env):
+			print "Run: %s" % step.getName()
+			step.run(env)
+		else:
+			print "Skip: %s" % step.getName()
+
+def runRecipe (steps):
+	allSteps = PREREQUISITES + steps + POST_CHECKS
+	runSteps(allSteps)
+
 COMMON_GCC_CFLAGS	= ["-Werror"]
 COMMON_CLANG_CFLAGS	= COMMON_GCC_CFLAGS + ["-Wno-error=unused-command-line-argument"]
 GCC_32BIT_CFLAGS	= COMMON_GCC_CFLAGS + ["-m32"]
@@ -129,8 +147,17 @@
 CLANG_64BIT_CFLAGS	= COMMON_CLANG_CFLAGS + ["-m64"]
 CLANG_VERSION		= getClangVersion()
 
-STEPS = [
-	RunScript(os.path.join("external", "fetch_sources.py")),
+# Always ran before any receipe
+PREREQUISITES		= [
+	RunScript(os.path.join("external", "fetch_sources.py"))
+]
+
+# Always ran after any receipe
+POST_CHECKS			= [
+	CheckSrcChanges()
+]
+
+BUILD_TARGETS		= [
 	Build("clang-64-debug",
 		  UnixConfig("null",
 					 "Debug",
@@ -155,19 +182,50 @@
 	Build("vs-64-debug",
 		  VSConfig("Debug"),
 		  ANY_VS_X64_GENERATOR),
-	RunScript(os.path.join("scripts", "build_android_mustpass.py")),
-	RunScript(os.path.join("external", "vulkancts", "scripts", "build_mustpass.py")),
-	RunScript(os.path.join("scripts", "gen_egl.py")),
-	RunScript(os.path.join("scripts", "opengl", "gen_all.py")),
-	RunScript(os.path.join("scripts", "src_util", "check_all.py")),
-	RunScript(os.path.join("external", "vulkancts", "scripts", "gen_framework.py")),
-	CheckSrcChanges(),
 ]
 
+SPECIAL_RECIPES		= [
+	('android-mustpass', [
+			RunScript(os.path.join("scripts", "build_android_mustpass.py"),
+					  lambda env: ["--build-dir", os.path.join(env.tmpDir, "android-mustpass")]),
+		]),
+	('vulkan-mustpass', [
+			RunScript(os.path.join("external", "vulkancts", "scripts", "build_mustpass.py"),
+					  lambda env: ["--build-dir", os.path.join(env.tmpDir, "vulkan-mustpass")]),
+		]),
+	('gen-inl-files', [
+			RunScript(os.path.join("scripts", "gen_egl.py")),
+			RunScript(os.path.join("scripts", "opengl", "gen_all.py")),
+			RunScript(os.path.join("external", "vulkancts", "scripts", "gen_framework.py")),
+			RunScript(os.path.join("scripts", "src_util", "check_all.py")),
+		])
+]
+
+def getBuildRecipes ():
+	return [(b.getName(), [b]) for b in BUILD_TARGETS]
+
+def getAllRecipe (recipes):
+	allSteps = []
+	for name, steps in recipes:
+		allSteps += steps
+	return ("all", allSteps)
+
+def getRecipes ():
+	recipes = getBuildRecipes()
+	recipes += SPECIAL_RECIPES
+	return recipes
+
+def getRecipe (recipes, recipeName):
+	for curName, steps in recipes:
+		if curName == recipeName:
+			return (curName, steps)
+	return None
+
+RECIPES			= getRecipes()
+
 def parseArgs ():
 	parser = argparse.ArgumentParser(description = "Build and test source",
 									 formatter_class=argparse.ArgumentDefaultsHelpFormatter)
-
 	parser.add_argument("-s",
 						"--src-dir",
 						dest="srcDir",
@@ -178,17 +236,35 @@
 						dest="tmpDir",
 						default=os.path.join(tempfile.gettempdir(), "deqp-build-test"),
 						help="Temporary directory")
+	parser.add_argument("-r",
+						"--recipe",
+						dest="recipe",
+						choices=[n for n, s in RECIPES] + ["all"],
+						default="all",
+						help="Build / test recipe")
+	parser.add_argument("-d",
+						"--dump-recipes",
+						dest="dumpRecipes",
+						action="store_true",
+						help="Print out recipes that have any available actions")
 	return parser.parse_args()
 
 if __name__ == "__main__":
 	args	= parseArgs()
 	env		= Environment(args.srcDir, args.tmpDir)
 
-	for step in STEPS:
-		if step.isAvailable(env):
-			print "Run: %s" % step.getName()
-			step.run(env)
-		else:
-			print "Skip: %s" % step.getName()
+	if args.dumpRecipes:
+		for name, steps in RECIPES:
+			for step in steps:
+				if step.isAvailable(env):
+					print name
+					break
+	else:
+		name, steps	= getAllRecipe(RECIPES) if args.recipe == "all" \
+					  else getRecipe(RECIPES, args.recipe)
 
-	print "All steps completed successfully"
+		print "Running %s" % name
+
+		runRecipe(steps)
+
+		print "All steps completed successfully"
diff --git a/scripts/mustpass.py b/scripts/mustpass.py
index 33b123d..5d4a92c 100644
--- a/scripts/mustpass.py
+++ b/scripts/mustpass.py
@@ -27,6 +27,7 @@
 from fnmatch import fnmatch
 from copy import copy
 
+import argparse
 import xml.etree.cElementTree as ElementTree
 import xml.dom.minidom as minidom
 
@@ -372,3 +373,27 @@
 
 	for mustpass in mustpassLists:
 		genMustpass(mustpass, moduleCaseLists)
+
+def parseCmdLineArgs ():
+	parser = argparse.ArgumentParser(description = "Build Android CTS mustpass",
+									 formatter_class=argparse.ArgumentDefaultsHelpFormatter)
+	parser.add_argument("-b",
+						"--build-dir",
+						dest="buildDir",
+						default=DEFAULT_BUILD_DIR,
+						help="Temporary build directory")
+	parser.add_argument("-t",
+						"--build-type",
+						dest="buildType",
+						default="Debug",
+						help="Build type")
+	parser.add_argument("-c",
+						"--deqp-target",
+						dest="targetName",
+						default=DEFAULT_TARGET,
+						help="dEQP build target")
+	return parser.parse_args()
+
+def parseBuildConfigFromCmdLineArgs ():
+	args = parseCmdLineArgs()
+	return getBuildConfig(args.buildDir, args.targetName, args.buildType)