Blame third_party/waf/waflib/Tools/msvc.py

rpm-build 95f51c
#!/usr/bin/env python
rpm-build 95f51c
# encoding: utf-8
rpm-build 95f51c
# Carlos Rafael Giani, 2006 (dv)
rpm-build 95f51c
# Tamas Pal, 2007 (folti)
rpm-build 95f51c
# Nicolas Mercier, 2009
rpm-build 95f51c
# Matt Clarkson, 2012
rpm-build 95f51c
rpm-build 95f51c
"""
rpm-build 95f51c
Microsoft Visual C++/Intel C++ compiler support
rpm-build 95f51c
rpm-build 95f51c
If you get detection problems, first try any of the following::
rpm-build 95f51c
rpm-build 95f51c
	chcp 65001
rpm-build 95f51c
	set PYTHONIOENCODING=...
rpm-build 95f51c
	set PYTHONLEGACYWINDOWSSTDIO=1
rpm-build 95f51c
rpm-build 95f51c
Usage::
rpm-build 95f51c
rpm-build 95f51c
	$ waf configure --msvc_version="msvc 10.0,msvc 9.0" --msvc_target="x64"
rpm-build 95f51c
rpm-build 95f51c
or::
rpm-build 95f51c
rpm-build 95f51c
	def configure(conf):
rpm-build 95f51c
		conf.env.MSVC_VERSIONS = ['msvc 10.0', 'msvc 9.0', 'msvc 8.0', 'msvc 7.1', 'msvc 7.0', 'msvc 6.0', 'wsdk 7.0', 'intel 11', 'PocketPC 9.0', 'Smartphone 8.0']
rpm-build 95f51c
		conf.env.MSVC_TARGETS = ['x64']
rpm-build 95f51c
		conf.load('msvc')
rpm-build 95f51c
rpm-build 95f51c
or::
rpm-build 95f51c
rpm-build 95f51c
	def configure(conf):
rpm-build 95f51c
		conf.load('msvc', funs='no_autodetect')
rpm-build 95f51c
		conf.check_lib_msvc('gdi32')
rpm-build 95f51c
		conf.check_libs_msvc('kernel32 user32')
rpm-build 95f51c
	def build(bld):
rpm-build 95f51c
		tg = bld.program(source='main.c', target='app', use='KERNEL32 USER32 GDI32')
rpm-build 95f51c
rpm-build 95f51c
Platforms and targets will be tested in the order they appear;
rpm-build 95f51c
the first good configuration will be used.
rpm-build 95f51c
rpm-build 95f51c
To force testing all the configurations that are not used, use the ``--no-msvc-lazy`` option
rpm-build 95f51c
or set ``conf.env.MSVC_LAZY_AUTODETECT=False``.
rpm-build 95f51c
rpm-build 95f51c
Supported platforms: ia64, x64, x86, x86_amd64, x86_ia64, x86_arm, amd64_x86, amd64_arm
rpm-build 95f51c
rpm-build 95f51c
Compilers supported:
rpm-build 95f51c
rpm-build 95f51c
* msvc       => Visual Studio, versions 6.0 (VC 98, VC .NET 2002) to 15 (Visual Studio 2017)
rpm-build 95f51c
* wsdk       => Windows SDK, versions 6.0, 6.1, 7.0, 7.1, 8.0
rpm-build 95f51c
* icl        => Intel compiler, versions 9, 10, 11, 13
rpm-build 95f51c
* winphone   => Visual Studio to target Windows Phone 8 native (version 8.0 for now)
rpm-build 95f51c
* Smartphone => Compiler/SDK for Smartphone devices (armv4/v4i)
rpm-build 95f51c
* PocketPC   => Compiler/SDK for PocketPC devices (armv4/v4i)
rpm-build 95f51c
rpm-build 95f51c
To use WAF in a VS2008 Make file project (see http://code.google.com/p/waf/issues/detail?id=894)
rpm-build 95f51c
You may consider to set the environment variable "VS_UNICODE_OUTPUT" to nothing before calling waf.
rpm-build 95f51c
So in your project settings use something like 'cmd.exe /C "set VS_UNICODE_OUTPUT=& set PYTHONUNBUFFERED=true & waf build"'.
rpm-build 95f51c
cmd.exe  /C  "chcp 1252 & set PYTHONUNBUFFERED=true && set && waf  configure"
rpm-build 95f51c
Setting PYTHONUNBUFFERED gives the unbuffered output.
rpm-build 95f51c
"""
rpm-build 95f51c
rpm-build 95f51c
import os, sys, re, traceback
rpm-build 95f51c
from waflib import Utils, Logs, Options, Errors
rpm-build 95f51c
from waflib.TaskGen import after_method, feature
rpm-build 95f51c
rpm-build 95f51c
from waflib.Configure import conf
rpm-build 95f51c
from waflib.Tools import ccroot, c, cxx, ar
rpm-build 95f51c
rpm-build 95f51c
g_msvc_systemlibs = '''
rpm-build 95f51c
aclui activeds ad1 adptif adsiid advapi32 asycfilt authz bhsupp bits bufferoverflowu cabinet
rpm-build 95f51c
cap certadm certidl ciuuid clusapi comctl32 comdlg32 comsupp comsuppd comsuppw comsuppwd comsvcs
rpm-build 95f51c
credui crypt32 cryptnet cryptui d3d8thk daouuid dbgeng dbghelp dciman32 ddao35 ddao35d
rpm-build 95f51c
ddao35u ddao35ud delayimp dhcpcsvc dhcpsapi dlcapi dnsapi dsprop dsuiext dtchelp
rpm-build 95f51c
faultrep fcachdll fci fdi framedyd framedyn gdi32 gdiplus glauxglu32 gpedit gpmuuid
rpm-build 95f51c
gtrts32w gtrtst32hlink htmlhelp httpapi icm32 icmui imagehlp imm32 iphlpapi iprop
rpm-build 95f51c
kernel32 ksguid ksproxy ksuser libcmt libcmtd libcpmt libcpmtd loadperf lz32 mapi
rpm-build 95f51c
mapi32 mgmtapi minidump mmc mobsync mpr mprapi mqoa mqrt msacm32 mscms mscoree
rpm-build 95f51c
msdasc msimg32 msrating mstask msvcmrt msvcurt msvcurtd mswsock msxml2 mtx mtxdm
rpm-build 95f51c
netapi32 nmapinmsupp npptools ntdsapi ntdsbcli ntmsapi ntquery odbc32 odbcbcp
rpm-build 95f51c
odbccp32 oldnames ole32 oleacc oleaut32 oledb oledlgolepro32 opends60 opengl32
rpm-build 95f51c
osptk parser pdh penter pgobootrun pgort powrprof psapi ptrustm ptrustmd ptrustu
rpm-build 95f51c
ptrustud qosname rasapi32 rasdlg rassapi resutils riched20 rpcndr rpcns4 rpcrt4 rtm
rpm-build 95f51c
rtutils runtmchk scarddlg scrnsave scrnsavw secur32 sensapi setupapi sfc shell32
rpm-build 95f51c
shfolder shlwapi sisbkup snmpapi sporder srclient sti strsafe svcguid tapi32 thunk32
rpm-build 95f51c
traffic unicows url urlmon user32 userenv usp10 uuid uxtheme vcomp vcompd vdmdbg
rpm-build 95f51c
version vfw32 wbemuuid  webpost wiaguid wininet winmm winscard winspool winstrm
rpm-build 95f51c
wintrust wldap32 wmiutils wow32 ws2_32 wsnmp32 wsock32 wst wtsapi32 xaswitch xolehlp
rpm-build 95f51c
'''.split()
rpm-build 95f51c
"""importlibs provided by MSVC/Platform SDK. Do NOT search them"""
rpm-build 95f51c
rpm-build 95f51c
all_msvc_platforms = [	('x64', 'amd64'), ('x86', 'x86'), ('ia64', 'ia64'),
rpm-build 95f51c
						('x86_amd64', 'amd64'), ('x86_ia64', 'ia64'), ('x86_arm', 'arm'), ('x86_arm64', 'arm64'),
rpm-build 95f51c
						('amd64_x86', 'x86'), ('amd64_arm', 'arm'), ('amd64_arm64', 'arm64') ]
rpm-build 95f51c
"""List of msvc platforms"""
rpm-build 95f51c
rpm-build 95f51c
all_wince_platforms = [ ('armv4', 'arm'), ('armv4i', 'arm'), ('mipsii', 'mips'), ('mipsii_fp', 'mips'), ('mipsiv', 'mips'), ('mipsiv_fp', 'mips'), ('sh4', 'sh'), ('x86', 'cex86') ]
rpm-build 95f51c
"""List of wince platforms"""
rpm-build 95f51c
rpm-build 95f51c
all_icl_platforms = [ ('intel64', 'amd64'), ('em64t', 'amd64'), ('ia32', 'x86'), ('Itanium', 'ia64')]
rpm-build 95f51c
"""List of icl platforms"""
rpm-build 95f51c
rpm-build 95f51c
def options(opt):
rpm-build 95f51c
	opt.add_option('--msvc_version', type='string', help = 'msvc version, eg: "msvc 10.0,msvc 9.0"', default='')
