mirror of https://gitlab.com/ita1024/waf.git
Merge pull request #1614 from shoover/lazy-msvc-detect-1.8
Optionally lazily check installed msvc compilers' environments
This commit is contained in:
commit
36e07b3eaf
|
@ -30,6 +30,10 @@ or::
|
|||
|
||||
Platforms and targets will be tested in the order they appear;
|
||||
the first good configuration will be used.
|
||||
|
||||
To skip testing all the configurations that are not used, use the ``--msvc_lazy_autodetect`` option
|
||||
or set ``conf.env['MSVC_LAZY_AUTODETECT']=True``.
|
||||
|
||||
Supported platforms: ia64, x64, x86, x86_amd64, x86_ia64, x86_arm, amd64_x86, amd64_arm
|
||||
|
||||
Compilers supported:
|
||||
|
@ -90,8 +94,19 @@ all_icl_platforms = [ ('intel64', 'amd64'), ('em64t', 'amd64'), ('ia32', 'x86'),
|
|||
def options(opt):
|
||||
opt.add_option('--msvc_version', type='string', help = 'msvc version, eg: "msvc 10.0,msvc 9.0"', default='')
|
||||
opt.add_option('--msvc_targets', type='string', help = 'msvc targets, eg: "x64,arm"', default='')
|
||||
opt.add_option('--msvc_lazy_autodetect', action='store_true', help = 'lazily check msvc target environments')
|
||||
|
||||
def setup_msvc(conf, versions, arch = False):
|
||||
"""
|
||||
Checks installed compilers and targets and returns the first combination from the user's
|
||||
options, env, or the global supported lists that checks.
|
||||
|
||||
:param versions: A list of tuples of all installed compilers and available targets.
|
||||
:param arch: Whether to return the target architecture.
|
||||
:return: the compiler, revision, path, include dirs, library paths, and (optionally) target architecture
|
||||
:rtype: tuple of strings
|
||||
"""
|
||||
|
||||
platforms = getattr(Options.options, 'msvc_targets', '').split(',')
|
||||
if platforms == ['']:
|
||||
platforms=Utils.to_list(conf.env['MSVC_TARGETS']) or [i for i,j in all_msvc_platforms+all_icl_platforms+all_wince_platforms]
|
||||
|
@ -102,15 +117,20 @@ def setup_msvc(conf, versions, arch = False):
|
|||
|
||||
for version in desired_versions:
|
||||
try:
|
||||
targets = dict(versiondict [version])
|
||||
targets = dict(versiondict[version])
|
||||
for target in platforms:
|
||||
try:
|
||||
arch,(p1,p2,p3) = targets[target]
|
||||
compiler,revision = version.rsplit(' ', 1)
|
||||
if arch:
|
||||
return compiler,revision,p1,p2,p3,arch
|
||||
try:
|
||||
arch,(p1,p2,p3) = targets[target]
|
||||
except conf.errors.ConfigurationError:
|
||||
# lazytup target evaluation errors
|
||||
del(targets[target])
|
||||
else:
|
||||
return compiler,revision,p1,p2,p3
|
||||
compiler,revision = version.rsplit(' ', 1)
|
||||
if arch:
|
||||
return compiler,revision,p1,p2,p3,arch
|
||||
else:
|
||||
return compiler,revision,p1,p2,p3
|
||||
except KeyError: continue
|
||||
except KeyError: continue
|
||||
conf.fatal('msvc: Impossible to find a valid architecture for building (in setup_msvc)')
|
||||
|
@ -118,13 +138,14 @@ def setup_msvc(conf, versions, arch = False):
|
|||
@conf
|
||||
def get_msvc_version(conf, compiler, version, target, vcvars):
|
||||
"""
|
||||
Create a bat file to obtain the location of the libraries
|
||||
Checks that an installed compiler actually runs and uses vcvars to obtain the
|
||||
environment needed by the compiler.
|
||||
|
||||
:param compiler: ?
|
||||
:param version: ?
|
||||
:target: ?
|
||||
:vcvars: ?
|
||||
:return: the location of msvc, the location of include dirs, and the library paths
|
||||
:param compiler: compiler type, for looking up the executable name
|
||||
:param version: compiler version, for debugging only
|
||||
:param target: target architecture
|
||||
:param vcvars: batch file to run to check the environment
|
||||
:return: the location of the compiler executable, the location of include dirs, and the library paths
|
||||
:rtype: tuple of strings
|
||||
"""
|
||||
debug('msvc: get_msvc_version: %r %r %r', compiler, version, target)
|
||||
|
@ -219,7 +240,7 @@ def gather_wsdk_versions(conf, versions):
|
|||
targets = []
|
||||
for target,arch in all_msvc_platforms:
|
||||
try:
|
||||
targets.append((target, (arch, conf.get_msvc_version('wsdk', version, '/'+target, os.path.join(path, 'bin', 'SetEnv.cmd')))))
|
||||
targets.append((target, (arch, get_compiler_env(conf, 'wsdk', version, '/'+target, os.path.join(path, 'bin', 'SetEnv.cmd')))))
|
||||
except conf.errors.ConfigurationError:
|
||||
pass
|
||||
versions.append(('wsdk ' + version[1:], targets))
|
||||
|
@ -304,6 +325,66 @@ def gather_msvc_detected_versions():
|
|||
detected_versions.sort(key = fun)
|
||||
return detected_versions
|
||||
|
||||
def get_compiler_env(conf, compiler, version, bat_target, bat, select=None):
|
||||
"""
|
||||
Gets the compiler environment variables as a tuple. Evaluation is eager by default.
|
||||
If set to lazy with ``--msvc_lazy_autodetect`` or ``env.MSVC_LAZY_AUTODETECT``
|
||||
the environment is evaluated when the tuple is destructured or iterated. This means
|
||||
destructuring can throw :py:class:`conf.errors.ConfigurationError`.
|
||||
|
||||
:param conf: configuration context to use to eventually get the version environment
|
||||
:param compiler: compiler name
|
||||
:param version: compiler version number
|
||||
:param bat: path to the batch file to run
|
||||
:param select: optional function to take the realized environment variables tup and map it (e.g. to combine other constant paths)
|
||||
"""
|
||||
lazy = getattr(Options.options, 'msvc_lazy_autodetect', False) or conf.env['MSVC_LAZY_AUTODETECT']
|
||||
|
||||
def msvc_thunk():
|
||||
vs = conf.get_msvc_version(compiler, version, bat_target, bat)
|
||||
if select:
|
||||
return select(vs)
|
||||
else:
|
||||
return vs
|
||||
return lazytup(msvc_thunk, lazy, ([], [], []))
|
||||
|
||||
class lazytup(object):
|
||||
"""
|
||||
A tuple that evaluates its elements from a function when iterated or destructured.
|
||||
|
||||
:param fn: thunk to evaluate the tuple on demand
|
||||
:param lazy: whether to delay evaluation or evaluate in the constructor
|
||||
:param default: optional default for :py:func:`repr` if it should not evaluate
|
||||
"""
|
||||
def __init__(self, fn, lazy=True, default=None):
|
||||
self.fn = fn
|
||||
self.default = default
|
||||
|
||||
if not lazy:
|
||||
self.evaluate()
|
||||
def __len__(self):
|
||||
self.evaluate()
|
||||
return len(self.value)
|
||||
def __iter__(self):
|
||||
self.evaluate()
|
||||
for i, v in enumerate(self.value):
|
||||
yield v
|
||||
def __getitem__(self, i):
|
||||
self.evaluate()
|
||||
return self.value[i]
|
||||
def __repr__(self):
|
||||
if hasattr(self, 'value'):
|
||||
return repr(self.value)
|
||||
elif self.default:
|
||||
return repr(self.default)
|
||||
else:
|
||||
self.evaluate()
|
||||
return repr(self.value)
|
||||
def evaluate(self):
|
||||
if hasattr(self, 'value'):
|
||||
return
|
||||
self.value = self.fn()
|
||||
|
||||
@conf
|
||||
def gather_msvc_targets(conf, versions, version, vc_path):
|
||||
#Looking for normal MSVC compilers!
|
||||
|
@ -311,17 +392,17 @@ def gather_msvc_targets(conf, versions, version, vc_path):
|
|||
if os.path.isfile(os.path.join(vc_path, 'vcvarsall.bat')):
|
||||
for target,realtarget in all_msvc_platforms[::-1]:
|
||||
try:
|
||||
targets.append((target, (realtarget, conf.get_msvc_version('msvc', version, target, os.path.join(vc_path, 'vcvarsall.bat')))))
|
||||
targets.append((target, (realtarget, get_compiler_env(conf, 'msvc', version, target, os.path.join(vc_path, 'vcvarsall.bat')))))
|
||||
except conf.errors.ConfigurationError:
|
||||
pass
|
||||
elif os.path.isfile(os.path.join(vc_path, 'Common7', 'Tools', 'vsvars32.bat')):
|
||||
try:
|
||||
targets.append(('x86', ('x86', conf.get_msvc_version('msvc', version, 'x86', os.path.join(vc_path, 'Common7', 'Tools', 'vsvars32.bat')))))
|
||||
targets.append(('x86', ('x86', get_compiler_env(conf, 'msvc', version, 'x86', os.path.join(vc_path, 'Common7', 'Tools', 'vsvars32.bat')))))
|
||||
except conf.errors.ConfigurationError:
|
||||
pass
|
||||
elif os.path.isfile(os.path.join(vc_path, 'Bin', 'vcvars32.bat')):
|
||||
try:
|
||||
targets.append(('x86', ('x86', conf.get_msvc_version('msvc', version, '', os.path.join(vc_path, 'Bin', 'vcvars32.bat')))))
|
||||
targets.append(('x86', ('x86', get_compiler_env(conf, 'msvc', version, '', os.path.join(vc_path, 'Bin', 'vcvars32.bat')))))
|
||||
except conf.errors.ConfigurationError:
|
||||
pass
|
||||
if targets:
|
||||
|
@ -336,15 +417,19 @@ def gather_wince_targets(conf, versions, version, vc_path, vsvars, supported_pla
|
|||
winCEpath = os.path.join(vc_path, 'ce')
|
||||
if not os.path.isdir(winCEpath):
|
||||
continue
|
||||
try:
|
||||
common_bindirs,_1,_2 = conf.get_msvc_version('msvc', version, 'x86', vsvars)
|
||||
except conf.errors.ConfigurationError:
|
||||
continue
|
||||
|
||||
if os.path.isdir(os.path.join(winCEpath, 'lib', platform)):
|
||||
bindirs = [os.path.join(winCEpath, 'bin', compiler), os.path.join(winCEpath, 'bin', 'x86_'+compiler)] + common_bindirs
|
||||
bindirs = [os.path.join(winCEpath, 'bin', compiler), os.path.join(winCEpath, 'bin', 'x86_'+compiler)]
|
||||
incdirs = [os.path.join(winCEpath, 'include'), os.path.join(winCEpath, 'atlmfc', 'include'), include]
|
||||
libdirs = [os.path.join(winCEpath, 'lib', platform), os.path.join(winCEpath, 'atlmfc', 'lib', platform), lib]
|
||||
cetargets.append((platform, (platform, (bindirs,incdirs,libdirs))))
|
||||
def combine_common(compiler_env):
|
||||
(common_bindirs,_1,_2) = compiler_env
|
||||
return (bindirs + common_bindirs, incdirs, libdirs)
|
||||
try:
|
||||
cetargets.append((platform, (platform, get_compiler_env(conf, 'msvc', version, 'x86', vsvars, combine_common))))
|
||||
except conf.errors.ConfigurationError:
|
||||
continue
|
||||
|
||||
if cetargets:
|
||||
versions.append((device + ' ' + version, cetargets))
|
||||
|
||||
|
@ -354,8 +439,8 @@ def gather_winphone_targets(conf, versions, version, vc_path, vsvars):
|
|||
targets = []
|
||||
for target,realtarget in all_msvc_platforms[::-1]:
|
||||
try:
|
||||
targets.append((target, (realtarget, conf.get_msvc_version('winphone', version, target, vsvars))))
|
||||
except conf.errors.ConfigurationError as e:
|
||||
targets.append((target, (realtarget, get_compiler_env(conf, 'winphone', version, target, vsvars))))
|
||||
except conf.errors.ConfigurationError:
|
||||
pass
|
||||
if targets:
|
||||
versions.append(('winphone '+ version, targets))
|
||||
|
@ -426,7 +511,7 @@ def gather_icl_versions(conf, versions):
|
|||
batch_file=os.path.join(path,'bin','iclvars.bat')
|
||||
if os.path.isfile(batch_file):
|
||||
try:
|
||||
targets.append((target,(arch,conf.get_msvc_version('intel',version,target,batch_file))))
|
||||
targets.append((target,(arch,get_compiler_env(conf,'intel',version,target,batch_file))))
|
||||
except conf.errors.ConfigurationError:
|
||||
pass
|
||||
except WindowsError:
|
||||
|
@ -438,7 +523,7 @@ def gather_icl_versions(conf, versions):
|
|||
batch_file=os.path.join(path,'bin','iclvars.bat')
|
||||
if os.path.isfile(batch_file):
|
||||
try:
|
||||
targets.append((target, (arch, conf.get_msvc_version('intel', version, target, batch_file))))
|
||||
targets.append((target, (arch, get_compiler_env(conf, 'intel', version, target, batch_file))))
|
||||
except conf.errors.ConfigurationError:
|
||||
pass
|
||||
except WindowsError:
|
||||
|
@ -490,8 +575,8 @@ def gather_intel_composer_versions(conf, versions):
|
|||
batch_file=os.path.join(path,'bin','iclvars.bat')
|
||||
if os.path.isfile(batch_file):
|
||||
try:
|
||||
targets.append((target,(arch,conf.get_msvc_version('intel',version,target,batch_file))))
|
||||
except conf.errors.ConfigurationError as e:
|
||||
targets.append((target,(arch,get_compiler_env(conf,'intel',version,target,batch_file))))
|
||||
except conf.errors.ConfigurationError:
|
||||
pass
|
||||
# The intel compilervar_arch.bat is broken when used with Visual Studio Express 2012
|
||||
# http://software.intel.com/en-us/forums/topic/328487
|
||||
|
|
Loading…
Reference in New Issue