forked from Tom/SconsLocal
init
This commit is contained in:
57
scons-local-3.0.0/SCons/Tool/MSCommon/__init__.py
Normal file
57
scons-local-3.0.0/SCons/Tool/MSCommon/__init__.py
Normal file
@@ -0,0 +1,57 @@
|
||||
#
|
||||
# Copyright (c) 2001 - 2017 The SCons Foundation
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining
|
||||
# a copy of this software and associated documentation files (the
|
||||
# "Software"), to deal in the Software without restriction, including
|
||||
# without limitation the rights to use, copy, modify, merge, publish,
|
||||
# distribute, sublicense, and/or sell copies of the Software, and to
|
||||
# permit persons to whom the Software is furnished to do so, subject to
|
||||
# the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be included
|
||||
# in all copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
|
||||
# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
|
||||
# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
#
|
||||
|
||||
__revision__ = "src/engine/SCons/Tool/MSCommon/__init__.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog"
|
||||
|
||||
__doc__ = """
|
||||
Common functions for Microsoft Visual Studio and Visual C/C++.
|
||||
"""
|
||||
|
||||
import copy
|
||||
import os
|
||||
import re
|
||||
import subprocess
|
||||
|
||||
import SCons.Errors
|
||||
import SCons.Platform.win32
|
||||
import SCons.Util
|
||||
|
||||
from SCons.Tool.MSCommon.sdk import mssdk_exists, \
|
||||
mssdk_setup_env
|
||||
|
||||
from SCons.Tool.MSCommon.vc import msvc_exists, \
|
||||
msvc_setup_env, \
|
||||
msvc_setup_env_once, \
|
||||
msvc_version_to_maj_min
|
||||
|
||||
from SCons.Tool.MSCommon.vs import get_default_version, \
|
||||
get_vs_by_version, \
|
||||
merge_default_version, \
|
||||
msvs_exists, \
|
||||
query_versions
|
||||
|
||||
# Local Variables:
|
||||
# tab-width:4
|
||||
# indent-tabs-mode:nil
|
||||
# End:
|
||||
# vim: set expandtab tabstop=4 shiftwidth=4:
|
67
scons-local-3.0.0/SCons/Tool/MSCommon/arch.py
Normal file
67
scons-local-3.0.0/SCons/Tool/MSCommon/arch.py
Normal file
@@ -0,0 +1,67 @@
|
||||
#
|
||||
# Copyright (c) 2001 - 2017 The SCons Foundation
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining
|
||||
# a copy of this software and associated documentation files (the
|
||||
# "Software"), to deal in the Software without restriction, including
|
||||
# without limitation the rights to use, copy, modify, merge, publish,
|
||||
# distribute, sublicense, and/or sell copies of the Software, and to
|
||||
# permit persons to whom the Software is furnished to do so, subject to
|
||||
# the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be included
|
||||
# in all copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
|
||||
# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
|
||||
# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
#
|
||||
|
||||
__revision__ = "src/engine/SCons/Tool/MSCommon/arch.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog"
|
||||
|
||||
__doc__ = """Module to define supported Windows chip architectures.
|
||||
"""
|
||||
|
||||
import os
|
||||
|
||||
class ArchDefinition(object):
|
||||
"""
|
||||
A class for defining architecture-specific settings and logic.
|
||||
"""
|
||||
def __init__(self, arch, synonyms=[]):
|
||||
self.arch = arch
|
||||
self.synonyms = synonyms
|
||||
|
||||
SupportedArchitectureList = [
|
||||
ArchitectureDefinition(
|
||||
'x86',
|
||||
['i386', 'i486', 'i586', 'i686'],
|
||||
),
|
||||
|
||||
ArchitectureDefinition(
|
||||
'x86_64',
|
||||
['AMD64', 'amd64', 'em64t', 'EM64T', 'x86_64'],
|
||||
),
|
||||
|
||||
ArchitectureDefinition(
|
||||
'ia64',
|
||||
['IA64'],
|
||||
),
|
||||
|
||||
ArchitectureDefinition(
|
||||
'arm',
|
||||
['ARM'],
|
||||
),
|
||||
|
||||
]
|
||||
|
||||
SupportedArchitectureMap = {}
|
||||
for a in SupportedArchitectureList:
|
||||
SupportedArchitectureMap[a.arch] = a
|
||||
for s in a.synonyms:
|
||||
SupportedArchitectureMap[s] = a
|
||||
|
247
scons-local-3.0.0/SCons/Tool/MSCommon/common.py
Normal file
247
scons-local-3.0.0/SCons/Tool/MSCommon/common.py
Normal file
@@ -0,0 +1,247 @@
|
||||
"""
|
||||
Common helper functions for working with the Microsoft tool chain.
|
||||
"""
|
||||
#
|
||||
# Copyright (c) 2001 - 2017 The SCons Foundation
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining
|
||||
# a copy of this software and associated documentation files (the
|
||||
# "Software"), to deal in the Software without restriction, including
|
||||
# without limitation the rights to use, copy, modify, merge, publish,
|
||||
# distribute, sublicense, and/or sell copies of the Software, and to
|
||||
# permit persons to whom the Software is furnished to do so, subject to
|
||||
# the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be included
|
||||
# in all copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
|
||||
# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
|
||||
# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
#
|
||||
from __future__ import print_function
|
||||
|
||||
__revision__ = "src/engine/SCons/Tool/MSCommon/common.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog"
|
||||
|
||||
import copy
|
||||
import os
|
||||
import subprocess
|
||||
import re
|
||||
|
||||
import SCons.Util
|
||||
|
||||
|
||||
LOGFILE = os.environ.get('SCONS_MSCOMMON_DEBUG')
|
||||
if LOGFILE == '-':
|
||||
def debug(message):
|
||||
print(message)
|
||||
elif LOGFILE:
|
||||
try:
|
||||
import logging
|
||||
except ImportError:
|
||||
debug = lambda message: open(LOGFILE, 'a').write(message + '\n')
|
||||
else:
|
||||
logging.basicConfig(filename=LOGFILE, level=logging.DEBUG)
|
||||
debug = logging.debug
|
||||
else:
|
||||
debug = lambda x: None
|
||||
|
||||
|
||||
_is_win64 = None
|
||||
|
||||
def is_win64():
|
||||
"""Return true if running on windows 64 bits.
|
||||
|
||||
Works whether python itself runs in 64 bits or 32 bits."""
|
||||
# Unfortunately, python does not provide a useful way to determine
|
||||
# if the underlying Windows OS is 32-bit or 64-bit. Worse, whether
|
||||
# the Python itself is 32-bit or 64-bit affects what it returns,
|
||||
# so nothing in sys.* or os.* help.
|
||||
|
||||
# Apparently the best solution is to use env vars that Windows
|
||||
# sets. If PROCESSOR_ARCHITECTURE is not x86, then the python
|
||||
# process is running in 64 bit mode (on a 64-bit OS, 64-bit
|
||||
# hardware, obviously).
|
||||
# If this python is 32-bit but the OS is 64, Windows will set
|
||||
# ProgramW6432 and PROCESSOR_ARCHITEW6432 to non-null.
|
||||
# (Checking for HKLM\Software\Wow6432Node in the registry doesn't
|
||||
# work, because some 32-bit installers create it.)
|
||||
global _is_win64
|
||||
if _is_win64 is None:
|
||||
# I structured these tests to make it easy to add new ones or
|
||||
# add exceptions in the future, because this is a bit fragile.
|
||||
_is_win64 = False
|
||||
if os.environ.get('PROCESSOR_ARCHITECTURE', 'x86') != 'x86':
|
||||
_is_win64 = True
|
||||
if os.environ.get('PROCESSOR_ARCHITEW6432'):
|
||||
_is_win64 = True
|
||||
if os.environ.get('ProgramW6432'):
|
||||
_is_win64 = True
|
||||
return _is_win64
|
||||
|
||||
|
||||
def read_reg(value, hkroot=SCons.Util.HKEY_LOCAL_MACHINE):
|
||||
return SCons.Util.RegGetValue(hkroot, value)[0]
|
||||
|
||||
def has_reg(value):
|
||||
"""Return True if the given key exists in HKEY_LOCAL_MACHINE, False
|
||||
otherwise."""
|
||||
try:
|
||||
SCons.Util.RegOpenKeyEx(SCons.Util.HKEY_LOCAL_MACHINE, value)
|
||||
ret = True
|
||||
except SCons.Util.WinError:
|
||||
ret = False
|
||||
return ret
|
||||
|
||||
# Functions for fetching environment variable settings from batch files.
|
||||
|
||||
def normalize_env(env, keys, force=False):
|
||||
"""Given a dictionary representing a shell environment, add the variables
|
||||
from os.environ needed for the processing of .bat files; the keys are
|
||||
controlled by the keys argument.
|
||||
|
||||
It also makes sure the environment values are correctly encoded.
|
||||
|
||||
If force=True, then all of the key values that exist are copied
|
||||
into the returned dictionary. If force=false, values are only
|
||||
copied if the key does not already exist in the copied dictionary.
|
||||
|
||||
Note: the environment is copied."""
|
||||
normenv = {}
|
||||
if env:
|
||||
for k in list(env.keys()):
|
||||
normenv[k] = copy.deepcopy(env[k])
|
||||
|
||||
for k in keys:
|
||||
if k in os.environ and (force or not k in normenv):
|
||||
normenv[k] = os.environ[k]
|
||||
|
||||
# This shouldn't be necessary, since the default environment should include system32,
|
||||
# but keep this here to be safe, since it's needed to find reg.exe which the MSVC
|
||||
# bat scripts use.
|
||||
sys32_dir = os.path.join(os.environ.get("SystemRoot",
|
||||
os.environ.get("windir", r"C:\Windows\system32")),
|
||||
"System32")
|
||||
|
||||
if sys32_dir not in normenv['PATH']:
|
||||
normenv['PATH'] = normenv['PATH'] + os.pathsep + sys32_dir
|
||||
|
||||
# Without Wbem in PATH, vcvarsall.bat has a "'wmic' is not recognized"
|
||||
# error starting with Visual Studio 2017, although the script still
|
||||
# seems to work anyway.
|
||||
sys32_wbem_dir = os.path.join(sys32_dir, 'Wbem')
|
||||
if sys32_wbem_dir not in normenv['PATH']:
|
||||
normenv['PATH'] = normenv['PATH'] + os.pathsep + sys32_wbem_dir
|
||||
|
||||
debug("PATH: %s"%normenv['PATH'])
|
||||
|
||||
return normenv
|
||||
|
||||
def get_output(vcbat, args = None, env = None):
|
||||
"""Parse the output of given bat file, with given args."""
|
||||
|
||||
if env is None:
|
||||
# Create a blank environment, for use in launching the tools
|
||||
env = SCons.Environment.Environment(tools=[])
|
||||
|
||||
# TODO: This is a hard-coded list of the variables that (may) need
|
||||
# to be imported from os.environ[] for v[sc]*vars*.bat file
|
||||
# execution to work. This list should really be either directly
|
||||
# controlled by vc.py, or else derived from the common_tools_var
|
||||
# settings in vs.py.
|
||||
vs_vc_vars = [
|
||||
'COMSPEC',
|
||||
# VS100 and VS110: Still set, but modern MSVC setup scripts will
|
||||
# discard these if registry has values. However Intel compiler setup
|
||||
# script still requires these as of 2013/2014.
|
||||
'VS140COMNTOOLS',
|
||||
'VS120COMNTOOLS',
|
||||
'VS110COMNTOOLS',
|
||||
'VS100COMNTOOLS',
|
||||
'VS90COMNTOOLS',
|
||||
'VS80COMNTOOLS',
|
||||
'VS71COMNTOOLS',
|
||||
'VS70COMNTOOLS',
|
||||
'VS60COMNTOOLS',
|
||||
]
|
||||
env['ENV'] = normalize_env(env['ENV'], vs_vc_vars, force=False)
|
||||
|
||||
if args:
|
||||
debug("Calling '%s %s'" % (vcbat, args))
|
||||
popen = SCons.Action._subproc(env,
|
||||
'"%s" %s & set' % (vcbat, args),
|
||||
stdin='devnull',
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.PIPE)
|
||||
else:
|
||||
debug("Calling '%s'" % vcbat)
|
||||
popen = SCons.Action._subproc(env,
|
||||
'"%s" & set' % vcbat,
|
||||
stdin='devnull',
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.PIPE)
|
||||
|
||||
# Use the .stdout and .stderr attributes directly because the
|
||||
# .communicate() method uses the threading module on Windows
|
||||
# and won't work under Pythons not built with threading.
|
||||
stdout = popen.stdout.read()
|
||||
stderr = popen.stderr.read()
|
||||
|
||||
# Extra debug logic, uncomment if necessary
|
||||
# debug('get_output():stdout:%s'%stdout)
|
||||
# debug('get_output():stderr:%s'%stderr)
|
||||
|
||||
if stderr:
|
||||
# TODO: find something better to do with stderr;
|
||||
# this at least prevents errors from getting swallowed.
|
||||
import sys
|
||||
sys.stderr.write(stderr)
|
||||
if popen.wait() != 0:
|
||||
raise IOError(stderr.decode("mbcs"))
|
||||
|
||||
output = stdout.decode("mbcs")
|
||||
return output
|
||||
|
||||
def parse_output(output, keep=("INCLUDE", "LIB", "LIBPATH", "PATH")):
|
||||
"""
|
||||
Parse output from running visual c++/studios vcvarsall.bat and running set
|
||||
To capture the values listed in keep
|
||||
"""
|
||||
|
||||
# dkeep is a dict associating key: path_list, where key is one item from
|
||||
# keep, and pat_list the associated list of paths
|
||||
dkeep = dict([(i, []) for i in keep])
|
||||
|
||||
# rdk will keep the regex to match the .bat file output line starts
|
||||
rdk = {}
|
||||
for i in keep:
|
||||
rdk[i] = re.compile('%s=(.*)' % i, re.I)
|
||||
|
||||
def add_env(rmatch, key, dkeep=dkeep):
|
||||
path_list = rmatch.group(1).split(os.pathsep)
|
||||
for path in path_list:
|
||||
# Do not add empty paths (when a var ends with ;)
|
||||
if path:
|
||||
# XXX: For some reason, VC98 .bat file adds "" around the PATH
|
||||
# values, and it screws up the environment later, so we strip
|
||||
# it.
|
||||
path = path.strip('"')
|
||||
dkeep[key].append(str(path))
|
||||
|
||||
for line in output.splitlines():
|
||||
for k, value in rdk.items():
|
||||
match = value.match(line)
|
||||
if match:
|
||||
add_env(match, k)
|
||||
|
||||
return dkeep
|
||||
|
||||
# Local Variables:
|
||||
# tab-width:4
|
||||
# indent-tabs-mode:nil
|
||||
# End:
|
||||
# vim: set expandtab tabstop=4 shiftwidth=4:
|
83
scons-local-3.0.0/SCons/Tool/MSCommon/netframework.py
Normal file
83
scons-local-3.0.0/SCons/Tool/MSCommon/netframework.py
Normal file
@@ -0,0 +1,83 @@
|
||||
#
|
||||
# Copyright (c) 2001 - 2017 The SCons Foundation
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining
|
||||
# a copy of this software and associated documentation files (the
|
||||
# "Software"), to deal in the Software without restriction, including
|
||||
# without limitation the rights to use, copy, modify, merge, publish,
|
||||
# distribute, sublicense, and/or sell copies of the Software, and to
|
||||
# permit persons to whom the Software is furnished to do so, subject to
|
||||
# the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be included
|
||||
# in all copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
|
||||
# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
|
||||
# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
__revision__ = "src/engine/SCons/Tool/MSCommon/netframework.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog"
|
||||
|
||||
__doc__ = """
|
||||
"""
|
||||
|
||||
import os
|
||||
import re
|
||||
import SCons.Util
|
||||
|
||||
from .common import read_reg, debug
|
||||
|
||||
# Original value recorded by dcournapeau
|
||||
_FRAMEWORKDIR_HKEY_ROOT = r'Software\Microsoft\.NETFramework\InstallRoot'
|
||||
# On SGK's system
|
||||
_FRAMEWORKDIR_HKEY_ROOT = r'Software\Microsoft\Microsoft SDKs\.NETFramework\v2.0\InstallationFolder'
|
||||
|
||||
def find_framework_root():
|
||||
# XXX: find it from environment (FrameworkDir)
|
||||
try:
|
||||
froot = read_reg(_FRAMEWORKDIR_HKEY_ROOT)
|
||||
debug("Found framework install root in registry: {}".format(froot))
|
||||
except SCons.Util.WinError as e:
|
||||
debug("Could not read reg key {}".format(_FRAMEWORKDIR_HKEY_ROOT))
|
||||
return None
|
||||
|
||||
if not os.path.exists(froot):
|
||||
debug("{} not found on fs".format(froot))
|
||||
return None
|
||||
|
||||
return froot
|
||||
|
||||
def query_versions():
|
||||
froot = find_framework_root()
|
||||
if froot:
|
||||
contents = os.listdir(froot)
|
||||
|
||||
l = re.compile('v[0-9]+.*')
|
||||
versions = [e for e in contents if l.match(e)]
|
||||
|
||||
def versrt(a,b):
|
||||
# since version numbers aren't really floats...
|
||||
aa = a[1:]
|
||||
bb = b[1:]
|
||||
aal = aa.split('.')
|
||||
bbl = bb.split('.')
|
||||
# sequence comparison in python is lexicographical
|
||||
# which is exactly what we want.
|
||||
# Note we sort backwards so the highest version is first.
|
||||
return cmp(bbl,aal)
|
||||
|
||||
versions.sort(versrt)
|
||||
else:
|
||||
versions = []
|
||||
|
||||
return versions
|
||||
|
||||
# Local Variables:
|
||||
# tab-width:4
|
||||
# indent-tabs-mode:nil
|
||||
# End:
|
||||
# vim: set expandtab tabstop=4 shiftwidth=4:
|
403
scons-local-3.0.0/SCons/Tool/MSCommon/sdk.py
Normal file
403
scons-local-3.0.0/SCons/Tool/MSCommon/sdk.py
Normal file
@@ -0,0 +1,403 @@
|
||||
#
|
||||
# Copyright (c) 2001 - 2017 The SCons Foundation
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining
|
||||
# a copy of this software and associated documentation files (the
|
||||
# "Software"), to deal in the Software without restriction, including
|
||||
# without limitation the rights to use, copy, modify, merge, publish,
|
||||
# distribute, sublicense, and/or sell copies of the Software, and to
|
||||
# permit persons to whom the Software is furnished to do so, subject to
|
||||
# the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be included
|
||||
# in all copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
|
||||
# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
|
||||
# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
|
||||
__revision__ = "src/engine/SCons/Tool/MSCommon/sdk.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog"
|
||||
|
||||
__doc__ = """Module to detect the Platform/Windows SDK
|
||||
|
||||
PSDK 2003 R1 is the earliest version detected.
|
||||
"""
|
||||
|
||||
import os
|
||||
|
||||
import SCons.Errors
|
||||
import SCons.Util
|
||||
|
||||
from . import common
|
||||
|
||||
debug = common.debug
|
||||
|
||||
# SDK Checks. This is of course a mess as everything else on MS platforms. Here
|
||||
# is what we do to detect the SDK:
|
||||
#
|
||||
# For Windows SDK >= 6.0: just look into the registry entries:
|
||||
# HKLM\Software\Microsoft\Microsoft SDKs\Windows
|
||||
# All the keys in there are the available versions.
|
||||
#
|
||||
# For Platform SDK before 6.0 (2003 server R1 and R2, etc...), there does not
|
||||
# seem to be any sane registry key, so the precise location is hardcoded.
|
||||
#
|
||||
# For versions below 2003R1, it seems the PSDK is included with Visual Studio?
|
||||
#
|
||||
# Also, per the following:
|
||||
# http://benjamin.smedbergs.us/blog/tag/atl/
|
||||
# VC++ Professional comes with the SDK, VC++ Express does not.
|
||||
|
||||
# Location of the SDK (checked for 6.1 only)
|
||||
_CURINSTALLED_SDK_HKEY_ROOT = \
|
||||
r"Software\Microsoft\Microsoft SDKs\Windows\CurrentInstallFolder"
|
||||
|
||||
|
||||
class SDKDefinition(object):
|
||||
"""
|
||||
An abstract base class for trying to find installed SDK directories.
|
||||
"""
|
||||
def __init__(self, version, **kw):
|
||||
self.version = version
|
||||
self.__dict__.update(kw)
|
||||
|
||||
def find_sdk_dir(self):
|
||||
"""Try to find the MS SDK from the registry.
|
||||
|
||||
Return None if failed or the directory does not exist.
|
||||
"""
|
||||
if not SCons.Util.can_read_reg:
|
||||
debug('find_sdk_dir(): can not read registry')
|
||||
return None
|
||||
|
||||
hkey = self.HKEY_FMT % self.hkey_data
|
||||
debug('find_sdk_dir(): checking registry:{}'.format(hkey))
|
||||
|
||||
try:
|
||||
sdk_dir = common.read_reg(hkey)
|
||||
except SCons.Util.WinError as e:
|
||||
debug('find_sdk_dir(): no SDK registry key {}'.format(repr(hkey)))
|
||||
return None
|
||||
|
||||
debug('find_sdk_dir(): Trying SDK Dir: {}'.format(sdk_dir))
|
||||
|
||||
if not os.path.exists(sdk_dir):
|
||||
debug('find_sdk_dir(): {} not on file system'.format(sdk_dir))
|
||||
return None
|
||||
|
||||
ftc = os.path.join(sdk_dir, self.sanity_check_file)
|
||||
if not os.path.exists(ftc):
|
||||
debug("find_sdk_dir(): sanity check {} not found".format(ftc))
|
||||
return None
|
||||
|
||||
return sdk_dir
|
||||
|
||||
def get_sdk_dir(self):
|
||||
"""Return the MSSSDK given the version string."""
|
||||
try:
|
||||
return self._sdk_dir
|
||||
except AttributeError:
|
||||
sdk_dir = self.find_sdk_dir()
|
||||
self._sdk_dir = sdk_dir
|
||||
return sdk_dir
|
||||
|
||||
def get_sdk_vc_script(self,host_arch, target_arch):
|
||||
""" Return the script to initialize the VC compiler installed by SDK
|
||||
"""
|
||||
|
||||
if (host_arch == 'amd64' and target_arch == 'x86'):
|
||||
# No cross tools needed compiling 32 bits on 64 bit machine
|
||||
host_arch=target_arch
|
||||
|
||||
arch_string=target_arch
|
||||
if (host_arch != target_arch):
|
||||
arch_string='%s_%s'%(host_arch,target_arch)
|
||||
|
||||
debug("sdk.py: get_sdk_vc_script():arch_string:%s host_arch:%s target_arch:%s"%(arch_string,
|
||||
host_arch,
|
||||
target_arch))
|
||||
file=self.vc_setup_scripts.get(arch_string,None)
|
||||
debug("sdk.py: get_sdk_vc_script():file:%s"%file)
|
||||
return file
|
||||
|
||||
class WindowsSDK(SDKDefinition):
|
||||
"""
|
||||
A subclass for trying to find installed Windows SDK directories.
|
||||
"""
|
||||
HKEY_FMT = r'Software\Microsoft\Microsoft SDKs\Windows\v%s\InstallationFolder'
|
||||
def __init__(self, *args, **kw):
|
||||
SDKDefinition.__init__(self, *args, **kw)
|
||||
self.hkey_data = self.version
|
||||
|
||||
class PlatformSDK(SDKDefinition):
|
||||
"""
|
||||
A subclass for trying to find installed Platform SDK directories.
|
||||
"""
|
||||
HKEY_FMT = r'Software\Microsoft\MicrosoftSDK\InstalledSDKS\%s\Install Dir'
|
||||
def __init__(self, *args, **kw):
|
||||
SDKDefinition.__init__(self, *args, **kw)
|
||||
self.hkey_data = self.uuid
|
||||
|
||||
#
|
||||
# The list of VC initialization scripts installed by the SDK
|
||||
# These should be tried if the vcvarsall.bat TARGET_ARCH fails
|
||||
preSDK61VCSetupScripts = { 'x86' : r'bin\vcvars32.bat',
|
||||
'amd64' : r'bin\vcvarsamd64.bat',
|
||||
'x86_amd64': r'bin\vcvarsx86_amd64.bat',
|
||||
'x86_ia64' : r'bin\vcvarsx86_ia64.bat',
|
||||
'ia64' : r'bin\vcvarsia64.bat'}
|
||||
|
||||
SDK61VCSetupScripts = {'x86' : r'bin\vcvars32.bat',
|
||||
'amd64' : r'bin\amd64\vcvarsamd64.bat',
|
||||
'x86_amd64': r'bin\x86_amd64\vcvarsx86_amd64.bat',
|
||||
'x86_ia64' : r'bin\x86_ia64\vcvarsx86_ia64.bat',
|
||||
'ia64' : r'bin\ia64\vcvarsia64.bat'}
|
||||
|
||||
SDK70VCSetupScripts = { 'x86' : r'bin\vcvars32.bat',
|
||||
'amd64' : r'bin\vcvars64.bat',
|
||||
'x86_amd64': r'bin\vcvarsx86_amd64.bat',
|
||||
'x86_ia64' : r'bin\vcvarsx86_ia64.bat',
|
||||
'ia64' : r'bin\vcvarsia64.bat'}
|
||||
|
||||
SDK100VCSetupScripts = {'x86' : r'bin\vcvars32.bat',
|
||||
'amd64' : r'bin\vcvars64.bat',
|
||||
'x86_amd64': r'bin\x86_amd64\vcvarsx86_amd64.bat',
|
||||
'x86_arm' : r'bin\x86_arm\vcvarsx86_arm.bat'}
|
||||
|
||||
|
||||
# The list of support SDKs which we know how to detect.
|
||||
#
|
||||
# The first SDK found in the list is the one used by default if there
|
||||
# are multiple SDKs installed. Barring good reasons to the contrary,
|
||||
# this means we should list SDKs from most recent to oldest.
|
||||
#
|
||||
# If you update this list, update the documentation in Tool/mssdk.xml.
|
||||
SupportedSDKList = [
|
||||
WindowsSDK('10.0',
|
||||
sanity_check_file=r'bin\SetEnv.Cmd',
|
||||
include_subdir='include',
|
||||
lib_subdir={
|
||||
'x86' : ['lib'],
|
||||
'x86_64' : [r'lib\x64'],
|
||||
'ia64' : [r'lib\ia64'],
|
||||
},
|
||||
vc_setup_scripts = SDK70VCSetupScripts,
|
||||
),
|
||||
WindowsSDK('7.1',
|
||||
sanity_check_file=r'bin\SetEnv.Cmd',
|
||||
include_subdir='include',
|
||||
lib_subdir={
|
||||
'x86' : ['lib'],
|
||||
'x86_64' : [r'lib\x64'],
|
||||
'ia64' : [r'lib\ia64'],
|
||||
},
|
||||
vc_setup_scripts = SDK70VCSetupScripts,
|
||||
),
|
||||
WindowsSDK('7.0A',
|
||||
sanity_check_file=r'bin\SetEnv.Cmd',
|
||||
include_subdir='include',
|
||||
lib_subdir={
|
||||
'x86' : ['lib'],
|
||||
'x86_64' : [r'lib\x64'],
|
||||
'ia64' : [r'lib\ia64'],
|
||||
},
|
||||
vc_setup_scripts = SDK70VCSetupScripts,
|
||||
),
|
||||
WindowsSDK('7.0',
|
||||
sanity_check_file=r'bin\SetEnv.Cmd',
|
||||
include_subdir='include',
|
||||
lib_subdir={
|
||||
'x86' : ['lib'],
|
||||
'x86_64' : [r'lib\x64'],
|
||||
'ia64' : [r'lib\ia64'],
|
||||
},
|
||||
vc_setup_scripts = SDK70VCSetupScripts,
|
||||
),
|
||||
WindowsSDK('6.1',
|
||||
sanity_check_file=r'bin\SetEnv.Cmd',
|
||||
include_subdir='include',
|
||||
lib_subdir={
|
||||
'x86' : ['lib'],
|
||||
'x86_64' : [r'lib\x64'],
|
||||
'ia64' : [r'lib\ia64'],
|
||||
},
|
||||
vc_setup_scripts = SDK61VCSetupScripts,
|
||||
),
|
||||
|
||||
WindowsSDK('6.0A',
|
||||
sanity_check_file=r'include\windows.h',
|
||||
include_subdir='include',
|
||||
lib_subdir={
|
||||
'x86' : ['lib'],
|
||||
'x86_64' : [r'lib\x64'],
|
||||
'ia64' : [r'lib\ia64'],
|
||||
},
|
||||
vc_setup_scripts = preSDK61VCSetupScripts,
|
||||
),
|
||||
|
||||
WindowsSDK('6.0',
|
||||
sanity_check_file=r'bin\gacutil.exe',
|
||||
include_subdir='include',
|
||||
lib_subdir='lib',
|
||||
vc_setup_scripts = preSDK61VCSetupScripts,
|
||||
),
|
||||
|
||||
PlatformSDK('2003R2',
|
||||
sanity_check_file=r'SetEnv.Cmd',
|
||||
uuid="D2FF9F89-8AA2-4373-8A31-C838BF4DBBE1",
|
||||
vc_setup_scripts = preSDK61VCSetupScripts,
|
||||
),
|
||||
|
||||
PlatformSDK('2003R1',
|
||||
sanity_check_file=r'SetEnv.Cmd',
|
||||
uuid="8F9E5EF3-A9A5-491B-A889-C58EFFECE8B3",
|
||||
vc_setup_scripts = preSDK61VCSetupScripts,
|
||||
),
|
||||
]
|
||||
|
||||
SupportedSDKMap = {}
|
||||
for sdk in SupportedSDKList:
|
||||
SupportedSDKMap[sdk.version] = sdk
|
||||
|
||||
|
||||
# Finding installed SDKs isn't cheap, because it goes not only to the
|
||||
# registry but also to the disk to sanity-check that there is, in fact,
|
||||
# an SDK installed there and that the registry entry isn't just stale.
|
||||
# Find this information once, when requested, and cache it.
|
||||
|
||||
InstalledSDKList = None
|
||||
InstalledSDKMap = None
|
||||
|
||||
def get_installed_sdks():
|
||||
global InstalledSDKList
|
||||
global InstalledSDKMap
|
||||
debug('sdk.py:get_installed_sdks()')
|
||||
if InstalledSDKList is None:
|
||||
InstalledSDKList = []
|
||||
InstalledSDKMap = {}
|
||||
for sdk in SupportedSDKList:
|
||||
debug('MSCommon/sdk.py: trying to find SDK %s' % sdk.version)
|
||||
if sdk.get_sdk_dir():
|
||||
debug('MSCommon/sdk.py:found SDK %s' % sdk.version)
|
||||
InstalledSDKList.append(sdk)
|
||||
InstalledSDKMap[sdk.version] = sdk
|
||||
return InstalledSDKList
|
||||
|
||||
|
||||
# We may be asked to update multiple construction environments with
|
||||
# SDK information. When doing this, we check on-disk for whether
|
||||
# the SDK has 'mfc' and 'atl' subdirectories. Since going to disk
|
||||
# is expensive, cache results by directory.
|
||||
|
||||
SDKEnvironmentUpdates = {}
|
||||
|
||||
def set_sdk_by_directory(env, sdk_dir):
|
||||
global SDKEnvironmentUpdates
|
||||
debug('set_sdk_by_directory: Using dir:%s'%sdk_dir)
|
||||
try:
|
||||
env_tuple_list = SDKEnvironmentUpdates[sdk_dir]
|
||||
except KeyError:
|
||||
env_tuple_list = []
|
||||
SDKEnvironmentUpdates[sdk_dir] = env_tuple_list
|
||||
|
||||
include_path = os.path.join(sdk_dir, 'include')
|
||||
mfc_path = os.path.join(include_path, 'mfc')
|
||||
atl_path = os.path.join(include_path, 'atl')
|
||||
|
||||
if os.path.exists(mfc_path):
|
||||
env_tuple_list.append(('INCLUDE', mfc_path))
|
||||
if os.path.exists(atl_path):
|
||||
env_tuple_list.append(('INCLUDE', atl_path))
|
||||
env_tuple_list.append(('INCLUDE', include_path))
|
||||
|
||||
env_tuple_list.append(('LIB', os.path.join(sdk_dir, 'lib')))
|
||||
env_tuple_list.append(('LIBPATH', os.path.join(sdk_dir, 'lib')))
|
||||
env_tuple_list.append(('PATH', os.path.join(sdk_dir, 'bin')))
|
||||
|
||||
for variable, directory in env_tuple_list:
|
||||
env.PrependENVPath(variable, directory)
|
||||
|
||||
def get_sdk_by_version(mssdk):
|
||||
if mssdk not in SupportedSDKMap:
|
||||
raise SCons.Errors.UserError("SDK version {} is not supported".format(repr(mssdk)))
|
||||
get_installed_sdks()
|
||||
return InstalledSDKMap.get(mssdk)
|
||||
|
||||
def get_default_sdk():
|
||||
"""Set up the default Platform/Windows SDK."""
|
||||
get_installed_sdks()
|
||||
if not InstalledSDKList:
|
||||
return None
|
||||
return InstalledSDKList[0]
|
||||
|
||||
def mssdk_setup_env(env):
|
||||
debug('sdk.py:mssdk_setup_env()')
|
||||
if 'MSSDK_DIR' in env:
|
||||
sdk_dir = env['MSSDK_DIR']
|
||||
if sdk_dir is None:
|
||||
return
|
||||
sdk_dir = env.subst(sdk_dir)
|
||||
debug('sdk.py:mssdk_setup_env: Using MSSDK_DIR:{}'.format(sdk_dir))
|
||||
elif 'MSSDK_VERSION' in env:
|
||||
sdk_version = env['MSSDK_VERSION']
|
||||
if sdk_version is None:
|
||||
msg = "SDK version is specified as None"
|
||||
raise SCons.Errors.UserError(msg)
|
||||
sdk_version = env.subst(sdk_version)
|
||||
mssdk = get_sdk_by_version(sdk_version)
|
||||
if mssdk is None:
|
||||
msg = "SDK version %s is not installed" % sdk_version
|
||||
raise SCons.Errors.UserError(msg)
|
||||
sdk_dir = mssdk.get_sdk_dir()
|
||||
debug('sdk.py:mssdk_setup_env: Using MSSDK_VERSION:%s'%sdk_dir)
|
||||
elif 'MSVS_VERSION' in env:
|
||||
msvs_version = env['MSVS_VERSION']
|
||||
debug('sdk.py:mssdk_setup_env:Getting MSVS_VERSION from env:%s'%msvs_version)
|
||||
if msvs_version is None:
|
||||
debug('sdk.py:mssdk_setup_env thinks msvs_version is None')
|
||||
return
|
||||
msvs_version = env.subst(msvs_version)
|
||||
from . import vs
|
||||
msvs = vs.get_vs_by_version(msvs_version)
|
||||
debug('sdk.py:mssdk_setup_env:msvs is :%s'%msvs)
|
||||
if not msvs:
|
||||
debug('sdk.py:mssdk_setup_env: no VS version detected, bailingout:%s'%msvs)
|
||||
return
|
||||
sdk_version = msvs.sdk_version
|
||||
debug('sdk.py:msvs.sdk_version is %s'%sdk_version)
|
||||
if not sdk_version:
|
||||
return
|
||||
mssdk = get_sdk_by_version(sdk_version)
|
||||
if not mssdk:
|
||||
mssdk = get_default_sdk()
|
||||
if not mssdk:
|
||||
return
|
||||
sdk_dir = mssdk.get_sdk_dir()
|
||||
debug('sdk.py:mssdk_setup_env: Using MSVS_VERSION:%s'%sdk_dir)
|
||||
else:
|
||||
mssdk = get_default_sdk()
|
||||
if not mssdk:
|
||||
return
|
||||
sdk_dir = mssdk.get_sdk_dir()
|
||||
debug('sdk.py:mssdk_setup_env: not using any env values. sdk_dir:%s'%sdk_dir)
|
||||
|
||||
set_sdk_by_directory(env, sdk_dir)
|
||||
|
||||
#print "No MSVS_VERSION: this is likely to be a bug"
|
||||
|
||||
def mssdk_exists(version=None):
|
||||
sdks = get_installed_sdks()
|
||||
if version is None:
|
||||
return len(sdks) > 0
|
||||
return version in sdks
|
||||
|
||||
# Local Variables:
|
||||
# tab-width:4
|
||||
# indent-tabs-mode:nil
|
||||
# End:
|
||||
# vim: set expandtab tabstop=4 shiftwidth=4:
|
573
scons-local-3.0.0/SCons/Tool/MSCommon/vc.py
Normal file
573
scons-local-3.0.0/SCons/Tool/MSCommon/vc.py
Normal file
@@ -0,0 +1,573 @@
|
||||
#
|
||||
# Copyright (c) 2001 - 2017 The SCons Foundation
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining
|
||||
# a copy of this software and associated documentation files (the
|
||||
# "Software"), to deal in the Software without restriction, including
|
||||
# without limitation the rights to use, copy, modify, merge, publish,
|
||||
# distribute, sublicense, and/or sell copies of the Software, and to
|
||||
# permit persons to whom the Software is furnished to do so, subject to
|
||||
# the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be included
|
||||
# in all copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
|
||||
# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
|
||||
# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
#
|
||||
|
||||
# TODO:
|
||||
# * supported arch for versions: for old versions of batch file without
|
||||
# argument, giving bogus argument cannot be detected, so we have to hardcode
|
||||
# this here
|
||||
# * print warning when msvc version specified but not found
|
||||
# * find out why warning do not print
|
||||
# * test on 64 bits XP + VS 2005 (and VS 6 if possible)
|
||||
# * SDK
|
||||
# * Assembly
|
||||
__revision__ = "src/engine/SCons/Tool/MSCommon/vc.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog"
|
||||
|
||||
__doc__ = """Module for Visual C/C++ detection and configuration.
|
||||
"""
|
||||
import SCons.compat
|
||||
import SCons.Util
|
||||
|
||||
import subprocess
|
||||
import os
|
||||
import platform
|
||||
from string import digits as string_digits
|
||||
|
||||
import SCons.Warnings
|
||||
|
||||
from . import common
|
||||
|
||||
debug = common.debug
|
||||
|
||||
from . import sdk
|
||||
|
||||
get_installed_sdks = sdk.get_installed_sdks
|
||||
|
||||
|
||||
class VisualCException(Exception):
|
||||
pass
|
||||
|
||||
class UnsupportedVersion(VisualCException):
|
||||
pass
|
||||
|
||||
class UnsupportedArch(VisualCException):
|
||||
pass
|
||||
|
||||
class MissingConfiguration(VisualCException):
|
||||
pass
|
||||
|
||||
class NoVersionFound(VisualCException):
|
||||
pass
|
||||
|
||||
class BatchFileExecutionError(VisualCException):
|
||||
pass
|
||||
|
||||
# Dict to 'canonalize' the arch
|
||||
_ARCH_TO_CANONICAL = {
|
||||
"amd64" : "amd64",
|
||||
"emt64" : "amd64",
|
||||
"i386" : "x86",
|
||||
"i486" : "x86",
|
||||
"i586" : "x86",
|
||||
"i686" : "x86",
|
||||
"ia64" : "ia64",
|
||||
"itanium" : "ia64",
|
||||
"x86" : "x86",
|
||||
"x86_64" : "amd64",
|
||||
"x86_amd64" : "x86_amd64", # Cross compile to 64 bit from 32bits
|
||||
}
|
||||
|
||||
# Given a (host, target) tuple, return the argument for the bat file. Both host
|
||||
# and targets should be canonalized.
|
||||
_HOST_TARGET_ARCH_TO_BAT_ARCH = {
|
||||
("x86", "x86"): "x86",
|
||||
("x86", "amd64"): "x86_amd64",
|
||||
("x86", "x86_amd64"): "x86_amd64",
|
||||
("amd64", "x86_amd64"): "x86_amd64", # This is present in (at least) VS2012 express
|
||||
("amd64", "amd64"): "amd64",
|
||||
("amd64", "x86"): "x86",
|
||||
("x86", "ia64"): "x86_ia64"
|
||||
}
|
||||
|
||||
def get_host_target(env):
|
||||
debug('vc.py:get_host_target()')
|
||||
|
||||
host_platform = env.get('HOST_ARCH')
|
||||
if not host_platform:
|
||||
host_platform = platform.machine()
|
||||
# TODO(2.5): the native Python platform.machine() function returns
|
||||
# '' on all Python versions before 2.6, after which it also uses
|
||||
# PROCESSOR_ARCHITECTURE.
|
||||
if not host_platform:
|
||||
host_platform = os.environ.get('PROCESSOR_ARCHITECTURE', '')
|
||||
|
||||
# Retain user requested TARGET_ARCH
|
||||
req_target_platform = env.get('TARGET_ARCH')
|
||||
debug('vc.py:get_host_target() req_target_platform:%s'%req_target_platform)
|
||||
|
||||
if req_target_platform:
|
||||
# If user requested a specific platform then only try that one.
|
||||
target_platform = req_target_platform
|
||||
else:
|
||||
target_platform = host_platform
|
||||
|
||||
try:
|
||||
host = _ARCH_TO_CANONICAL[host_platform.lower()]
|
||||
except KeyError as e:
|
||||
msg = "Unrecognized host architecture %s"
|
||||
raise ValueError(msg % repr(host_platform))
|
||||
|
||||
try:
|
||||
target = _ARCH_TO_CANONICAL[target_platform.lower()]
|
||||
except KeyError as e:
|
||||
all_archs = str(list(_ARCH_TO_CANONICAL.keys()))
|
||||
raise ValueError("Unrecognized target architecture %s\n\tValid architectures: %s" % (target_platform, all_archs))
|
||||
|
||||
return (host, target,req_target_platform)
|
||||
|
||||
# If you update this, update SupportedVSList in Tool/MSCommon/vs.py, and the
|
||||
# MSVC_VERSION documentation in Tool/msvc.xml.
|
||||
_VCVER = ["14.1", "14.0", "14.0Exp", "12.0", "12.0Exp", "11.0", "11.0Exp", "10.0", "10.0Exp", "9.0", "9.0Exp","8.0", "8.0Exp","7.1", "7.0", "6.0"]
|
||||
|
||||
_VCVER_TO_PRODUCT_DIR = {
|
||||
'14.1' : [
|
||||
(SCons.Util.HKEY_LOCAL_MACHINE, r'')], # Visual Studio 2017 doesn't set this registry key anymore
|
||||
'14.0' : [
|
||||
(SCons.Util.HKEY_LOCAL_MACHINE, r'Microsoft\VisualStudio\14.0\Setup\VC\ProductDir')],
|
||||
'14.0Exp' : [
|
||||
(SCons.Util.HKEY_LOCAL_MACHINE, r'Microsoft\VCExpress\14.0\Setup\VC\ProductDir')],
|
||||
'12.0' : [
|
||||
(SCons.Util.HKEY_LOCAL_MACHINE, r'Microsoft\VisualStudio\12.0\Setup\VC\ProductDir'),
|
||||
],
|
||||
'12.0Exp' : [
|
||||
(SCons.Util.HKEY_LOCAL_MACHINE, r'Microsoft\VCExpress\12.0\Setup\VC\ProductDir'),
|
||||
],
|
||||
'11.0': [
|
||||
(SCons.Util.HKEY_LOCAL_MACHINE, r'Microsoft\VisualStudio\11.0\Setup\VC\ProductDir'),
|
||||
],
|
||||
'11.0Exp' : [
|
||||
(SCons.Util.HKEY_LOCAL_MACHINE, r'Microsoft\VCExpress\11.0\Setup\VC\ProductDir'),
|
||||
],
|
||||
'10.0': [
|
||||
(SCons.Util.HKEY_LOCAL_MACHINE, r'Microsoft\VisualStudio\10.0\Setup\VC\ProductDir'),
|
||||
],
|
||||
'10.0Exp' : [
|
||||
(SCons.Util.HKEY_LOCAL_MACHINE, r'Microsoft\VCExpress\10.0\Setup\VC\ProductDir'),
|
||||
],
|
||||
'9.0': [
|
||||
(SCons.Util.HKEY_CURRENT_USER, r'Microsoft\DevDiv\VCForPython\9.0\installdir',),
|
||||
(SCons.Util.HKEY_LOCAL_MACHINE, r'Microsoft\VisualStudio\9.0\Setup\VC\ProductDir',),
|
||||
],
|
||||
'9.0Exp' : [
|
||||
(SCons.Util.HKEY_LOCAL_MACHINE, r'Microsoft\VCExpress\9.0\Setup\VC\ProductDir'),
|
||||
],
|
||||
'8.0': [
|
||||
(SCons.Util.HKEY_LOCAL_MACHINE, r'Microsoft\VisualStudio\8.0\Setup\VC\ProductDir'),
|
||||
],
|
||||
'8.0Exp': [
|
||||
(SCons.Util.HKEY_LOCAL_MACHINE, r'Microsoft\VCExpress\8.0\Setup\VC\ProductDir'),
|
||||
],
|
||||
'7.1': [
|
||||
(SCons.Util.HKEY_LOCAL_MACHINE, r'Microsoft\VisualStudio\7.1\Setup\VC\ProductDir'),
|
||||
],
|
||||
'7.0': [
|
||||
(SCons.Util.HKEY_LOCAL_MACHINE, r'Microsoft\VisualStudio\7.0\Setup\VC\ProductDir'),
|
||||
],
|
||||
'6.0': [
|
||||
(SCons.Util.HKEY_LOCAL_MACHINE, r'Microsoft\VisualStudio\6.0\Setup\Microsoft Visual C++\ProductDir'),
|
||||
]
|
||||
}
|
||||
|
||||
def msvc_version_to_maj_min(msvc_version):
|
||||
msvc_version_numeric = ''.join([x for x in msvc_version if x in string_digits + '.'])
|
||||
|
||||
t = msvc_version_numeric.split(".")
|
||||
if not len(t) == 2:
|
||||
raise ValueError("Unrecognized version %s (%s)" % (msvc_version,msvc_version_numeric))
|
||||
try:
|
||||
maj = int(t[0])
|
||||
min = int(t[1])
|
||||
return maj, min
|
||||
except ValueError as e:
|
||||
raise ValueError("Unrecognized version %s (%s)" % (msvc_version,msvc_version_numeric))
|
||||
|
||||
def is_host_target_supported(host_target, msvc_version):
|
||||
"""Return True if the given (host, target) tuple is supported given the
|
||||
msvc version.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
host_target: tuple
|
||||
tuple of (canonalized) host-target, e.g. ("x86", "amd64") for cross
|
||||
compilation from 32 bits windows to 64 bits.
|
||||
msvc_version: str
|
||||
msvc version (major.minor, e.g. 10.0)
|
||||
|
||||
Note
|
||||
----
|
||||
This only check whether a given version *may* support the given (host,
|
||||
target), not that the toolchain is actually present on the machine.
|
||||
"""
|
||||
# We assume that any Visual Studio version supports x86 as a target
|
||||
if host_target[1] != "x86":
|
||||
maj, min = msvc_version_to_maj_min(msvc_version)
|
||||
if maj < 8:
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
|
||||
def find_vc_pdir_vswhere(msvc_version):
|
||||
"""
|
||||
Find the MSVC product directory using vswhere.exe .
|
||||
Run it asking for specified version and get MSVS install location
|
||||
:param msvc_version:
|
||||
:return: MSVC install dir
|
||||
"""
|
||||
vswhere_path = os.path.join(
|
||||
'C:\\',
|
||||
'Program Files (x86)',
|
||||
'Microsoft Visual Studio',
|
||||
'Installer',
|
||||
'vswhere.exe'
|
||||
)
|
||||
vswhere_cmd = [vswhere_path, '-version', msvc_version, '-property', 'installationPath']
|
||||
|
||||
if os.path.exists(vswhere_path):
|
||||
sp = subprocess.Popen(vswhere_cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
vsdir, err = sp.communicate()
|
||||
vsdir = vsdir.decode("mbcs")
|
||||
vsdir = vsdir.rstrip()
|
||||
vc_pdir = os.path.join(vsdir, 'VC')
|
||||
return vc_pdir
|
||||
else:
|
||||
# No vswhere on system, no install info available
|
||||
return None
|
||||
|
||||
|
||||
def find_vc_pdir(msvc_version):
|
||||
"""Try to find the product directory for the given
|
||||
version.
|
||||
|
||||
Note
|
||||
----
|
||||
If for some reason the requested version could not be found, an
|
||||
exception which inherits from VisualCException will be raised."""
|
||||
root = 'Software\\'
|
||||
try:
|
||||
hkeys = _VCVER_TO_PRODUCT_DIR[msvc_version]
|
||||
except KeyError:
|
||||
debug("Unknown version of MSVC: %s" % msvc_version)
|
||||
raise UnsupportedVersion("Unknown version %s" % msvc_version)
|
||||
|
||||
for hkroot, key in hkeys:
|
||||
try:
|
||||
comps = None
|
||||
if not key:
|
||||
comps = find_vc_pdir_vswhere(msvc_version)
|
||||
if not comps:
|
||||
debug('find_vc_dir(): no VC found via vswhere for version {}'.format(repr(key)))
|
||||
raise SCons.Util.WinError
|
||||
else:
|
||||
if common.is_win64():
|
||||
try:
|
||||
# ordinally at win64, try Wow6432Node first.
|
||||
comps = common.read_reg(root + 'Wow6432Node\\' + key, hkroot)
|
||||
except SCons.Util.WinError as e:
|
||||
# at Microsoft Visual Studio for Python 2.7, value is not in Wow6432Node
|
||||
pass
|
||||
if not comps:
|
||||
# not Win64, or Microsoft Visual Studio for Python 2.7
|
||||
comps = common.read_reg(root + key, hkroot)
|
||||
except SCons.Util.WinError as e:
|
||||
debug('find_vc_dir(): no VC registry key {}'.format(repr(key)))
|
||||
else:
|
||||
debug('find_vc_dir(): found VC in registry: {}'.format(comps))
|
||||
if os.path.exists(comps):
|
||||
return comps
|
||||
else:
|
||||
debug('find_vc_dir(): reg says dir is {}, but it does not exist. (ignoring)'.format(comps))
|
||||
raise MissingConfiguration("registry dir {} not found on the filesystem".format(comps))
|
||||
return None
|
||||
|
||||
def find_batch_file(env,msvc_version,host_arch,target_arch):
|
||||
"""
|
||||
Find the location of the batch script which should set up the compiler
|
||||
for any TARGET_ARCH whose compilers were installed by Visual Studio/VCExpress
|
||||
"""
|
||||
pdir = find_vc_pdir(msvc_version)
|
||||
if pdir is None:
|
||||
raise NoVersionFound("No version of Visual Studio found")
|
||||
|
||||
debug('vc.py: find_batch_file() pdir:{}'.format(pdir))
|
||||
|
||||
# filter out e.g. "Exp" from the version name
|
||||
msvc_ver_numeric = ''.join([x for x in msvc_version if x in string_digits + "."])
|
||||
vernum = float(msvc_ver_numeric)
|
||||
if 7 <= vernum < 8:
|
||||
pdir = os.path.join(pdir, os.pardir, "Common7", "Tools")
|
||||
batfilename = os.path.join(pdir, "vsvars32.bat")
|
||||
elif vernum < 7:
|
||||
pdir = os.path.join(pdir, "Bin")
|
||||
batfilename = os.path.join(pdir, "vcvars32.bat")
|
||||
elif 8 <= vernum <= 14:
|
||||
batfilename = os.path.join(pdir, "vcvarsall.bat")
|
||||
else: # vernum >= 14.1 VS2017 and above
|
||||
batfilename = os.path.join(pdir, "Auxiliary", "Build", "vcvarsall.bat")
|
||||
|
||||
if not os.path.exists(batfilename):
|
||||
debug("Not found: %s" % batfilename)
|
||||
batfilename = None
|
||||
|
||||
installed_sdks=get_installed_sdks()
|
||||
for _sdk in installed_sdks:
|
||||
sdk_bat_file = _sdk.get_sdk_vc_script(host_arch,target_arch)
|
||||
if not sdk_bat_file:
|
||||
debug("vc.py:find_batch_file() not found:%s"%_sdk)
|
||||
else:
|
||||
sdk_bat_file_path = os.path.join(pdir,sdk_bat_file)
|
||||
if os.path.exists(sdk_bat_file_path):
|
||||
debug('vc.py:find_batch_file() sdk_bat_file_path:%s'%sdk_bat_file_path)
|
||||
return (batfilename,sdk_bat_file_path)
|
||||
return (batfilename,None)
|
||||
|
||||
|
||||
__INSTALLED_VCS_RUN = None
|
||||
|
||||
def cached_get_installed_vcs():
|
||||
global __INSTALLED_VCS_RUN
|
||||
|
||||
if __INSTALLED_VCS_RUN is None:
|
||||
ret = get_installed_vcs()
|
||||
__INSTALLED_VCS_RUN = ret
|
||||
|
||||
return __INSTALLED_VCS_RUN
|
||||
|
||||
def get_installed_vcs():
|
||||
installed_versions = []
|
||||
for ver in _VCVER:
|
||||
debug('trying to find VC %s' % ver)
|
||||
try:
|
||||
if find_vc_pdir(ver):
|
||||
debug('found VC %s' % ver)
|
||||
installed_versions.append(ver)
|
||||
else:
|
||||
debug('find_vc_pdir return None for ver %s' % ver)
|
||||
except VisualCException as e:
|
||||
debug('did not find VC %s: caught exception %s' % (ver, str(e)))
|
||||
return installed_versions
|
||||
|
||||
def reset_installed_vcs():
|
||||
"""Make it try again to find VC. This is just for the tests."""
|
||||
__INSTALLED_VCS_RUN = None
|
||||
|
||||
# Running these batch files isn't cheap: most of the time spent in
|
||||
# msvs.generate() is due to vcvars*.bat. In a build that uses "tools='msvs'"
|
||||
# in multiple environments, for example:
|
||||
# env1 = Environment(tools='msvs')
|
||||
# env2 = Environment(tools='msvs')
|
||||
# we can greatly improve the speed of the second and subsequent Environment
|
||||
# (or Clone) calls by memoizing the environment variables set by vcvars*.bat.
|
||||
script_env_stdout_cache = {}
|
||||
def script_env(script, args=None):
|
||||
cache_key = (script, args)
|
||||
stdout = script_env_stdout_cache.get(cache_key, None)
|
||||
if stdout is None:
|
||||
stdout = common.get_output(script, args)
|
||||
script_env_stdout_cache[cache_key] = stdout
|
||||
|
||||
# Stupid batch files do not set return code: we take a look at the
|
||||
# beginning of the output for an error message instead
|
||||
olines = stdout.splitlines()
|
||||
if olines[0].startswith("The specified configuration type is missing"):
|
||||
raise BatchFileExecutionError("\n".join(olines[:2]))
|
||||
|
||||
return common.parse_output(stdout)
|
||||
|
||||
def get_default_version(env):
|
||||
debug('get_default_version()')
|
||||
|
||||
msvc_version = env.get('MSVC_VERSION')
|
||||
msvs_version = env.get('MSVS_VERSION')
|
||||
|
||||
debug('get_default_version(): msvc_version:%s msvs_version:%s'%(msvc_version,msvs_version))
|
||||
|
||||
if msvs_version and not msvc_version:
|
||||
SCons.Warnings.warn(
|
||||
SCons.Warnings.DeprecatedWarning,
|
||||
"MSVS_VERSION is deprecated: please use MSVC_VERSION instead ")
|
||||
return msvs_version
|
||||
elif msvc_version and msvs_version:
|
||||
if not msvc_version == msvs_version:
|
||||
SCons.Warnings.warn(
|
||||
SCons.Warnings.VisualVersionMismatch,
|
||||
"Requested msvc version (%s) and msvs version (%s) do " \
|
||||
"not match: please use MSVC_VERSION only to request a " \
|
||||
"visual studio version, MSVS_VERSION is deprecated" \
|
||||
% (msvc_version, msvs_version))
|
||||
return msvs_version
|
||||
if not msvc_version:
|
||||
installed_vcs = cached_get_installed_vcs()
|
||||
debug('installed_vcs:%s' % installed_vcs)
|
||||
if not installed_vcs:
|
||||
#msg = 'No installed VCs'
|
||||
#debug('msv %s\n' % repr(msg))
|
||||
#SCons.Warnings.warn(SCons.Warnings.VisualCMissingWarning, msg)
|
||||
debug('msvc_setup_env: No installed VCs')
|
||||
return None
|
||||
msvc_version = installed_vcs[0]
|
||||
debug('msvc_setup_env: using default installed MSVC version %s\n' % repr(msvc_version))
|
||||
|
||||
return msvc_version
|
||||
|
||||
def msvc_setup_env_once(env):
|
||||
try:
|
||||
has_run = env["MSVC_SETUP_RUN"]
|
||||
except KeyError:
|
||||
has_run = False
|
||||
|
||||
if not has_run:
|
||||
msvc_setup_env(env)
|
||||
env["MSVC_SETUP_RUN"] = True
|
||||
|
||||
def msvc_find_valid_batch_script(env,version):
|
||||
debug('vc.py:msvc_find_valid_batch_script()')
|
||||
# Find the host platform, target platform, and if present the requested
|
||||
# target platform
|
||||
(host_platform, target_platform,req_target_platform) = get_host_target(env)
|
||||
|
||||
try_target_archs = [target_platform]
|
||||
debug("msvs_find_valid_batch_script(): req_target_platform %s target_platform:%s"%(req_target_platform,target_platform))
|
||||
|
||||
# VS2012 has a "cross compile" environment to build 64 bit
|
||||
# with x86_amd64 as the argument to the batch setup script
|
||||
if req_target_platform in ('amd64','x86_64'):
|
||||
try_target_archs.append('x86_amd64')
|
||||
elif not req_target_platform and target_platform in ['amd64','x86_64']:
|
||||
# There may not be "native" amd64, but maybe "cross" x86_amd64 tools
|
||||
try_target_archs.append('x86_amd64')
|
||||
# If the user hasn't specifically requested a TARGET_ARCH, and
|
||||
# The TARGET_ARCH is amd64 then also try 32 bits if there are no viable
|
||||
# 64 bit tools installed
|
||||
try_target_archs.append('x86')
|
||||
|
||||
debug("msvs_find_valid_batch_script(): host_platform: %s try_target_archs:%s"%(host_platform, try_target_archs))
|
||||
|
||||
d = None
|
||||
for tp in try_target_archs:
|
||||
# Set to current arch.
|
||||
env['TARGET_ARCH']=tp
|
||||
|
||||
debug("vc.py:msvc_find_valid_batch_script() trying target_platform:%s"%tp)
|
||||
host_target = (host_platform, tp)
|
||||
if not is_host_target_supported(host_target, version):
|
||||
warn_msg = "host, target = %s not supported for MSVC version %s" % \
|
||||
(host_target, version)
|
||||
SCons.Warnings.warn(SCons.Warnings.VisualCMissingWarning, warn_msg)
|
||||
arg = _HOST_TARGET_ARCH_TO_BAT_ARCH[host_target]
|
||||
|
||||
# Get just version numbers
|
||||
maj, min = msvc_version_to_maj_min(version)
|
||||
# VS2015+
|
||||
if maj >= 14:
|
||||
if env.get('MSVC_UWP_APP') == '1':
|
||||
# Initialize environment variables with store/universal paths
|
||||
arg += ' store'
|
||||
|
||||
# Try to locate a batch file for this host/target platform combo
|
||||
try:
|
||||
(vc_script,sdk_script) = find_batch_file(env,version,host_platform,tp)
|
||||
debug('vc.py:msvc_find_valid_batch_script() vc_script:%s sdk_script:%s'%(vc_script,sdk_script))
|
||||
except VisualCException as e:
|
||||
msg = str(e)
|
||||
debug('Caught exception while looking for batch file (%s)' % msg)
|
||||
warn_msg = "VC version %s not installed. " + \
|
||||
"C/C++ compilers are most likely not set correctly.\n" + \
|
||||
" Installed versions are: %s"
|
||||
warn_msg = warn_msg % (version, cached_get_installed_vcs())
|
||||
SCons.Warnings.warn(SCons.Warnings.VisualCMissingWarning, warn_msg)
|
||||
continue
|
||||
|
||||
# Try to use the located batch file for this host/target platform combo
|
||||
debug('vc.py:msvc_find_valid_batch_script() use_script 2 %s, args:%s\n' % (repr(vc_script), arg))
|
||||
if vc_script:
|
||||
try:
|
||||
d = script_env(vc_script, args=arg)
|
||||
except BatchFileExecutionError as e:
|
||||
debug('vc.py:msvc_find_valid_batch_script() use_script 3: failed running VC script %s: %s: Error:%s'%(repr(vc_script),arg,e))
|
||||
vc_script=None
|
||||
continue
|
||||
if not vc_script and sdk_script:
|
||||
debug('vc.py:msvc_find_valid_batch_script() use_script 4: trying sdk script: %s'%(sdk_script))
|
||||
try:
|
||||
d = script_env(sdk_script)
|
||||
except BatchFileExecutionError as e:
|
||||
debug('vc.py:msvc_find_valid_batch_script() use_script 5: failed running SDK script %s: Error:%s'%(repr(sdk_script),e))
|
||||
continue
|
||||
elif not vc_script and not sdk_script:
|
||||
debug('vc.py:msvc_find_valid_batch_script() use_script 6: Neither VC script nor SDK script found')
|
||||
continue
|
||||
|
||||
debug("vc.py:msvc_find_valid_batch_script() Found a working script/target: %s %s"%(repr(sdk_script),arg))
|
||||
break # We've found a working target_platform, so stop looking
|
||||
|
||||
# If we cannot find a viable installed compiler, reset the TARGET_ARCH
|
||||
# To it's initial value
|
||||
if not d:
|
||||
env['TARGET_ARCH']=req_target_platform
|
||||
|
||||
return d
|
||||
|
||||
|
||||
def msvc_setup_env(env):
|
||||
debug('msvc_setup_env()')
|
||||
|
||||
version = get_default_version(env)
|
||||
if version is None:
|
||||
warn_msg = "No version of Visual Studio compiler found - C/C++ " \
|
||||
"compilers most likely not set correctly"
|
||||
SCons.Warnings.warn(SCons.Warnings.VisualCMissingWarning, warn_msg)
|
||||
return None
|
||||
debug('msvc_setup_env: using specified MSVC version %s\n' % repr(version))
|
||||
|
||||
# XXX: we set-up both MSVS version for backward
|
||||
# compatibility with the msvs tool
|
||||
env['MSVC_VERSION'] = version
|
||||
env['MSVS_VERSION'] = version
|
||||
env['MSVS'] = {}
|
||||
|
||||
|
||||
use_script = env.get('MSVC_USE_SCRIPT', True)
|
||||
if SCons.Util.is_String(use_script):
|
||||
debug('vc.py:msvc_setup_env() use_script 1 %s\n' % repr(use_script))
|
||||
d = script_env(use_script)
|
||||
elif use_script:
|
||||
d = msvc_find_valid_batch_script(env,version)
|
||||
debug('vc.py:msvc_setup_env() use_script 2 %s\n' % d)
|
||||
if not d:
|
||||
return d
|
||||
else:
|
||||
debug('MSVC_USE_SCRIPT set to False')
|
||||
warn_msg = "MSVC_USE_SCRIPT set to False, assuming environment " \
|
||||
"set correctly."
|
||||
SCons.Warnings.warn(SCons.Warnings.VisualCMissingWarning, warn_msg)
|
||||
return None
|
||||
|
||||
for k, v in d.items():
|
||||
debug('vc.py:msvc_setup_env() env:%s -> %s'%(k,v))
|
||||
env.PrependENVPath(k, v, delete_existing=True)
|
||||
|
||||
def msvc_exists(version=None):
|
||||
vcs = cached_get_installed_vcs()
|
||||
if version is None:
|
||||
return len(vcs) > 0
|
||||
return version in vcs
|
573
scons-local-3.0.0/SCons/Tool/MSCommon/vs.py
Normal file
573
scons-local-3.0.0/SCons/Tool/MSCommon/vs.py
Normal file
@@ -0,0 +1,573 @@
|
||||
#
|
||||
# Copyright (c) 2001 - 2017 The SCons Foundation
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining
|
||||
# a copy of this software and associated documentation files (the
|
||||
# "Software"), to deal in the Software without restriction, including
|
||||
# without limitation the rights to use, copy, modify, merge, publish,
|
||||
# distribute, sublicense, and/or sell copies of the Software, and to
|
||||
# permit persons to whom the Software is furnished to do so, subject to
|
||||
# the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be included
|
||||
# in all copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
|
||||
# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
|
||||
# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
#
|
||||
|
||||
__revision__ = "src/engine/SCons/Tool/MSCommon/vs.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog"
|
||||
|
||||
__doc__ = """Module to detect Visual Studio and/or Visual C/C++
|
||||
"""
|
||||
|
||||
import os
|
||||
|
||||
import SCons.Errors
|
||||
import SCons.Util
|
||||
|
||||
from .common import debug, \
|
||||
get_output, \
|
||||
is_win64, \
|
||||
normalize_env, \
|
||||
parse_output, \
|
||||
read_reg
|
||||
|
||||
import SCons.Tool.MSCommon.vc
|
||||
|
||||
class VisualStudio(object):
|
||||
"""
|
||||
An abstract base class for trying to find installed versions of
|
||||
Visual Studio.
|
||||
"""
|
||||
def __init__(self, version, **kw):
|
||||
self.version = version
|
||||
kw['vc_version'] = kw.get('vc_version', version)
|
||||
kw['sdk_version'] = kw.get('sdk_version', version)
|
||||
self.__dict__.update(kw)
|
||||
self._cache = {}
|
||||
|
||||
def find_batch_file(self):
|
||||
vs_dir = self.get_vs_dir()
|
||||
if not vs_dir:
|
||||
debug('find_executable(): no vs_dir')
|
||||
return None
|
||||
batch_file = os.path.join(vs_dir, self.batch_file_path)
|
||||
batch_file = os.path.normpath(batch_file)
|
||||
if not os.path.isfile(batch_file):
|
||||
debug('find_batch_file(): %s not on file system' % batch_file)
|
||||
return None
|
||||
return batch_file
|
||||
|
||||
def find_vs_dir_by_vc(self):
|
||||
SCons.Tool.MSCommon.vc.get_installed_vcs()
|
||||
dir = SCons.Tool.MSCommon.vc.find_vc_pdir(self.vc_version)
|
||||
if not dir:
|
||||
debug('find_vs_dir(): no installed VC %s' % self.vc_version)
|
||||
return None
|
||||
return dir
|
||||
|
||||
def find_vs_dir_by_reg(self):
|
||||
root = 'Software\\'
|
||||
|
||||
if is_win64():
|
||||
root = root + 'Wow6432Node\\'
|
||||
for key in self.hkeys:
|
||||
if key=='use_dir':
|
||||
return self.find_vs_dir_by_vc()
|
||||
key = root + key
|
||||
try:
|
||||
comps = read_reg(key)
|
||||
except SCons.Util.WinError as e:
|
||||
debug('find_vs_dir_by_reg(): no VS registry key {}'.format(repr(key)))
|
||||
else:
|
||||
debug('find_vs_dir_by_reg(): found VS in registry: {}'.format(comps))
|
||||
return comps
|
||||
return None
|
||||
|
||||
def find_vs_dir(self):
|
||||
""" Can use registry or location of VC to find vs dir
|
||||
First try to find by registry, and if that fails find via VC dir
|
||||
"""
|
||||
|
||||
|
||||
if True:
|
||||
vs_dir=self.find_vs_dir_by_reg()
|
||||
return vs_dir
|
||||
else:
|
||||
return self.find_vs_dir_by_vc()
|
||||
|
||||
def find_executable(self):
|
||||
vs_dir = self.get_vs_dir()
|
||||
if not vs_dir:
|
||||
debug('find_executable(): no vs_dir ({})'.format(vs_dir))
|
||||
return None
|
||||
executable = os.path.join(vs_dir, self.executable_path)
|
||||
executable = os.path.normpath(executable)
|
||||
if not os.path.isfile(executable):
|
||||
debug('find_executable(): {} not on file system'.format(executable))
|
||||
return None
|
||||
return executable
|
||||
|
||||
def get_batch_file(self):
|
||||
try:
|
||||
return self._cache['batch_file']
|
||||
except KeyError:
|
||||
batch_file = self.find_batch_file()
|
||||
self._cache['batch_file'] = batch_file
|
||||
return batch_file
|
||||
|
||||
def get_executable(self):
|
||||
try:
|
||||
debug('get_executable using cache:%s'%self._cache['executable'])
|
||||
return self._cache['executable']
|
||||
except KeyError:
|
||||
executable = self.find_executable()
|
||||
self._cache['executable'] = executable
|
||||
debug('get_executable not in cache:%s'%executable)
|
||||
return executable
|
||||
|
||||
def get_vs_dir(self):
|
||||
try:
|
||||
return self._cache['vs_dir']
|
||||
except KeyError:
|
||||
vs_dir = self.find_vs_dir()
|
||||
self._cache['vs_dir'] = vs_dir
|
||||
return vs_dir
|
||||
|
||||
def get_supported_arch(self):
|
||||
try:
|
||||
return self._cache['supported_arch']
|
||||
except KeyError:
|
||||
# RDEVE: for the time being use hardcoded lists
|
||||
# supported_arch = self.find_supported_arch()
|
||||
self._cache['supported_arch'] = self.supported_arch
|
||||
return self.supported_arch
|
||||
|
||||
def reset(self):
|
||||
self._cache = {}
|
||||
|
||||
# The list of supported Visual Studio versions we know how to detect.
|
||||
#
|
||||
# How to look for .bat file ?
|
||||
# - VS 2008 Express (x86):
|
||||
# * from registry key productdir, gives the full path to vsvarsall.bat. In
|
||||
# HKEY_LOCAL_MACHINE):
|
||||
# Software\Microsoft\VCEpress\9.0\Setup\VC\productdir
|
||||
# * from environmnent variable VS90COMNTOOLS: the path is then ..\..\VC
|
||||
# relatively to the path given by the variable.
|
||||
#
|
||||
# - VS 2008 Express (WoW6432: 32 bits on windows x64):
|
||||
# Software\Wow6432Node\Microsoft\VCEpress\9.0\Setup\VC\productdir
|
||||
#
|
||||
# - VS 2005 Express (x86):
|
||||
# * from registry key productdir, gives the full path to vsvarsall.bat. In
|
||||
# HKEY_LOCAL_MACHINE):
|
||||
# Software\Microsoft\VCEpress\8.0\Setup\VC\productdir
|
||||
# * from environmnent variable VS80COMNTOOLS: the path is then ..\..\VC
|
||||
# relatively to the path given by the variable.
|
||||
#
|
||||
# - VS 2005 Express (WoW6432: 32 bits on windows x64): does not seem to have a
|
||||
# productdir ?
|
||||
#
|
||||
# - VS 2003 .Net (pro edition ? x86):
|
||||
# * from registry key productdir. The path is then ..\Common7\Tools\
|
||||
# relatively to the key. The key is in HKEY_LOCAL_MACHINE):
|
||||
# Software\Microsoft\VisualStudio\7.1\Setup\VC\productdir
|
||||
# * from environmnent variable VS71COMNTOOLS: the path is the full path to
|
||||
# vsvars32.bat
|
||||
#
|
||||
# - VS 98 (VS 6):
|
||||
# * from registry key productdir. The path is then Bin
|
||||
# relatively to the key. The key is in HKEY_LOCAL_MACHINE):
|
||||
# Software\Microsoft\VisualStudio\6.0\Setup\VC98\productdir
|
||||
#
|
||||
# The first version found in the list is the one used by default if
|
||||
# there are multiple versions installed. Barring good reasons to
|
||||
# the contrary, this means we should list versions from most recent
|
||||
# to oldest. Pro versions get listed before Express versions on the
|
||||
# assumption that, by default, you'd rather use the version you paid
|
||||
# good money for in preference to whatever Microsoft makes available
|
||||
# for free.
|
||||
#
|
||||
# If you update this list, update _VCVER and _VCVER_TO_PRODUCT_DIR in
|
||||
# Tool/MSCommon/vc.py, and the MSVC_VERSION documentation in Tool/msvc.xml.
|
||||
|
||||
SupportedVSList = [
|
||||
# Visual Studio 2017
|
||||
VisualStudio('14.1',
|
||||
vc_version='14.1',
|
||||
sdk_version='10.0A',
|
||||
hkeys=[],
|
||||
common_tools_var='VS150COMNTOOLS',
|
||||
executable_path=r'Common7\IDE\devenv.com',
|
||||
batch_file_path=r'VC\Auxiliary\Build\vsvars32.bat',
|
||||
supported_arch=['x86', 'amd64', "arm"],
|
||||
),
|
||||
|
||||
# Visual Studio 2015
|
||||
VisualStudio('14.0',
|
||||
vc_version='14.0',
|
||||
sdk_version='10.0',
|
||||
hkeys=[r'Microsoft\VisualStudio\14.0\Setup\VS\ProductDir'],
|
||||
common_tools_var='VS140COMNTOOLS',
|
||||
executable_path=r'Common7\IDE\devenv.com',
|
||||
batch_file_path=r'Common7\Tools\vsvars32.bat',
|
||||
supported_arch=['x86', 'amd64', "arm"],
|
||||
),
|
||||
|
||||
# Visual C++ 2015 Express Edition (for Desktop)
|
||||
VisualStudio('14.0Exp',
|
||||
vc_version='14.0',
|
||||
sdk_version='10.0A',
|
||||
hkeys=[r'Microsoft\VisualStudio\14.0\Setup\VS\ProductDir'],
|
||||
common_tools_var='VS140COMNTOOLS',
|
||||
executable_path=r'Common7\IDE\WDExpress.exe',
|
||||
batch_file_path=r'Common7\Tools\vsvars32.bat',
|
||||
supported_arch=['x86', 'amd64', "arm"],
|
||||
),
|
||||
|
||||
# Visual Studio 2013
|
||||
VisualStudio('12.0',
|
||||
vc_version='12.0',
|
||||
sdk_version='8.1A',
|
||||
hkeys=[r'Microsoft\VisualStudio\12.0\Setup\VS\ProductDir'],
|
||||
common_tools_var='VS120COMNTOOLS',
|
||||
executable_path=r'Common7\IDE\devenv.com',
|
||||
batch_file_path=r'Common7\Tools\vsvars32.bat',
|
||||
supported_arch=['x86', 'amd64'],
|
||||
),
|
||||
|
||||
# Visual C++ 2013 Express Edition (for Desktop)
|
||||
VisualStudio('12.0Exp',
|
||||
vc_version='12.0',
|
||||
sdk_version='8.1A',
|
||||
hkeys=[r'Microsoft\VisualStudio\12.0\Setup\VS\ProductDir'],
|
||||
common_tools_var='VS120COMNTOOLS',
|
||||
executable_path=r'Common7\IDE\WDExpress.exe',
|
||||
batch_file_path=r'Common7\Tools\vsvars32.bat',
|
||||
supported_arch=['x86', 'amd64'],
|
||||
),
|
||||
|
||||
# Visual Studio 2012
|
||||
VisualStudio('11.0',
|
||||
sdk_version='8.0A',
|
||||
hkeys=[r'Microsoft\VisualStudio\11.0\Setup\VS\ProductDir'],
|
||||
common_tools_var='VS110COMNTOOLS',
|
||||
executable_path=r'Common7\IDE\devenv.com',
|
||||
batch_file_path=r'Common7\Tools\vsvars32.bat',
|
||||
supported_arch=['x86', 'amd64'],
|
||||
),
|
||||
|
||||
# Visual C++ 2012 Express Edition (for Desktop)
|
||||
VisualStudio('11.0Exp',
|
||||
vc_version='11.0',
|
||||
sdk_version='8.0A',
|
||||
hkeys=[r'Microsoft\VisualStudio\11.0\Setup\VS\ProductDir'],
|
||||
common_tools_var='VS110COMNTOOLS',
|
||||
executable_path=r'Common7\IDE\WDExpress.exe',
|
||||
batch_file_path=r'Common7\Tools\vsvars32.bat',
|
||||
supported_arch=['x86', 'amd64'],
|
||||
),
|
||||
|
||||
# Visual Studio 2010
|
||||
VisualStudio('10.0',
|
||||
sdk_version='7.0A',
|
||||
hkeys=[r'Microsoft\VisualStudio\10.0\Setup\VS\ProductDir'],
|
||||
common_tools_var='VS100COMNTOOLS',
|
||||
executable_path=r'Common7\IDE\devenv.com',
|
||||
batch_file_path=r'Common7\Tools\vsvars32.bat',
|
||||
supported_arch=['x86', 'amd64'],
|
||||
),
|
||||
|
||||
# Visual C++ 2010 Express Edition
|
||||
VisualStudio('10.0Exp',
|
||||
vc_version='10.0',
|
||||
sdk_version='7.0A',
|
||||
hkeys=[r'Microsoft\VCExpress\10.0\Setup\VS\ProductDir'],
|
||||
common_tools_var='VS100COMNTOOLS',
|
||||
executable_path=r'Common7\IDE\VCExpress.exe',
|
||||
batch_file_path=r'Common7\Tools\vsvars32.bat',
|
||||
supported_arch=['x86'],
|
||||
),
|
||||
|
||||
# Visual Studio 2008
|
||||
VisualStudio('9.0',
|
||||
sdk_version='6.0A',
|
||||
hkeys=[r'Microsoft\VisualStudio\9.0\Setup\VS\ProductDir'],
|
||||
common_tools_var='VS90COMNTOOLS',
|
||||
executable_path=r'Common7\IDE\devenv.com',
|
||||
batch_file_path=r'Common7\Tools\vsvars32.bat',
|
||||
supported_arch=['x86', 'amd64'],
|
||||
),
|
||||
|
||||
# Visual C++ 2008 Express Edition
|
||||
VisualStudio('9.0Exp',
|
||||
vc_version='9.0',
|
||||
sdk_version='6.0A',
|
||||
hkeys=[r'Microsoft\VCExpress\9.0\Setup\VS\ProductDir'],
|
||||
common_tools_var='VS90COMNTOOLS',
|
||||
executable_path=r'Common7\IDE\VCExpress.exe',
|
||||
batch_file_path=r'Common7\Tools\vsvars32.bat',
|
||||
supported_arch=['x86'],
|
||||
),
|
||||
|
||||
# Visual Studio 2005
|
||||
VisualStudio('8.0',
|
||||
sdk_version='6.0A',
|
||||
hkeys=[r'Microsoft\VisualStudio\8.0\Setup\VS\ProductDir'],
|
||||
common_tools_var='VS80COMNTOOLS',
|
||||
executable_path=r'Common7\IDE\devenv.com',
|
||||
batch_file_path=r'Common7\Tools\vsvars32.bat',
|
||||
default_dirname='Microsoft Visual Studio 8',
|
||||
supported_arch=['x86', 'amd64'],
|
||||
),
|
||||
|
||||
# Visual C++ 2005 Express Edition
|
||||
VisualStudio('8.0Exp',
|
||||
vc_version='8.0Exp',
|
||||
sdk_version='6.0A',
|
||||
hkeys=[r'Microsoft\VCExpress\8.0\Setup\VS\ProductDir'],
|
||||
common_tools_var='VS80COMNTOOLS',
|
||||
executable_path=r'Common7\IDE\VCExpress.exe',
|
||||
batch_file_path=r'Common7\Tools\vsvars32.bat',
|
||||
default_dirname='Microsoft Visual Studio 8',
|
||||
supported_arch=['x86'],
|
||||
),
|
||||
|
||||
# Visual Studio .NET 2003
|
||||
VisualStudio('7.1',
|
||||
sdk_version='6.0',
|
||||
hkeys=[r'Microsoft\VisualStudio\7.1\Setup\VS\ProductDir'],
|
||||
common_tools_var='VS71COMNTOOLS',
|
||||
executable_path=r'Common7\IDE\devenv.com',
|
||||
batch_file_path=r'Common7\Tools\vsvars32.bat',
|
||||
default_dirname='Microsoft Visual Studio .NET 2003',
|
||||
supported_arch=['x86'],
|
||||
),
|
||||
|
||||
# Visual Studio .NET
|
||||
VisualStudio('7.0',
|
||||
sdk_version='2003R2',
|
||||
hkeys=[r'Microsoft\VisualStudio\7.0\Setup\VS\ProductDir'],
|
||||
common_tools_var='VS70COMNTOOLS',
|
||||
executable_path=r'IDE\devenv.com',
|
||||
batch_file_path=r'Common7\Tools\vsvars32.bat',
|
||||
default_dirname='Microsoft Visual Studio .NET',
|
||||
supported_arch=['x86'],
|
||||
),
|
||||
|
||||
# Visual Studio 6.0
|
||||
VisualStudio('6.0',
|
||||
sdk_version='2003R1',
|
||||
hkeys=[r'Microsoft\VisualStudio\6.0\Setup\Microsoft Visual Studio\ProductDir',
|
||||
'use_dir'],
|
||||
common_tools_var='VS60COMNTOOLS',
|
||||
executable_path=r'Common\MSDev98\Bin\MSDEV.COM',
|
||||
batch_file_path=r'Common7\Tools\vsvars32.bat',
|
||||
default_dirname='Microsoft Visual Studio',
|
||||
supported_arch=['x86'],
|
||||
),
|
||||
]
|
||||
|
||||
SupportedVSMap = {}
|
||||
for vs in SupportedVSList:
|
||||
SupportedVSMap[vs.version] = vs
|
||||
|
||||
|
||||
# Finding installed versions of Visual Studio isn't cheap, because it
|
||||
# goes not only to the registry but also to the disk to sanity-check
|
||||
# that there is, in fact, a Visual Studio directory there and that the
|
||||
# registry entry isn't just stale. Find this information once, when
|
||||
# requested, and cache it.
|
||||
|
||||
InstalledVSList = None
|
||||
InstalledVSMap = None
|
||||
|
||||
def get_installed_visual_studios():
|
||||
global InstalledVSList
|
||||
global InstalledVSMap
|
||||
if InstalledVSList is None:
|
||||
InstalledVSList = []
|
||||
InstalledVSMap = {}
|
||||
for vs in SupportedVSList:
|
||||
debug('trying to find VS %s' % vs.version)
|
||||
if vs.get_executable():
|
||||
debug('found VS %s' % vs.version)
|
||||
InstalledVSList.append(vs)
|
||||
InstalledVSMap[vs.version] = vs
|
||||
return InstalledVSList
|
||||
|
||||
def reset_installed_visual_studios():
|
||||
global InstalledVSList
|
||||
global InstalledVSMap
|
||||
InstalledVSList = None
|
||||
InstalledVSMap = None
|
||||
for vs in SupportedVSList:
|
||||
vs.reset()
|
||||
|
||||
# Need to clear installed VC's as well as they are used in finding
|
||||
# installed VS's
|
||||
SCons.Tool.MSCommon.vc.reset_installed_vcs()
|
||||
|
||||
|
||||
# We may be asked to update multiple construction environments with
|
||||
# SDK information. When doing this, we check on-disk for whether
|
||||
# the SDK has 'mfc' and 'atl' subdirectories. Since going to disk
|
||||
# is expensive, cache results by directory.
|
||||
|
||||
#SDKEnvironmentUpdates = {}
|
||||
#
|
||||
#def set_sdk_by_directory(env, sdk_dir):
|
||||
# global SDKEnvironmentUpdates
|
||||
# try:
|
||||
# env_tuple_list = SDKEnvironmentUpdates[sdk_dir]
|
||||
# except KeyError:
|
||||
# env_tuple_list = []
|
||||
# SDKEnvironmentUpdates[sdk_dir] = env_tuple_list
|
||||
#
|
||||
# include_path = os.path.join(sdk_dir, 'include')
|
||||
# mfc_path = os.path.join(include_path, 'mfc')
|
||||
# atl_path = os.path.join(include_path, 'atl')
|
||||
#
|
||||
# if os.path.exists(mfc_path):
|
||||
# env_tuple_list.append(('INCLUDE', mfc_path))
|
||||
# if os.path.exists(atl_path):
|
||||
# env_tuple_list.append(('INCLUDE', atl_path))
|
||||
# env_tuple_list.append(('INCLUDE', include_path))
|
||||
#
|
||||
# env_tuple_list.append(('LIB', os.path.join(sdk_dir, 'lib')))
|
||||
# env_tuple_list.append(('LIBPATH', os.path.join(sdk_dir, 'lib')))
|
||||
# env_tuple_list.append(('PATH', os.path.join(sdk_dir, 'bin')))
|
||||
#
|
||||
# for variable, directory in env_tuple_list:
|
||||
# env.PrependENVPath(variable, directory)
|
||||
|
||||
def msvs_exists():
|
||||
return (len(get_installed_visual_studios()) > 0)
|
||||
|
||||
def get_vs_by_version(msvs):
|
||||
global InstalledVSMap
|
||||
global SupportedVSMap
|
||||
|
||||
debug('vs.py:get_vs_by_version()')
|
||||
if msvs not in SupportedVSMap:
|
||||
msg = "Visual Studio version %s is not supported" % repr(msvs)
|
||||
raise SCons.Errors.UserError(msg)
|
||||
get_installed_visual_studios()
|
||||
vs = InstalledVSMap.get(msvs)
|
||||
debug('InstalledVSMap:%s'%InstalledVSMap)
|
||||
debug('vs.py:get_vs_by_version: found vs:%s'%vs)
|
||||
# Some check like this would let us provide a useful error message
|
||||
# if they try to set a Visual Studio version that's not installed.
|
||||
# However, we also want to be able to run tests (like the unit
|
||||
# tests) on systems that don't, or won't ever, have it installed.
|
||||
# It might be worth resurrecting this, with some configurable
|
||||
# setting that the tests can use to bypass the check.
|
||||
#if not vs:
|
||||
# msg = "Visual Studio version %s is not installed" % repr(msvs)
|
||||
# raise SCons.Errors.UserError, msg
|
||||
return vs
|
||||
|
||||
def get_default_version(env):
|
||||
"""Returns the default version string to use for MSVS.
|
||||
|
||||
If no version was requested by the user through the MSVS environment
|
||||
variable, query all the available visual studios through
|
||||
get_installed_visual_studios, and take the highest one.
|
||||
|
||||
Return
|
||||
------
|
||||
version: str
|
||||
the default version.
|
||||
"""
|
||||
if 'MSVS' not in env or not SCons.Util.is_Dict(env['MSVS']):
|
||||
# get all versions, and remember them for speed later
|
||||
versions = [vs.version for vs in get_installed_visual_studios()]
|
||||
env['MSVS'] = {'VERSIONS' : versions}
|
||||
else:
|
||||
versions = env['MSVS'].get('VERSIONS', [])
|
||||
|
||||
if 'MSVS_VERSION' not in env:
|
||||
if versions:
|
||||
env['MSVS_VERSION'] = versions[0] #use highest version by default
|
||||
else:
|
||||
debug('get_default_version: WARNING: no installed versions found, '
|
||||
'using first in SupportedVSList (%s)'%SupportedVSList[0].version)
|
||||
env['MSVS_VERSION'] = SupportedVSList[0].version
|
||||
|
||||
env['MSVS']['VERSION'] = env['MSVS_VERSION']
|
||||
|
||||
return env['MSVS_VERSION']
|
||||
|
||||
def get_default_arch(env):
|
||||
"""Return the default arch to use for MSVS
|
||||
|
||||
if no version was requested by the user through the MSVS_ARCH environment
|
||||
variable, select x86
|
||||
|
||||
Return
|
||||
------
|
||||
arch: str
|
||||
"""
|
||||
arch = env.get('MSVS_ARCH', 'x86')
|
||||
|
||||
msvs = InstalledVSMap.get(env['MSVS_VERSION'])
|
||||
|
||||
if not msvs:
|
||||
arch = 'x86'
|
||||
elif not arch in msvs.get_supported_arch():
|
||||
fmt = "Visual Studio version %s does not support architecture %s"
|
||||
raise SCons.Errors.UserError(fmt % (env['MSVS_VERSION'], arch))
|
||||
|
||||
return arch
|
||||
|
||||
def merge_default_version(env):
|
||||
version = get_default_version(env)
|
||||
arch = get_default_arch(env)
|
||||
|
||||
def msvs_setup_env(env):
|
||||
batfilename = msvs.get_batch_file()
|
||||
msvs = get_vs_by_version(version)
|
||||
if msvs is None:
|
||||
return
|
||||
|
||||
# XXX: I think this is broken. This will silently set a bogus tool instead
|
||||
# of failing, but there is no other way with the current scons tool
|
||||
# framework
|
||||
if batfilename is not None:
|
||||
|
||||
vars = ('LIB', 'LIBPATH', 'PATH', 'INCLUDE')
|
||||
|
||||
msvs_list = get_installed_visual_studios()
|
||||
vscommonvarnames = [vs.common_tools_var for vs in msvs_list]
|
||||
save_ENV = env['ENV']
|
||||
nenv = normalize_env(env['ENV'],
|
||||
['COMSPEC'] + vscommonvarnames,
|
||||
force=True)
|
||||
try:
|
||||
output = get_output(batfilename, arch, env=nenv)
|
||||
finally:
|
||||
env['ENV'] = save_ENV
|
||||
vars = parse_output(output, vars)
|
||||
|
||||
for k, v in vars.items():
|
||||
env.PrependENVPath(k, v, delete_existing=1)
|
||||
|
||||
def query_versions():
|
||||
"""Query the system to get available versions of VS. A version is
|
||||
considered when a batfile is found."""
|
||||
msvs_list = get_installed_visual_studios()
|
||||
versions = [msvs.version for msvs in msvs_list]
|
||||
return versions
|
||||
|
||||
# Local Variables:
|
||||
# tab-width:4
|
||||
# indent-tabs-mode:nil
|
||||
# End:
|
||||
# vim: set expandtab tabstop=4 shiftwidth=4:
|
Reference in New Issue
Block a user