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 platform
27import multiprocessing
28
29from common import which, DEQP_DIR
30
31try:
32	import _winreg
33except:
34	_winreg = None
35
36class BuildConfig:
37	def __init__ (self, buildDir, buildType, args, srcPath = DEQP_DIR):
38		self.srcPath		= srcPath
39		self.buildDir		= buildDir
40		self.buildType		= buildType
41		self.args			= copy.copy(args)
42
43	def getSrcPath (self):
44		return self.srcPath
45
46	def getBuildDir (self):
47		return self.buildDir
48
49	def getBuildType (self):
50		return self.buildType
51
52	def getArgs (self):
53		return self.args
54
55class CMakeGenerator:
56	def __init__ (self, name, isMultiConfig = False, extraBuildArgs = []):
57		self.name			= name
58		self.isMultiConfig	= isMultiConfig
59		self.extraBuildArgs	= copy.copy(extraBuildArgs)
60
61	def getName (self):
62		return self.name
63
64	def getGenerateArgs (self, buildType):
65		args = ['-G', self.name]
66		if not self.isMultiConfig:
67			args.append('-DCMAKE_BUILD_TYPE=%s' % buildType)
68		return args
69
70	def getBuildArgs (self, buildType):
71		args = []
72		if self.isMultiConfig:
73			args += ['--config', buildType]
74		if len(self.extraBuildArgs) > 0:
75			args += ['--'] + self.extraBuildArgs
76		return args
77
78	def getBinaryPath (self, buildType, basePath):
79		return basePath
80
81class UnixMakefileGenerator(CMakeGenerator):
82	def __init__(self):
83		CMakeGenerator.__init__(self, "Unix Makefiles", extraBuildArgs = ["-j%d" % multiprocessing.cpu_count()])
84
85	def isAvailable (self):
86		return which('make') != None
87
88class NinjaGenerator(CMakeGenerator):
89	def __init__(self):
90		CMakeGenerator.__init__(self, "Ninja")
91
92	def isAvailable (self):
93		return which('ninja') != None
94
95class VSProjectGenerator(CMakeGenerator):
96	ARCH_32BIT	= 0
97	ARCH_64BIT	= 1
98
99	def __init__(self, version, arch):
100		name = "Visual Studio %d" % version
101		if arch == self.ARCH_64BIT:
102			name += " Win64"
103
104		CMakeGenerator.__init__(self, name, isMultiConfig = True, extraBuildArgs = ['/m'])
105		self.version		= version
106		self.arch			= arch
107
108	def getBinaryPath (self, buildType, basePath):
109		return os.path.join(os.path.dirname(basePath), buildType, os.path.basename(basePath) + ".exe")
110
111	@staticmethod
112	def getNativeArch ():
113		arch = platform.machine().lower()
114
115		if arch == 'x86':
116			return VSProjectGenerator.ARCH_32BIT
117		elif arch == 'amd64':
118			return VSProjectGenerator.ARCH_64BIT
119		else:
120			raise Exception("Unhandled arch '%s'" % arch)
121
122	@staticmethod
123	def registryKeyAvailable (root, arch, name):
124		try:
125			key = _winreg.OpenKey(root, name, 0, _winreg.KEY_READ | arch)
126			_winreg.CloseKey(key)
127			return True
128		except:
129			return False
130
131	def isAvailable (self):
132		if sys.platform == 'win32' and _winreg != None:
133			nativeArch = VSProjectGenerator.getNativeArch()
134			if nativeArch == self.ARCH_32BIT and self.arch == self.ARCH_64BIT:
135				return False
136
137			arch = _winreg.KEY_WOW64_32KEY if nativeArch == self.ARCH_64BIT else 0
138			keyMap = {
139				10:		[(_winreg.HKEY_CLASSES_ROOT, "VisualStudio.DTE.10.0"), (_winreg.HKEY_LOCAL_MACHINE, "Software\\Microsoft\\VCExpress\\10.0")],
140				11:		[(_winreg.HKEY_CLASSES_ROOT, "VisualStudio.DTE.11.0"), (_winreg.HKEY_LOCAL_MACHINE, "Software\\Microsoft\\VCExpress\\11.0")],
141				12:		[(_winreg.HKEY_CLASSES_ROOT, "VisualStudio.DTE.12.0"), (_winreg.HKEY_LOCAL_MACHINE, "Software\\Microsoft\\VCExpress\\12.0")],
142			}
143
144			if not self.version in keyMap:
145				raise Exception("Unsupported VS version %d" % self.version)
146
147			keys = keyMap[self.version]
148			for root, name in keys:
149				if VSProjectGenerator.registryKeyAvailable(root, arch, name):
150					return True
151			return False
152		else:
153			return False
154
155# Pre-defined generators
156
157MAKEFILE_GENERATOR		= UnixMakefileGenerator()
158NINJA_GENERATOR			= NinjaGenerator()
159VS2010_X32_GENERATOR	= VSProjectGenerator(10, VSProjectGenerator.ARCH_32BIT)
160VS2010_X64_GENERATOR	= VSProjectGenerator(10, VSProjectGenerator.ARCH_64BIT)
161VS2012_X32_GENERATOR	= VSProjectGenerator(11, VSProjectGenerator.ARCH_32BIT)
162VS2012_X64_GENERATOR	= VSProjectGenerator(11, VSProjectGenerator.ARCH_64BIT)
163VS2013_X32_GENERATOR	= VSProjectGenerator(12, VSProjectGenerator.ARCH_32BIT)
164VS2013_X64_GENERATOR	= VSProjectGenerator(12, VSProjectGenerator.ARCH_64BIT)
165
166def selectFirstAvailableGenerator (generators):
167	for generator in generators:
168		if generator.isAvailable():
169			return generator
170	return None
171
172ANY_VS_X32_GENERATOR	= selectFirstAvailableGenerator([
173								VS2013_X32_GENERATOR,
174								VS2012_X32_GENERATOR,
175								VS2010_X32_GENERATOR,
176							])
177ANY_VS_X64_GENERATOR	= selectFirstAvailableGenerator([
178								VS2013_X64_GENERATOR,
179								VS2012_X64_GENERATOR,
180								VS2010_X64_GENERATOR,
181							])
182ANY_UNIX_GENERATOR		= selectFirstAvailableGenerator([
183								NINJA_GENERATOR,
184								MAKEFILE_GENERATOR,
185							])
186ANY_GENERATOR			= selectFirstAvailableGenerator([
187								VS2013_X64_GENERATOR,
188								VS2012_X64_GENERATOR,
189								VS2010_X64_GENERATOR,
190								VS2013_X32_GENERATOR,
191								VS2012_X32_GENERATOR,
192								VS2010_X32_GENERATOR,
193								NINJA_GENERATOR,
194								MAKEFILE_GENERATOR,
195							])
196