1 # -*- coding: utf-8 -*-
3 #-------------------------------------------------------------------------
4 # drawElements Quality Program utilities
5 # --------------------------------------
7 # Copyright 2016 The Android Open Source Project
9 # Licensed under the Apache License, Version 2.0 (the "License");
10 # you may not use this file except in compliance with the License.
11 # You may obtain a copy of the License at
13 # http://www.apache.org/licenses/LICENSE-2.0
15 # Unless required by applicable law or agreed to in writing, software
16 # distributed under the License is distributed on an "AS IS" BASIS,
17 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18 # See the License for the specific language governing permissions and
19 # limitations under the License.
21 #-------------------------------------------------------------------------
28 from ctsbuild.common import *
29 from ctsbuild.build import *
31 pythonExecutable = sys.executable or "python"
34 def __init__ (self, srcDir, tmpDir):
42 def isAvailable (self, env):
46 raise Exception("Not implemented")
48 class RunScript(BuildTestStep):
49 def __init__ (self, scriptPath, getExtraArgs = None):
50 self.scriptPath = scriptPath
51 self.getExtraArgs = getExtraArgs
54 return self.scriptPath
57 args = [pythonExecutable, os.path.join(env.srcDir, self.scriptPath)]
59 if self.getExtraArgs != None:
60 args += self.getExtraArgs(env)
64 def makeCflagsArgs (cflags):
65 cflagsStr = " ".join(cflags)
66 return ["-DCMAKE_C_FLAGS=%s" % cflagsStr, "-DCMAKE_CXX_FLAGS=%s" % cflagsStr]
68 def makeBuildArgs (target, cc, cpp, cflags):
69 return ["-DDEQP_TARGET=%s" % target, "-DCMAKE_C_COMPILER=%s" % cc, "-DCMAKE_CXX_COMPILER=%s" % cpp] + makeCflagsArgs(cflags)
72 def isAvailable (self, env):
75 class UnixConfig(BuildConfigGen):
76 def __init__ (self, target, buildType, cc, cpp, cflags):
78 self.buildType = buildType
83 def isAvailable (self, env):
84 return which(self.cc) != None and which(self.cpp) != None
86 def getBuildConfig (self, env, buildDir):
87 args = makeBuildArgs(self.target, self.cc, self.cpp, self.cflags)
88 return BuildConfig(buildDir, self.buildType, args, env.srcDir)
90 class VSConfig(BuildConfigGen):
91 def __init__ (self, buildType):
92 self.buildType = buildType
94 def getBuildConfig (self, env, buildDir):
95 args = ["-DCMAKE_C_FLAGS=/WX -DCMAKE_CXX_FLAGS=/WX"]
96 return BuildConfig(buildDir, self.buildType, args, env.srcDir)
98 class Build(BuildTestStep):
99 def __init__ (self, buildDir, configGen, generator):
100 self.buildDir = buildDir
101 self.configGen = configGen
102 self.generator = generator
107 def isAvailable (self, env):
108 return self.configGen.isAvailable(env) and self.generator != None and self.generator.isAvailable()
111 # specialize config for env
112 buildDir = os.path.join(env.tmpDir, self.buildDir)
113 curConfig = self.configGen.getBuildConfig(env, buildDir)
115 build(curConfig, self.generator)
117 class CheckSrcChanges(BuildTestStep):
119 return "check for changes"
122 pushWorkingDir(env.srcDir)
123 execute(["git", "diff", "--exit-code"])
126 def getClangVersion ():
127 knownVersions = ["4.0", "3.9", "3.8", "3.7", "3.6", "3.5"]
128 for version in knownVersions:
129 if which("clang-" + version) != None:
133 def runSteps (steps):
135 if step.isAvailable(env):
136 print("Run: %s" % step.getName())
139 print("Skip: %s" % step.getName())
141 COMMON_CFLAGS = ["-Werror", "-Wno-error=unused-function"]
142 COMMON_GCC_CFLAGS = COMMON_CFLAGS + ["-Wno-error=array-bounds"]
143 COMMON_CLANG_CFLAGS = COMMON_CFLAGS + ["-Wno-error=unused-command-line-argument"]
144 GCC_32BIT_CFLAGS = COMMON_GCC_CFLAGS + ["-m32"]
145 CLANG_32BIT_CFLAGS = COMMON_CLANG_CFLAGS + ["-m32"]
146 GCC_64BIT_CFLAGS = COMMON_GCC_CFLAGS + ["-m64"]
147 CLANG_64BIT_CFLAGS = COMMON_CLANG_CFLAGS + ["-m64"]
148 CLANG_VERSION = getClangVersion()
150 # Always ran before any receipe
152 RunScript(os.path.join("external", "fetch_sources.py"), lambda env: ["--force"])
155 # Always ran after any receipe
161 Build("clang-64-debug",
164 "clang" + CLANG_VERSION,
165 "clang++" + CLANG_VERSION,
168 Build("gcc-32-debug",
175 Build("gcc-64-release",
184 ANY_VS_X64_GENERATOR),
187 EARLY_SPECIAL_RECIPES = [
189 RunScript(os.path.join("scripts", "gen_egl.py")),
190 RunScript(os.path.join("scripts", "opengl", "gen_all.py")),
191 RunScript(os.path.join("external", "vulkancts", "scripts", "gen_framework.py")),
192 RunScript(os.path.join("external", "vulkancts", "scripts", "gen_framework_c.py")),
193 RunScript(os.path.join("external", "vulkancts", "scripts", "gen_framework.py"), lambda env: ["--api", "SC"] ),
194 RunScript(os.path.join("external", "vulkancts", "scripts", "gen_framework_c.py"), lambda env: ["--api", "SC"] ),
195 RunScript(os.path.join("scripts", "gen_android_mk.py"))
199 LATE_SPECIAL_RECIPES = [
200 ('android-mustpass', [
201 RunScript(os.path.join("scripts", "build_android_mustpass.py"),
202 lambda env: ["--build-dir", os.path.join(env.tmpDir, "android-mustpass")]),
204 ('vulkan-mustpass', [
205 RunScript(os.path.join("external", "vulkancts", "scripts", "build_mustpass.py"),
206 lambda env: ["--build-dir", os.path.join(env.tmpDir, "vulkan-mustpass")]),
209 RunScript(os.path.join("external", "vulkancts", "scripts", "build_spirv_binaries.py"),
210 lambda env: ["--build-type", "Release",
211 "--build-dir", os.path.join(env.tmpDir, "spirv-binaries"),
212 "--dst-path", os.path.join(env.tmpDir, "spirv-binaries")]),
215 RunScript(os.path.join("external", "vulkancts", "scripts", "amber_verify.py"),
216 lambda env: ["--build-type", "Release",
217 "--build-dir", os.path.join(env.tmpDir, "amber-verify"),
218 "--dst-path", os.path.join(env.tmpDir, "amber-verify")]),
221 RunScript(os.path.join("scripts", "src_util", "check_all.py")),
225 def getBuildRecipes ():
226 return [(b.getName(), [b]) for b in BUILD_TARGETS]
228 def getAllRecipe (recipes):
230 for name, steps in recipes:
232 return ("all", allSteps)
235 recipes = EARLY_SPECIAL_RECIPES + getBuildRecipes() + LATE_SPECIAL_RECIPES
238 def getRecipe (recipes, recipeName):
239 for curName, steps in recipes:
240 if curName == recipeName:
241 return (curName, steps)
244 RECIPES = getRecipes()
247 parser = argparse.ArgumentParser(description = "Build and test source",
248 formatter_class=argparse.ArgumentDefaultsHelpFormatter)
249 parser.add_argument("-s",
253 help="Source directory")
254 parser.add_argument("-t",
257 default=os.path.join(tempfile.gettempdir(), "deqp-build-test"),
258 help="Temporary directory")
259 parser.add_argument("-r",
262 choices=[n for n, s in RECIPES] + ["all"],
264 help="Build / test recipe")
265 parser.add_argument("-d",
269 help="Print out recipes that have any available actions")
270 parser.add_argument("--skip-prerequisites",
271 dest="skipPrerequisites",
273 help="Skip external dependency fetch")
275 return parser.parse_args()
277 if __name__ == "__main__":
279 env = Environment(args.srcDir, args.tmpDir)
282 for name, steps in RECIPES:
284 if step.isAvailable(env):
288 name, steps = getAllRecipe(RECIPES) if args.recipe == "all" \
289 else getRecipe(RECIPES, args.recipe)
291 print("Running %s" % name)
293 allSteps = (PREREQUISITES if (args.skipPrerequisites == False) else []) + steps + POST_CHECKS
296 print("All steps completed successfully")