~mwinter4/maus/ckov_0_9_3

« back to all changes in this revision

Viewing changes to third_party/scons-2.0.1/lib/scons-2.0.1/SCons/Tool/MSCommon/vc.py

  • Committer: tunnell
  • Date: 2010-09-30 13:56:05 UTC
  • Revision ID: tunnell@itchy-20100930135605-wxbkfgy75p0sndk3
add third party

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#
 
2
# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 The SCons 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
# TODO:
 
25
#   * supported arch for versions: for old versions of batch file without
 
26
#     argument, giving bogus argument cannot be detected, so we have to hardcode
 
27
#     this here
 
28
#   * print warning when msvc version specified but not found
 
29
#   * find out why warning do not print
 
30
#   * test on 64 bits XP +  VS 2005 (and VS 6 if possible)
 
31
#   * SDK
 
32
#   * Assembly
 
33
__revision__ = "src/engine/SCons/Tool/MSCommon/vc.py 5134 2010/08/16 23:02:40 bdeegan"
 
34
 
 
35
__doc__ = """Module for Visual C/C++ detection and configuration.
 
36
"""
 
37
import SCons.compat
 
38
 
 
39
import os
 
40
import platform
 
41
from string import digits as string_digits
 
42
 
 
43
import SCons.Warnings
 
44
 
 
45
import common
 
46
 
 
47
debug = common.debug
 
48
 
 
49
import sdk
 
50
 
 
51
get_installed_sdks = sdk.get_installed_sdks
 
52
 
 
53
 
 
54
class VisualCException(Exception):
 
55
    pass
 
56
 
 
57
class UnsupportedVersion(VisualCException):
 
58
    pass
 
59
 
 
60
class UnsupportedArch(VisualCException):
 
61
    pass
 
62
 
 
63
class MissingConfiguration(VisualCException):
 
64
    pass
 
65
 
 
66
class NoVersionFound(VisualCException):
 
67
    pass
 
68
 
 
69
class BatchFileExecutionError(VisualCException):
 
70
    pass
 
71
 
 
72
# Dict to 'canonalize' the arch
 
73
_ARCH_TO_CANONICAL = {
 
74
    "amd64"     : "amd64",
 
75
    "emt64"     : "amd64",
 
76
    "i386"      : "x86",
 
77
    "i486"      : "x86",
 
78
    "i586"      : "x86",
 
79
    "i686"      : "x86",
 
80
    "ia64"      : "ia64",
 
81
    "itanium"   : "ia64",
 
82
    "x86"       : "x86",
 
83
    "x86_64"    : "amd64",
 
84
}
 
85
 
 
86
# Given a (host, target) tuple, return the argument for the bat file. Both host
 
87
# and targets should be canonalized.
 
88
_HOST_TARGET_ARCH_TO_BAT_ARCH = {
 
89
    ("x86", "x86"): "x86",
 
90
    ("x86", "amd64"): "x86_amd64",
 
91
    ("amd64", "amd64"): "amd64",
 
92
    ("amd64", "x86"): "x86",
 
93
    ("x86", "ia64"): "x86_ia64"
 
94
}
 
95
 
 
96
def get_host_target(env):
 
97
    debug('vc.py:get_host_target()')
 
98
 
 
99
    host_platform = env.get('HOST_ARCH')
 
100
    if not host_platform:
 
101
        host_platform = platform.machine()
 
102
        # TODO(2.5):  the native Python platform.machine() function returns
 
103
        # '' on all Python versions before 2.6, after which it also uses
 
104
        # PROCESSOR_ARCHITECTURE.
 
105
        if not host_platform:
 
106
            host_platform = os.environ.get('PROCESSOR_ARCHITECTURE', '')
 
107
            
 
108
    # Retain user requested TARGET_ARCH
 
109
    req_target_platform = env.get('TARGET_ARCH')
 
110
    debug('vc.py:get_host_target() req_target_platform:%s'%req_target_platform)
 
111
 
 
112
    if  req_target_platform:
 
113
        # If user requested a specific platform then only try that one.
 
114
        target_platform = req_target_platform
 
115
    else:
 
116
        target_platform = host_platform
 
117
        
 
118
    try:
 
119
        host = _ARCH_TO_CANONICAL[host_platform.lower()]
 
