• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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				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
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)
217VS2022_X32_GENERATOR	= VSProjectGenerator(17, VSProjectGenerator.ARCH_32BIT)
218VS2022_X64_GENERATOR	= VSProjectGenerator(17, VSProjectGenerator.ARCH_64BIT)
219
220def selectFirstAvailableGenerator (generators):
221	for generator in generators:
222		if generator.isAvailable():
223			return generator
224	return None
225
226ANY_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							])
235ANY_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							])
244ANY_UNIX_GENERATOR		= selectFirstAvailableGenerator([
245								NINJA_GENERATOR,
246								MAKEFILE_GENERATOR,
247								NMAKE_GENERATOR,
248							])
249ANY_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							])
268