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/sdk.py 5134 2010/08/16 23:02:40 b
deegan" |
| 25 |
| 26 __doc__ = """Module to detect the Platform/Windows SDK |
| 27 |
| 28 PSDK 2003 R1 is the earliest version detected. |
| 29 """ |
| 30 |
| 31 import os |
| 32 |
| 33 import SCons.Errors |
| 34 import SCons.Util |
| 35 |
| 36 import common |
| 37 |
| 38 debug = common.debug |
| 39 |
| 40 # SDK Checks. This is of course a mess as everything else on MS platforms. Here |
| 41 # is what we do to detect the SDK: |
| 42 # |
| 43 # For Windows SDK >= 6.0: just look into the registry entries: |
| 44 # HKLM\Software\Microsoft\Microsoft SDKs\Windows |
| 45 # All the keys in there are the available versions. |
| 46 # |
| 47 # For Platform SDK before 6.0 (2003 server R1 and R2, etc...), there does not |
| 48 # seem to be any sane registry key, so the precise location is hardcoded. |
| 49 # |
| 50 # For versions below 2003R1, it seems the PSDK is included with Visual Studio? |
| 51 # |
| 52 # Also, per the following: |
| 53 # http://benjamin.smedbergs.us/blog/tag/atl/ |
| 54 # VC++ Professional comes with the SDK, VC++ Express does not. |
| 55 |
| 56 # Location of the SDK (checked for 6.1 only) |
| 57 _CURINSTALLED_SDK_HKEY_ROOT = \ |
| 58 r"Software\Microsoft\Microsoft SDKs\Windows\CurrentInstallFolder" |
| 59 |
| 60 |
| 61 class SDKDefinition(object): |
| 62 """ |
| 63 An abstract base class for trying to find installed SDK directories. |
| 64 """ |
| 65 def __init__(self, version, **kw): |
| 66 self.version = version |
| 67 self.__dict__.update(kw) |
| 68 |
| 69 def find_sdk_dir(self): |
| 70 """Try to find the MS SDK from the registry. |
| 71 |
| 72 Return None if failed or the directory does not exist. |
| 73 """ |
| 74 if not SCons.Util.can_read_reg: |
| 75 debug('find_sdk_dir(): can not read registry') |
| 76 return None |
| 77 |
| 78 hkey = self.HKEY_FMT % self.hkey_data |
| 79 debug('find_sdk_dir(): checking registry:%s'%hkey) |
| 80 |
| 81 try: |
| 82 sdk_dir = common.read_reg(hkey) |
| 83 except WindowsError, e: |
| 84 debug('find_sdk_dir(): no SDK registry key %s' % repr(hkey)) |
| 85 return None |
| 86 |
| 87 debug('find_sdk_dir(): Trying SDK Dir: %s'%sdk_dir) |
| 88 |
| 89 if not os.path.exists(sdk_dir): |
| 90 debug('find_sdk_dir(): %s not on file system' % sdk_dir) |
| 91 return None |
| 92 |
| 93 ftc = os.path.join(sdk_dir, self.sanity_check_file) |
| 94 if not os.path.exists(ftc): |
| 95 debug("find_sdk_dir(): sanity check %s not found" % ftc) |
| 96 return None |
| 97 |
| 98 return sdk_dir |
| 99 |
| 100 def get_sdk_dir(self): |
| 101 """Return the MSSSDK given the version string.""" |
| 102 try: |
| 103 return self._sdk_dir |
| 104 except AttributeError: |
| 105 sdk_dir = self.find_sdk_dir() |
| 106 self._sdk_dir = sdk_dir |
| 107 return sdk_dir |
| 108 |
| 109 def get_sdk_vc_script(self,host_arch, target_arch): |
| 110 """ Return the script to initialize the VC compiler installed by SDK |
| 111 """ |
| 112 |
| 113 if (host_arch == 'amd64' and target_arch == 'x86'): |
| 114 # No cross tools needed compiling 32 bits on 64 bit machine |
| 115 host_arch=target_arch |
| 116 |
| 117 arch_string=target_arch |
| 118 if (host_arch != target_arch): |
| 119 arch_string='%s_%s'%(host_arch,target_arch) |
| 120 |
| 121 debug("sdk.py: get_sdk_vc_script():arch_string:%s host_arch:%s target_ar
ch:%s"%(arch_string, |
| 122 host_arch, |
| 123 target_arch)) |
| 124 file=self.vc_setup_scripts.get(arch_string,None) |
| 125 debug("sdk.py: get_sdk_vc_script():file:%s"%file) |
| 126 return file |
| 127 |
| 128 class WindowsSDK(SDKDefinition): |
| 129 """ |
| 130 A subclass for trying to find installed Windows SDK directories. |
| 131 """ |
| 132 HKEY_FMT = r'Software\Microsoft\Microsoft SDKs\Windows\v%s\InstallationFolde
r' |
| 133 def __init__(self, *args, **kw): |
| 134 SDKDefinition.__init__(self, *args, **kw) |
| 135 self.hkey_data = self.version |
| 136 |
| 137 class PlatformSDK(SDKDefinition): |
| 138 """ |
| 139 A subclass for trying to find installed Platform SDK directories. |
| 140 """ |
| 141 HKEY_FMT = r'Software\Microsoft\MicrosoftSDK\InstalledSDKS\%s\Install Dir' |
| 142 def __init__(self, *args, **kw): |
| 143 SDKDefinition.__init__(self, *args, **kw) |
| 144 self.hkey_data = self.uuid |
| 145 |
| 146 # |
| 147 # The list of VC initialization scripts installed by the SDK |
| 148 # These should be tried if the vcvarsall.bat TARGET_ARCH fails |
| 149 preSDK61VCSetupScripts = { 'x86' : r'bin\vcvars32.bat', |
| 150 'amd64' : r'bin\vcvarsamd64.bat', |
| 151 'x86_amd64': r'bin\vcvarsx86_amd64.bat', |
| 152 'x86_ia64' : r'bin\vcvarsx86_ia64.bat', |
| 153 'ia64' : r'bin\vcvarsia64.bat'} |
| 154 |
| 155 SDK61VCSetupScripts = {'x86' : r'bin\vcvars32.bat', |
| 156 'amd64' : r'bin\amd64\vcvarsamd64.bat', |
| 157 'x86_amd64': r'bin\x86_amd64\vcvarsx86_amd64.bat', |
| 158 'x86_ia64' : r'bin\x86_ia64\vcvarsx86_ia64.bat', |
| 159 'ia64' : r'bin\ia64\vcvarsia64.bat'} |
| 160 |
| 161 SDK70VCSetupScripts = { 'x86' : r'bin\vcvars32.bat', |
| 162 'amd64' : r'bin\vcvars64.bat', |
| 163 'x86_amd64': r'bin\vcvarsx86_amd64.bat', |
| 164 'x86_ia64' : r'bin\vcvarsx86_ia64.bat', |
| 165 'ia64' : r'bin\vcvarsia64.bat'} |
| 166 |
| 167 # The list of support SDKs which we know how to detect. |
| 168 # |
| 169 # The first SDK found in the list is the one used by default if there |
| 170 # are multiple SDKs installed. Barring good reasons to the contrary, |
| 171 # this means we should list SDKs with from most recent to oldest. |
| 172 # |
| 173 # If you update this list, update the documentation in Tool/mssdk.xml. |
| 174 SupportedSDKList = [ |
| 175 WindowsSDK('7.0', |
| 176 sanity_check_file=r'bin\SetEnv.Cmd', |
| 177 include_subdir='include', |
| 178 lib_subdir={ |
| 179 'x86' : ['lib'], |
| 180 'x86_64' : [r'lib\x64'], |
| 181 'ia64' : [r'lib\ia64'], |
| 182 }, |
| 183 vc_setup_scripts = SDK70VCSetupScripts, |
| 184 ), |
| 185 WindowsSDK('6.1', |
| 186 sanity_check_file=r'bin\SetEnv.Cmd', |
| 187 include_subdir='include', |
| 188 lib_subdir={ |
| 189 'x86' : ['lib'], |
| 190 'x86_64' : [r'lib\x64'], |
| 191 'ia64' : [r'lib\ia64'], |
| 192 }, |
| 193 vc_setup_scripts = SDK61VCSetupScripts, |
| 194 ), |
| 195 |
| 196 WindowsSDK('6.0A', |
| 197 sanity_check_file=r'include\windows.h', |
| 198 include_subdir='include', |
| 199 lib_subdir={ |
| 200 'x86' : ['lib'], |
| 201 'x86_64' : [r'lib\x64'], |
| 202 'ia64' : [r'lib\ia64'], |
| 203 }, |
| 204 vc_setup_scripts = preSDK61VCSetupScripts, |
| 205 ), |
| 206 |
| 207 WindowsSDK('6.0', |
| 208 sanity_check_file=r'bin\gacutil.exe', |
| 209 include_subdir='include', |
| 210 lib_subdir='lib', |
| 211 vc_setup_scripts = preSDK61VCSetupScripts, |
| 212 ), |
| 213 |
| 214 PlatformSDK('2003R2', |
| 215 sanity_check_file=r'SetEnv.Cmd', |
| 216 uuid="D2FF9F89-8AA2-4373-8A31-C838BF4DBBE1", |
| 217 vc_setup_scripts = preSDK61VCSetupScripts, |
| 218 ), |
| 219 |
| 220 PlatformSDK('2003R1', |
| 221 sanity_check_file=r'SetEnv.Cmd', |
| 222 uuid="8F9E5EF3-A9A5-491B-A889-C58EFFECE8B3", |
| 223 vc_setup_scripts = preSDK61VCSetupScripts, |
| 224 ), |
| 225 ] |
| 226 |
| 227 SupportedSDKMap = {} |
| 228 for sdk in SupportedSDKList: |
| 229 SupportedSDKMap[sdk.version] = sdk |
| 230 |
| 231 |
| 232 # Finding installed SDKs isn't cheap, because it goes not only to the |
| 233 # registry but also to the disk to sanity-check that there is, in fact, |
| 234 # an SDK installed there and that the registry entry isn't just stale. |
| 235 # Find this information once, when requested, and cache it. |
| 236 |
| 237 InstalledSDKList = None |
| 238 InstalledSDKMap = None |
| 239 |
| 240 def get_installed_sdks(): |
| 241 global InstalledSDKList |
| 242 global InstalledSDKMap |
| 243 debug('sdk.py:get_installed_sdks()') |
| 244 if InstalledSDKList is None: |
| 245 InstalledSDKList = [] |
| 246 InstalledSDKMap = {} |
| 247 for sdk in SupportedSDKList: |
| 248 debug('MSCommon/sdk.py: trying to find SDK %s' % sdk.version) |
| 249 if sdk.get_sdk_dir(): |
| 250 debug('MSCommon/sdk.py:found SDK %s' % sdk.version) |
| 251 InstalledSDKList.append(sdk) |
| 252 InstalledSDKMap[sdk.version] = sdk |
| 253 return InstalledSDKList |
| 254 |
| 255 |
| 256 # We may be asked to update multiple construction environments with |
| 257 # SDK information. When doing this, we check on-disk for whether |
| 258 # the SDK has 'mfc' and 'atl' subdirectories. Since going to disk |
| 259 # is expensive, cache results by directory. |
| 260 |
| 261 SDKEnvironmentUpdates = {} |
| 262 |
| 263 def set_sdk_by_directory(env, sdk_dir): |
| 264 global SDKEnvironmentUpdates |
| 265 debug('set_sdk_by_directory: Using dir:%s'%sdk_dir) |
| 266 try: |
| 267 env_tuple_list = SDKEnvironmentUpdates[sdk_dir] |
| 268 except KeyError: |
| 269 env_tuple_list = [] |
| 270 SDKEnvironmentUpdates[sdk_dir] = env_tuple_list |
| 271 |
| 272 include_path = os.path.join(sdk_dir, 'include') |
| 273 mfc_path = os.path.join(include_path, 'mfc') |
| 274 atl_path = os.path.join(include_path, 'atl') |
| 275 |
| 276 if os.path.exists(mfc_path): |
| 277 env_tuple_list.append(('INCLUDE', mfc_path)) |
| 278 if os.path.exists(atl_path): |
| 279 env_tuple_list.append(('INCLUDE', atl_path)) |
| 280 env_tuple_list.append(('INCLUDE', include_path)) |
| 281 |
| 282 env_tuple_list.append(('LIB', os.path.join(sdk_dir, 'lib'))) |
| 283 env_tuple_list.append(('LIBPATH', os.path.join(sdk_dir, 'lib'))) |
| 284 env_tuple_list.append(('PATH', os.path.join(sdk_dir, 'bin'))) |
| 285 |
| 286 for variable, directory in env_tuple_list: |
| 287 env.PrependENVPath(variable, directory) |
| 288 |
| 289 |
| 290 # TODO(sgk): currently unused; remove? |
| 291 def get_cur_sdk_dir_from_reg(): |
| 292 """Try to find the platform sdk directory from the registry. |
| 293 |
| 294 Return None if failed or the directory does not exist""" |
| 295 if not SCons.Util.can_read_reg: |
| 296 debug('SCons cannot read registry') |
| 297 return None |
| 298 |
| 299 try: |
| 300 val = common.read_reg(_CURINSTALLED_SDK_HKEY_ROOT) |
| 301 debug("Found current sdk dir in registry: %s" % val) |
| 302 except WindowsError, e: |
| 303 debug("Did not find current sdk in registry") |
| 304 return None |
| 305 |
| 306 if not os.path.exists(val): |
| 307 debug("Current sdk dir %s not on fs" % val) |
| 308 return None |
| 309 |
| 310 return val |
| 311 |
| 312 def get_sdk_by_version(mssdk): |
| 313 if mssdk not in SupportedSDKMap: |
| 314 msg = "SDK version %s is not supported" % repr(mssdk) |
| 315 raise SCons.Errors.UserError(msg) |
| 316 get_installed_sdks() |
| 317 return InstalledSDKMap.get(mssdk) |
| 318 |
| 319 def get_default_sdk(): |
| 320 """Set up the default Platform/Windows SDK.""" |
| 321 get_installed_sdks() |
| 322 if not InstalledSDKList: |
| 323 return None |
| 324 return InstalledSDKList[0] |
| 325 |
| 326 |
| 327 |
| 328 |
| 329 def mssdk_setup_env(env): |
| 330 debug('sdk.py:mssdk_setup_env()') |
| 331 if 'MSSDK_DIR' in env: |
| 332 sdk_dir = env['MSSDK_DIR'] |
| 333 if sdk_dir is None: |
| 334 return |
| 335 sdk_dir = env.subst(sdk_dir) |
| 336 debug('sdk.py:mssdk_setup_env: Using MSSDK_DIR:%s'%sdk_dir) |
| 337 elif 'MSSDK_VERSION' in env: |
| 338 sdk_version = env['MSSDK_VERSION'] |
| 339 if sdk_version is None: |
| 340 msg = "SDK version %s is not installed" % repr(mssdk) |
| 341 raise SCons.Errors.UserError(msg) |
| 342 sdk_version = env.subst(sdk_version) |
| 343 mssdk = get_sdk_by_version(sdk_version) |
| 344 sdk_dir = mssdk.get_sdk_dir() |
| 345 debug('sdk.py:mssdk_setup_env: Using MSSDK_VERSION:%s'%sdk_dir) |
| 346 elif 'MSVS_VERSION' in env: |
| 347 msvs_version = env['MSVS_VERSION'] |
| 348 debug('sdk.py:mssdk_setup_env:Getting MSVS_VERSION from env:%s'%msvs_ver
sion) |
| 349 if msvs_version is None: |
| 350 debug('sdk.py:mssdk_setup_env thinks msvs_version is None') |
| 351 return |
| 352 msvs_version = env.subst(msvs_version) |
| 353 import vs |
| 354 msvs = vs.get_vs_by_version(msvs_version) |
| 355 debug('sdk.py:mssdk_setup_env:msvs is :%s'%msvs) |
| 356 if not msvs: |
| 357 debug('sdk.py:mssdk_setup_env: no VS version detected, bailingout:%s
'%msvs) |
| 358 return |
| 359 sdk_version = msvs.sdk_version |
| 360 debug('sdk.py:msvs.sdk_version is %s'%sdk_version) |
| 361 if not sdk_version: |
| 362 return |
| 363 mssdk = get_sdk_by_version(sdk_version) |
| 364 if not mssdk: |
| 365 mssdk = get_default_sdk() |
| 366 if not mssdk: |
| 367 return |
| 368 sdk_dir = mssdk.get_sdk_dir() |
| 369 debug('sdk.py:mssdk_setup_env: Using MSVS_VERSION:%s'%sdk_dir) |
| 370 else: |
| 371 mssdk = get_default_sdk() |
| 372 if not mssdk: |
| 373 return |
| 374 sdk_dir = mssdk.get_sdk_dir() |
| 375 debug('sdk.py:mssdk_setup_env: not using any env values. sdk_dir:%s'%sdk
_dir) |
| 376 |
| 377 set_sdk_by_directory(env, sdk_dir) |
| 378 |
| 379 #print "No MSVS_VERSION: this is likely to be a bug" |
| 380 |
| 381 def mssdk_exists(version=None): |
| 382 sdks = get_installed_sdks() |
| 383 if version is None: |
| 384 return len(sdks) > 0 |
| 385 return version in sdks |
| 386 |
| 387 # Local Variables: |
| 388 # tab-width:4 |
| 389 # indent-tabs-mode:nil |
| 390 # End: |
| 391 # vim: set expandtab tabstop=4 shiftwidth=4: |
OLD | NEW |