mirror of https://gitlab.com/ita1024/waf.git
Optionally lazily check installed msvc compilers' environments and stop when one
is found that matches the user's options. This happens during autodetect only when the new option msvc_lazy_autodetect or env.MSVC_LAZY_AUTODETECT is set.
This commit is contained in:
parent
61f09a3f7c
commit
4b65d3f875
|
@ -90,8 +90,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 +113,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 +134,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)
|
||||
|
@ -186,7 +203,7 @@ echo LIB=%%LIB%%;%%LIBPATH%%
|
|||
return (MSVC_PATH, MSVC_INCDIR, MSVC_LIBDIR)
|
||||
|
||||
@conf
|
||||
def gather_wsdk_versions(conf, versions):
|
||||
def gather_wsdk_versions(conf, versions, lazy=False):
|
||||
"""
|
||||
Use winreg to add the msvc versions to the input list
|
||||
|
||||
|
@ -219,7 +236,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, lazy, 'wsdk', version, '/'+target, os.path.join(path, 'bin', 'SetEnv.cmd')))))
|
||||
except conf.errors.ConfigurationError:
|
||||
pass
|
||||
versions.append(('wsdk ' + version[1:], targets))
|
||||
|
@ -304,31 +321,88 @@ def gather_msvc_detected_versions():
|
|||
detected_versions.sort(key = fun)
|
||||
return detected_versions
|
||||
|
||||
def get_compiler_env(conf, lazy, compiler, version, bat_target, bat, select=None):
|
||||
"""
|
||||
Gets the compiler environment variables as a tuple, optionally as a lazy tuple
|
||||
that checks on destructuring, iteration, etc.
|
||||
|
||||
:param conf: configuration context to use to eventually get the version environment
|
||||
:param lazy: whether to defer checking the environment for all discovered targets or do it immediately
|
||||
: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)
|
||||
"""
|
||||
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):
|
||||
def gather_msvc_targets(conf, versions, version, vc_path, lazy=False):
|
||||
#Looking for normal MSVC compilers!
|
||||
targets = []
|
||||
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, lazy, '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, lazy, '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, lazy, 'msvc', version, '', os.path.join(vc_path, 'Bin', 'vcvars32.bat')))))
|
||||
except conf.errors.ConfigurationError:
|
||||
pass
|
||||
if targets:
|
||||
versions.append(('msvc '+ version, targets))
|
||||
|
||||
@conf
|
||||
def gather_wince_targets(conf, versions, version, vc_path, vsvars, supported_platforms):
|
||||
def gather_wince_targets(conf, versions, version, vc_path, vsvars, supported_platforms, lazy=False):
|
||||
#Looking for Win CE compilers!
|
||||
for device,platforms in supported_platforms:
|
||||
cetargets = []
|
||||
|
@ -336,32 +410,36 @@ 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, lazy, 'msvc', version, 'x86', vsvars, combine_common))))
|
||||
except conf.errors.ConfigurationError:
|
||||
continue
|
||||
|
||||
if cetargets:
|
||||
versions.append((device + ' ' + version, cetargets))
|
||||
|
||||
@conf
|
||||
def gather_winphone_targets(conf, versions, version, vc_path, vsvars):
|
||||
def gather_winphone_targets(conf, versions, version, vc_path, vsvars, lazy=False):
|
||||
#Looking for WinPhone compilers
|
||||
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, lazy, 'winphone', version, target, vsvars))))
|
||||
except conf.errors.ConfigurationError:
|
||||
pass
|
||||
if targets:
|
||||
versions.append(('winphone '+ version, targets))
|
||||
|
||||
@conf
|
||||
def gather_msvc_versions(conf, versions):
|
||||
def gather_msvc_versions(conf, versions, lazy=False):
|
||||
vc_paths = []
|
||||
for (v,version,reg) in gather_msvc_detected_versions():
|
||||
try:
|
||||
|
@ -380,18 +458,18 @@ def gather_msvc_versions(conf, versions):
|
|||
vs_path = os.path.dirname(vc_path)
|
||||
vsvars = os.path.join(vs_path, 'Common7', 'Tools', 'vsvars32.bat')
|
||||
if wince_supported_platforms and os.path.isfile(vsvars):
|
||||
conf.gather_wince_targets(versions, version, vc_path, vsvars, wince_supported_platforms)
|
||||
conf.gather_wince_targets(versions, version, vc_path, vsvars, wince_supported_platforms, lazy)
|
||||
|
||||
vsvars = os.path.join(vs_path, 'VC', 'WPSDK', 'WP80', 'vcvarsphoneall.bat')
|
||||
if os.path.isfile(vsvars):
|
||||
conf.gather_winphone_targets(versions, '8.0', vc_path, vsvars)
|
||||
conf.gather_winphone_targets(versions, '8.0', vc_path, vsvars, lazy)
|
||||
|
||||
for version,vc_path in vc_paths:
|
||||
vs_path = os.path.dirname(vc_path)
|
||||
conf.gather_msvc_targets(versions, version, vc_path)
|
||||
conf.gather_msvc_targets(versions, version, vc_path, lazy)
|
||||
|
||||
@conf
|
||||
def gather_icl_versions(conf, versions):
|
||||
def gather_icl_versions(conf, versions, lazy=False):
|
||||
"""
|
||||
Checks ICL compilers
|
||||
|
||||
|
@ -426,7 +504,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,lazy,'intel',version,target,batch_file))))
|
||||
except conf.errors.ConfigurationError:
|
||||
pass
|
||||
except WindowsError:
|
||||
|
@ -438,7 +516,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, lazy, 'intel', version, target, batch_file))))
|
||||
except conf.errors.ConfigurationError:
|
||||
pass
|
||||
except WindowsError:
|
||||
|
@ -447,7 +525,7 @@ def gather_icl_versions(conf, versions):
|
|||
versions.append(('intel ' + major, targets))
|
||||
|
||||
@conf
|
||||
def gather_intel_composer_versions(conf, versions):
|
||||
def gather_intel_composer_versions(conf, versions, lazy=False):
|
||||
"""
|
||||
Checks ICL compilers that are part of Intel Composer Suites
|
||||
|
||||
|
@ -490,8 +568,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,lazy,'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
|
||||
|
@ -516,17 +594,17 @@ def gather_intel_composer_versions(conf, versions):
|
|||
versions.append(('intel ' + major, targets))
|
||||
|
||||
@conf
|
||||
def get_msvc_versions(conf):
|
||||
def get_msvc_versions(conf, lazy=False):
|
||||
"""
|
||||
:return: list of compilers installed
|
||||
:rtype: list of string
|
||||
"""
|
||||
if not conf.env['MSVC_INSTALLED_VERSIONS']:
|
||||
lst = []
|
||||
conf.gather_icl_versions(lst)
|
||||
conf.gather_intel_composer_versions(lst)
|
||||
conf.gather_wsdk_versions(lst)
|
||||
conf.gather_msvc_versions(lst)
|
||||
conf.gather_icl_versions(lst, lazy)
|
||||
conf.gather_intel_composer_versions(lst, lazy)
|
||||
conf.gather_wsdk_versions(lst, lazy)
|
||||
conf.gather_msvc_versions(lst, lazy)
|
||||
conf.env['MSVC_INSTALLED_VERSIONS'] = lst
|
||||
return conf.env['MSVC_INSTALLED_VERSIONS']
|
||||
|
||||
|
@ -541,8 +619,8 @@ def print_all_msvc_detected(conf):
|
|||
Logs.info("\t"+target)
|
||||
|
||||
@conf
|
||||
def detect_msvc(conf, arch = False):
|
||||
versions = get_msvc_versions(conf)
|
||||
def detect_msvc(conf, arch=False, lazy=False):
|
||||
versions = get_msvc_versions(conf, lazy)
|
||||
return setup_msvc(conf, versions, arch)
|
||||
|
||||
@conf
|
||||
|
@ -664,7 +742,8 @@ def configure(conf):
|
|||
"""
|
||||
Configuration methods to call for detecting msvc
|
||||
"""
|
||||
conf.autodetect(True)
|
||||
lazy = getattr(Options.options, 'msvc_lazy_autodetect', False) or conf.env['MSVC_LAZY_AUTODETECT']
|
||||
conf.autodetect(True, lazy)
|
||||
conf.find_msvc()
|
||||
conf.msvc_common_flags()
|
||||
conf.cc_load_tools()
|
||||
|
@ -680,15 +759,15 @@ def no_autodetect(conf):
|
|||
configure(conf)
|
||||
|
||||
@conf
|
||||
def autodetect(conf, arch = False):
|
||||
def autodetect(conf, arch=False, lazy=False):
|
||||
v = conf.env
|
||||
if v.NO_MSVC_DETECT:
|
||||
return
|
||||
if arch:
|
||||
compiler, version, path, includes, libdirs, arch = conf.detect_msvc(True)
|
||||
compiler, version, path, includes, libdirs, arch = conf.detect_msvc(True, lazy)
|
||||
v['DEST_CPU'] = arch
|
||||
else:
|
||||
compiler, version, path, includes, libdirs = conf.detect_msvc()
|
||||
compiler, version, path, includes, libdirs = conf.detect_msvc(False, lazy)
|
||||
|
||||
v['PATH'] = path
|
||||
v['INCLUDES'] = includes
|
||||
|
|
Loading…
Reference in New Issue