4 # Permission is hereby granted, free of charge, to any person obtaining
5 # a copy of this software and associated documentation files (the
6 # "Software"), to deal in the Software without restriction, including
7 # without limitation the rights to use, copy, modify, merge, publish,
8 # distribute, sublicense, and/or sell copies of the Software, and to
9 # permit persons to whom the Software is furnished to do so, subject to
10 # the following conditions:
12 # The above copyright notice and this permission notice shall be included
13 # in all copies or substantial portions of the Software.
15 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
16 # KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
17 # WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19 # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20 # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21 # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
26 __doc__ = """Module to detect Visual Studio and/or Visual C/C++
34 from common import debug, \
41 import SCons.Tool.MSCommon.vc
45 An abstract base class for trying to find installed versions of
48 def __init__(self, version, **kw):
49 self.version = version
50 kw['vc_version'] = kw.get('vc_version', version)
51 kw['sdk_version'] = kw.get('sdk_version', version)
52 self.__dict__.update(kw)
57 def find_batch_file(self):
58 vs_dir = self.get_vs_dir()
60 debug('find_executable(): no vs_dir')
62 batch_file = os.path.join(vs_dir, self.batch_file_path)
63 batch_file = os.path.normpath(batch_file)
64 if not os.path.isfile(batch_file):
65 debug('find_batch_file(): %s not on file system' % batch_file)
69 def find_vs_dir_by_vc(self):
70 SCons.Tool.MSCommon.vc.get_installed_vcs()
71 dir = SCons.Tool.MSCommon.vc.find_vc_pdir(self.vc_version)
73 debug('find_vs_dir(): no installed VC %s' % self.vc_version)
77 def find_vs_dir_by_reg(self):
81 root = root + 'Wow6432Node\\'
82 for key in self.hkeys:
84 return self.find_vs_dir_by_vc()
88 except WindowsError, e:
89 debug('find_vs_dir_by_reg(): no VS registry key %s' % repr(key))
91 debug('find_vs_dir_by_reg(): found VS in registry: %s' % comps)
95 def find_vs_dir(self):
96 """ Can use registry or location of VC to find vs dir
97 First try to find by registry, and if that fails find via VC dir
102 vs_dir=self.find_vs_dir_by_reg()
105 return self.find_vs_dir_by_vc()
107 def find_executable(self):
108 vs_dir = self.get_vs_dir()
110 debug('find_executable(): no vs_dir (%s)'%vs_dir)
112 executable = os.path.join(vs_dir, self.executable_path)
113 executable = os.path.normpath(executable)
114 if not os.path.isfile(executable):
115 debug('find_executable(): %s not on file system' % executable)
121 def get_batch_file(self):
123 return self._cache['batch_file']
125 batch_file = self.find_batch_file()
126 self._cache['batch_file'] = batch_file
129 def get_executable(self):
131 debug('get_executable using cache:%s'%self._cache['executable'])
132 return self._cache['executable']
134 executable = self.find_executable()
135 self._cache['executable'] = executable
136 debug('get_executable not in cache:%s'%executable)
139 def get_vs_dir(self):
141 return self._cache['vs_dir']
143 vs_dir = self.find_vs_dir()
144 self._cache['vs_dir'] = vs_dir
147 def get_supported_arch(self):
149 return self._cache['supported_arch']
151 # RDEVE: for the time being use hardcoded lists
152 # supported_arch = self.find_supported_arch()
153 self._cache['supported_arch'] = self.supported_arch
154 return self.supported_arch
159 # The list of supported Visual Studio versions we know how to detect.
161 # How to look for .bat file ?
162 # - VS 2008 Express (x86):
163 # * from registry key productdir, gives the full path to vsvarsall.bat. In
164 # HKEY_LOCAL_MACHINE):
165 # Software\Microsoft\VCEpress\9.0\Setup\VC\productdir
166 # * from environmnent variable VS90COMNTOOLS: the path is then ..\..\VC
167 # relatively to the path given by the variable.
169 # - VS 2008 Express (WoW6432: 32 bits on windows x64):
170 # Software\Wow6432Node\Microsoft\VCEpress\9.0\Setup\VC\productdir
172 # - VS 2005 Express (x86):
173 # * from registry key productdir, gives the full path to vsvarsall.bat. In
174 # HKEY_LOCAL_MACHINE):
175 # Software\Microsoft\VCEpress\8.0\Setup\VC\productdir
176 # * from environmnent variable VS80COMNTOOLS: the path is then ..\..\VC
177 # relatively to the path given by the variable.
179 # - VS 2005 Express (WoW6432: 32 bits on windows x64): does not seem to have a
182 # - VS 2003 .Net (pro edition ? x86):
183 # * from registry key productdir. The path is then ..\Common7\Tools\
184 # relatively to the key. The key is in HKEY_LOCAL_MACHINE):
185 # Software\Microsoft\VisualStudio\7.1\Setup\VC\productdir
186 # * from environmnent variable VS71COMNTOOLS: the path is the full path to
190 # * from registry key productdir. The path is then Bin
191 # relatively to the key. The key is in HKEY_LOCAL_MACHINE):
192 # Software\Microsoft\VisualStudio\6.0\Setup\VC98\productdir
194 # The first version found in the list is the one used by default if
195 # there are multiple versions installed. Barring good reasons to
196 # the contrary, this means we should list versions from most recent
197 # to oldest. Pro versions get listed before Express versions on the
198 # assumption that, by default, you'd rather use the version you paid
199 # good money for in preference to whatever Microsoft makes available
202 # If you update this list, update the documentation in Tool/msvs.xml.
206 # TODO: find the settings, perhaps from someone with a CTP copy?
209 # common_tools_var='TBD',
210 # executable_path=r'TBD',
211 # default_dirname='TBD',
215 # The batch file we look for is in the VC directory,
216 # so the devenv.com executable is up in ..\..\Common7\IDE.
219 hkeys=[r'Microsoft\VisualStudio\9.0\Setup\VS\ProductDir'],
220 common_tools_var='VS90COMNTOOLS',
221 executable_path=r'Common7\IDE\devenv.com',
222 batch_file_path=r'Common7\Tools\vsvars32.bat',
223 default_dirname='Microsoft Visual Studio 9',
224 supported_arch=['x86', 'amd64'],
227 # Visual C++ 2008 Express Edition
228 # The batch file we look for is in the VC directory,
229 # so the VCExpress.exe executable is up in ..\..\Common7\IDE.
230 VisualStudio('9.0Exp',
233 hkeys=[r'Microsoft\VCExpress\9.0\Setup\VS\ProductDir'],
234 common_tools_var='VS90COMNTOOLS',
235 executable_path=r'Common7\IDE\VCExpress.exe',
236 batch_file_path=r'Common7\Tools\vsvars32.bat',
237 default_dirname='Microsoft Visual Studio 9',
238 supported_arch=['x86'],
242 # The batch file we look for is in the VC directory,
243 # so the devenv.com executable is up in ..\..\Common7\IDE.
246 hkeys=[r'Microsoft\VisualStudio\8.0\Setup\VS\ProductDir'],
247 common_tools_var='VS80COMNTOOLS',
248 executable_path=r'Common7\IDE\devenv.com',
249 batch_file_path=r'Common7\Tools\vsvars32.bat',
250 default_dirname='Microsoft Visual Studio 8',
251 supported_arch=['x86', 'amd64'],
254 # Visual C++ 2005 Express Edition
255 # The batch file we look for is in the VC directory,
256 # so the VCExpress.exe executable is up in ..\..\Common7\IDE.
257 VisualStudio('8.0Exp',
260 hkeys=[r'Microsoft\VCExpress\8.0\Setup\VS\ProductDir'],
261 common_tools_var='VS80COMNTOOLS',
262 executable_path=r'Common7\IDE\VCExpress.exe',
263 batch_file_path=r'Common7\Tools\vsvars32.bat',
264 default_dirname='Microsoft Visual Studio 8',
265 supported_arch=['x86'],
268 # Visual Studio .NET 2003
269 # The batch file we look for is in the Common7\Tools directory,
270 # so the devenv.com executable is next door in ..\IDE.
273 hkeys=[r'Microsoft\VisualStudio\7.1\Setup\VS\ProductDir'],
274 common_tools_var='VS71COMNTOOLS',
275 executable_path=r'Common7\IDE\devenv.com',
276 batch_file_path=r'Common7\Tools\vsvars32.bat',
277 default_dirname='Microsoft Visual Studio .NET 2003',
278 supported_arch=['x86'],
282 # The batch file we look for is in the Common7\Tools directory,
283 # so the devenv.com executable is next door in ..\IDE.
285 sdk_version='2003R2',
286 hkeys=[r'Microsoft\VisualStudio\7.0\Setup\VS\ProductDir'],
287 common_tools_var='VS70COMNTOOLS',
288 executable_path=r'IDE\devenv.com',
289 batch_file_path=r'Common7\Tools\vsvars32.bat',
290 default_dirname='Microsoft Visual Studio .NET',
291 supported_arch=['x86'],
296 sdk_version='2003R1',
297 hkeys=[r'Microsoft\VisualStudio\6.0\Setup\Microsoft Visual Studio\ProductDir',
299 common_tools_var='VS60COMNTOOLS',
300 executable_path=r'Common\MSDev98\Bin\MSDEV.COM',
301 batch_file_path=r'Common7\Tools\vsvars32.bat',
302 default_dirname='Microsoft Visual Studio',
303 supported_arch=['x86'],
308 for vs in SupportedVSList:
309 SupportedVSMap[vs.version] = vs
312 # Finding installed versions of Visual Studio isn't cheap, because it
313 # goes not only to the registry but also to the disk to sanity-check
314 # that there is, in fact, a Visual Studio directory there and that the
315 # registry entry isn't just stale. Find this information once, when
316 # requested, and cache it.
318 InstalledVSList = None
319 InstalledVSMap = None
321 def get_installed_visual_studios():
322 global InstalledVSList
323 global InstalledVSMap
324 if InstalledVSList is None:
327 for vs in SupportedVSList:
328 debug('trying to find VS %s' % vs.version)
329 if vs.get_executable():
330 debug('found VS %s' % vs.version)
331 InstalledVSList.append(vs)
332 InstalledVSMap[vs.version] = vs
333 return InstalledVSList
335 def reset_installed_visual_studios():
336 global InstalledVSList
337 global InstalledVSMap
338 InstalledVSList = None
339 InstalledVSMap = None
340 for vs in SupportedVSList:
343 # Need to clear installed VC's as well as they are used in finding
345 SCons.Tool.MSCommon.vc.reset_installed_vcs()
348 # We may be asked to update multiple construction environments with
349 # SDK information. When doing this, we check on-disk for whether
350 # the SDK has 'mfc' and 'atl' subdirectories. Since going to disk
351 # is expensive, cache results by directory.
353 #SDKEnvironmentUpdates = {}
355 #def set_sdk_by_directory(env, sdk_dir):
356 # global SDKEnvironmentUpdates
358 # env_tuple_list = SDKEnvironmentUpdates[sdk_dir]
360 # env_tuple_list = []
361 # SDKEnvironmentUpdates[sdk_dir] = env_tuple_list
363 # include_path = os.path.join(sdk_dir, 'include')
364 # mfc_path = os.path.join(include_path, 'mfc')
365 # atl_path = os.path.join(include_path, 'atl')
367 # if os.path.exists(mfc_path):
368 # env_tuple_list.append(('INCLUDE', mfc_path))
369 # if os.path.exists(atl_path):
370 # env_tuple_list.append(('INCLUDE', atl_path))
371 # env_tuple_list.append(('INCLUDE', include_path))
373 # env_tuple_list.append(('LIB', os.path.join(sdk_dir, 'lib')))
374 # env_tuple_list.append(('LIBPATH', os.path.join(sdk_dir, 'lib')))
375 # env_tuple_list.append(('PATH', os.path.join(sdk_dir, 'bin')))
377 # for variable, directory in env_tuple_list:
378 # env.PrependENVPath(variable, directory)
381 return (len(get_installed_visual_studios()) > 0)
383 def get_vs_by_version(msvs):
384 global InstalledVSMap
385 global SupportedVSMap
387 debug('vs.py:get_vs_by_version()')
388 if msvs not in SupportedVSMap:
389 msg = "Visual Studio version %s is not supported" % repr(msvs)
390 raise SCons.Errors.UserError(msg)
391 get_installed_visual_studios()
392 vs = InstalledVSMap.get(msvs)
393 debug('InstalledVSMap:%s'%InstalledVSMap)
394 debug('vs.py:get_vs_by_version: found vs:%s'%vs)
395 # Some check like this would let us provide a useful error message
396 # if they try to set a Visual Studio version that's not installed.
397 # However, we also want to be able to run tests (like the unit
398 # tests) on systems that don't, or won't ever, have it installed.
399 # It might be worth resurrecting this, with some configurable
400 # setting that the tests can use to bypass the check.
402 # msg = "Visual Studio version %s is not installed" % repr(msvs)
403 # raise SCons.Errors.UserError, msg
406 def get_default_version(env):
407 """Returns the default version string to use for MSVS.
409 If no version was requested by the user through the MSVS environment
410 variable, query all the available the visual studios through
411 query_versions, and take the highest one.
418 if 'MSVS' not in env or not SCons.Util.is_Dict(env['MSVS']):
420 #versions = [vs.version for vs in get_installed_visual_studios()]
421 versions = [vs.version for vs in get_installed_visual_studios()]
422 env['MSVS'] = {'VERSIONS' : versions}
424 versions = env['MSVS'].get('VERSIONS', [])
426 if 'MSVS_VERSION' not in env:
428 env['MSVS_VERSION'] = versions[0] #use highest version by default
430 env['MSVS_VERSION'] = SupportedVSList[0].version
432 env['MSVS']['VERSION'] = env['MSVS_VERSION']
434 return env['MSVS_VERSION']
436 def get_default_arch(env):
437 """Return the default arch to use for MSVS
439 if no version was requested by the user through the MSVS_ARCH environment
446 arch = env.get('MSVS_ARCH', 'x86')
448 msvs = InstalledVSMap.get(env['MSVS_VERSION'])
452 elif not arch in msvs.get_supported_arch():
453 fmt = "Visual Studio version %s does not support architecture %s"
454 raise SCons.Errors.UserError(fmt % (env['MSVS_VERSION'], arch))
458 def merge_default_version(env):
459 version = get_default_version(env)
460 arch = get_default_arch(env)
462 def msvs_setup_env(env):
463 batfilename = msvs.get_batch_file()
464 msvs = get_vs_by_version(version)
468 # XXX: I think this is broken. This will silently set a bogus tool instead
469 # of failing, but there is no other way with the current scons tool
471 if batfilename is not None:
473 vars = ('LIB', 'LIBPATH', 'PATH', 'INCLUDE')
475 msvs_list = get_installed_visual_studios()
477 #vscommonvarnames = [ vs.common_tools_var for vs in msvs_list ]
478 vscommonvarnames = [vs.common_tools_var for vs in msvs_list]
479 nenv = normalize_env(env['ENV'], vscommonvarnames + ['COMSPEC'])
480 output = get_output(batfilename, arch, env=nenv)
481 vars = parse_output(output, vars)
483 for k, v in vars.items():
484 env.PrependENVPath(k, v, delete_existing=1)
486 def query_versions():
487 """Query the system to get available versions of VS. A version is
488 considered when a batfile is found."""
489 msvs_list = get_installed_visual_studios()
491 #versions = [ msvs.version for msvs in msvs_list ]
492 versions = [msvs.version for msvs in msvs_list]
497 # indent-tabs-mode:nil
499 # vim: set expandtab tabstop=4 shiftwidth=4: