Rename CTS "build" Python module to "ctsbuild"
[platform/upstream/VK-GL-CTS.git] / scripts / ctsbuild / config.py
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
23 import os
24 import sys
25 import copy
26 import multiprocessing
27
28 from . common import which, HostInfo, DEQP_DIR
29
30 try:
31         if sys.version_info < (3, 0):
32                 import _winreg
33         else:
34                 import winreg
35                 _winreg = winreg
36 except:
37         _winreg = None
38
39 class 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
74 class 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
105 class 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
112 class NMakeGenerator(CMakeGenerator):
113         def __init__(self):
114                 CMakeGenerator.__init__(self, "NMake Makefiles")
115
116         def isAvailable (self):
117                 return which('nmake') != None
118
119 class NinjaGenerator(CMakeGenerator):
120         def __init__(self):
121                 CMakeGenerator.__init__(self, "Ninja")
122
123         def isAvailable (self):
124                 return which('ninja') != None
125
126 class 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                                 17:             [(_winreg.HKEY_CLASSES_ROOT, "VisualStudio.DTE.17.0"), (_winreg.HKEY_LOCAL_MACHINE, "Software\\Microsoft\\VCExpress\\17.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
202 MAKEFILE_GENERATOR              = UnixMakefileGenerator()
203 NMAKE_GENERATOR                 = NMakeGenerator()
204 NINJA_GENERATOR                 = NinjaGenerator()
205 VS2010_X32_GENERATOR    = VSProjectGenerator(10, VSProjectGenerator.ARCH_32BIT)
206 VS2010_X64_GENERATOR    = VSProjectGenerator(10, VSProjectGenerator.ARCH_64BIT)
207 VS2012_X32_GENERATOR    = VSProjectGenerator(11, VSProjectGenerator.ARCH_32BIT)
208 VS2012_X64_GENERATOR    = VSProjectGenerator(11, VSProjectGenerator.ARCH_64BIT)
209 VS2013_X32_GENERATOR    = VSProjectGenerator(12, VSProjectGenerator.ARCH_32BIT)
210 VS2013_X64_GENERATOR    = VSProjectGenerator(12, VSProjectGenerator.ARCH_64BIT)
211 VS2015_X32_GENERATOR    = VSProjectGenerator(14, VSProjectGenerator.ARCH_32BIT)
212 VS2015_X64_GENERATOR    = VSProjectGenerator(14, VSProjectGenerator.ARCH_64BIT)
213 VS2017_X32_GENERATOR    = VSProjectGenerator(15, VSProjectGenerator.ARCH_32BIT)
214 VS2017_X64_GENERATOR    = VSProjectGenerator(15, VSProjectGenerator.ARCH_64BIT)
215 VS2019_X32_GENERATOR    = VSProjectGenerator(16, VSProjectGenerator.ARCH_32BIT)
216 VS2019_X64_GENERATOR    = VSProjectGenerator(16, VSProjectGenerator.ARCH_64BIT)
217 VS2022_X32_GENERATOR    = VSProjectGenerator(17, VSProjectGenerator.ARCH_32BIT)
218 VS2022_X64_GENERATOR    = VSProjectGenerator(17, VSProjectGenerator.ARCH_64BIT)
219
220 def selectFirstAvailableGenerator (generators):
221         for generator in generators:
222                 if generator.isAvailable():
223                         return generator
224         return None
225
226 ANY_VS_X32_GENERATOR    = selectFirstAvailableGenerator([
227                                                                 VS2022_X32_GENERATOR,
228                                                                 VS2019_X32_GENERATOR,
229                                                                 VS2017_X32_GENERATOR,
230                                                                 VS2015_X32_GENERATOR,
231                                                                 VS2013_X32_GENERATOR,
232                                                                 VS2012_X32_GENERATOR,
233                                                                 VS2010_X32_GENERATOR,
234                                                         ])
235 ANY_VS_X64_GENERATOR    = selectFirstAvailableGenerator([
236                                                                 VS2022_X64_GENERATOR,
237                                                                 VS2019_X64_GENERATOR,
238                                                                 VS2017_X64_GENERATOR,
239                                                                 VS2015_X64_GENERATOR,
240                                                                 VS2013_X64_GENERATOR,
241                                                                 VS2012_X64_GENERATOR,
242                                                                 VS2010_X64_GENERATOR,
243                                                         ])
244 ANY_UNIX_GENERATOR              = selectFirstAvailableGenerator([
245                                                                 NINJA_GENERATOR,
246                                                                 MAKEFILE_GENERATOR,
247                                                                 NMAKE_GENERATOR,
248                                                         ])
249 ANY_GENERATOR                   = selectFirstAvailableGenerator([
250                                                                 VS2022_X64_GENERATOR,
251                                                                 VS2022_X32_GENERATOR,
252                                                                 VS2019_X64_GENERATOR,
253                                                                 VS2019_X32_GENERATOR,
254                                                                 VS2017_X64_GENERATOR,
255                                                                 VS2017_X32_GENERATOR,
256                                                                 VS2015_X64_GENERATOR,
257                                                                 VS2015_X32_GENERATOR,
258                                                                 VS2013_X64_GENERATOR,
259                                                                 VS2012_X64_GENERATOR,
260                                                                 VS2010_X64_GENERATOR,
261                                                                 VS2013_X32_GENERATOR,
262                                                                 VS2012_X32_GENERATOR,
263                                                                 VS2010_X32_GENERATOR,
264                                                                 NINJA_GENERATOR,
265                                                                 MAKEFILE_GENERATOR,
266                                                                 NMAKE_GENERATOR,
267                                                         ])