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