rpm-build 95f51c
	opt.add_option('--msvc_targets', type='string', help = 'msvc targets, eg: "x64,arm"', default='')
rpm-build 95f51c
	opt.add_option('--no-msvc-lazy', action='store_false', help = 'lazily check msvc target environments', default=True, dest='msvc_lazy')
rpm-build 95f51c
rpm-build 95f51c
@conf
rpm-build 95f51c
def setup_msvc(conf, versiondict):
rpm-build 95f51c
	"""
rpm-build 95f51c
	Checks installed compilers and targets and returns the first combination from the user's
rpm-build 95f51c
	options, env, or the global supported lists that checks.
rpm-build 95f51c
rpm-build 95f51c
	:param versiondict: dict(platform -> dict(architecture -> configuration))
rpm-build 95f51c
	:type versiondict: dict(string -> dict(string -> target_compiler)
rpm-build 95f51c
	:return: the compiler, revision, path, include dirs, library paths and target architecture
rpm-build 95f51c
	:rtype: tuple of strings
rpm-build 95f51c
	"""
rpm-build 95f51c
	platforms = getattr(Options.options, 'msvc_targets', '').split(',')
rpm-build 95f51c
	if platforms == ['']:
rpm-build 95f51c
		platforms=Utils.to_list(conf.env.MSVC_TARGETS) or [i for i,j in all_msvc_platforms+all_icl_platforms+all_wince_platforms]
rpm-build 95f51c
	desired_versions = getattr(Options.options, 'msvc_version', '').split(',')
rpm-build 95f51c
	if desired_versions == ['']:
rpm-build 95f51c
		desired_versions = conf.env.MSVC_VERSIONS or list(reversed(sorted(versiondict.keys())))
rpm-build 95f51c
rpm-build 95f51c
	# Override lazy detection by evaluating after the fact.
rpm-build 95f51c
	lazy_detect = getattr(Options.options, 'msvc_lazy', True)
rpm-build 95f51c
	if conf.env.MSVC_LAZY_AUTODETECT is False:
rpm-build 95f51c
		lazy_detect = False
rpm-build 95f51c
rpm-build 95f51c
	if not lazy_detect:
rpm-build 95f51c
		for val in versiondict.values():
rpm-build 95f51c
			for arch in list(val.keys()):
rpm-build 95f51c
				cfg = val[arch]
rpm-build 95f51c
				cfg.evaluate()
rpm-build 95f51c
				if not cfg.is_valid:
rpm-build 95f51c
					del val[arch]
rpm-build 95f51c
		conf.env.MSVC_INSTALLED_VERSIONS = versiondict
rpm-build 95f51c
rpm-build 95f51c
	for version in desired_versions:
rpm-build 95f51c
		Logs.debug('msvc: detecting %r - %r', version, desired_versions)
rpm-build 95f51c
		try:
rpm-build 95f51c
			targets = versiondict[version]
rpm-build 95f51c
		except KeyError:
rpm-build 95f51c
			continue
rpm-build 95f51c
rpm-build 95f51c
		seen = set()
rpm-build 95f51c
		for arch in platforms:
rpm-build 95f51c
			if arch in seen:
rpm-build 95f51c
				continue
rpm-build 95f51c
			else:
rpm-build 95f51c
				seen.add(arch)
rpm-build 95f51c
			try:
rpm-build 95f51c
				cfg = targets[arch]
rpm-build 95f51c
			except KeyError:
rpm-build 95f51c
				continue
rpm-build 95f51c
rpm-build 95f51c
			cfg.evaluate()
rpm-build 95f51c
			if cfg.is_valid:
rpm-build 95f51c
				compiler,revision = version.rsplit(' ', 1)
rpm-build 95f51c
				return compiler,revision,cfg.bindirs,cfg.incdirs,cfg.libdirs,cfg.cpu
rpm-build 95f51c
	conf.fatal('msvc: Impossible to find a valid architecture for building %r - %r' % (desired_versions, list(versiondict.keys())))
rpm-build 95f51c
rpm-build 95f51c
@conf
rpm-build 95f51c
def get_msvc_version(conf, compiler, version, target, vcvars):
rpm-build 95f51c
	"""
rpm-build 95f51c
	Checks that an installed compiler actually runs and uses vcvars to obtain the
rpm-build 95f51c
	environment needed by the compiler.
rpm-build 95f51c
rpm-build 95f51c
	:param compiler: compiler type, for looking up the executable name
rpm-build 95f51c
	:param version: compiler version, for debugging only
rpm-build 95f51c
	:param target: target architecture
rpm-build 95f51c
	:param vcvars: batch file to run to check the environment
rpm-build 95f51c
	:return: the location of the compiler executable, the location of include dirs, and the library paths
rpm-build 95f51c
	:rtype: tuple of strings
rpm-build 95f51c
	"""
rpm-build 95f51c
	Logs.debug('msvc: get_msvc_version: %r %r %r', compiler, version, target)
rpm-build 95f51c
rpm-build 95f51c
	try:
rpm-build 95f51c
		conf.msvc_cnt += 1
rpm-build 95f51c
	except AttributeError:
rpm-build 95f51c
		conf.msvc_cnt = 1
rpm-build 95f51c
	batfile = conf.bldnode.make_node('waf-print-msvc-%d.bat' % conf.msvc_cnt)
rpm-build 95f51c
	batfile.write("""@echo off
rpm-build 95f51c
set INCLUDE=
rpm-build 95f51c
set LIB=
rpm-build 95f51c
call "%s" %s
rpm-build 95f51c
echo PATH=%%PATH%%
rpm-build 95f51c
echo INCLUDE=%%INCLUDE%%
rpm-build 95f51c
echo LIB=%%LIB%%;%%LIBPATH%%
rpm-build 95f51c
""" % (vcvars,target))
rpm-build 95f51c
	sout = conf.cmd_and_log(['cmd.exe', '/E:on', '/V:on', '/C', batfile.abspath()])
rpm-build 95f51c
	lines = sout.splitlines()
rpm-build 95f51c
rpm-build 95f51c
	if not lines[0]:
rpm-build 95f51c
		lines.pop(0)
rpm-build 95f51c
rpm-build 95f51c
	MSVC_PATH = MSVC_INCDIR = MSVC_LIBDIR = None
rpm-build 95f51c
	for line in lines:
rpm-build 95f51c
		if line.startswith('PATH='):
rpm-build 95f51c
			path = line[5:]
rpm-build 95f51c
			MSVC_PATH = path.split(';')
rpm-build 95f51c
		elif line.startswith('INCLUDE='):
rpm-build 95f51c
			MSVC_INCDIR = [i for i in line[8:].split(';') if i]
rpm-build 95f51c
		elif line.startswith('LIB='):
rpm-build 95f51c
			MSVC_LIBDIR = [i for i in line[4:].split(';') if i]
rpm-build 95f51c
	if None in (MSVC_PATH, MSVC_INCDIR, MSVC_LIBDIR):
rpm-build 95f51c
		conf.fatal('msvc: Could not find a valid architecture for building (get_msvc_version_3)')
rpm-build 95f51c
rpm-build 95f51c
	# Check if the compiler is usable at all.
rpm-build 95f51c
	# The detection may return 64-bit versions even on 32-bit systems, and these would fail to run.
rpm-build 95f51c
	env = dict(os.environ)
rpm-build 95f51c
	env.update(PATH = path)
rpm-build 95f51c
	compiler_name, linker_name, lib_name = _get_prog_names(conf, compiler)
rpm-build 95f51c
	cxx = conf.find_program(compiler_name, path_list=MSVC_PATH)
rpm-build 95f51c
rpm-build 95f51c
	# delete CL if exists. because it could contain parameters which can change cl's behaviour rather catastrophically.
rpm-build 95f51c
	if 'CL' in env:
rpm-build 95f51c
		del(env['CL'])
rpm-build 95f51c
rpm-build 95f51c
	try:
rpm-build 95f51c
		conf.cmd_and_log(cxx + ['/help'], env=env)
rpm-build 95f51c
	except UnicodeError:
rpm-build 95f51c
		st = traceback.format_exc()
rpm-build 95f51c
		if conf.logger:
rpm-build 95f51c
			conf.logger.error(st)
rpm-build 95f51c
		conf.fatal('msvc: Unicode error - check the code page?')
rpm-build 95f51c
	except Exception as e:
rpm-build 95f51c
		Logs.debug('msvc: get_msvc_version: %r %r %r -> failure %s', compiler, version, target, str(e))