120
    except KeyError, e:
 
121
        msg = "Unrecognized host architecture %s"
 
122
        raise ValueError(msg % repr(host_platform))
 
123
 
 
124
    try:
 
125
        target = _ARCH_TO_CANONICAL[target_platform.lower()]
 
126
    except KeyError, e:
 
127
        raise ValueError("Unrecognized target architecture %s" % target_platform)
 
128
 
 
129
    return (host, target,req_target_platform)
 
130
 
 
131
_VCVER = ["10.0", "9.0", "9.0Exp","8.0", "8.0Exp","7.1", "7.0", "6.0"]
 
132
 
 
133
_VCVER_TO_PRODUCT_DIR = {
 
134
        '10.0': [
 
135
            r'Microsoft\VisualStudio\10.0\Setup\VC\ProductDir'],
 
136
        '9.0': [
 
137
            r'Microsoft\VisualStudio\9.0\Setup\VC\ProductDir'],
 
138
        '9.0Exp' : [
 
139
            r'Microsoft\VCExpress\9.0\Setup\VC\ProductDir'],
 
140
        '8.0': [
 
141
            r'Microsoft\VisualStudio\8.0\Setup\VC\ProductDir'],
 
142
        '8.0Exp': [
 
143
            r'Microsoft\VCExpress\8.0\Setup\VC\ProductDir'],
 
144
        '7.1': [
 
145
            r'Microsoft\VisualStudio\7.1\Setup\VC\ProductDir'],
 
146
        '7.0': [
 
147
            r'Microsoft\VisualStudio\7.0\Setup\VC\ProductDir'],
 
148
        '6.0': [
 
149
            r'Microsoft\VisualStudio\6.0\Setup\Microsoft Visual C++\ProductDir']
 
150
}
 
151
        
 
152
def msvc_version_to_maj_min(msvc_version):
 
153
   msvc_version_numeric = ''.join([x for  x in msvc_version if x in string_digits + '.'])
 
154
 
 
155
   t = msvc_version_numeric.split(".")
 
156
   if not len(t) == 2:
 
157
       raise ValueError("Unrecognized version %s (%s)" % (msvc_version,msvc_version_numeric))
 
158
   try:
 
159
       maj = int(t[0])
 
160
       min = int(t[1])
 
161
       return maj, min
 
162
   except ValueError, e:
 
163
       raise ValueError("Unrecognized version %s (%s)" % (msvc_version,msvc_version_numeric))
 
164
 
 
165
def is_host_target_supported(host_target, msvc_version):
 
166
    """Return True if the given (host, target) tuple is supported given the
 
167
    msvc version.
 
168
 
 
169
    Parameters
 
170
    ----------
 
171
    host_target: tuple
 
172
        tuple of (canonalized) host-target, e.g. ("x86", "amd64") for cross
 
173
        compilation from 32 bits windows to 64 bits.
 
174
    msvc_version: str
 
175
        msvc version (major.minor, e.g. 10.0)
 
176
 
 
177
    Note
 
178
    ----
 
179
    This only check whether a given version *may* support the given (host,
 
180
    target), not that the toolchain is actually present on the machine.
 
181
    """
 
182
    # We assume that any Visual Studio version supports x86 as a target
 
183
    if host_target[1] != "x86":
 
184
        maj, min = msvc_version_to_maj_min(msvc_version)
 
185
        if maj < 8:
 
186
            return False
 
187
 
 
188
    return True
 
189
 
 
190
def find_vc_pdir(msvc_version):
 
191
    """Try to find the product directory for the given
 
192
    version.
 
193
 
 
194
    Note
 
195
    ----
 
196
    If for some reason the requested version could not be found, an
 
197
    exception which inherits from VisualCException will be raised."""
 
198
    root = 'Software\\'
 
199
    if common.is_win64():
 
200
        root = root + 'Wow6432Node\\'
 
201
    try:
 
202
        hkeys = _VCVER_TO_PRODUCT_DIR[msvc_version]
 
203
    except KeyError:
 
204
        debug("Unknown version of MSVC: %s" % msvc_version)
 
205
        raise UnsupportedVersion("Unknown version %s" % msvc_version)
 
206
 
 
207
    for key in hkeys:
 
