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