rpm-build 95f51c
		conf.fatal('msvc: cannot run the compiler in get_msvc_version (run with -v to display errors)')
rpm-build 95f51c
	else:
rpm-build 95f51c
		Logs.debug('msvc: get_msvc_version: %r %r %r -> OK', compiler, version, target)
rpm-build 95f51c
	finally:
rpm-build 95f51c
		conf.env[compiler_name] = ''
rpm-build 95f51c
rpm-build 95f51c
	return (MSVC_PATH, MSVC_INCDIR, MSVC_LIBDIR)
rpm-build 95f51c
rpm-build 95f51c
def gather_wince_supported_platforms():
rpm-build 95f51c
	"""
rpm-build 95f51c
	Checks SmartPhones SDKs
rpm-build 95f51c
rpm-build 95f51c
	:param versions: list to modify
rpm-build 95f51c
	:type versions: list
rpm-build 95f51c
	"""
rpm-build 95f51c
	supported_wince_platforms = []
rpm-build 95f51c
	try:
rpm-build 95f51c
		ce_sdk = Utils.winreg.OpenKey(Utils.winreg.HKEY_LOCAL_MACHINE, 'SOFTWARE\\Wow6432node\\Microsoft\\Windows CE Tools\\SDKs')
rpm-build 95f51c
	except OSError:
rpm-build 95f51c
		try:
rpm-build 95f51c
			ce_sdk = Utils.winreg.OpenKey(Utils.winreg.HKEY_LOCAL_MACHINE, 'SOFTWARE\\Microsoft\\Windows CE Tools\\SDKs')
rpm-build 95f51c
		except OSError:
rpm-build 95f51c
			ce_sdk = ''
rpm-build 95f51c
	if not ce_sdk:
rpm-build 95f51c
		return supported_wince_platforms
rpm-build 95f51c
rpm-build 95f51c
	index = 0
rpm-build 95f51c
	while 1:
rpm-build 95f51c
		try:
rpm-build 95f51c
			sdk_device = Utils.winreg.EnumKey(ce_sdk, index)
rpm-build 95f51c
			sdk = Utils.winreg.OpenKey(ce_sdk, sdk_device)
rpm-build 95f51c
		except OSError:
rpm-build 95f51c
			break
rpm-build 95f51c
		index += 1
rpm-build 95f51c
		try:
rpm-build 95f51c
			path,type = Utils.winreg.QueryValueEx(sdk, 'SDKRootDir')
rpm-build 95f51c
		except OSError:
rpm-build 95f51c
			try:
rpm-build 95f51c
				path,type = Utils.winreg.QueryValueEx(sdk,'SDKInformation')
rpm-build 95f51c
			except OSError:
rpm-build 95f51c
				continue
rpm-build 95f51c
			path,xml = os.path.split(path)
rpm-build 95f51c
		path = str(path)
rpm-build 95f51c
		path,device = os.path.split(path)
rpm-build 95f51c
		if not device:
rpm-build 95f51c
			path,device = os.path.split(path)
rpm-build 95f51c
		platforms = []
rpm-build 95f51c
		for arch,compiler in all_wince_platforms:
rpm-build 95f51c
			if os.path.isdir(os.path.join(path, device, 'Lib', arch)):
rpm-build 95f51c
				platforms.append((arch, compiler, os.path.join(path, device, 'Include', arch), os.path.join(path, device, 'Lib', arch)))
rpm-build 95f51c
		if platforms:
rpm-build 95f51c
			supported_wince_platforms.append((device, platforms))
rpm-build 95f51c
	return supported_wince_platforms
rpm-build 95f51c
rpm-build 95f51c
def gather_msvc_detected_versions():
rpm-build 95f51c
	#Detected MSVC versions!
rpm-build 95f51c
	version_pattern = re.compile(r'^(\d\d?\.\d\d?)(Exp)?$')
rpm-build 95f51c
	detected_versions = []
rpm-build 95f51c
	for vcver,vcvar in (('VCExpress','Exp'), ('VisualStudio','')):
rpm-build 95f51c
		prefix = 'SOFTWARE\\Wow6432node\\Microsoft\\' + vcver
rpm-build 95f51c
		try:
rpm-build 95f51c
			all_versions = Utils.winreg.OpenKey(Utils.winreg.HKEY_LOCAL_MACHINE, prefix)
rpm-build 95f51c
		except OSError:
rpm-build 95f51c
			prefix = 'SOFTWARE\\Microsoft\\' + vcver
rpm-build 95f51c
			try:
rpm-build 95f51c
				all_versions = Utils.winreg.OpenKey(Utils.winreg.HKEY_LOCAL_MACHINE, prefix)
rpm-build 95f51c
			except OSError:
rpm-build 95f51c
				continue
rpm-build 95f51c
rpm-build 95f51c
		index = 0
rpm-build 95f51c
		while 1:
rpm-build 95f51c
			try:
rpm-build 95f51c
				version = Utils.winreg.EnumKey(all_versions, index)
rpm-build 95f51c
			except OSError:
rpm-build 95f51c
				break
rpm-build 95f51c
			index += 1
rpm-build 95f51c
			match = version_pattern.match(version)
rpm-build 95f51c
			if match:
rpm-build 95f51c
				versionnumber = float(match.group(1))
rpm-build 95f51c
			else:
rpm-build 95f51c
				continue
rpm-build 95f51c
			detected_versions.append((versionnumber, version+vcvar, prefix+'\\'+version))
rpm-build 95f51c
	def fun(tup):
rpm-build 95f51c
		return tup[0]
rpm-build 95f51c
rpm-build 95f51c
	detected_versions.sort(key = fun)
rpm-build 95f51c
	return detected_versions
rpm-build 95f51c
rpm-build 95f51c
class target_compiler(object):
rpm-build 95f51c
	"""
rpm-build 95f51c
	Wrap a compiler configuration; call evaluate() to determine
rpm-build 95f51c
	whether the configuration is usable.
rpm-build 95f51c
	"""
rpm-build 95f51c
	def __init__(self, ctx, compiler, cpu, version, bat_target, bat, callback=None):
rpm-build 95f51c
		"""
rpm-build 95f51c
		:param ctx: configuration context to use to eventually get the version environment
rpm-build 95f51c
		:param compiler: compiler name
rpm-build 95f51c
		:param cpu: target cpu
rpm-build 95f51c
		:param version: compiler version number
rpm-build 95f51c
		:param bat_target: ?
rpm-build 95f51c
		:param bat: path to the batch file to run
rpm-build 95f51c
		"""
rpm-build 95f51c
		self.conf = ctx
rpm-build 95f51c
		self.name = None
rpm-build 95f51c
		self.is_valid = False
rpm-build 95f51c
		self.is_done = False
rpm-build 95f51c
rpm-build 95f51c
		self.compiler = compiler
rpm-build 95f51c
		self.cpu = cpu
rpm-build 95f51c
		self.version = version
rpm-build 95f51c
		self.bat_target = bat_target
rpm-build 95f51c
		self.bat = bat
rpm-build 95f51c
		self.callback = callback
rpm-build 95f51c
rpm-build 95f51c
	def evaluate(self):
rpm-build 95f51c
		if self.is_done:
rpm-build 95f51c
			return
rpm-build 95f51c
		self.is_done = True
rpm-build 95f51c
		try:
rpm-build 95f51c
			vs = self.conf.get_msvc_version(self.compiler, self.version, self.bat_target, self.bat)
rpm-build 95f51c
		except Errors.ConfigurationError:
rpm-build 95f51c
			self.is_valid = False
rpm-build 95f51c
			return
rpm-build 95f51c
		if self.callback:
rpm-build 95f51c
			vs = self.callback(self, vs)
rpm-build 95f51c
		self.is_valid = True
rpm-build 95f51c
		(self.bindirs, self.incdirs, self.libdirs) = vs
rpm-build 95f51c
rpm-build 95f51c
	def __str__(self):
rpm-build 95f51c
		return str((self.compiler, self.cpu, self.version, self.bat_target, self.bat))
rpm-build 95f51c
rpm-build 95f51c
	def __repr__(self):
rpm-build 95f51c
		return repr((self.compiler, self.cpu, self.version, self.bat_target, self.bat))
rpm-build 95f51c
rpm-build 95f51c
@conf
rpm-build 95f51c
def gather_wsdk_versions(conf, versions):
rpm-build 95f51c
	"""
rpm-build 95f51c
	Use winreg to add the msvc versions to the input list
rpm-build 95f51c
rpm-build 95f51c
	:param versions: list to modify
rpm-build 95f51c
	:type versions: list
rpm-build 95f51c
	"""
rpm-build 95f51c
	version_pattern = re.compile(r'^v..?.?\...?.?')
rpm-build 95f51c
	try:
rpm-build 95f51c
		all_versions = Utils.winreg.OpenKey(Utils.winreg.HKEY_LOCAL_MACHINE, 'SOFTWARE\\Wow6432node\\Microsoft\\Microsoft SDKs\\Windows')
