OLD | NEW |
(Empty) | |
| 1 # |
| 2 # Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 The S
Cons Foundation |
| 3 # |
| 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: |
| 11 # |
| 12 # The above copyright notice and this permission notice shall be included |
| 13 # in all copies or substantial portions of the Software. |
| 14 # |
| 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. |
| 22 # |
| 23 |
| 24 __revision__ = "src/engine/SCons/Tool/MSCommon/vs.py 5134 2010/08/16 23:02:40 bd
eegan" |
| 25 |
| 26 __doc__ = """Module to detect Visual Studio and/or Visual C/C++ |
| 27 """ |
| 28 |
| 29 import os |
| 30 |
| 31 import SCons.Errors |
| 32 import SCons.Util |
| 33 |
| 34 from common import debug, \ |
| 35 get_output, \ |
| 36 is_win64, \ |
| 37 normalize_env, \ |
| 38 parse_output, \ |
| 39 read_reg |
| 40 |
| 41 import SCons.Tool.MSCommon.vc |
| 42 |
| 43 class VisualStudio(object): |
| 44 """ |
| 45 An abstract base class for trying to find installed versions of |
| 46 Visual Studio. |
| 47 """ |
| 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) |
| 53 self._cache = {} |
| 54 |
| 55 # |
| 56 |
| 57 def find_batch_file(self): |
| 58 vs_dir = self.get_vs_dir() |
| 59 if not vs_dir: |
| 60 debug('find_executable(): no vs_dir') |
| 61 return None |
| 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) |
| 66 return None |
| 67 return batch_file |
| 68 |
| 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) |
| 72 if not dir: |
| 73 debug('find_vs_dir(): no installed VC %s' % self.vc_version) |
| 74 return None |
| 75 return dir |
| 76 |
| 77 def find_vs_dir_by_reg(self): |
| 78 root = 'Software\\' |
| 79 |
| 80 if is_win64(): |
| 81 root = root + 'Wow6432Node\\' |
| 82 for key in self.hkeys: |
| 83 if key=='use_dir': |
| 84 return self.find_vs_dir_by_vc() |
| 85 key = root + key |
| 86 try: |
| 87 comps = read_reg(key) |
| 88 except WindowsError, e: |
| 89 debug('find_vs_dir_by_reg(): no VS registry key %s' % repr(key)) |
| 90 else: |
| 91 debug('find_vs_dir_by_reg(): found VS in registry: %s' % comps) |
| 92 return comps |
| 93 return None |
| 94 |
| 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 |
| 98 """ |
| 99 |
| 100 |
| 101 if True: |
| 102 vs_dir=self.find_vs_dir_by_reg() |
| 103 return vs_dir |
| 104 else: |
| 105 return self.find_vs_dir_by_vc() |
| 106 |
| 107 def find_executable(self): |
| 108 vs_dir = self.get_vs_dir() |
| 109 if not vs_dir: |
| 110 debug('find_executable(): no vs_dir (%s)'%vs_dir) |
| 111 return None |
| 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) |
| 116 return None |
| 117 return executable |
| 118 |
| 119 # |
| 120 |
| 121 def get_batch_file(self): |
| 122 try: |
| 123 return self._cache['batch_file'] |
| 124 except KeyError: |
| 125 batch_file = self.find_batch_file() |
| 126 self._cache['batch_file'] = batch_file |
| 127 return batch_file |
| 128 |
| 129 def get_executable(self): |
| 130 try: |
| 131 debug('get_executable using cache:%s'%self._cache['executable']) |
| 132 return self._cache['executable'] |
| 133 except KeyError: |
| 134 executable = self.find_executable() |
| 135 self._cache['executable'] = executable |
| 136 debug('get_executable not in cache:%s'%executable) |
| 137 return executable |
| 138 |
| 139 def get_vs_dir(self): |
| 140 try: |
| 141 return self._cache['vs_dir'] |
| 142 except KeyError: |
| 143 vs_dir = self.find_vs_dir() |
| 144 self._cache['vs_dir'] = vs_dir |
| 145 return vs_dir |
| 146 |
| 147 def get_supported_arch(self): |
| 148 try: |
| 149 return self._cache['supported_arch'] |
| 150 except KeyError: |
| 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 |
| 155 |
| 156 def reset(self): |
| 157 self._cache = {} |
| 158 |
| 159 # The list of supported Visual Studio versions we know how to detect. |
| 160 # |
| 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. |
| 168 # |
| 169 # - VS 2008 Express (WoW6432: 32 bits on windows x64): |
| 170 # Software\Wow6432Node\Microsoft\VCEpress\9.0\Setup\VC\productdir |
| 171 # |
| 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. |
| 178 # |
| 179 # - VS 2005 Express (WoW6432: 32 bits on windows x64): does not seem to have a |
| 180 # productdir ? |
| 181 # |
| 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 |
| 187 # vsvars32.bat |
| 188 # |
| 189 # - VS 98 (VS 6): |
| 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 |
| 193 # |
| 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 |
| 200 # for free. |
| 201 # |
| 202 # If you update this list, update the documentation in Tool/msvs.xml. |
| 203 |
| 204 SupportedVSList = [ |
| 205 # Visual Studio 2010 |
| 206 # TODO: find the settings, perhaps from someone with a CTP copy? |
| 207 #VisualStudio('TBD', |
| 208 # hkey_root=r'TBD', |
| 209 # common_tools_var='TBD', |
| 210 # executable_path=r'TBD', |
| 211 # default_dirname='TBD', |
| 212 #), |
| 213 |
| 214 # Visual Studio 2008 |
| 215 # The batch file we look for is in the VC directory, |
| 216 # so the devenv.com executable is up in ..\..\Common7\IDE. |
| 217 VisualStudio('9.0', |
| 218 sdk_version='6.1', |
| 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'], |
| 225 ), |
| 226 |
| 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', |
| 231 vc_version='9.0', |
| 232 sdk_version='6.1', |
| 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'], |
| 239 ), |
| 240 |
| 241 # Visual Studio 2005 |
| 242 # The batch file we look for is in the VC directory, |
| 243 # so the devenv.com executable is up in ..\..\Common7\IDE. |
| 244 VisualStudio('8.0', |
| 245 sdk_version='6.0A', |
| 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'], |
| 252 ), |
| 253 |
| 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', |
| 258 vc_version='8.0Exp', |
| 259 sdk_version='6.0A', |
| 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'], |
| 266 ), |
| 267 |
| 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. |
| 271 VisualStudio('7.1', |
| 272 sdk_version='6.0', |
| 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'], |
| 279 ), |
| 280 |
| 281 # Visual Studio .NET |
| 282 # The batch file we look for is in the Common7\Tools directory, |
| 283 # so the devenv.com executable is next door in ..\IDE. |
| 284 VisualStudio('7.0', |
| 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'], |
| 292 ), |
| 293 |
| 294 # Visual Studio 6.0 |
| 295 VisualStudio('6.0', |
| 296 sdk_version='2003R1', |
| 297 hkeys=[r'Microsoft\VisualStudio\6.0\Setup\Microsoft Visual Stud
io\ProductDir', |
| 298 'use_dir'], |
| 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'], |
| 304 ), |
| 305 ] |
| 306 |
| 307 SupportedVSMap = {} |
| 308 for vs in SupportedVSList: |
| 309 SupportedVSMap[vs.version] = vs |
| 310 |
| 311 |
| 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. |
| 317 |
| 318 InstalledVSList = None |
| 319 InstalledVSMap = None |
| 320 |
| 321 def get_installed_visual_studios(): |
| 322 global InstalledVSList |
| 323 global InstalledVSMap |
| 324 if InstalledVSList is None: |
| 325 InstalledVSList = [] |
| 326 InstalledVSMap = {} |
| 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 |
| 334 |
| 335 def reset_installed_visual_studios(): |
| 336 global InstalledVSList |
| 337 global InstalledVSMap |
| 338 InstalledVSList = None |
| 339 InstalledVSMap = None |
| 340 for vs in SupportedVSList: |
| 341 vs.reset() |
| 342 |
| 343 # Need to clear installed VC's as well as they are used in finding |
| 344 # installed VS's |
| 345 SCons.Tool.MSCommon.vc.reset_installed_vcs() |
| 346 |
| 347 |
| 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. |
| 352 |
| 353 #SDKEnvironmentUpdates = {} |
| 354 # |
| 355 #def set_sdk_by_directory(env, sdk_dir): |
| 356 # global SDKEnvironmentUpdates |
| 357 # try: |
| 358 # env_tuple_list = SDKEnvironmentUpdates[sdk_dir] |
| 359 # except KeyError: |
| 360 # env_tuple_list = [] |
| 361 # SDKEnvironmentUpdates[sdk_dir] = env_tuple_list |
| 362 # |
| 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') |
| 366 # |
| 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)) |
| 372 # |
| 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'))) |
| 376 # |
| 377 # for variable, directory in env_tuple_list: |
| 378 # env.PrependENVPath(variable, directory) |
| 379 |
| 380 def msvs_exists(): |
| 381 return (len(get_installed_visual_studios()) > 0) |
| 382 |
| 383 def get_vs_by_version(msvs): |
| 384 global InstalledVSMap |
| 385 global SupportedVSMap |
| 386 |
| 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. |
| 401 #if not vs: |
| 402 # msg = "Visual Studio version %s is not installed" % repr(msvs) |
| 403 # raise SCons.Errors.UserError, msg |
| 404 return vs |
| 405 |
| 406 def get_default_version(env): |
| 407 """Returns the default version string to use for MSVS. |
| 408 |
| 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. |
| 412 |
| 413 Return |
| 414 ------ |
| 415 version: str |
| 416 the default version. |
| 417 """ |
| 418 if 'MSVS' not in env or not SCons.Util.is_Dict(env['MSVS']): |
| 419 versions = [vs.version for vs in get_installed_visual_studios()] |
| 420 env['MSVS'] = {'VERSIONS' : versions} |
| 421 else: |
| 422 versions = env['MSVS'].get('VERSIONS', []) |
| 423 |
| 424 if 'MSVS_VERSION' not in env: |
| 425 if versions: |
| 426 env['MSVS_VERSION'] = versions[0] #use highest version by default |
| 427 else: |
| 428 env['MSVS_VERSION'] = SupportedVSList[0].version |
| 429 |
| 430 env['MSVS']['VERSION'] = env['MSVS_VERSION'] |
| 431 |
| 432 return env['MSVS_VERSION'] |
| 433 |
| 434 def get_default_arch(env): |
| 435 """Return the default arch to use for MSVS |
| 436 |
| 437 if no version was requested by the user through the MSVS_ARCH environment |
| 438 variable, select x86 |
| 439 |
| 440 Return |
| 441 ------ |
| 442 arch: str |
| 443 """ |
| 444 arch = env.get('MSVS_ARCH', 'x86') |
| 445 |
| 446 msvs = InstalledVSMap.get(env['MSVS_VERSION']) |
| 447 |
| 448 if not msvs: |
| 449 arch = 'x86' |
| 450 elif not arch in msvs.get_supported_arch(): |
| 451 fmt = "Visual Studio version %s does not support architecture %s" |
| 452 raise SCons.Errors.UserError(fmt % (env['MSVS_VERSION'], arch)) |
| 453 |
| 454 return arch |
| 455 |
| 456 def merge_default_version(env): |
| 457 version = get_default_version(env) |
| 458 arch = get_default_arch(env) |
| 459 |
| 460 def msvs_setup_env(env): |
| 461 batfilename = msvs.get_batch_file() |
| 462 msvs = get_vs_by_version(version) |
| 463 if msvs is None: |
| 464 return |
| 465 |
| 466 # XXX: I think this is broken. This will silently set a bogus tool instead |
| 467 # of failing, but there is no other way with the current scons tool |
| 468 # framework |
| 469 if batfilename is not None: |
| 470 |
| 471 vars = ('LIB', 'LIBPATH', 'PATH', 'INCLUDE') |
| 472 |
| 473 msvs_list = get_installed_visual_studios() |
| 474 vscommonvarnames = [vs.common_tools_var for vs in msvs_list] |
| 475 save_ENV = env['ENV'] |
| 476 nenv = normalize_env(env['ENV'], |
| 477 ['COMSPEC'] + vscommonvarnames, |
| 478 force=True) |
| 479 try: |
| 480 output = get_output(batfilename, arch, env=nenv) |
| 481 finally: |
| 482 env['ENV'] = save_ENV |
| 483 vars = parse_output(output, vars) |
| 484 |
| 485 for k, v in vars.items(): |
| 486 env.PrependENVPath(k, v, delete_existing=1) |
| 487 |
| 488 def query_versions(): |
| 489 """Query the system to get available versions of VS. A version is |
| 490 considered when a batfile is found.""" |
| 491 msvs_list = get_installed_visual_studios() |
| 492 versions = [msvs.version for msvs in msvs_list] |
| 493 return versions |
| 494 |
| 495 # Local Variables: |
| 496 # tab-width:4 |
| 497 # indent-tabs-mode:nil |
| 498 # End: |
| 499 # vim: set expandtab tabstop=4 shiftwidth=4: |
OLD | NEW |