208
        key = root + key
 
209
        try:
 
210
            comps = common.read_reg(key)
 
211
        except WindowsError, e:
 
212
            debug('find_vc_dir(): no VC registry key %s' % repr(key))
 
213
        else:
 
214
            debug('find_vc_dir(): found VC in registry: %s' % comps)
 
215
            if os.path.exists(comps):
 
216
                return comps
 
217
            else:
 
218
                debug('find_vc_dir(): reg says dir is %s, but it does not exist. (ignoring)'\
 
219
                          % comps)
 
220
                raise MissingConfiguration("registry dir %s not found on the filesystem" % comps)
 
221
    return None
 
222
 
 
223
def find_batch_file(env,msvc_version,host_arch,target_arch):
 
224
    """
 
225
    Find the location of the batch script which should set up the compiler
 
226
    for any TARGET_ARCH whose compilers were installed by Visual Studio/VCExpress
 
227
    """
 
228
    pdir = find_vc_pdir(msvc_version)
 
229
    if pdir is None:
 
230
        raise NoVersionFound("No version of Visual Studio found")
 
231
        
 
232
    debug('vc.py: find_batch_file() pdir:%s'%pdir)
 
233
 
 
234
    # filter out e.g. "Exp" from the version name
 
235
    msvc_ver_numeric = ''.join([x for x in msvc_version if x in string_digits + "."])
 
236
    vernum = float(msvc_ver_numeric)
 
237
    if 7 <= vernum < 8:
 
238
        pdir = os.path.join(pdir, os.pardir, "Common7", "Tools")
 
239
        batfilename = os.path.join(pdir, "vsvars32.bat")
 
240
    elif vernum < 7:
 
241
        pdir = os.path.join(pdir, "Bin")
 
242
        batfilename = os.path.join(pdir, "vcvars32.bat")
 
243
    else: # >= 8
 
244
        batfilename = os.path.join(pdir, "vcvarsall.bat")
 
245
 
 
246
    if not os.path.exists(batfilename):
 
247
        debug("Not found: %s" % batfilename)
 
248
        batfilename = None
 
249
    
 
250
    installed_sdks=get_installed_sdks()
 
251
    for _sdk in installed_sdks:
 
252
        sdk_bat_file=_sdk.get_sdk_vc_script(host_arch,target_arch)
 
253
        sdk_bat_file_path=os.path.join(pdir,sdk_bat_file)
 
254
        debug('vc.py:find_batch_file() sdk_bat_file_path:%s'%sdk_bat_file_path)
 
255
        if os.path.exists(sdk_bat_file_path):
 
256
            return (batfilename,sdk_bat_file_path)
 
257
        else:
 
258
            debug("vc.py:find_batch_file() not found:%s"%sdk_bat_file_path)
 
259
    else:
 
260
        return (batfilename,None)
 
261
 
 
262
__INSTALLED_VCS_RUN = None
 
263
 
 
264
def cached_get_installed_vcs():
 
265
    global __INSTALLED_VCS_RUN
 
266
 
 
267
    if __INSTALLED_VCS_RUN is None:
 
268
        ret = get_installed_vcs()
 
269
        __INSTALLED_VCS_RUN = ret
 
270
 
 
271
    return __INSTALLED_VCS_RUN
 
272
 
 
273
def get_installed_vcs():
 
274
    installed_versions = []
 
275
    for ver in _VCVER:
 
276
        debug('trying to find VC %s' % ver)
 
277
        try:
 
278
            if find_vc_pdir(ver):
 
279
                debug('found VC %s' % ver)
 
280
                installed_versions.append(ver)
 
281
            else:
 
282
                debug('find_vc_pdir return None for ver %s' % ver)
 
283
        except VisualCException, e:
 
284
            debug('did not find VC %s: caught exception %s' % (ver, str(e)))
 
285
    return installed_versions
 
286
 
 
287
def reset_installed_vcs():
 
288
    """Make it try again to find VC.  This is just for the tests."""
 
289
    __INSTALLED_VCS_RUN = None
 
290
 
 
291
def script_env(script, args=None):
 
292
    stdout = common.get_output(script, args)
 
293
    # Stupid batch files do not set return code: we take a look at the
 