rpm-build 95f51c
	except OSError:
rpm-build 95f51c
		try:
rpm-build 95f51c
			all_versions = Utils.winreg.OpenKey(Utils.winreg.HKEY_LOCAL_MACHINE, 'SOFTWARE\\Microsoft\\Microsoft SDKs\\Windows')
rpm-build 95f51c
		except OSError:
rpm-build 95f51c
			return
rpm-build 95f51c
	index = 0
rpm-build 95f51c
	while 1:
rpm-build 95f51c
		try:
rpm-build 95f51c
			version = Utils.winreg.EnumKey(all_versions, index)
rpm-build 95f51c
		except OSError:
rpm-build 95f51c
			break
rpm-build 95f51c
		index += 1
rpm-build 95f51c
		if not version_pattern.match(version):
rpm-build 95f51c
			continue
rpm-build 95f51c
		try:
rpm-build 95f51c
			msvc_version = Utils.winreg.OpenKey(all_versions, version)
rpm-build 95f51c
			path,type = Utils.winreg.QueryValueEx(msvc_version,'InstallationFolder')
rpm-build 95f51c
		except OSError:
rpm-build 95f51c
			continue
rpm-build 95f51c
		if path and os.path.isfile(os.path.join(path, 'bin', 'SetEnv.cmd')):
rpm-build 95f51c
			targets = {}
rpm-build 95f51c
			for target,arch in all_msvc_platforms:
rpm-build 95f51c
				targets[target] = target_compiler(conf, 'wsdk', arch, version, '/'+target, os.path.join(path, 'bin', 'SetEnv.cmd'))
rpm-build 95f51c
			versions['wsdk ' + version[1:]] = targets
rpm-build 95f51c
rpm-build 95f51c
@conf
rpm-build 95f51c
def gather_msvc_targets(conf, versions, version, vc_path):
rpm-build 95f51c
	#Looking for normal MSVC compilers!
rpm-build 95f51c
	targets = {}
rpm-build 95f51c
rpm-build 95f51c
	if os.path.isfile(os.path.join(vc_path, 'VC', 'Auxiliary', 'Build', 'vcvarsall.bat')):
rpm-build 95f51c
		for target,realtarget in all_msvc_platforms[::-1]:
rpm-build 95f51c
			targets[target] = target_compiler(conf, 'msvc', realtarget, version, target, os.path.join(vc_path, 'VC', 'Auxiliary', 'Build', 'vcvarsall.bat'))
rpm-build 95f51c
	elif os.path.isfile(os.path.join(vc_path, 'vcvarsall.bat')):
rpm-build 95f51c
		for target,realtarget in all_msvc_platforms[::-1]:
rpm-build 95f51c
			targets[target] = target_compiler(conf, 'msvc', realtarget, version, target, os.path.join(vc_path, 'vcvarsall.bat'))
rpm-build 95f51c
	elif os.path.isfile(os.path.join(vc_path, 'Common7', 'Tools', 'vsvars32.bat')):
rpm-build 95f51c
		targets['x86'] = target_compiler(conf, 'msvc', 'x86', version, 'x86', os.path.join(vc_path, 'Common7', 'Tools', 'vsvars32.bat'))
rpm-build 95f51c
	elif os.path.isfile(os.path.join(vc_path, 'Bin', 'vcvars32.bat')):
rpm-build 95f51c
		targets['x86'] = target_compiler(conf, 'msvc', 'x86', version, '', os.path.join(vc_path, 'Bin', 'vcvars32.bat'))
rpm-build 95f51c
	if targets:
rpm-build 95f51c
		versions['msvc %s' % version] = targets
rpm-build 95f51c
rpm-build 95f51c
@conf
rpm-build 95f51c
def gather_wince_targets(conf, versions, version, vc_path, vsvars, supported_platforms):
rpm-build 95f51c
	#Looking for Win CE compilers!
rpm-build 95f51c
	for device,platforms in supported_platforms:
rpm-build 95f51c
		targets = {}
rpm-build 95f51c
		for platform,compiler,include,lib in platforms:
rpm-build 95f51c
			winCEpath = os.path.join(vc_path, 'ce')
rpm-build 95f51c
			if not os.path.isdir(winCEpath):
rpm-build 95f51c
				continue
rpm-build 95f51c
rpm-build 95f51c
			if os.path.isdir(os.path.join(winCEpath, 'lib', platform)):
rpm-build 95f51c
				bindirs = [os.path.join(winCEpath, 'bin', compiler), os.path.join(winCEpath, 'bin', 'x86_'+compiler)]
rpm-build 95f51c
				incdirs = [os.path.join(winCEpath, 'include'), os.path.join(winCEpath, 'atlmfc', 'include'), include]
rpm-build 95f51c
				libdirs = [os.path.join(winCEpath, 'lib', platform), os.path.join(winCEpath, 'atlmfc', 'lib', platform), lib]
rpm-build 95f51c
				def combine_common(obj, compiler_env):
rpm-build 95f51c
					# TODO this is likely broken, remove in waf 2.1
rpm-build 95f51c
					(common_bindirs,_1,_2) = compiler_env
rpm-build 95f51c
					return (bindirs + common_bindirs, incdirs, libdirs)
rpm-build 95f51c
				targets[platform] = target_compiler(conf, 'msvc', platform, version, 'x86', vsvars, combine_common)
rpm-build 95f51c
		if targets:
rpm-build 95f51c
			versions[device + ' ' + version] = targets
rpm-build 95f51c
rpm-build 95f51c
@conf
rpm-build 95f51c
def gather_winphone_targets(conf, versions, version, vc_path, vsvars):
rpm-build 95f51c
	#Looking for WinPhone compilers
rpm-build 95f51c
	targets = {}
rpm-build 95f51c
	for target,realtarget in all_msvc_platforms[::-1]:
rpm-build 95f51c
		targets[target] = target_compiler(conf, 'winphone', realtarget, version, target, vsvars)
rpm-build 95f51c
	if targets:
rpm-build 95f51c
		versions['winphone ' + version] = targets
rpm-build 95f51c
rpm-build 95f51c
@conf
rpm-build 95f51c
def gather_vswhere_versions(conf, versions):
rpm-build 95f51c
	try:
rpm-build 95f51c
		import json
rpm-build 95f51c
	except ImportError:
rpm-build 95f51c
		Logs.error('Visual Studio 2017 detection requires Python 2.6')
rpm-build 95f51c
		return
rpm-build 95f51c
rpm-build 95f51c
	prg_path = os.environ.get('ProgramFiles(x86)', os.environ.get('ProgramFiles', 'C:\\Program Files (x86)'))
rpm-build 95f51c
rpm-build 95f51c
	vswhere = os.path.join(prg_path, 'Microsoft Visual Studio', 'Installer', 'vswhere.exe')
rpm-build 95f51c
	args = [vswhere, '-products', '*', '-legacy', '-format', 'json']
rpm-build 95f51c
	try:
rpm-build 95f51c
		txt = conf.cmd_and_log(args)
rpm-build 95f51c
	except Errors.WafError as e:
rpm-build 95f51c
		Logs.debug('msvc: vswhere.exe failed %s', e)
rpm-build 95f51c
		return
rpm-build 95f51c
rpm-build 95f51c
	if sys.version_info[0] < 3:
rpm-build 95f51c
		txt = txt.decode(Utils.console_encoding())
rpm-build 95f51c
rpm-build 95f51c
	arr = json.loads(txt)
rpm-build 95f51c
	arr.sort(key=lambda x: x['installationVersion'])
rpm-build 95f51c
	for entry in arr:
rpm-build 95f51c
		ver = entry['installationVersion']
rpm-build 95f51c
		ver = str('.'.join(ver.split('.')[:2]))
rpm-build 95f51c
		path = str(os.path.abspath(entry['installationPath']))
rpm-build 95f51c
		if os.path.exists(path) and ('msvc %s' % ver) not in versions:
rpm-build 95f51c
			conf.gather_msvc_targets(versions, ver, path)
rpm-build 95f51c
rpm-build 95f51c
@conf
rpm-build 95f51c
def gather_msvc_versions(conf, versions):
rpm-build 95f51c
	vc_paths = []
rpm-build 95f51c
	for (v,version,reg) in gather_msvc_detected_versions():
rpm-build 95f51c
		try:
rpm-build 95f51c
			try:
rpm-build 95f51c
				msvc_version = Utils.winreg.OpenKey(Utils.winreg.HKEY_LOCAL_MACHINE, reg + "\\Setup\\VC")
rpm-build 95f51c
			except OSError:
rpm-build 95f51c
				msvc_version = Utils.winreg.OpenKey(Utils.winreg.HKEY_LOCAL_MACHINE, reg + "\\Setup\\Microsoft Visual C++")
rpm-build 95f51c
			path,type = Utils.winreg.QueryValueEx(msvc_version, 'ProductDir')
