1# -*- coding: utf-8 -*- 2 3#------------------------------------------------------------------------- 4# drawElements Quality Program utilities 5# -------------------------------------- 6# 7# Copyright 2015 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 sys 25import copy 26import multiprocessing 27 28from common import which, HostInfo, DEQP_DIR 29 30try: 31 import _winreg 32except: 33 _winreg = None 34 35class BuildConfig: 36 def __init__ (self, buildDir, buildType, args, srcPath = DEQP_DIR): 37 self.srcPath = srcPath 38 self.buildDir = buildDir 39 self.buildType = buildType 40 self.args = copy.copy(args) 41 self.cmakePath = BuildConfig.findCMake() 42 43 def getSrcPath (self): 44 return self.srcPath 45 46 def getBuildDir (self): 47 return self.buildDir 48 49 def getBuildType (self): 50 return self.buildType 51 52 def getArgs (self): 53 return self.args 54 55 def getCMakePath (self): 56 return self.cmakePath 57 58 @staticmethod 59 def findCMake (): 60 if which("cmake") == None: 61 possiblePaths = [ 62 "/Applications/CMake.app/Contents/bin/cmake" 63 ] 64 for path in possiblePaths: 65 if os.path.exists(path): 66 return path 67 68 # Fall back to PATH - may fail later 69 return "cmake" 70 71class CMakeGenerator: 72 def __init__ (self, name, isMultiConfig = False, extraBuildArgs = []): 73 self.name = name 74 self.isMultiConfig = isMultiConfig 75 self.extraBuildArgs = copy.copy(extraBuildArgs) 76 77 def getName (self): 78 return self.name 79 80 def getGenerateArgs (self, buildType): 81 args = ['-G', self.name] 82 if not self.isMultiConfig: 83 args.append('-DCMAKE_BUILD_TYPE=%s' % buildType) 84 return args 85 86 def getBuildArgs (self, buildType): 87 args = [] 88 if self.isMultiConfig: 89 args += ['--config', buildType] 90 if len(self.extraBuildArgs) > 0: 91 args += ['--'] + self.extraBuildArgs 92 return args 93 94 def getBinaryPath (self, buildType, basePath): 95 return basePath 96 97class UnixMakefileGenerator(CMakeGenerator): 98 def __init__(self): 99 CMakeGenerator.__init__(self, "Unix Makefiles", extraBuildArgs = ["-j%d" % multiprocessing.cpu_count()]) 100 101 def isAvailable (self): 102 return which('make') != None 103 104class NMakeGenerator(CMakeGenerator): 105 def __init__(self): 106 CMakeGenerator.__init__(self, "NMake Makefiles") 107 108 def isAvailable (self): 109 return which('nmake') != None 110 111class NinjaGenerator(CMakeGenerator): 112 def __init__(self): 113 CMakeGenerator.__init__(self, "Ninja") 114 115 def isAvailable (self): 116 return which('ninja') != None 117 118class VSProjectGenerator(CMakeGenerator): 119 ARCH_32BIT = 0 120 ARCH_64BIT = 1 121 122 def __init__(self, version, arch): 123 name = "Visual Studio %d" % version 124 if arch == self.ARCH_64BIT: 125 name += " Win64" 126 127 CMakeGenerator.__init__(self, name, isMultiConfig = True, extraBuildArgs = ['/m']) 128 self.version = version 129 self.arch = arch 130 131 def getBinaryPath (self, buildType, basePath): 132 return os.path.join(os.path.dirname(basePath), buildType, os.path.basename(basePath) + ".exe") 133 134 @staticmethod 135 def getNativeArch (): 136 bits = HostInfo.getArchBits() 137 138 if bits == 32: 139 return VSProjectGenerator.ARCH_32BIT 140 elif bits == 64: 141 return VSProjectGenerator.ARCH_64BIT 142 else: 143 raise Exception("Unhandled bits '%s'" % bits) 144 145 @staticmethod 146 def registryKeyAvailable (root, arch, name): 147 try: 148 key = _winreg.OpenKey(root, name, 0, _winreg.KEY_READ | arch) 149 _winreg.CloseKey(key) 150 return True 151 except: 152 return False 153 154 def isAvailable (self): 155 if sys.platform == 'win32' and _winreg != None: 156 nativeArch = VSProjectGenerator.getNativeArch() 157 if nativeArch == self.ARCH_32BIT and self.arch == self.ARCH_64BIT: 158 return False 159 160 arch = _winreg.KEY_WOW64_32KEY if nativeArch == self.ARCH_64BIT else 0 161 keyMap = { 162 10: [(_winreg.HKEY_CLASSES_ROOT, "VisualStudio.DTE.10.0"), (_winreg.HKEY_LOCAL_MACHINE, "Software\\Microsoft\\VCExpress\\10.0")], 163 11: [(_winreg.HKEY_CLASSES_ROOT, "VisualStudio.DTE.11.0"), (_winreg.HKEY_LOCAL_MACHINE, "Software\\Microsoft\\VCExpress\\11.0")], 164 12: [(_winreg.HKEY_CLASSES_ROOT, "VisualStudio.DTE.12.0"), (_winreg.HKEY_LOCAL_MACHINE, "Software\\Microsoft\\VCExpress\\12.0")], 165 14: [(_winreg.HKEY_CLASSES_ROOT, "VisualStudio.DTE.14.0"), (_winreg.HKEY_LOCAL_MACHINE, "Software\\Microsoft\\VCExpress\\14.0")], 166 15: [(_winreg.HKEY_CLASSES_ROOT, "VisualStudio.DTE.15.0"), (_winreg.HKEY_LOCAL_MACHINE, "Software\\Microsoft\\VCExpress\\15.0")] 167 } 168 169 if not self.version in keyMap: 170 raise Exception("Unsupported VS version %d" % self.version) 171 172 keys = keyMap[self.version] 173 for root, name in keys: 174 if VSProjectGenerator.registryKeyAvailable(root, arch, name): 175 return True 176 return False 177 else: 178 return False 179 180# Pre-defined generators 181 182MAKEFILE_GENERATOR = UnixMakefileGenerator() 183NMAKE_GENERATOR = NMakeGenerator() 184NINJA_GENERATOR = NinjaGenerator() 185VS2010_X32_GENERATOR = VSProjectGenerator(10, VSProjectGenerator.ARCH_32BIT) 186VS2010_X64_GENERATOR = VSProjectGenerator(10, VSProjectGenerator.ARCH_64BIT) 187VS2012_X32_GENERATOR = VSProjectGenerator(11, VSProjectGenerator.ARCH_32BIT) 188VS2012_X64_GENERATOR = VSProjectGenerator(11, VSProjectGenerator.ARCH_64BIT) 189VS2013_X32_GENERATOR = VSProjectGenerator(12, VSProjectGenerator.ARCH_32BIT) 190VS2013_X64_GENERATOR = VSProjectGenerator(12, VSProjectGenerator.ARCH_64BIT) 191VS2015_X32_GENERATOR = VSProjectGenerator(14, VSProjectGenerator.ARCH_32BIT) 192VS2015_X64_GENERATOR = VSProjectGenerator(14, VSProjectGenerator.ARCH_64BIT) 193VS2017_X32_GENERATOR = VSProjectGenerator(15, VSProjectGenerator.ARCH_32BIT) 194VS2017_X64_GENERATOR = VSProjectGenerator(15, VSProjectGenerator.ARCH_64BIT) 195 196def selectFirstAvailableGenerator (generators): 197 for generator in generators: 198 if generator.isAvailable(): 199 return generator 200 return None 201 202ANY_VS_X32_GENERATOR = selectFirstAvailableGenerator([ 203 VS2017_X32_GENERATOR, 204 VS2015_X32_GENERATOR, 205 VS2013_X32_GENERATOR, 206 VS2012_X32_GENERATOR, 207 VS2010_X32_GENERATOR, 208 ]) 209ANY_VS_X64_GENERATOR = selectFirstAvailableGenerator([ 210 VS2017_X64_GENERATOR, 211 VS2015_X64_GENERATOR, 212 VS2013_X64_GENERATOR, 213 VS2012_X64_GENERATOR, 214 VS2010_X64_GENERATOR, 215 ]) 216ANY_UNIX_GENERATOR = selectFirstAvailableGenerator([ 217 NINJA_GENERATOR, 218 MAKEFILE_GENERATOR, 219 NMAKE_GENERATOR, 220 ]) 221ANY_GENERATOR = selectFirstAvailableGenerator([ 222 VS2017_X64_GENERATOR, 223 VS2017_X32_GENERATOR, 224 VS2015_X64_GENERATOR, 225 VS2015_X32_GENERATOR, 226 VS2013_X64_GENERATOR, 227 VS2012_X64_GENERATOR, 228 VS2010_X64_GENERATOR, 229 VS2013_X32_GENERATOR, 230 VS2012_X32_GENERATOR, 231 VS2010_X32_GENERATOR, 232 NINJA_GENERATOR, 233 MAKEFILE_GENERATOR, 234 NMAKE_GENERATOR, 235 ]) 236