1e5c31af7Sopenharmony_ci# -*- coding: utf-8 -*-
2e5c31af7Sopenharmony_ci
3e5c31af7Sopenharmony_ci#-------------------------------------------------------------------------
4e5c31af7Sopenharmony_ci# drawElements Quality Program utilities
5e5c31af7Sopenharmony_ci# --------------------------------------
6e5c31af7Sopenharmony_ci#
7e5c31af7Sopenharmony_ci# Copyright 2016 The Android Open Source Project
8e5c31af7Sopenharmony_ci#
9e5c31af7Sopenharmony_ci# Licensed under the Apache License, Version 2.0 (the "License");
10e5c31af7Sopenharmony_ci# you may not use this file except in compliance with the License.
11e5c31af7Sopenharmony_ci# You may obtain a copy of the License at
12e5c31af7Sopenharmony_ci#
13e5c31af7Sopenharmony_ci#      http://www.apache.org/licenses/LICENSE-2.0
14e5c31af7Sopenharmony_ci#
15e5c31af7Sopenharmony_ci# Unless required by applicable law or agreed to in writing, software
16e5c31af7Sopenharmony_ci# distributed under the License is distributed on an "AS IS" BASIS,
17e5c31af7Sopenharmony_ci# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18e5c31af7Sopenharmony_ci# See the License for the specific language governing permissions and
19e5c31af7Sopenharmony_ci# limitations under the License.
20e5c31af7Sopenharmony_ci#
21e5c31af7Sopenharmony_ci#-------------------------------------------------------------------------
22e5c31af7Sopenharmony_ci
23e5c31af7Sopenharmony_ciimport os
24e5c31af7Sopenharmony_ciimport argparse
25e5c31af7Sopenharmony_ciimport tempfile
26e5c31af7Sopenharmony_ciimport sys
27e5c31af7Sopenharmony_ci
28e5c31af7Sopenharmony_cifrom ctsbuild.common import *
29e5c31af7Sopenharmony_cifrom ctsbuild.build import *
30e5c31af7Sopenharmony_ci
31e5c31af7Sopenharmony_cipythonExecutable = sys.executable or "python"
32e5c31af7Sopenharmony_ci
33e5c31af7Sopenharmony_ciclass Environment:
34e5c31af7Sopenharmony_ci	def __init__ (self, srcDir, tmpDir):
35e5c31af7Sopenharmony_ci		self.srcDir	= srcDir
36e5c31af7Sopenharmony_ci		self.tmpDir	= tmpDir
37e5c31af7Sopenharmony_ci
38e5c31af7Sopenharmony_ciclass BuildTestStep:
39e5c31af7Sopenharmony_ci	def getName (self):
40e5c31af7Sopenharmony_ci		return "<unknown>"
41e5c31af7Sopenharmony_ci
42e5c31af7Sopenharmony_ci	def isAvailable (self, env):
43e5c31af7Sopenharmony_ci		return True
44e5c31af7Sopenharmony_ci
45e5c31af7Sopenharmony_ci	def run (self, env):
46e5c31af7Sopenharmony_ci		raise Exception("Not implemented")
47e5c31af7Sopenharmony_ci
48e5c31af7Sopenharmony_ciclass RunScript(BuildTestStep):
49e5c31af7Sopenharmony_ci	def __init__ (self, scriptPath, getExtraArgs = None):
50e5c31af7Sopenharmony_ci		self.scriptPath		= scriptPath
51e5c31af7Sopenharmony_ci		self.getExtraArgs	= getExtraArgs
52e5c31af7Sopenharmony_ci
53e5c31af7Sopenharmony_ci	def getName (self):
54e5c31af7Sopenharmony_ci		return self.scriptPath
55e5c31af7Sopenharmony_ci
56e5c31af7Sopenharmony_ci	def run (self, env):
57e5c31af7Sopenharmony_ci		args = [pythonExecutable, os.path.join(env.srcDir, self.scriptPath)]
58e5c31af7Sopenharmony_ci
59e5c31af7Sopenharmony_ci		if self.getExtraArgs != None:
60e5c31af7Sopenharmony_ci			args += self.getExtraArgs(env)
61e5c31af7Sopenharmony_ci
62e5c31af7Sopenharmony_ci		execute(args)
63e5c31af7Sopenharmony_ci
64e5c31af7Sopenharmony_cidef makeCflagsArgs (cflags):
65e5c31af7Sopenharmony_ci	cflagsStr = " ".join(cflags)
66e5c31af7Sopenharmony_ci	return ["-DCMAKE_C_FLAGS=%s" % cflagsStr, "-DCMAKE_CXX_FLAGS=%s" % cflagsStr]
67e5c31af7Sopenharmony_ci
68e5c31af7Sopenharmony_cidef makeBuildArgs (target, cc, cpp, cflags):
69e5c31af7Sopenharmony_ci	return ["-DDEQP_TARGET=%s" % target, "-DCMAKE_C_COMPILER=%s" % cc, "-DCMAKE_CXX_COMPILER=%s" % cpp] + makeCflagsArgs(cflags)
70e5c31af7Sopenharmony_ci
71e5c31af7Sopenharmony_ciclass BuildConfigGen:
72e5c31af7Sopenharmony_ci	def isAvailable (self, env):
73e5c31af7Sopenharmony_ci		return True
74e5c31af7Sopenharmony_ci
75e5c31af7Sopenharmony_ciclass UnixConfig(BuildConfigGen):
76e5c31af7Sopenharmony_ci	def __init__ (self, target, buildType, cc, cpp, cflags):
77e5c31af7Sopenharmony_ci		self.target		= target
78e5c31af7Sopenharmony_ci		self.buildType	= buildType
79e5c31af7Sopenharmony_ci		self.cc			= cc
80e5c31af7Sopenharmony_ci		self.cpp		= cpp
81e5c31af7Sopenharmony_ci		self.cflags		= cflags
82e5c31af7Sopenharmony_ci
83e5c31af7Sopenharmony_ci	def isAvailable (self, env):
84e5c31af7Sopenharmony_ci		return which(self.cc) != None and which(self.cpp) != None
85e5c31af7Sopenharmony_ci
86e5c31af7Sopenharmony_ci	def getBuildConfig (self, env, buildDir):
87e5c31af7Sopenharmony_ci		args = makeBuildArgs(self.target, self.cc, self.cpp, self.cflags)
88e5c31af7Sopenharmony_ci		return BuildConfig(buildDir, self.buildType, args, env.srcDir)
89e5c31af7Sopenharmony_ci
90e5c31af7Sopenharmony_ciclass VSConfig(BuildConfigGen):
91e5c31af7Sopenharmony_ci	def __init__ (self, buildType):
92e5c31af7Sopenharmony_ci		self.buildType = buildType
93e5c31af7Sopenharmony_ci
94e5c31af7Sopenharmony_ci	def getBuildConfig (self, env, buildDir):
95e5c31af7Sopenharmony_ci		args = ["-DCMAKE_C_FLAGS=/WX -DCMAKE_CXX_FLAGS=/WX"]
96e5c31af7Sopenharmony_ci		return BuildConfig(buildDir, self.buildType, args, env.srcDir)
97e5c31af7Sopenharmony_ci
98e5c31af7Sopenharmony_ciclass Build(BuildTestStep):
99e5c31af7Sopenharmony_ci	def __init__ (self, buildDir, configGen, generator):
100e5c31af7Sopenharmony_ci		self.buildDir	= buildDir
101e5c31af7Sopenharmony_ci		self.configGen	= configGen
102e5c31af7Sopenharmony_ci		self.generator	= generator
103e5c31af7Sopenharmony_ci
104e5c31af7Sopenharmony_ci	def getName (self):
105e5c31af7Sopenharmony_ci		return self.buildDir
106e5c31af7Sopenharmony_ci
107e5c31af7Sopenharmony_ci	def isAvailable (self, env):
108e5c31af7Sopenharmony_ci		return self.configGen.isAvailable(env) and self.generator != None and self.generator.isAvailable()
109e5c31af7Sopenharmony_ci
110e5c31af7Sopenharmony_ci	def run (self, env):
111e5c31af7Sopenharmony_ci		# specialize config for env
112e5c31af7Sopenharmony_ci		buildDir	= os.path.join(env.tmpDir, self.buildDir)
113e5c31af7Sopenharmony_ci		curConfig	= self.configGen.getBuildConfig(env, buildDir)
114e5c31af7Sopenharmony_ci
115e5c31af7Sopenharmony_ci		build(curConfig, self.generator)
116e5c31af7Sopenharmony_ci
117e5c31af7Sopenharmony_ciclass CheckSrcChanges(BuildTestStep):
118e5c31af7Sopenharmony_ci	def getName (self):
119e5c31af7Sopenharmony_ci		return "check for changes"
120e5c31af7Sopenharmony_ci
121e5c31af7Sopenharmony_ci	def run (self, env):
122e5c31af7Sopenharmony_ci		pushWorkingDir(env.srcDir)
123e5c31af7Sopenharmony_ci		execute(["git", "diff", "--exit-code"])
124e5c31af7Sopenharmony_ci		popWorkingDir()
125e5c31af7Sopenharmony_ci
126e5c31af7Sopenharmony_cidef getClangVersion ():
127e5c31af7Sopenharmony_ci	knownVersions = ["4.0", "3.9", "3.8", "3.7", "3.6", "3.5"]
128e5c31af7Sopenharmony_ci	for version in knownVersions:
129e5c31af7Sopenharmony_ci		if which("clang-" + version) != None:
130e5c31af7Sopenharmony_ci			return "-" + version
131e5c31af7Sopenharmony_ci	return ""
132e5c31af7Sopenharmony_ci
133e5c31af7Sopenharmony_cidef runSteps (steps):
134e5c31af7Sopenharmony_ci	for step in steps:
135e5c31af7Sopenharmony_ci		if step.isAvailable(env):
136e5c31af7Sopenharmony_ci			print("Run: %s" % step.getName())
137e5c31af7Sopenharmony_ci			step.run(env)
138e5c31af7Sopenharmony_ci		else:
139e5c31af7Sopenharmony_ci			print("Skip: %s" % step.getName())
140e5c31af7Sopenharmony_ci
141e5c31af7Sopenharmony_ciCOMMON_CFLAGS		= ["-Werror", "-Wno-error=unused-function"]
142e5c31af7Sopenharmony_ciCOMMON_GCC_CFLAGS	= COMMON_CFLAGS + ["-Wno-error=array-bounds"]
143e5c31af7Sopenharmony_ciCOMMON_CLANG_CFLAGS	= COMMON_CFLAGS + ["-Wno-error=unused-command-line-argument"]
144e5c31af7Sopenharmony_ciGCC_32BIT_CFLAGS	= COMMON_GCC_CFLAGS + ["-m32"]
145e5c31af7Sopenharmony_ciCLANG_32BIT_CFLAGS	= COMMON_CLANG_CFLAGS + ["-m32"]
146e5c31af7Sopenharmony_ciGCC_64BIT_CFLAGS	= COMMON_GCC_CFLAGS + ["-m64"]
147e5c31af7Sopenharmony_ciCLANG_64BIT_CFLAGS	= COMMON_CLANG_CFLAGS + ["-m64"]
148e5c31af7Sopenharmony_ciCLANG_VERSION		= getClangVersion()
149e5c31af7Sopenharmony_ci
150e5c31af7Sopenharmony_ci# Always ran before any receipe
151e5c31af7Sopenharmony_ciPREREQUISITES		= [
152e5c31af7Sopenharmony_ci	RunScript(os.path.join("external", "fetch_sources.py"), lambda env: ["--force"])
153e5c31af7Sopenharmony_ci]
154e5c31af7Sopenharmony_ci
155e5c31af7Sopenharmony_ci# Always ran after any receipe
156e5c31af7Sopenharmony_ciPOST_CHECKS			= [
157e5c31af7Sopenharmony_ci	CheckSrcChanges()
158e5c31af7Sopenharmony_ci]
159e5c31af7Sopenharmony_ci
160e5c31af7Sopenharmony_ciBUILD_TARGETS		= [
161e5c31af7Sopenharmony_ci	Build("clang-64-debug",
162e5c31af7Sopenharmony_ci		  UnixConfig("null",
163e5c31af7Sopenharmony_ci					 "Debug",
164e5c31af7Sopenharmony_ci					 "clang" + CLANG_VERSION,
165e5c31af7Sopenharmony_ci					 "clang++" + CLANG_VERSION,
166e5c31af7Sopenharmony_ci					 CLANG_64BIT_CFLAGS),
167e5c31af7Sopenharmony_ci		  ANY_UNIX_GENERATOR),
168e5c31af7Sopenharmony_ci	Build("gcc-32-debug",
169e5c31af7Sopenharmony_ci		  UnixConfig("null",
170e5c31af7Sopenharmony_ci					 "Debug",
171e5c31af7Sopenharmony_ci					 "gcc",
172e5c31af7Sopenharmony_ci					 "g++",
173e5c31af7Sopenharmony_ci					 GCC_32BIT_CFLAGS),
174e5c31af7Sopenharmony_ci		  ANY_UNIX_GENERATOR),
175e5c31af7Sopenharmony_ci	Build("gcc-64-release",
176e5c31af7Sopenharmony_ci		  UnixConfig("null",
177e5c31af7Sopenharmony_ci					 "Release",
178e5c31af7Sopenharmony_ci					 "gcc",
179e5c31af7Sopenharmony_ci					 "g++",
180e5c31af7Sopenharmony_ci					 GCC_64BIT_CFLAGS),
181e5c31af7Sopenharmony_ci		  ANY_UNIX_GENERATOR),
182e5c31af7Sopenharmony_ci	Build("vs-64-debug",
183e5c31af7Sopenharmony_ci		  VSConfig("Debug"),
184e5c31af7Sopenharmony_ci		  ANY_VS_X64_GENERATOR),
185e5c31af7Sopenharmony_ci]
186e5c31af7Sopenharmony_ci
187e5c31af7Sopenharmony_ciEARLY_SPECIAL_RECIPES	= [
188e5c31af7Sopenharmony_ci	('gen-inl-files', [
189e5c31af7Sopenharmony_ci			RunScript(os.path.join("scripts", "gen_egl.py")),
190e5c31af7Sopenharmony_ci			RunScript(os.path.join("scripts", "opengl", "gen_all.py")),
191e5c31af7Sopenharmony_ci			RunScript(os.path.join("external", "vulkancts", "scripts", "gen_framework.py")),
192e5c31af7Sopenharmony_ci			RunScript(os.path.join("external", "vulkancts", "scripts", "gen_framework_c.py")),
193e5c31af7Sopenharmony_ci			RunScript(os.path.join("external", "vulkancts", "scripts", "gen_framework.py"), lambda env: ["--api", "SC"] ),
194e5c31af7Sopenharmony_ci			RunScript(os.path.join("external", "vulkancts", "scripts", "gen_framework_c.py"), lambda env: ["--api", "SC"] ),
195e5c31af7Sopenharmony_ci			RunScript(os.path.join("scripts", "gen_android_bp.py"))
196e5c31af7Sopenharmony_ci		]),
197e5c31af7Sopenharmony_ci]
198e5c31af7Sopenharmony_ci
199e5c31af7Sopenharmony_ciLATE_SPECIAL_RECIPES	= [
200e5c31af7Sopenharmony_ci	('android-mustpass', [
201e5c31af7Sopenharmony_ci			RunScript(os.path.join("scripts", "build_android_mustpass.py"),
202e5c31af7Sopenharmony_ci					  lambda env: ["--build-dir", os.path.join(env.tmpDir, "android-mustpass")]),
203e5c31af7Sopenharmony_ci		]),
204e5c31af7Sopenharmony_ci	('vulkan-mustpass', [
205e5c31af7Sopenharmony_ci			RunScript(os.path.join("external", "vulkancts", "scripts", "build_mustpass.py"),
206e5c31af7Sopenharmony_ci					  lambda env: ["--build-dir", os.path.join(env.tmpDir, "vulkan-mustpass")]),
207e5c31af7Sopenharmony_ci		]),
208e5c31af7Sopenharmony_ci	('spirv-binaries', [
209e5c31af7Sopenharmony_ci			RunScript(os.path.join("external", "vulkancts", "scripts", "build_spirv_binaries.py"),
210e5c31af7Sopenharmony_ci					  lambda env: ["--build-type", "Release",
211e5c31af7Sopenharmony_ci									"--build-dir", os.path.join(env.tmpDir, "spirv-binaries"),
212e5c31af7Sopenharmony_ci									"--dst-path", os.path.join(env.tmpDir, "spirv-binaries")]),
213e5c31af7Sopenharmony_ci		]),
214e5c31af7Sopenharmony_ci	('amber-verify', [
215e5c31af7Sopenharmony_ci			RunScript(os.path.join("external", "vulkancts", "scripts", "amber_verify.py"),
216e5c31af7Sopenharmony_ci					  lambda env: ["--build-type", "Release",
217e5c31af7Sopenharmony_ci									"--build-dir", os.path.join(env.tmpDir, "amber-verify"),
218e5c31af7Sopenharmony_ci									"--dst-path", os.path.join(env.tmpDir, "amber-verify")]),
219e5c31af7Sopenharmony_ci		]),
220e5c31af7Sopenharmony_ci	('check-all', [
221e5c31af7Sopenharmony_ci			RunScript(os.path.join("scripts", "src_util", "check_all.py")),
222e5c31af7Sopenharmony_ci		])
223e5c31af7Sopenharmony_ci]
224e5c31af7Sopenharmony_ci
225e5c31af7Sopenharmony_cidef getBuildRecipes ():
226e5c31af7Sopenharmony_ci	return [(b.getName(), [b]) for b in BUILD_TARGETS]
227e5c31af7Sopenharmony_ci
228e5c31af7Sopenharmony_cidef getAllRecipe (recipes):
229e5c31af7Sopenharmony_ci	allSteps = []
230e5c31af7Sopenharmony_ci	for name, steps in recipes:
231e5c31af7Sopenharmony_ci		allSteps += steps
232e5c31af7Sopenharmony_ci	return ("all", allSteps)
233e5c31af7Sopenharmony_ci
234e5c31af7Sopenharmony_cidef getRecipes ():
235e5c31af7Sopenharmony_ci	recipes = EARLY_SPECIAL_RECIPES + getBuildRecipes() + LATE_SPECIAL_RECIPES
236e5c31af7Sopenharmony_ci	return recipes
237e5c31af7Sopenharmony_ci
238e5c31af7Sopenharmony_cidef getRecipe (recipes, recipeName):
239e5c31af7Sopenharmony_ci	for curName, steps in recipes:
240e5c31af7Sopenharmony_ci		if curName == recipeName:
241e5c31af7Sopenharmony_ci			return (curName, steps)
242e5c31af7Sopenharmony_ci	return None
243e5c31af7Sopenharmony_ci
244e5c31af7Sopenharmony_ciRECIPES			= getRecipes()
245e5c31af7Sopenharmony_ci
246e5c31af7Sopenharmony_cidef parseArgs ():
247e5c31af7Sopenharmony_ci	parser = argparse.ArgumentParser(description = "Build and test source",
248e5c31af7Sopenharmony_ci									 formatter_class=argparse.ArgumentDefaultsHelpFormatter)
249e5c31af7Sopenharmony_ci	parser.add_argument("-s",
250e5c31af7Sopenharmony_ci						"--src-dir",
251e5c31af7Sopenharmony_ci						dest="srcDir",
252e5c31af7Sopenharmony_ci						default=DEQP_DIR,
253e5c31af7Sopenharmony_ci						help="Source directory")
254e5c31af7Sopenharmony_ci	parser.add_argument("-t",
255e5c31af7Sopenharmony_ci						"--tmp-dir",
256e5c31af7Sopenharmony_ci						dest="tmpDir",
257e5c31af7Sopenharmony_ci						default=os.path.join(tempfile.gettempdir(), "deqp-build-test"),
258e5c31af7Sopenharmony_ci						help="Temporary directory")
259e5c31af7Sopenharmony_ci	parser.add_argument("-r",
260e5c31af7Sopenharmony_ci						"--recipe",
261e5c31af7Sopenharmony_ci						dest="recipe",
262e5c31af7Sopenharmony_ci						choices=[n for n, s in RECIPES] + ["all"],
263e5c31af7Sopenharmony_ci						default="all",
264e5c31af7Sopenharmony_ci						help="Build / test recipe")
265e5c31af7Sopenharmony_ci	parser.add_argument("-d",
266e5c31af7Sopenharmony_ci						"--dump-recipes",
267e5c31af7Sopenharmony_ci						dest="dumpRecipes",
268e5c31af7Sopenharmony_ci						action="store_true",
269e5c31af7Sopenharmony_ci						help="Print out recipes that have any available actions")
270e5c31af7Sopenharmony_ci	parser.add_argument("--skip-prerequisites",
271e5c31af7Sopenharmony_ci						dest="skipPrerequisites",
272e5c31af7Sopenharmony_ci						action="store_true",
273e5c31af7Sopenharmony_ci						help="Skip external dependency fetch")
274e5c31af7Sopenharmony_ci	parser.add_argument("--skip-post-checks",
275e5c31af7Sopenharmony_ci						dest="skipPostCheck",
276e5c31af7Sopenharmony_ci						action="store_true",
277e5c31af7Sopenharmony_ci						help="Skip post recipe checks")
278e5c31af7Sopenharmony_ci
279e5c31af7Sopenharmony_ci	return parser.parse_args()
280e5c31af7Sopenharmony_ci
281e5c31af7Sopenharmony_ciif __name__ == "__main__":
282e5c31af7Sopenharmony_ci	args	= parseArgs()
283e5c31af7Sopenharmony_ci	env		= Environment(args.srcDir, args.tmpDir)
284e5c31af7Sopenharmony_ci
285e5c31af7Sopenharmony_ci	if args.dumpRecipes:
286e5c31af7Sopenharmony_ci		for name, steps in RECIPES:
287e5c31af7Sopenharmony_ci			for step in steps:
288e5c31af7Sopenharmony_ci				if step.isAvailable(env):
289e5c31af7Sopenharmony_ci					print(name)
290e5c31af7Sopenharmony_ci					break
291e5c31af7Sopenharmony_ci	else:
292e5c31af7Sopenharmony_ci		name, steps	= getAllRecipe(RECIPES) if args.recipe == "all" \
293e5c31af7Sopenharmony_ci					  else getRecipe(RECIPES, args.recipe)
294e5c31af7Sopenharmony_ci
295e5c31af7Sopenharmony_ci		print("Running %s" % name)
296e5c31af7Sopenharmony_ci
297e5c31af7Sopenharmony_ci		allSteps = (PREREQUISITES if (args.skipPrerequisites == False) else []) + steps + (POST_CHECKS if (args.skipPostCheck == False) else [])
298e5c31af7Sopenharmony_ci		runSteps(allSteps)
299e5c31af7Sopenharmony_ci
300e5c31af7Sopenharmony_ci		print("All steps completed successfully")
301