rpm-build 95f51c
		except OSError:
rpm-build 95f51c
			try:
rpm-build 95f51c
				msvc_version = Utils.winreg.OpenKey(Utils.winreg.HKEY_LOCAL_MACHINE, "SOFTWARE\\Wow6432node\\Microsoft\\VisualStudio\\SxS\\VS7")
rpm-build 95f51c
				path,type = Utils.winreg.QueryValueEx(msvc_version, version)
rpm-build 95f51c
			except OSError:
rpm-build 95f51c
				continue
rpm-build 95f51c
			else:
rpm-build 95f51c
				vc_paths.append((version, os.path.abspath(str(path))))
rpm-build 95f51c
			continue
rpm-build 95f51c
		else:
rpm-build 95f51c
			vc_paths.append((version, os.path.abspath(str(path))))
rpm-build 95f51c
rpm-build 95f51c
	wince_supported_platforms = gather_wince_supported_platforms()
rpm-build 95f51c
rpm-build 95f51c
	for version,vc_path in vc_paths:
rpm-build 95f51c
		vs_path = os.path.dirname(vc_path)
rpm-build 95f51c
		vsvars = os.path.join(vs_path, 'Common7', 'Tools', 'vsvars32.bat')
rpm-build 95f51c
		if wince_supported_platforms and os.path.isfile(vsvars):
rpm-build 95f51c
			conf.gather_wince_targets(versions, version, vc_path, vsvars, wince_supported_platforms)
rpm-build 95f51c
rpm-build 95f51c
	# WP80 works with 11.0Exp and 11.0, both of which resolve to the same vc_path.
rpm-build 95f51c
	# Stop after one is found.
rpm-build 95f51c
	for version,vc_path in vc_paths:
rpm-build 95f51c
		vs_path = os.path.dirname(vc_path)
rpm-build 95f51c
		vsvars = os.path.join(vs_path, 'VC', 'WPSDK', 'WP80', 'vcvarsphoneall.bat')
rpm-build 95f51c
		if os.path.isfile(vsvars):
rpm-build 95f51c
			conf.gather_winphone_targets(versions, '8.0', vc_path, vsvars)
rpm-build 95f51c
			break
rpm-build 95f51c
rpm-build 95f51c
	for version,vc_path in vc_paths:
rpm-build 95f51c
		vs_path = os.path.dirname(vc_path)
rpm-build 95f51c
		conf.gather_msvc_targets(versions, version, vc_path)
rpm-build 95f51c
rpm-build 95f51c
@conf
rpm-build 95f51c
def gather_icl_versions(conf, versions):
rpm-build 95f51c
	"""
rpm-build 95f51c
	Checks ICL compilers
rpm-build 95f51c
rpm-build 95f51c
	:param versions: list to modify
rpm-build 95f51c
	:type versions: list
rpm-build 95f51c
	"""
rpm-build 95f51c
	version_pattern = re.compile(r'^...?.?\....?.?')
rpm-build 95f51c
	try:
rpm-build 95f51c
		all_versions = Utils.winreg.OpenKey(Utils.winreg.HKEY_LOCAL_MACHINE, 'SOFTWARE\\Wow6432node\\Intel\\Compilers\\C++')
rpm-build 95f51c
	except OSError:
rpm-build 95f51c
		try:
rpm-build 95f51c
			all_versions = Utils.winreg.OpenKey(Utils.winreg.HKEY_LOCAL_MACHINE, 'SOFTWARE\\Intel\\Compilers\\C++')
rpm-build 95f51c
		except OSError:
rpm-build 95f51c
			return
rpm-build 95f51c
	index = 0
rpm-build 95f51c
	while 1:
rpm-build 95f51c
		try:
rpm-build 95f51c
			version = Utils.winreg.EnumKey(all_versions, index)
rpm-build 95f51c
		except OSError:
rpm-build 95f51c
			break
rpm-build 95f51c
		index += 1
rpm-build 95f51c
		if not version_pattern.match(version):
rpm-build 95f51c
			continue
rpm-build 95f51c
		targets = {}
rpm-build 95f51c
		for target,arch in all_icl_platforms:
rpm-build 95f51c
			if target=='intel64':
rpm-build 95f51c
				targetDir='EM64T_NATIVE'
rpm-build 95f51c
			else:
rpm-build 95f51c
				targetDir=target
rpm-build 95f51c
			try:
rpm-build 95f51c
				Utils.winreg.OpenKey(all_versions,version+'\\'+targetDir)
rpm-build 95f51c
				icl_version=Utils.winreg.OpenKey(all_versions,version)
rpm-build 95f51c
				path,type=Utils.winreg.QueryValueEx(icl_version,'ProductDir')
rpm-build 95f51c
			except OSError:
rpm-build 95f51c
				pass
rpm-build 95f51c
			else:
rpm-build 95f51c
				batch_file=os.path.join(path,'bin','iclvars.bat')
rpm-build 95f51c
				if os.path.isfile(batch_file):
rpm-build 95f51c
					targets[target] = target_compiler(conf, 'intel', arch, version, target, batch_file)
rpm-build 95f51c
		for target,arch in all_icl_platforms:
rpm-build 95f51c
			try:
rpm-build 95f51c
				icl_version = Utils.winreg.OpenKey(all_versions, version+'\\'+target)
rpm-build 95f51c
				path,type = Utils.winreg.QueryValueEx(icl_version,'ProductDir')
rpm-build 95f51c
			except OSError:
rpm-build 95f51c
				continue
rpm-build 95f51c
			else:
rpm-build 95f51c
				batch_file=os.path.join(path,'bin','iclvars.bat')
rpm-build 95f51c
				if os.path.isfile(batch_file):
rpm-build 95f51c
					targets[target] = target_compiler(conf, 'intel', arch, version, target, batch_file)
rpm-build 95f51c
		major = version[0:2]
rpm-build 95f51c
		versions['intel ' + major] = targets
rpm-build 95f51c
rpm-build 95f51c
@conf
rpm-build 95f51c
def gather_intel_composer_versions(conf, versions):
rpm-build 95f51c
	"""
rpm-build 95f51c
	Checks ICL compilers that are part of Intel Composer Suites
rpm-build 95f51c
rpm-build 95f51c
	:param versions: list to modify
rpm-build 95f51c
	:type versions: list
rpm-build 95f51c
	"""
rpm-build 95f51c
	version_pattern = re.compile(r'^...?.?\...?.?.?')
rpm-build 95f51c
	try:
rpm-build 95f51c
		all_versions = Utils.winreg.OpenKey(Utils.winreg.HKEY_LOCAL_MACHINE, 'SOFTWARE\\Wow6432node\\Intel\\Suites')
rpm-build 95f51c
	except OSError:
rpm-build 95f51c
		try:
rpm-build 95f51c
			all_versions = Utils.winreg.OpenKey(Utils.winreg.HKEY_LOCAL_MACHINE, 'SOFTWARE\\Intel\\Suites')
rpm-build 95f51c
		except OSError:
rpm-build 95f51c
			return
rpm-build 95f51c
	index = 0
rpm-build 95f51c
	while 1:
rpm-build 95f51c
		try:
rpm-build 95f51c
			version = Utils.winreg.EnumKey(all_versions, index)
rpm-build 95f51c
		except OSError:
rpm-build 95f51c
			break
rpm-build 95f51c
		index += 1
rpm-build 95f51c
		if not version_pattern.match(version):
rpm-build 95f51c
			continue
rpm-build 95f51c
		targets = {}
rpm-build 95f51c
		for target,arch in all_icl_platforms:
rpm-build 95f51c
			if target=='intel64':
rpm-build 95f51c
				targetDir='EM64T_NATIVE'
rpm-build 95f51c
			else:
rpm-build 95f51c
				targetDir=target
rpm-build 95f51c
			try:
rpm-build 95f51c
				try:
rpm-build 95f51c
					defaults = Utils.winreg.OpenKey(all_versions,version+'\\Defaults\\C++\\'+targetDir)
rpm-build 95f51c
				except OSError:
rpm-build 95f51c
					if targetDir == 'EM64T_NATIVE':
rpm-build 95f51c
						defaults = Utils.winreg.OpenKey(all_versions,version+'\\Defaults\\C++\\EM64T')
rpm-build 95f51c
					else:
rpm-build 95f51c
						raise
rpm-build 95f51c
				uid,type = Utils.winreg.QueryValueEx(defaults, 'SubKey')
rpm-build 95f51c
				Utils.winreg.OpenKey(all_versions,version+'\\'+uid+'\\C++\\'+targetDir)
rpm-build 95f51c
				icl_version=Utils.winreg.OpenKey(all_versions,version+'\\'+uid+'\\C++')
rpm-build 95f51c
				path,type=Utils.winreg.QueryValueEx(icl_version,'ProductDir')