294
    # beginning of the output for an error message instead
 
295
    olines = stdout.splitlines()
 
296
    if olines[0].startswith("The specified configuration type is missing"):
 
297
        raise BatchFileExecutionError("\n".join(olines[:2]))
 
298
 
 
299
    return common.parse_output(stdout)
 
300
 
 
301
def get_default_version(env):
 
302
    debug('get_default_version()')
 
303
 
 
304
    msvc_version = env.get('MSVC_VERSION')
 
305
    msvs_version = env.get('MSVS_VERSION')
 
306
    
 
307
    debug('get_default_version(): msvc_version:%s msvs_version:%s'%(msvc_version,msvs_version))
 
308
 
 
309
    if msvs_version and not msvc_version:
 
310
        SCons.Warnings.warn(
 
311
                SCons.Warnings.DeprecatedWarning,
 
312
                "MSVS_VERSION is deprecated: please use MSVC_VERSION instead ")
 
313
        return msvs_version
 
314
    elif msvc_version and msvs_version:
 
315
        if not msvc_version == msvs_version:
 
316
            SCons.Warnings.warn(
 
317
                    SCons.Warnings.VisualVersionMismatch,
 
318
                    "Requested msvc version (%s) and msvs version (%s) do " \
 
319
                    "not match: please use MSVC_VERSION only to request a " \
 
320
                    "visual studio version, MSVS_VERSION is deprecated" \
 
321
                    % (msvc_version, msvs_version))
 
322
        return msvs_version
 
323
    if not msvc_version:
 
324
        installed_vcs = cached_get_installed_vcs()
 
325
        debug('installed_vcs:%s' % installed_vcs)
 
326
        if not installed_vcs:
 
327
            msg = 'No installed VCs'
 
328
            debug('msv %s\n' % repr(msg))
 
329
            SCons.Warnings.warn(SCons.Warnings.VisualCMissingWarning, msg)
 
330
            return None
 
331
        msvc_version = installed_vcs[0]
 
332
        debug('msvc_setup_env: using default installed MSVC version %s\n' % repr(msvc_version))
 
333
 
 
334
    return msvc_version
 
335
 
 
336
def msvc_setup_env_once(env):
 
337
    try:
 
338
        has_run  = env["MSVC_SETUP_RUN"]
 
339
    except KeyError:
 
340
        has_run = False
 
341
 
 
342
    if not has_run:
 
343
        msvc_setup_env(env)
 
344
        env["MSVC_SETUP_RUN"] = True
 
345
 
 
346
def msvc_find_valid_batch_script(env,version):
 
347
    debug('vc.py:msvc_find_valid_batch_script()')
 
348
    # Find the host platform, target platform, and if present the requested
 
349
    # target platform
 
350
    (host_platform, target_platform,req_target_platform) = get_host_target(env)
 
351
 
 
352
    # If the user hasn't specifically requested a TARGET_ARCH, and
 
353
    # The TARGET_ARCH is amd64 then also try 32 bits if there are no viable
 
354
    # 64 bit tools installed
 
355
    try_target_archs = [target_platform]
 
356
    if not req_target_platform and target_platform=='amd64':
 
357
        try_target_archs.append('x86')
 
358
 
 
359
    d = None
 
360
    for tp in try_target_archs:
 
361
        # Set to current arch.
 
362
        env['TARGET_ARCH']=tp
 
363
        
 
364
        debug("vc.py:msvc_find_valid_batch_script() trying target_platform:%s"%tp)
 
365
        host_target = (host_platform, tp)
 
366
        if not is_host_target_supported(host_target, version):
 
367
            warn_msg = "host, target = %s not supported for MSVC version %s" % \
 
368
                (host_target, version)
 
369
            SCons.Warnings.warn(SCons.Warnings.VisualCMissingWarning, warn_msg)
 
370
        arg = _HOST_TARGET_ARCH_TO_BAT_ARCH[host_target]
 
371
        
 
372
        # Try to locate a batch file for this host/target platform combo
 
373
        try:
 
374
            (vc_script,sdk_script) = find_batch_file(env,version,host_platform,tp)
 
375
            debug('vc.py:msvc_find_valid_batch_script() vc_script:%s sdk_script:%s'%(vc_script,sdk_script))
 
