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