rpm-build 95f51c
			except OSError:
rpm-build 95f51c
				pass
rpm-build 95f51c
			else:
rpm-build 95f51c
				batch_file=os.path.join(path,'bin','iclvars.bat')
rpm-build 95f51c
				if os.path.isfile(batch_file):
rpm-build 95f51c
					targets[target] = target_compiler(conf, 'intel', arch, version, target, batch_file)
rpm-build 95f51c
				# The intel compilervar_arch.bat is broken when used with Visual Studio Express 2012
rpm-build 95f51c
				# http://software.intel.com/en-us/forums/topic/328487
rpm-build 95f51c
				compilervars_warning_attr = '_compilervars_warning_key'
rpm-build 95f51c
				if version[0:2] == '13' and getattr(conf, compilervars_warning_attr, True):
rpm-build 95f51c
					setattr(conf, compilervars_warning_attr, False)
rpm-build 95f51c
					patch_url = 'http://software.intel.com/en-us/forums/topic/328487'
rpm-build 95f51c
					compilervars_arch = os.path.join(path, 'bin', 'compilervars_arch.bat')
rpm-build 95f51c
					for vscomntool in ('VS110COMNTOOLS', 'VS100COMNTOOLS'):
rpm-build 95f51c
						if vscomntool in os.environ:
rpm-build 95f51c
							vs_express_path = os.environ[vscomntool] + r'..\IDE\VSWinExpress.exe'
rpm-build 95f51c
							dev_env_path = os.environ[vscomntool] + r'..\IDE\devenv.exe'
rpm-build 95f51c
							if (r'if exist "%VS110COMNTOOLS%..\IDE\VSWinExpress.exe"' in Utils.readf(compilervars_arch) and
rpm-build 95f51c
								not os.path.exists(vs_express_path) and not os.path.exists(dev_env_path)):
rpm-build 95f51c
								Logs.warn(('The Intel compilervar_arch.bat only checks for one Visual Studio SKU '
rpm-build 95f51c
								'(VSWinExpress.exe) but it does not seem to be installed at %r. '
rpm-build 95f51c
								'The intel command line set up will fail to configure unless the file %r'
rpm-build 95f51c
								'is patched. See: %s') % (vs_express_path, compilervars_arch, patch_url))
rpm-build 95f51c
		major = version[0:2]
rpm-build 95f51c
		versions['intel ' + major] = targets
rpm-build 95f51c
rpm-build 95f51c
@conf
rpm-build 95f51c
def detect_msvc(self):
rpm-build 95f51c
	return self.setup_msvc(self.get_msvc_versions())
rpm-build 95f51c
rpm-build 95f51c
@conf
rpm-build 95f51c
def get_msvc_versions(self):
rpm-build 95f51c
	"""
rpm-build 95f51c
	:return: platform to compiler configurations
rpm-build 95f51c
	:rtype: dict
rpm-build 95f51c
	"""
rpm-build 95f51c
	dct = Utils.ordered_iter_dict()
rpm-build 95f51c
	self.gather_icl_versions(dct)
rpm-build 95f51c
	self.gather_intel_composer_versions(dct)
rpm-build 95f51c
	self.gather_wsdk_versions(dct)
rpm-build 95f51c
	self.gather_msvc_versions(dct)
rpm-build 95f51c
	self.gather_vswhere_versions(dct)
rpm-build 95f51c
	Logs.debug('msvc: detected versions %r', list(dct.keys()))
rpm-build 95f51c
	return dct
rpm-build 95f51c
rpm-build 95f51c
@conf
rpm-build 95f51c
def find_lt_names_msvc(self, libname, is_static=False):
rpm-build 95f51c
	"""
rpm-build 95f51c
	Win32/MSVC specific code to glean out information from libtool la files.
rpm-build 95f51c
	this function is not attached to the task_gen class. Returns a triplet:
rpm-build 95f51c
	(library absolute path, library name without extension, whether the library is static)
rpm-build 95f51c
	"""
rpm-build 95f51c
	lt_names=[
rpm-build 95f51c
		'lib%s.la' % libname,
rpm-build 95f51c
		'%s.la' % libname,
rpm-build 95f51c
	]
rpm-build 95f51c
rpm-build 95f51c
	for path in self.env.LIBPATH:
rpm-build 95f51c
		for la in lt_names:
rpm-build 95f51c
			laf=os.path.join(path,la)
rpm-build 95f51c
			dll=None
rpm-build 95f51c
			if os.path.exists(laf):
rpm-build 95f51c
				ltdict = Utils.read_la_file(laf)
rpm-build 95f51c
				lt_libdir=None
rpm-build 95f51c
				if ltdict.get('libdir', ''):
rpm-build 95f51c
					lt_libdir = ltdict['libdir']
rpm-build 95f51c
				if not is_static and ltdict.get('library_names', ''):
rpm-build 95f51c
					dllnames=ltdict['library_names'].split()
rpm-build 95f51c
					dll=dllnames[0].lower()
rpm-build 95f51c
					dll=re.sub(r'\.dll$', '', dll)
rpm-build 95f51c
					return (lt_libdir, dll, False)
rpm-build 95f51c
				elif ltdict.get('old_library', ''):
rpm-build 95f51c
					olib=ltdict['old_library']
rpm-build 95f51c
					if os.path.exists(os.path.join(path,olib)):
rpm-build 95f51c
						return (path, olib, True)
rpm-build 95f51c
					elif lt_libdir != '' and os.path.exists(os.path.join(lt_libdir,olib)):
rpm-build 95f51c
						return (lt_libdir, olib, True)
rpm-build 95f51c
					else:
rpm-build 95f51c
						return (None, olib, True)
rpm-build 95f51c
				else:
rpm-build 95f51c
					raise self.errors.WafError('invalid libtool object file: %s' % laf)
rpm-build 95f51c
	return (None, None, None)
rpm-build 95f51c
rpm-build 95f51c
@conf
rpm-build 95f51c
def libname_msvc(self, libname, is_static=False):
rpm-build 95f51c
	lib = libname.lower()
rpm-build 95f51c
	lib = re.sub(r'\.lib$','',lib)
rpm-build 95f51c
rpm-build 95f51c
	if lib in g_msvc_systemlibs:
rpm-build 95f51c
		return lib
rpm-build 95f51c
rpm-build 95f51c
	lib=re.sub('^lib','',lib)
rpm-build 95f51c
rpm-build 95f51c
	if lib == 'm':
rpm-build 95f51c
		return None
rpm-build 95f51c
rpm-build 95f51c
	(lt_path, lt_libname, lt_static) = self.find_lt_names_msvc(lib, is_static)
rpm-build 95f51c
rpm-build 95f51c
	if lt_path != None and lt_libname != None:
rpm-build 95f51c
		if lt_static:
rpm-build 95f51c
			# file existence check has been made by find_lt_names
rpm-build 95f51c
			return os.path.join(lt_path,lt_libname)
rpm-build 95f51c
rpm-build 95f51c
	if lt_path != None:
rpm-build 95f51c
		_libpaths = [lt_path] + self.env.LIBPATH
rpm-build 95f51c
	else:
rpm-build 95f51c
		_libpaths = self.env.LIBPATH
rpm-build 95f51c
rpm-build 95f51c
	static_libs=[
rpm-build 95f51c
		'lib%ss.lib' % lib,
rpm-build 95f51c
		'lib%s.lib' % lib,
rpm-build 95f51c
		'%ss.lib' % lib,
rpm-build 95f51c
		'%s.lib' %lib,
rpm-build 95f51c
		]
rpm-build 95f51c
rpm-build 95f51c
	dynamic_libs=[
rpm-build 95f51c
		'lib%s.dll.lib' % lib,
rpm-build 95f51c
		'lib%s.dll.a' % lib,
rpm-build 95f51c
		'%s.dll.lib' % lib,
rpm-build 95f51c
		'%s.dll.a' % lib,
rpm-build 95f51c
		'lib%s_d.lib' % lib,
rpm-build 95f51c
		'%s_d.lib' % lib,
rpm-build 95f51c
		'%s.lib' %lib,
rpm-build 95f51c
		]
rpm-build 95f51c
rpm-build 95f51c
	libnames=static_libs
rpm-build 95f51c
	if not is_static:
rpm-build 95f51c
		libnames=dynamic_libs + static_libs
rpm-build 95f51c
rpm-build 95f51c
	for path in _libpaths:
rpm-build 95f51c
		for libn in libnames:
rpm-build 95f51c
			if os.path.exists(os.path.join(path, libn)):
rpm-build 95f51c
				Logs.debug('msvc: lib found: %s', os.path.join(path,libn))
rpm-build 95f51c
				return re.sub(r'\.lib$', '',libn)
rpm-build 95f51c
rpm-build 95f51c
	#if no lib can be found, just return the libname as msvc expects it
rpm-build 95f51c
	self.fatal('The library %r could not be found' % libname)