376
        except VisualCException, e:
 
377
            msg = str(e)
 
378
            debug('Caught exception while looking for batch file (%s)' % msg)
 
379
            warn_msg = "VC version %s not installed.  " + \
 
380
                       "C/C++ compilers are most likely not set correctly.\n" + \
 
381
                       " Installed versions are: %s"
 
382
            warn_msg = warn_msg % (version, cached_get_installed_vcs())
 
383
            SCons.Warnings.warn(SCons.Warnings.VisualCMissingWarning, warn_msg)
 
384
            continue
 
385
        
 
386
        # Try to use the located batch file for this host/target platform combo
 
387
        debug('vc.py:msvc_find_valid_batch_script() use_script 2 %s, args:%s\n' % (repr(vc_script), arg))
 
388
        if vc_script:
 
389
            try:
 
390
                d = script_env(vc_script, args=arg)
 
391
            except BatchFileExecutionError, e:
 
392
                debug('vc.py:msvc_find_valid_batch_script() use_script 3: failed running VC script %s: %s: Error:%s'%(repr(vc_script),arg,e))
 
393
                vc_script=None
 
394
        if not vc_script and sdk_script:
 
395
            debug('vc.py:msvc_find_valid_batch_script() use_script 4: trying sdk script: %s'%(sdk_script))
 
396
            try:
 
397
                d = script_env(sdk_script,args=[])
 
398
            except BatchFileExecutionError,e:
 
399
                debug('vc.py:msvc_find_valid_batch_script() use_script 5: failed running SDK script %s: Error:%s'%(repr(sdk_script),e))
 
400
                continue
 
401
        elif not vc_script and not sdk_script:
 
402
            debug('vc.py:msvc_find_valid_batch_script() use_script 6: Neither VC script nor SDK script found')
 
403
            continue
 
404
    
 
405
    # If we cannot find a viable installed compiler, reset the TARGET_ARCH
 
406
    # To it's initial value
 
407
    if not d:
 
408
        env['TARGET_ARCH']=req_target_platform
 
409
    
 
410
    return d
 
411
    
 
412
 
 
413
def msvc_setup_env(env):
 
414
    debug('msvc_setup_env()')
 
415
 
 
416
    version = get_default_version(env)
 
417
    if version is None:
 
418
        warn_msg = "No version of Visual Studio compiler found - C/C++ " \
 
419
                   "compilers most likely not set correctly"
 
420
        SCons.Warnings.warn(SCons.Warnings.VisualCMissingWarning, warn_msg)
 
421
        return None
 
422
    debug('msvc_setup_env: using specified MSVC version %s\n' % repr(version))
 
423
 
 
424
    # XXX: we set-up both MSVS version for backward
 
425
    # compatibility with the msvs tool
 
426
    env['MSVC_VERSION'] = version
 
427
    env['MSVS_VERSION'] = version
 
428
    env['MSVS'] = {}
 
429
 
 
430
    
 
431
    use_script = env.get('MSVC_USE_SCRIPT', True)
 
432
    if SCons.Util.is_String(use_script):
 
433
        debug('vc.py:msvc_setup_env() use_script 1 %s\n' % repr(use_script))
 
434
        d = script_env(use_script)
 
435
    elif use_script:      
 
436
        d = msvc_find_valid_batch_script(env,version)
 
437
        debug('vc.py:msvc_setup_env() use_script 2 %s\n' % d)
 
438
        if not d:
 
439
            return d
 
440
    else:
 
441
        debug('MSVC_USE_SCRIPT set to False')
 
442
        warn_msg = "MSVC_USE_SCRIPT set to False, assuming environment " \
 
443
                   "set correctly."
 
444
        SCons.Warnings.warn(SCons.Warnings.VisualCMissingWarning, warn_msg)
 
445
        return None
 
446
 
 
447
    for k, v in d.items():
 
448
        debug('vc.py:msvc_setup_env() env:%s -> %s'%(k,v))
 
449
        env.PrependENVPath(k, v, delete_existing=True)
 
450
 
 
451
def msvc_exists(version=None):
 
452
    vcs = cached_get_installed_vcs()
 
453
    if version is None:
 
454
        return len(vcs) > 0
 
455
    return version in vcs
 
456