1# -*- coding: utf-8 -*- 2 3#------------------------------------------------------------------------- 4# drawElements Quality Program utilities 5# -------------------------------------- 6# 7# Copyright 2016 The Android Open Source Project 8# 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 12# 13# http://www.apache.org/licenses/LICENSE-2.0 14# 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. 20# 21#------------------------------------------------------------------------- 22 23import os 24import argparse 25import tempfile 26 27from build.common import * 28from build.build import * 29 30class Environment: 31 def __init__ (self, srcDir, tmpDir): 32 self.srcDir = srcDir 33 self.tmpDir = tmpDir 34 35class BuildTestStep: 36 def getName (self): 37 return "<unknown>" 38 39 def isAvailable (self, env): 40 return True 41 42 def run (self, env): 43 raise Exception("Not implemented") 44 45class RunScript(BuildTestStep): 46 def __init__ (self, scriptPath, getExtraArgs = None): 47 self.scriptPath = scriptPath 48 self.getExtraArgs = getExtraArgs 49 50 def getName (self): 51 return self.scriptPath 52 53 def run (self, env): 54 args = ["python", os.path.join(env.srcDir, self.scriptPath)] 55 56 if self.getExtraArgs != None: 57 args += self.getExtraArgs(env) 58 59 execute(args) 60 61def makeCflagsArgs (cflags): 62 cflagsStr = " ".join(cflags) 63 return ["-DCMAKE_C_FLAGS=%s" % cflagsStr, "-DCMAKE_CXX_FLAGS=%s" % cflagsStr] 64 65def makeBuildArgs (target, cc, cpp, cflags): 66 return ["-DDEQP_TARGET=%s" % target, "-DCMAKE_C_COMPILER=%s" % cc, "-DCMAKE_CXX_COMPILER=%s" % cpp] + makeCflagsArgs(cflags) 67 68class BuildConfigGen: 69 def isAvailable (self, env): 70 return True 71 72class UnixConfig(BuildConfigGen): 73 def __init__ (self, target, buildType, cc, cpp, cflags): 74 self.target = target 75 self.buildType = buildType 76 self.cc = cc 77 self.cpp = cpp 78 self.cflags = cflags 79 80 def isAvailable (self, env): 81 return which(self.cc) != None and which(self.cpp) != None 82 83 def getBuildConfig (self, env, buildDir): 84 args = makeBuildArgs(self.target, self.cc, self.cpp, self.cflags) 85 return BuildConfig(buildDir, self.buildType, args, env.srcDir) 86 87class VSConfig(BuildConfigGen): 88 def __init__ (self, buildType): 89 self.buildType = buildType 90 91 def getBuildConfig (self, env, buildDir): 92 args = ["-DCMAKE_C_FLAGS=/WX -DCMAKE_CXX_FLAGS=/WX"] 93 return BuildConfig(buildDir, self.buildType, args, env.srcDir) 94 95class Build(BuildTestStep): 96 def __init__ (self, buildDir, configGen, generator): 97 self.buildDir = buildDir 98 self.configGen = configGen 99 self.generator = generator 100 101 def getName (self): 102 return self.buildDir 103 104 def isAvailable (self, env): 105 return self.configGen.isAvailable(env) and self.generator != None and self.generator.isAvailable() 106 107 def run (self, env): 108 # specialize config for env 109 buildDir = os.path.join(env.tmpDir, self.buildDir) 110 curConfig = self.configGen.getBuildConfig(env, buildDir) 111 112 build(curConfig, self.generator) 113 114class CheckSrcChanges(BuildTestStep): 115 def getName (self): 116 return "check for changes" 117 118 def run (self, env): 119 pushWorkingDir(env.srcDir) 120 execute(["git", "diff", "--exit-code"]) 121 popWorkingDir() 122 123def getClangVersion (): 124 knownVersions = ["4.0", "3.9", "3.8", "3.7", "3.6", "3.5"] 125 for version in knownVersions: 126 if which("clang-" + version) != None: 127 return "-" + version 128 return "" 129 130def runSteps (steps): 131 for step in steps: 132 if step.isAvailable(env): 133 print "Run: %s" % step.getName() 134 step.run(env) 135 else: 136 print "Skip: %s" % step.getName() 137 138COMMON_CFLAGS = ["-Werror", "-Wno-error=unused-function"] 139COMMON_GCC_CFLAGS = COMMON_CFLAGS + ["-Wno-implicit-fallthrough"] 140COMMON_CLANG_CFLAGS = COMMON_CFLAGS + ["-Wno-error=unused-command-line-argument"] 141GCC_32BIT_CFLAGS = COMMON_GCC_CFLAGS + ["-m32"] 142CLANG_32BIT_CFLAGS = COMMON_CLANG_CFLAGS + ["-m32"] 143GCC_64BIT_CFLAGS = COMMON_GCC_CFLAGS + ["-m64"] 144CLANG_64BIT_CFLAGS = COMMON_CLANG_CFLAGS + ["-m64"] 145CLANG_VERSION = getClangVersion() 146 147# Always ran before any receipe 148PREREQUISITES = [ 149 RunScript(os.path.join("external", "fetch_sources.py")) 150] 151 152# Always ran after any receipe 153POST_CHECKS = [ 154 CheckSrcChanges() 155] 156 157BUILD_TARGETS = [ 158 Build("clang-64-debug", 159 UnixConfig("null", 160 "Debug", 161 "clang" + CLANG_VERSION, 162 "clang++" + CLANG_VERSION, 163 CLANG_64BIT_CFLAGS), 164 ANY_UNIX_GENERATOR), 165 Build("gcc-32-debug", 166 UnixConfig("null", 167 "Debug", 168 "gcc", 169 "g++", 170 GCC_32BIT_CFLAGS), 171 ANY_UNIX_GENERATOR), 172 Build("gcc-64-release", 173 UnixConfig("null", 174 "Release", 175 "gcc", 176 "g++", 177 GCC_64BIT_CFLAGS), 178 ANY_UNIX_GENERATOR), 179 Build("vs-64-debug", 180 VSConfig("Debug"), 181 ANY_VS_X64_GENERATOR), 182] 183 184SPECIAL_RECIPES = [ 185 ('android-mustpass', [ 186 RunScript(os.path.join("scripts", "build_android_mustpass.py"), 187 lambda env: ["--build-dir", os.path.join(env.tmpDir, "android-mustpass")]), 188 ]), 189 ('vulkan-mustpass', [ 190 RunScript(os.path.join("external", "vulkancts", "scripts", "build_mustpass.py"), 191 lambda env: ["--build-dir", os.path.join(env.tmpDir, "vulkan-mustpass")]), 192 ]), 193 ('spirv-binaries', [ 194 RunScript(os.path.join("external", "vulkancts", "scripts", "build_spirv_binaries.py"), 195 lambda env: ["--build-dir", os.path.join(env.tmpDir, "spirv-binaries")]), 196 ]), 197 ('gen-inl-files', [ 198 RunScript(os.path.join("scripts", "gen_egl.py")), 199 RunScript(os.path.join("scripts", "opengl", "gen_all.py")), 200 RunScript(os.path.join("external", "vulkancts", "scripts", "gen_framework.py")), 201 RunScript(os.path.join("scripts", "gen_android_mk.py")), 202 RunScript(os.path.join("scripts", "src_util", "check_all.py")), 203 ]) 204] 205 206def getBuildRecipes (): 207 return [(b.getName(), [b]) for b in BUILD_TARGETS] 208 209def getAllRecipe (recipes): 210 allSteps = [] 211 for name, steps in recipes: 212 allSteps += steps 213 return ("all", allSteps) 214 215def getRecipes (): 216 recipes = getBuildRecipes() 217 recipes += SPECIAL_RECIPES 218 return recipes 219 220def getRecipe (recipes, recipeName): 221 for curName, steps in recipes: 222 if curName == recipeName: 223 return (curName, steps) 224 return None 225 226RECIPES = getRecipes() 227 228def parseArgs (): 229 parser = argparse.ArgumentParser(description = "Build and test source", 230 formatter_class=argparse.ArgumentDefaultsHelpFormatter) 231 parser.add_argument("-s", 232 "--src-dir", 233 dest="srcDir", 234 default=DEQP_DIR, 235 help="Source directory") 236 parser.add_argument("-t", 237 "--tmp-dir", 238 dest="tmpDir", 239 default=os.path.join(tempfile.gettempdir(), "deqp-build-test"), 240 help="Temporary directory") 241 parser.add_argument("-r", 242 "--recipe", 243 dest="recipe", 244 choices=[n for n, s in RECIPES] + ["all"], 245 default="all", 246 help="Build / test recipe") 247 parser.add_argument("-d", 248 "--dump-recipes", 249 dest="dumpRecipes", 250 action="store_true", 251 help="Print out recipes that have any available actions") 252 parser.add_argument("--skip-prerequisites", 253 dest="skipPrerequisites", 254 action="store_true", 255 help="Skip external dependency fetch") 256 257 return parser.parse_args() 258 259if __name__ == "__main__": 260 args = parseArgs() 261 env = Environment(args.srcDir, args.tmpDir) 262 263 if args.dumpRecipes: 264 for name, steps in RECIPES: 265 for step in steps: 266 if step.isAvailable(env): 267 print name 268 break 269 else: 270 name, steps = getAllRecipe(RECIPES) if args.recipe == "all" \ 271 else getRecipe(RECIPES, args.recipe) 272 273 print "Running %s" % name 274 275 allSteps = (PREREQUISITES if (args.skipPrerequisites == False) else []) + steps + POST_CHECKS 276 runSteps(allSteps) 277 278 print "All steps completed successfully" 279