rpm-build 95f51c
	return re.sub(r'\.lib$', '', libname)
rpm-build 95f51c
rpm-build 95f51c
@conf
rpm-build 95f51c
def check_lib_msvc(self, libname, is_static=False, uselib_store=None):
rpm-build 95f51c
	"""
rpm-build 95f51c
	Ideally we should be able to place the lib in the right env var, either STLIB or LIB,
rpm-build 95f51c
	but we don't distinguish static libs from shared libs.
rpm-build 95f51c
	This is ok since msvc doesn't have any special linker flag to select static libs (no env.STLIB_MARKER)
rpm-build 95f51c
	"""
rpm-build 95f51c
	libn = self.libname_msvc(libname, is_static)
rpm-build 95f51c
rpm-build 95f51c
	if not uselib_store:
rpm-build 95f51c
		uselib_store = libname.upper()
rpm-build 95f51c
rpm-build 95f51c
	if False and is_static: # disabled
rpm-build 95f51c
		self.env['STLIB_' + uselib_store] = [libn]
rpm-build 95f51c
	else:
rpm-build 95f51c
		self.env['LIB_' + uselib_store] = [libn]
rpm-build 95f51c
rpm-build 95f51c
@conf
rpm-build 95f51c
def check_libs_msvc(self, libnames, is_static=False):
rpm-build 95f51c
	for libname in Utils.to_list(libnames):
rpm-build 95f51c
		self.check_lib_msvc(libname, is_static)
rpm-build 95f51c
rpm-build 95f51c
def configure(conf):
rpm-build 95f51c
	"""
rpm-build 95f51c
	Configuration methods to call for detecting msvc
rpm-build 95f51c
	"""
rpm-build 95f51c
	conf.autodetect(True)
rpm-build 95f51c
	conf.find_msvc()
rpm-build 95f51c
	conf.msvc_common_flags()
rpm-build 95f51c
	conf.cc_load_tools()
rpm-build 95f51c
	conf.cxx_load_tools()
rpm-build 95f51c
	conf.cc_add_flags()
rpm-build 95f51c
	conf.cxx_add_flags()
rpm-build 95f51c
	conf.link_add_flags()
rpm-build 95f51c
	conf.visual_studio_add_flags()
rpm-build 95f51c
rpm-build 95f51c
@conf
rpm-build 95f51c
def no_autodetect(conf):
rpm-build 95f51c
	conf.env.NO_MSVC_DETECT = 1
rpm-build 95f51c
	configure(conf)
rpm-build 95f51c
rpm-build 95f51c
@conf
rpm-build 95f51c
def autodetect(conf, arch=False):
rpm-build 95f51c
	v = conf.env
rpm-build 95f51c
	if v.NO_MSVC_DETECT:
rpm-build 95f51c
		return
rpm-build 95f51c
rpm-build 95f51c
	compiler, version, path, includes, libdirs, cpu = conf.detect_msvc()
rpm-build 95f51c
	if arch:
rpm-build 95f51c
		v.DEST_CPU = cpu
rpm-build 95f51c
rpm-build 95f51c
	v.PATH = path
rpm-build 95f51c
	v.INCLUDES = includes
rpm-build 95f51c
	v.LIBPATH = libdirs
rpm-build 95f51c
	v.MSVC_COMPILER = compiler
rpm-build 95f51c
	try:
rpm-build 95f51c
		v.MSVC_VERSION = float(version)
rpm-build 95f51c
	except ValueError:
rpm-build 95f51c
		v.MSVC_VERSION = float(version[:-3])
rpm-build 95f51c
rpm-build 95f51c
def _get_prog_names(conf, compiler):
rpm-build 95f51c
	if compiler == 'intel':
rpm-build 95f51c
		compiler_name = 'ICL'
rpm-build 95f51c
		linker_name = 'XILINK'
rpm-build 95f51c
		lib_name = 'XILIB'
rpm-build 95f51c
	else:
rpm-build 95f51c
		# assumes CL.exe
rpm-build 95f51c
		compiler_name = 'CL'
rpm-build 95f51c
		linker_name = 'LINK'
rpm-build 95f51c
		lib_name = 'LIB'
rpm-build 95f51c
	return compiler_name, linker_name, lib_name
rpm-build 95f51c
rpm-build 95f51c
@conf
rpm-build 95f51c
def find_msvc(conf):
rpm-build 95f51c
	"""Due to path format limitations, limit operation only to native Win32. Yeah it sucks."""
rpm-build 95f51c
	if sys.platform == 'cygwin':
rpm-build 95f51c
		conf.fatal('MSVC module does not work under cygwin Python!')
rpm-build 95f51c
rpm-build 95f51c
	# the autodetection is supposed to be performed before entering in this method
rpm-build 95f51c
	v = conf.env
rpm-build 95f51c
	path = v.PATH
rpm-build 95f51c
	compiler = v.MSVC_COMPILER
rpm-build 95f51c
	version = v.MSVC_VERSION
rpm-build 95f51c
rpm-build 95f51c
	compiler_name, linker_name, lib_name = _get_prog_names(conf, compiler)
rpm-build 95f51c
	v.MSVC_MANIFEST = (compiler == 'msvc' and version >= 8) or (compiler == 'wsdk' and version >= 6) or (compiler == 'intel' and version >= 11)
rpm-build 95f51c
rpm-build 95f51c
	# compiler
rpm-build 95f51c
	cxx = conf.find_program(compiler_name, var='CXX', path_list=path)
rpm-build 95f51c
rpm-build 95f51c
	# before setting anything, check if the compiler is really msvc
rpm-build 95f51c
	env = dict(conf.environ)
rpm-build 95f51c
	if path:
rpm-build 95f51c
		env.update(PATH = ';'.join(path))
rpm-build 95f51c
	if not conf.cmd_and_log(cxx + ['/nologo', '/help'], env=env):
rpm-build 95f51c
		conf.fatal('the msvc compiler could not be identified')
rpm-build 95f51c
rpm-build 95f51c
	# c/c++ compiler
rpm-build 95f51c
	v.CC = v.CXX = cxx
rpm-build 95f51c
	v.CC_NAME = v.CXX_NAME = 'msvc'
rpm-build 95f51c
rpm-build 95f51c
	# linker
rpm-build 95f51c
	if not v.LINK_CXX:
rpm-build 95f51c
		conf.find_program(linker_name, path_list=path, errmsg='%s was not found (linker)' % linker_name, var='LINK_CXX')
rpm-build 95f51c
rpm-build 95f51c
	if not v.LINK_CC:
rpm-build 95f51c
		v.LINK_CC = v.LINK_CXX
rpm-build 95f51c
rpm-build 95f51c
	# staticlib linker
rpm-build 95f51c
	if not v.AR:
rpm-build 95f51c
		stliblink = conf.find_program(lib_name, path_list=path, var='AR')
rpm-build 95f51c
		if not stliblink:
rpm-build 95f51c
			return
rpm-build 95f51c
		v.ARFLAGS = ['/nologo']
rpm-build 95f51c
rpm-build 95f51c
	# manifest tool. Not required for VS 2003 and below. Must have for VS 2005 and later
rpm-build 95f51c
	if v.MSVC_MANIFEST:
rpm-build 95f51c
		conf.find_program('MT', path_list=path, var='MT')
rpm-build 95f51c
		v.MTFLAGS = ['/nologo']
rpm-build 95f51c
rpm-build 95f51c
	try:
rpm-build 95f51c
		conf.load('winres')
rpm-build 95f51c
	except Errors.ConfigurationError:
rpm-build 95f51c
		Logs.warn('Resource compiler not found. Compiling resource file is disabled')
rpm-build 95f51c
rpm-build 95f51c
@conf
rpm-build 95f51c
def visual_studio_add_flags(self):
rpm-build 95f51c
	"""visual studio flags found in the system environment"""
rpm-build 95f51c
	v = self.env
rpm-build 95f51c
	if self.environ.get('INCLUDE'):
rpm-build 95f51c
		v.prepend_value('INCLUDES', [x for x in self.environ['INCLUDE'].split(';') if x]) # notice the 'S'
rpm-build 95f51c
	if self.environ.get('LIB'):
rpm-build 95f51c
		v.prepend_value('LIBPATH', [x for x in self.environ['LIB'].split(';') if x])
rpm-build 95f51c
rpm-build 95f51c
@conf
rpm-build 95f51c
def msvc_common_flags(conf):
rpm-build 95f51c
	"""
rpm-build 95f51c
	Setup the flags required for executing the msvc compiler
rpm-build 95f51c
	"""
rpm-build 95f51c
	v = conf.env
rpm-build 95f51c
rpm-build 95f51c
	v.DEST_BINFMT = 'pe'
rpm-build 95f51c
	v.append_value('CFLAGS', ['/nologo'])
rpm-build 95f51c
	v.append_value('CXXFLAGS', ['/nologo'])
