• 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
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