rpm-build 95f51c
	v.append_value('LINKFLAGS', ['/nologo'])
rpm-build 95f51c
	v.DEFINES_ST   = '/D%s'
rpm-build 95f51c
rpm-build 95f51c
	v.CC_SRC_F     = ''
rpm-build 95f51c
	v.CC_TGT_F     = ['/c', '/Fo']
rpm-build 95f51c
	v.CXX_SRC_F    = ''
rpm-build 95f51c
	v.CXX_TGT_F    = ['/c', '/Fo']
rpm-build 95f51c
rpm-build 95f51c
	if (v.MSVC_COMPILER == 'msvc' and v.MSVC_VERSION >= 8) or (v.MSVC_COMPILER == 'wsdk' and v.MSVC_VERSION >= 6):
rpm-build 95f51c
		v.CC_TGT_F = ['/FC'] + v.CC_TGT_F
rpm-build 95f51c
		v.CXX_TGT_F = ['/FC'] + v.CXX_TGT_F
rpm-build 95f51c
rpm-build 95f51c
	v.CPPPATH_ST = '/I%s' # template for adding include paths
rpm-build 95f51c
rpm-build 95f51c
	v.AR_TGT_F = v.CCLNK_TGT_F = v.CXXLNK_TGT_F = '/OUT:'
rpm-build 95f51c
rpm-build 95f51c
	# CRT specific flags
rpm-build 95f51c
	v.CFLAGS_CRT_MULTITHREADED     = v.CXXFLAGS_CRT_MULTITHREADED     = ['/MT']
rpm-build 95f51c
	v.CFLAGS_CRT_MULTITHREADED_DLL = v.CXXFLAGS_CRT_MULTITHREADED_DLL = ['/MD']
rpm-build 95f51c
rpm-build 95f51c
	v.CFLAGS_CRT_MULTITHREADED_DBG     = v.CXXFLAGS_CRT_MULTITHREADED_DBG     = ['/MTd']
rpm-build 95f51c
	v.CFLAGS_CRT_MULTITHREADED_DLL_DBG = v.CXXFLAGS_CRT_MULTITHREADED_DLL_DBG = ['/MDd']
rpm-build 95f51c
rpm-build 95f51c
	v.LIB_ST            = '%s.lib'
rpm-build 95f51c
	v.LIBPATH_ST        = '/LIBPATH:%s'
rpm-build 95f51c
	v.STLIB_ST          = '%s.lib'
rpm-build 95f51c
	v.STLIBPATH_ST      = '/LIBPATH:%s'
rpm-build 95f51c
rpm-build 95f51c
	if v.MSVC_MANIFEST:
rpm-build 95f51c
		v.append_value('LINKFLAGS', ['/MANIFEST'])
rpm-build 95f51c
rpm-build 95f51c
	v.CFLAGS_cshlib     = []
rpm-build 95f51c
	v.CXXFLAGS_cxxshlib = []
rpm-build 95f51c
	v.LINKFLAGS_cshlib  = v.LINKFLAGS_cxxshlib = ['/DLL']
rpm-build 95f51c
	v.cshlib_PATTERN    = v.cxxshlib_PATTERN = '%s.dll'
rpm-build 95f51c
	v.implib_PATTERN    = '%s.lib'
rpm-build 95f51c
	v.IMPLIB_ST         = '/IMPLIB:%s'
rpm-build 95f51c
rpm-build 95f51c
	v.LINKFLAGS_cstlib  = []
rpm-build 95f51c
	v.cstlib_PATTERN    = v.cxxstlib_PATTERN = '%s.lib'
rpm-build 95f51c
rpm-build 95f51c
	v.cprogram_PATTERN  = v.cxxprogram_PATTERN = '%s.exe'
rpm-build 95f51c
rpm-build 95f51c
	v.def_PATTERN       = '/def:%s'
rpm-build 95f51c
rpm-build 95f51c
rpm-build 95f51c
#######################################################################################################
rpm-build 95f51c
##### conf above, build below
rpm-build 95f51c
rpm-build 95f51c
@after_method('apply_link')
rpm-build 95f51c
@feature('c', 'cxx')
rpm-build 95f51c
def apply_flags_msvc(self):
rpm-build 95f51c
	"""
rpm-build 95f51c
	Add additional flags implied by msvc, such as subsystems and pdb files::
rpm-build 95f51c
rpm-build 95f51c
		def build(bld):
rpm-build 95f51c
			bld.stlib(source='main.c', target='bar', subsystem='gruik')
rpm-build 95f51c
	"""
rpm-build 95f51c
	if self.env.CC_NAME != 'msvc' or not getattr(self, 'link_task', None):
rpm-build 95f51c
		return
rpm-build 95f51c
rpm-build 95f51c
	is_static = isinstance(self.link_task, ccroot.stlink_task)
rpm-build 95f51c
rpm-build 95f51c
	subsystem = getattr(self, 'subsystem', '')
rpm-build 95f51c
	if subsystem:
rpm-build 95f51c
		subsystem = '/subsystem:%s' % subsystem
rpm-build 95f51c
		flags = is_static and 'ARFLAGS' or 'LINKFLAGS'
rpm-build 95f51c
		self.env.append_value(flags, subsystem)
rpm-build 95f51c
rpm-build 95f51c
	if not is_static:
rpm-build 95f51c
		for f in self.env.LINKFLAGS:
rpm-build 95f51c
			d = f.lower()
rpm-build 95f51c
			if d[1:] in ('debug', 'debug:full', 'debug:fastlink'):
rpm-build 95f51c
				pdbnode = self.link_task.outputs[0].change_ext('.pdb')
rpm-build 95f51c
				self.link_task.outputs.append(pdbnode)
rpm-build 95f51c
rpm-build 95f51c
				if getattr(self, 'install_task', None):
rpm-build 95f51c
					self.pdb_install_task = self.add_install_files(
rpm-build 95f51c
						install_to=self.install_task.install_to, install_from=pdbnode)
rpm-build 95f51c
				break
rpm-build 95f51c
rpm-build 95f51c
@feature('cprogram', 'cshlib', 'cxxprogram', 'cxxshlib')
rpm-build 95f51c
@after_method('apply_link')
rpm-build 95f51c
def apply_manifest(self):
rpm-build 95f51c
	"""
rpm-build 95f51c
	Special linker for MSVC with support for embedding manifests into DLL's
rpm-build 95f51c
	and executables compiled by Visual Studio 2005 or probably later. Without
rpm-build 95f51c
	the manifest file, the binaries are unusable.
rpm-build 95f51c
	See: http://msdn2.microsoft.com/en-us/library/ms235542(VS.80).aspx
rpm-build 95f51c
	"""
rpm-build 95f51c
	if self.env.CC_NAME == 'msvc' and self.env.MSVC_MANIFEST and getattr(self, 'link_task', None):
rpm-build 95f51c
		out_node = self.link_task.outputs[0]
rpm-build 95f51c
		man_node = out_node.parent.find_or_declare(out_node.name + '.manifest')
rpm-build 95f51c
		self.link_task.outputs.append(man_node)
rpm-build 95f51c
		self.env.DO_MANIFEST = True
rpm-build 95f51c
rpm-build 95f51c
def make_winapp(self, family):
rpm-build 95f51c
	append = self.env.append_unique
rpm-build 95f51c
	append('DEFINES', 'WINAPI_FAMILY=%s' % family)
rpm-build 95f51c
	append('CXXFLAGS', ['/ZW', '/TP'])
rpm-build 95f51c
	for lib_path in self.env.LIBPATH:
rpm-build 95f51c
		append('CXXFLAGS','/AI%s'%lib_path)
rpm-build 95f51c
rpm-build 95f51c
@feature('winphoneapp')
rpm-build 95f51c
@after_method('process_use')
rpm-build 95f51c
@after_method('propagate_uselib_vars')
rpm-build 95f51c
def make_winphone_app(self):
rpm-build 95f51c
	"""
rpm-build 95f51c
	Insert configuration flags for windows phone applications (adds /ZW, /TP...)
rpm-build 95f51c
	"""
rpm-build 95f51c
	make_winapp(self, 'WINAPI_FAMILY_PHONE_APP')
rpm-build 95f51c
	self.env.append_unique('LINKFLAGS', ['/NODEFAULTLIB:ole32.lib', 'PhoneAppModelHost.lib'])
rpm-build 95f51c
rpm-build 95f51c
@feature('winapp')
rpm-build 95f51c
@after_method('process_use')
rpm-build 95f51c
@after_method('propagate_uselib_vars')
rpm-build 95f51c
def make_windows_app(self):
rpm-build 95f51c
	"""
rpm-build 95f51c
	Insert configuration flags for windows applications (adds /ZW, /TP...)
rpm-build 95f51c
	"""
rpm-build 95f51c
	make_winapp(self, 'WINAPI_FAMILY_DESKTOP_APP')