waf

FORK: waf with some random patches
git clone https://git.neptards.moe/neptards/waf.git
Log | Files | Refs | README

msvc.py (35520B)


      1 #!/usr/bin/env python
      2 # encoding: utf-8
      3 # Carlos Rafael Giani, 2006 (dv)
      4 # Tamas Pal, 2007 (folti)
      5 # Nicolas Mercier, 2009
      6 # Matt Clarkson, 2012
      7 
      8 """
      9 Microsoft Visual C++/Intel C++ compiler support
     10 
     11 If you get detection problems, first try any of the following::
     12 
     13 	chcp 65001
     14 	set PYTHONIOENCODING=...
     15 	set PYTHONLEGACYWINDOWSSTDIO=1
     16 
     17 Usage::
     18 
     19 	$ waf configure --msvc_version="msvc 10.0,msvc 9.0" --msvc_target="x64"
     20 
     21 or::
     22 
     23 	def configure(conf):
     24 		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']
     25 		conf.env.MSVC_TARGETS = ['x64']
     26 		conf.load('msvc')
     27 
     28 or::
     29 
     30 	def configure(conf):
     31 		conf.load('msvc', funs='no_autodetect')
     32 		conf.check_lib_msvc('gdi32')
     33 		conf.check_libs_msvc('kernel32 user32')
     34 	def build(bld):
     35 		tg = bld.program(source='main.c', target='app', use='KERNEL32 USER32 GDI32')
     36 
     37 Platforms and targets will be tested in the order they appear;
     38 the first good configuration will be used.
     39 
     40 To force testing all the configurations that are not used, use the ``--no-msvc-lazy`` option
     41 or set ``conf.env.MSVC_LAZY_AUTODETECT=False``.
     42 
     43 Supported platforms: ia64, x64, x86, x86_amd64, x86_ia64, x86_arm, amd64_x86, amd64_arm
     44 
     45 Compilers supported:
     46 
     47 * msvc       => Visual Studio, versions 6.0 (VC 98, VC .NET 2002) to 15 (Visual Studio 2017)
     48 * wsdk       => Windows SDK, versions 6.0, 6.1, 7.0, 7.1, 8.0
     49 * icl        => Intel compiler, versions 9, 10, 11, 13
     50 * winphone   => Visual Studio to target Windows Phone 8 native (version 8.0 for now)
     51 * Smartphone => Compiler/SDK for Smartphone devices (armv4/v4i)
     52 * PocketPC   => Compiler/SDK for PocketPC devices (armv4/v4i)
     53 
     54 To use WAF in a VS2008 Make file project (see http://code.google.com/p/waf/issues/detail?id=894)
     55 You may consider to set the environment variable "VS_UNICODE_OUTPUT" to nothing before calling waf.
     56 So in your project settings use something like 'cmd.exe /C "set VS_UNICODE_OUTPUT=& set PYTHONUNBUFFERED=true & waf build"'.
     57 cmd.exe  /C  "chcp 1252 & set PYTHONUNBUFFERED=true && set && waf  configure"
     58 Setting PYTHONUNBUFFERED gives the unbuffered output.
     59 """
     60 
     61 import os, sys, re, traceback
     62 from waflib import Utils, Logs, Options, Errors
     63 from waflib.TaskGen import after_method, feature
     64 
     65 from waflib.Configure import conf
     66 from waflib.Tools import ccroot, c, cxx, ar
     67 
     68 g_msvc_systemlibs = '''
     69 aclui activeds ad1 adptif adsiid advapi32 asycfilt authz bhsupp bits bufferoverflowu cabinet
     70 cap certadm certidl ciuuid clusapi comctl32 comdlg32 comsupp comsuppd comsuppw comsuppwd comsvcs
     71 credui crypt32 cryptnet cryptui d3d8thk daouuid dbgeng dbghelp dciman32 ddao35 ddao35d
     72 ddao35u ddao35ud delayimp dhcpcsvc dhcpsapi dlcapi dnsapi dsprop dsuiext dtchelp
     73 faultrep fcachdll fci fdi framedyd framedyn gdi32 gdiplus glauxglu32 gpedit gpmuuid
     74 gtrts32w gtrtst32hlink htmlhelp httpapi icm32 icmui imagehlp imm32 iphlpapi iprop
     75 kernel32 ksguid ksproxy ksuser libcmt libcmtd libcpmt libcpmtd loadperf lz32 mapi
     76 mapi32 mgmtapi minidump mmc mobsync mpr mprapi mqoa mqrt msacm32 mscms mscoree
     77 msdasc msimg32 msrating mstask msvcmrt msvcurt msvcurtd mswsock msxml2 mtx mtxdm
     78 netapi32 nmapinmsupp npptools ntdsapi ntdsbcli ntmsapi ntquery odbc32 odbcbcp
     79 odbccp32 oldnames ole32 oleacc oleaut32 oledb oledlgolepro32 opends60 opengl32
     80 osptk parser pdh penter pgobootrun pgort powrprof psapi ptrustm ptrustmd ptrustu
     81 ptrustud qosname rasapi32 rasdlg rassapi resutils riched20 rpcndr rpcns4 rpcrt4 rtm
     82 rtutils runtmchk scarddlg scrnsave scrnsavw secur32 sensapi setupapi sfc shell32
     83 shfolder shlwapi sisbkup snmpapi sporder srclient sti strsafe svcguid tapi32 thunk32
     84 traffic unicows url urlmon user32 userenv usp10 uuid uxtheme vcomp vcompd vdmdbg
     85 version vfw32 wbemuuid  webpost wiaguid wininet winmm winscard winspool winstrm
     86 wintrust wldap32 wmiutils wow32 ws2_32 wsnmp32 wsock32 wst wtsapi32 xaswitch xolehlp
     87 '''.split()
     88 """importlibs provided by MSVC/Platform SDK. Do NOT search them"""
     89 
     90 all_msvc_platforms = [	('x64', 'amd64'), ('x86', 'x86'), ('ia64', 'ia64'),
     91 						('x86_amd64', 'amd64'), ('x86_ia64', 'ia64'), ('x86_arm', 'arm'), ('x86_arm64', 'arm64'),
     92 						('amd64_x86', 'x86'), ('amd64_arm', 'arm'), ('amd64_arm64', 'arm64') ]
     93 """List of msvc platforms"""
     94 
     95 all_wince_platforms = [ ('armv4', 'arm'), ('armv4i', 'arm'), ('mipsii', 'mips'), ('mipsii_fp', 'mips'), ('mipsiv', 'mips'), ('mipsiv_fp', 'mips'), ('sh4', 'sh'), ('x86', 'cex86') ]
     96 """List of wince platforms"""
     97 
     98 all_icl_platforms = [ ('intel64', 'amd64'), ('em64t', 'amd64'), ('ia32', 'x86'), ('Itanium', 'ia64')]
     99 """List of icl platforms"""
    100 
    101 def options(opt):
    102 	default_ver = ''
    103 	vsver = os.getenv('VSCMD_VER')
    104 	if vsver:
    105 		m = re.match(r'(^\d+\.\d+).*', vsver)
    106 		if m:
    107 			default_ver = 'msvc %s' % m.group(1)
    108 	opt.add_option('--msvc_version', type='string', help = 'msvc version, eg: "msvc 10.0,msvc 9.0"', default=default_ver)
    109 	opt.add_option('--msvc_targets', type='string', help = 'msvc targets, eg: "x64,arm"', default='')
    110 	opt.add_option('--no-msvc-lazy', action='store_false', help = 'lazily check msvc target environments', default=True, dest='msvc_lazy')
    111 
    112 class MSVCVersion(object):
    113 	def __init__(self, ver):
    114 		m = re.search(r'^(.*)\s+(\d+[.]\d+)', ver)
    115 		if m:
    116 			self.name = m.group(1)
    117 			self.number = float(m.group(2))
    118 		else:
    119 			self.name = ver
    120 			self.number = 0.
    121 
    122 	def __lt__(self, other):
    123 		if self.number == other.number:
    124 			return self.name < other.name
    125 		return self.number < other.number
    126 
    127 @conf
    128 def setup_msvc(conf, versiondict):
    129 	"""
    130 	Checks installed compilers and targets and returns the first combination from the user's
    131 	options, env, or the global supported lists that checks.
    132 
    133 	:param versiondict: dict(platform -> dict(architecture -> configuration))
    134 	:type versiondict: dict(string -> dict(string -> target_compiler)
    135 	:return: the compiler, revision, path, include dirs, library paths and target architecture
    136 	:rtype: tuple of strings
    137 	"""
    138 	platforms = getattr(Options.options, 'msvc_targets', '').split(',')
    139 	if platforms == ['']:
    140 		platforms=Utils.to_list(conf.env.MSVC_TARGETS) or [i for i,j in all_msvc_platforms+all_icl_platforms+all_wince_platforms]
    141 	desired_versions = getattr(Options.options, 'msvc_version', '').split(',')
    142 	if desired_versions == ['']:
    143 		desired_versions = conf.env.MSVC_VERSIONS or list(sorted(versiondict.keys(), key=MSVCVersion, reverse=True))
    144 
    145 	# Override lazy detection by evaluating after the fact.
    146 	lazy_detect = getattr(Options.options, 'msvc_lazy', True)
    147 	if conf.env.MSVC_LAZY_AUTODETECT is False:
    148 		lazy_detect = False
    149 
    150 	if not lazy_detect:
    151 		for val in versiondict.values():
    152 			for arch in list(val.keys()):
    153 				cfg = val[arch]
    154 				cfg.evaluate()
    155 				if not cfg.is_valid:
    156 					del val[arch]
    157 		conf.env.MSVC_INSTALLED_VERSIONS = versiondict
    158 
    159 	for version in desired_versions:
    160 		Logs.debug('msvc: detecting %r - %r', version, desired_versions)
    161 		try:
    162 			targets = versiondict[version]
    163 		except KeyError:
    164 			continue
    165 
    166 		seen = set()
    167 		for arch in platforms:
    168 			if arch in seen:
    169 				continue
    170 			else:
    171 				seen.add(arch)
    172 			try:
    173 				cfg = targets[arch]
    174 			except KeyError:
    175 				continue
    176 
    177 			cfg.evaluate()
    178 			if cfg.is_valid:
    179 				compiler,revision = version.rsplit(' ', 1)
    180 				return compiler,revision,cfg.bindirs,cfg.incdirs,cfg.libdirs,cfg.cpu
    181 	conf.fatal('msvc: Impossible to find a valid architecture for building %r - %r' % (desired_versions, list(versiondict.keys())))
    182 
    183 @conf
    184 def get_msvc_version(conf, compiler, version, target, vcvars):
    185 	"""
    186 	Checks that an installed compiler actually runs and uses vcvars to obtain the
    187 	environment needed by the compiler.
    188 
    189 	:param compiler: compiler type, for looking up the executable name
    190 	:param version: compiler version, for debugging only
    191 	:param target: target architecture
    192 	:param vcvars: batch file to run to check the environment
    193 	:return: the location of the compiler executable, the location of include dirs, and the library paths
    194 	:rtype: tuple of strings
    195 	"""
    196 	Logs.debug('msvc: get_msvc_version: %r %r %r', compiler, version, target)
    197 
    198 	try:
    199 		conf.msvc_cnt += 1
    200 	except AttributeError:
    201 		conf.msvc_cnt = 1
    202 	batfile = conf.bldnode.make_node('waf-print-msvc-%d.bat' % conf.msvc_cnt)
    203 	batfile.write("""@echo off
    204 set INCLUDE=
    205 set LIB=
    206 call "%s" %s
    207 echo PATH=%%PATH%%
    208 echo INCLUDE=%%INCLUDE%%
    209 echo LIB=%%LIB%%;%%LIBPATH%%
    210 """ % (vcvars,target))
    211 	sout = conf.cmd_and_log(['cmd.exe', '/E:on', '/V:on', '/C', batfile.abspath()], stdin=getattr(Utils.subprocess, 'DEVNULL', None))
    212 	lines = sout.splitlines()
    213 
    214 	if not lines[0]:
    215 		lines.pop(0)
    216 
    217 	MSVC_PATH = MSVC_INCDIR = MSVC_LIBDIR = None
    218 	for line in lines:
    219 		if line.startswith('PATH='):
    220 			path = line[5:]
    221 			MSVC_PATH = path.split(';')
    222 		elif line.startswith('INCLUDE='):
    223 			MSVC_INCDIR = [i for i in line[8:].split(';') if i]
    224 		elif line.startswith('LIB='):
    225 			MSVC_LIBDIR = [i for i in line[4:].split(';') if i]
    226 	if None in (MSVC_PATH, MSVC_INCDIR, MSVC_LIBDIR):
    227 		conf.fatal('msvc: Could not find a valid architecture for building (get_msvc_version_3)')
    228 
    229 	# Check if the compiler is usable at all.
    230 	# The detection may return 64-bit versions even on 32-bit systems, and these would fail to run.
    231 	env = dict(os.environ)
    232 	env.update(PATH = path)
    233 	compiler_name, linker_name, lib_name = _get_prog_names(conf, compiler)
    234 	cxx = conf.find_program(compiler_name, path_list=MSVC_PATH)
    235 
    236 	# delete CL if exists. because it could contain parameters which can change cl's behaviour rather catastrophically.
    237 	if 'CL' in env:
    238 		del(env['CL'])
    239 
    240 	try:
    241 		conf.cmd_and_log(cxx + ['/help'], env=env)
    242 	except UnicodeError:
    243 		st = traceback.format_exc()
    244 		if conf.logger:
    245 			conf.logger.error(st)
    246 		conf.fatal('msvc: Unicode error - check the code page?')
    247 	except Exception as e:
    248 		Logs.debug('msvc: get_msvc_version: %r %r %r -> failure %s', compiler, version, target, str(e))
    249 		conf.fatal('msvc: cannot run the compiler in get_msvc_version (run with -v to display errors)')
    250 	else:
    251 		Logs.debug('msvc: get_msvc_version: %r %r %r -> OK', compiler, version, target)
    252 	finally:
    253 		conf.env[compiler_name] = ''
    254 
    255 	return (MSVC_PATH, MSVC_INCDIR, MSVC_LIBDIR)
    256 
    257 def gather_wince_supported_platforms():
    258 	"""
    259 	Checks SmartPhones SDKs
    260 
    261 	:param versions: list to modify
    262 	:type versions: list
    263 	"""
    264 	supported_wince_platforms = []
    265 	try:
    266 		ce_sdk = Utils.winreg.OpenKey(Utils.winreg.HKEY_LOCAL_MACHINE, 'SOFTWARE\\Wow6432node\\Microsoft\\Windows CE Tools\\SDKs')
    267 	except OSError:
    268 		try:
    269 			ce_sdk = Utils.winreg.OpenKey(Utils.winreg.HKEY_LOCAL_MACHINE, 'SOFTWARE\\Microsoft\\Windows CE Tools\\SDKs')
    270 		except OSError:
    271 			ce_sdk = ''
    272 	if not ce_sdk:
    273 		return supported_wince_platforms
    274 
    275 	index = 0
    276 	while 1:
    277 		try:
    278 			sdk_device = Utils.winreg.EnumKey(ce_sdk, index)
    279 			sdk = Utils.winreg.OpenKey(ce_sdk, sdk_device)
    280 		except OSError:
    281 			break
    282 		index += 1
    283 		try:
    284 			path,type = Utils.winreg.QueryValueEx(sdk, 'SDKRootDir')
    285 		except OSError:
    286 			try:
    287 				path,type = Utils.winreg.QueryValueEx(sdk,'SDKInformation')
    288 			except OSError:
    289 				continue
    290 			path,xml = os.path.split(path)
    291 		path = str(path)
    292 		path,device = os.path.split(path)
    293 		if not device:
    294 			path,device = os.path.split(path)
    295 		platforms = []
    296 		for arch,compiler in all_wince_platforms:
    297 			if os.path.isdir(os.path.join(path, device, 'Lib', arch)):
    298 				platforms.append((arch, compiler, os.path.join(path, device, 'Include', arch), os.path.join(path, device, 'Lib', arch)))
    299 		if platforms:
    300 			supported_wince_platforms.append((device, platforms))
    301 	return supported_wince_platforms
    302 
    303 def gather_msvc_detected_versions():
    304 	#Detected MSVC versions!
    305 	version_pattern = re.compile(r'^(\d\d?\.\d\d?)(Exp)?$')
    306 	detected_versions = []
    307 	for vcver,vcvar in (('VCExpress','Exp'), ('VisualStudio','')):
    308 		prefix = 'SOFTWARE\\Wow6432node\\Microsoft\\' + vcver
    309 		try:
    310 			all_versions = Utils.winreg.OpenKey(Utils.winreg.HKEY_LOCAL_MACHINE, prefix)
    311 		except OSError:
    312 			prefix = 'SOFTWARE\\Microsoft\\' + vcver
    313 			try:
    314 				all_versions = Utils.winreg.OpenKey(Utils.winreg.HKEY_LOCAL_MACHINE, prefix)
    315 			except OSError:
    316 				continue
    317 
    318 		index = 0
    319 		while 1:
    320 			try:
    321 				version = Utils.winreg.EnumKey(all_versions, index)
    322 			except OSError:
    323 				break
    324 			index += 1
    325 			match = version_pattern.match(version)
    326 			if match:
    327 				versionnumber = float(match.group(1))
    328 			else:
    329 				continue
    330 			detected_versions.append((versionnumber, version+vcvar, prefix+'\\'+version))
    331 	def fun(tup):
    332 		return tup[0]
    333 
    334 	detected_versions.sort(key = fun)
    335 	return detected_versions
    336 
    337 class target_compiler(object):
    338 	"""
    339 	Wrap a compiler configuration; call evaluate() to determine
    340 	whether the configuration is usable.
    341 	"""
    342 	def __init__(self, ctx, compiler, cpu, version, bat_target, bat, callback=None):
    343 		"""
    344 		:param ctx: configuration context to use to eventually get the version environment
    345 		:param compiler: compiler name
    346 		:param cpu: target cpu
    347 		:param version: compiler version number
    348 		:param bat_target: ?
    349 		:param bat: path to the batch file to run
    350 		"""
    351 		self.conf = ctx
    352 		self.name = None
    353 		self.is_valid = False
    354 		self.is_done = False
    355 
    356 		self.compiler = compiler
    357 		self.cpu = cpu
    358 		self.version = version
    359 		self.bat_target = bat_target
    360 		self.bat = bat
    361 		self.callback = callback
    362 
    363 	def evaluate(self):
    364 		if self.is_done:
    365 			return
    366 		self.is_done = True
    367 		try:
    368 			vs = self.conf.get_msvc_version(self.compiler, self.version, self.bat_target, self.bat)
    369 		except Errors.ConfigurationError:
    370 			self.is_valid = False
    371 			return
    372 		if self.callback:
    373 			vs = self.callback(self, vs)
    374 		self.is_valid = True
    375 		(self.bindirs, self.incdirs, self.libdirs) = vs
    376 
    377 	def __str__(self):
    378 		return str((self.compiler, self.cpu, self.version, self.bat_target, self.bat))
    379 
    380 	def __repr__(self):
    381 		return repr((self.compiler, self.cpu, self.version, self.bat_target, self.bat))
    382 
    383 @conf
    384 def gather_wsdk_versions(conf, versions):
    385 	"""
    386 	Use winreg to add the msvc versions to the input list
    387 
    388 	:param versions: list to modify
    389 	:type versions: list
    390 	"""
    391 	version_pattern = re.compile(r'^v..?.?\...?.?')
    392 	try:
    393 		all_versions = Utils.winreg.OpenKey(Utils.winreg.HKEY_LOCAL_MACHINE, 'SOFTWARE\\Wow6432node\\Microsoft\\Microsoft SDKs\\Windows')
    394 	except OSError:
    395 		try:
    396 			all_versions = Utils.winreg.OpenKey(Utils.winreg.HKEY_LOCAL_MACHINE, 'SOFTWARE\\Microsoft\\Microsoft SDKs\\Windows')
    397 		except OSError:
    398 			return
    399 	index = 0
    400 	while 1:
    401 		try:
    402 			version = Utils.winreg.EnumKey(all_versions, index)
    403 		except OSError:
    404 			break
    405 		index += 1
    406 		if not version_pattern.match(version):
    407 			continue
    408 		try:
    409 			msvc_version = Utils.winreg.OpenKey(all_versions, version)
    410 			path,type = Utils.winreg.QueryValueEx(msvc_version,'InstallationFolder')
    411 		except OSError:
    412 			continue
    413 		if path and os.path.isfile(os.path.join(path, 'bin', 'SetEnv.cmd')):
    414 			targets = {}
    415 			for target,arch in all_msvc_platforms:
    416 				targets[target] = target_compiler(conf, 'wsdk', arch, version, '/'+target, os.path.join(path, 'bin', 'SetEnv.cmd'))
    417 			versions['wsdk ' + version[1:]] = targets
    418 
    419 @conf
    420 def gather_msvc_targets(conf, versions, version, vc_path):
    421 	#Looking for normal MSVC compilers!
    422 	targets = {}
    423 
    424 	if os.path.isfile(os.path.join(vc_path, 'VC', 'Auxiliary', 'Build', 'vcvarsall.bat')):
    425 		for target,realtarget in all_msvc_platforms[::-1]:
    426 			targets[target] = target_compiler(conf, 'msvc', realtarget, version, target, os.path.join(vc_path, 'VC', 'Auxiliary', 'Build', 'vcvarsall.bat'))
    427 	elif os.path.isfile(os.path.join(vc_path, 'vcvarsall.bat')):
    428 		for target,realtarget in all_msvc_platforms[::-1]:
    429 			targets[target] = target_compiler(conf, 'msvc', realtarget, version, target, os.path.join(vc_path, 'vcvarsall.bat'))
    430 	elif os.path.isfile(os.path.join(vc_path, 'Common7', 'Tools', 'vsvars32.bat')):
    431 		targets['x86'] = target_compiler(conf, 'msvc', 'x86', version, 'x86', os.path.join(vc_path, 'Common7', 'Tools', 'vsvars32.bat'))
    432 	elif os.path.isfile(os.path.join(vc_path, 'Bin', 'vcvars32.bat')):
    433 		targets['x86'] = target_compiler(conf, 'msvc', 'x86', version, '', os.path.join(vc_path, 'Bin', 'vcvars32.bat'))
    434 	if targets:
    435 		versions['msvc %s' % version] = targets
    436 
    437 @conf
    438 def gather_wince_targets(conf, versions, version, vc_path, vsvars, supported_platforms):
    439 	#Looking for Win CE compilers!
    440 	for device,platforms in supported_platforms:
    441 		targets = {}
    442 		for platform,compiler,include,lib in platforms:
    443 			winCEpath = os.path.join(vc_path, 'ce')
    444 			if not os.path.isdir(winCEpath):
    445 				continue
    446 
    447 			if os.path.isdir(os.path.join(winCEpath, 'lib', platform)):
    448 				bindirs = [os.path.join(winCEpath, 'bin', compiler), os.path.join(winCEpath, 'bin', 'x86_'+compiler)]
    449 				incdirs = [os.path.join(winCEpath, 'include'), os.path.join(winCEpath, 'atlmfc', 'include'), include]
    450 				libdirs = [os.path.join(winCEpath, 'lib', platform), os.path.join(winCEpath, 'atlmfc', 'lib', platform), lib]
    451 				def combine_common(obj, compiler_env):
    452 					# TODO this is likely broken, remove in waf 2.1
    453 					(common_bindirs,_1,_2) = compiler_env
    454 					return (bindirs + common_bindirs, incdirs, libdirs)
    455 				targets[platform] = target_compiler(conf, 'msvc', platform, version, 'x86', vsvars, combine_common)
    456 		if targets:
    457 			versions[device + ' ' + version] = targets
    458 
    459 @conf
    460 def gather_winphone_targets(conf, versions, version, vc_path, vsvars):
    461 	#Looking for WinPhone compilers
    462 	targets = {}
    463 	for target,realtarget in all_msvc_platforms[::-1]:
    464 		targets[target] = target_compiler(conf, 'winphone', realtarget, version, target, vsvars)
    465 	if targets:
    466 		versions['winphone ' + version] = targets
    467 
    468 @conf
    469 def gather_vswhere_versions(conf, versions):
    470 	try:
    471 		import json
    472 	except ImportError:
    473 		Logs.error('Visual Studio 2017 detection requires Python 2.6')
    474 		return
    475 
    476 	prg_path = os.environ.get('ProgramFiles(x86)', os.environ.get('ProgramFiles', 'C:\\Program Files (x86)'))
    477 
    478 	vswhere = os.path.join(prg_path, 'Microsoft Visual Studio', 'Installer', 'vswhere.exe')
    479 	args = [vswhere, '-products', '*', '-legacy', '-format', 'json']
    480 	try:
    481 		txt = conf.cmd_and_log(args)
    482 	except Errors.WafError as e:
    483 		Logs.debug('msvc: vswhere.exe failed %s', e)
    484 		return
    485 
    486 	if sys.version_info[0] < 3:
    487 		txt = txt.decode(Utils.console_encoding())
    488 
    489 	arr = json.loads(txt)
    490 	arr.sort(key=lambda x: x['installationVersion'])
    491 	for entry in arr:
    492 		ver = entry['installationVersion']
    493 		ver = str('.'.join(ver.split('.')[:2]))
    494 		path = str(os.path.abspath(entry['installationPath']))
    495 		if os.path.exists(path) and ('msvc %s' % ver) not in versions:
    496 			conf.gather_msvc_targets(versions, ver, path)
    497 
    498 @conf
    499 def gather_msvc_versions(conf, versions):
    500 	vc_paths = []
    501 	for (v,version,reg) in gather_msvc_detected_versions():
    502 		try:
    503 			try:
    504 				msvc_version = Utils.winreg.OpenKey(Utils.winreg.HKEY_LOCAL_MACHINE, reg + "\\Setup\\VC")
    505 			except OSError:
    506 				msvc_version = Utils.winreg.OpenKey(Utils.winreg.HKEY_LOCAL_MACHINE, reg + "\\Setup\\Microsoft Visual C++")
    507 			path,type = Utils.winreg.QueryValueEx(msvc_version, 'ProductDir')
    508 		except OSError:
    509 			try:
    510 				msvc_version = Utils.winreg.OpenKey(Utils.winreg.HKEY_LOCAL_MACHINE, "SOFTWARE\\Wow6432node\\Microsoft\\VisualStudio\\SxS\\VS7")
    511 				path,type = Utils.winreg.QueryValueEx(msvc_version, version)
    512 			except OSError:
    513 				continue
    514 			else:
    515 				vc_paths.append((version, os.path.abspath(str(path))))
    516 			continue
    517 		else:
    518 			vc_paths.append((version, os.path.abspath(str(path))))
    519 
    520 	wince_supported_platforms = gather_wince_supported_platforms()
    521 
    522 	for version,vc_path in vc_paths:
    523 		vs_path = os.path.dirname(vc_path)
    524 		vsvars = os.path.join(vs_path, 'Common7', 'Tools', 'vsvars32.bat')
    525 		if wince_supported_platforms and os.path.isfile(vsvars):
    526 			conf.gather_wince_targets(versions, version, vc_path, vsvars, wince_supported_platforms)
    527 
    528 	# WP80 works with 11.0Exp and 11.0, both of which resolve to the same vc_path.
    529 	# Stop after one is found.
    530 	for version,vc_path in vc_paths:
    531 		vs_path = os.path.dirname(vc_path)
    532 		vsvars = os.path.join(vs_path, 'VC', 'WPSDK', 'WP80', 'vcvarsphoneall.bat')
    533 		if os.path.isfile(vsvars):
    534 			conf.gather_winphone_targets(versions, '8.0', vc_path, vsvars)
    535 			break
    536 
    537 	for version,vc_path in vc_paths:
    538 		vs_path = os.path.dirname(vc_path)
    539 		conf.gather_msvc_targets(versions, version, vc_path)
    540 
    541 @conf
    542 def gather_icl_versions(conf, versions):
    543 	"""
    544 	Checks ICL compilers
    545 
    546 	:param versions: list to modify
    547 	:type versions: list
    548 	"""
    549 	version_pattern = re.compile(r'^...?.?\....?.?')
    550 	try:
    551 		all_versions = Utils.winreg.OpenKey(Utils.winreg.HKEY_LOCAL_MACHINE, 'SOFTWARE\\Wow6432node\\Intel\\Compilers\\C++')
    552 	except OSError:
    553 		try:
    554 			all_versions = Utils.winreg.OpenKey(Utils.winreg.HKEY_LOCAL_MACHINE, 'SOFTWARE\\Intel\\Compilers\\C++')
    555 		except OSError:
    556 			return
    557 	index = 0
    558 	while 1:
    559 		try:
    560 			version = Utils.winreg.EnumKey(all_versions, index)
    561 		except OSError:
    562 			break
    563 		index += 1
    564 		if not version_pattern.match(version):
    565 			continue
    566 		targets = {}
    567 		for target,arch in all_icl_platforms:
    568 			if target=='intel64':
    569 				targetDir='EM64T_NATIVE'
    570 			else:
    571 				targetDir=target
    572 			try:
    573 				Utils.winreg.OpenKey(all_versions,version+'\\'+targetDir)
    574 				icl_version=Utils.winreg.OpenKey(all_versions,version)
    575 				path,type=Utils.winreg.QueryValueEx(icl_version,'ProductDir')
    576 			except OSError:
    577 				pass
    578 			else:
    579 				batch_file=os.path.join(path,'bin','iclvars.bat')
    580 				if os.path.isfile(batch_file):
    581 					targets[target] = target_compiler(conf, 'intel', arch, version, target, batch_file)
    582 		for target,arch in all_icl_platforms:
    583 			try:
    584 				icl_version = Utils.winreg.OpenKey(all_versions, version+'\\'+target)
    585 				path,type = Utils.winreg.QueryValueEx(icl_version,'ProductDir')
    586 			except OSError:
    587 				continue
    588 			else:
    589 				batch_file=os.path.join(path,'bin','iclvars.bat')
    590 				if os.path.isfile(batch_file):
    591 					targets[target] = target_compiler(conf, 'intel', arch, version, target, batch_file)
    592 		major = version[0:2]
    593 		versions['intel ' + major] = targets
    594 
    595 @conf
    596 def gather_intel_composer_versions(conf, versions):
    597 	"""
    598 	Checks ICL compilers that are part of Intel Composer Suites
    599 
    600 	:param versions: list to modify
    601 	:type versions: list
    602 	"""
    603 	version_pattern = re.compile(r'^...?.?\...?.?.?')
    604 	try:
    605 		all_versions = Utils.winreg.OpenKey(Utils.winreg.HKEY_LOCAL_MACHINE, 'SOFTWARE\\Wow6432node\\Intel\\Suites')
    606 	except OSError:
    607 		try:
    608 			all_versions = Utils.winreg.OpenKey(Utils.winreg.HKEY_LOCAL_MACHINE, 'SOFTWARE\\Intel\\Suites')
    609 		except OSError:
    610 			return
    611 	index = 0
    612 	while 1:
    613 		try:
    614 			version = Utils.winreg.EnumKey(all_versions, index)
    615 		except OSError:
    616 			break
    617 		index += 1
    618 		if not version_pattern.match(version):
    619 			continue
    620 		targets = {}
    621 		for target,arch in all_icl_platforms:
    622 			if target=='intel64':
    623 				targetDir='EM64T_NATIVE'
    624 			else:
    625 				targetDir=target
    626 			try:
    627 				try:
    628 					defaults = Utils.winreg.OpenKey(all_versions,version+'\\Defaults\\C++\\'+targetDir)
    629 				except OSError:
    630 					if targetDir == 'EM64T_NATIVE':
    631 						defaults = Utils.winreg.OpenKey(all_versions,version+'\\Defaults\\C++\\EM64T')
    632 					else:
    633 						raise
    634 				uid,type = Utils.winreg.QueryValueEx(defaults, 'SubKey')
    635 				Utils.winreg.OpenKey(all_versions,version+'\\'+uid+'\\C++\\'+targetDir)
    636 				icl_version=Utils.winreg.OpenKey(all_versions,version+'\\'+uid+'\\C++')
    637 				path,type=Utils.winreg.QueryValueEx(icl_version,'ProductDir')
    638 			except OSError:
    639 				pass
    640 			else:
    641 				batch_file=os.path.join(path,'bin','iclvars.bat')
    642 				if os.path.isfile(batch_file):
    643 					targets[target] = target_compiler(conf, 'intel', arch, version, target, batch_file)
    644 				# The intel compilervar_arch.bat is broken when used with Visual Studio Express 2012
    645 				# http://software.intel.com/en-us/forums/topic/328487
    646 				compilervars_warning_attr = '_compilervars_warning_key'
    647 				if version[0:2] == '13' and getattr(conf, compilervars_warning_attr, True):
    648 					setattr(conf, compilervars_warning_attr, False)
    649 					patch_url = 'http://software.intel.com/en-us/forums/topic/328487'
    650 					compilervars_arch = os.path.join(path, 'bin', 'compilervars_arch.bat')
    651 					for vscomntool in ('VS110COMNTOOLS', 'VS100COMNTOOLS'):
    652 						if vscomntool in os.environ:
    653 							vs_express_path = os.environ[vscomntool] + r'..\IDE\VSWinExpress.exe'
    654 							dev_env_path = os.environ[vscomntool] + r'..\IDE\devenv.exe'
    655 							if (r'if exist "%VS110COMNTOOLS%..\IDE\VSWinExpress.exe"' in Utils.readf(compilervars_arch) and
    656 								not os.path.exists(vs_express_path) and not os.path.exists(dev_env_path)):
    657 								Logs.warn(('The Intel compilervar_arch.bat only checks for one Visual Studio SKU '
    658 								'(VSWinExpress.exe) but it does not seem to be installed at %r. '
    659 								'The intel command line set up will fail to configure unless the file %r'
    660 								'is patched. See: %s') % (vs_express_path, compilervars_arch, patch_url))
    661 		major = version[0:2]
    662 		versions['intel ' + major] = targets
    663 
    664 @conf
    665 def detect_msvc(self):
    666 	return self.setup_msvc(self.get_msvc_versions())
    667 
    668 @conf
    669 def get_msvc_versions(self):
    670 	"""
    671 	:return: platform to compiler configurations
    672 	:rtype: dict
    673 	"""
    674 	dct = Utils.ordered_iter_dict()
    675 	self.gather_icl_versions(dct)
    676 	self.gather_intel_composer_versions(dct)
    677 	self.gather_wsdk_versions(dct)
    678 	self.gather_msvc_versions(dct)
    679 	self.gather_vswhere_versions(dct)
    680 	Logs.debug('msvc: detected versions %r', list(dct.keys()))
    681 	return dct
    682 
    683 @conf
    684 def find_lt_names_msvc(self, libname, is_static=False):
    685 	"""
    686 	Win32/MSVC specific code to glean out information from libtool la files.
    687 	this function is not attached to the task_gen class. Returns a triplet:
    688 	(library absolute path, library name without extension, whether the library is static)
    689 	"""
    690 	lt_names=[
    691 		'lib%s.la' % libname,
    692 		'%s.la' % libname,
    693 	]
    694 
    695 	for path in self.env.LIBPATH:
    696 		for la in lt_names:
    697 			laf=os.path.join(path,la)
    698 			dll=None
    699 			if os.path.exists(laf):
    700 				ltdict = Utils.read_la_file(laf)
    701 				lt_libdir=None
    702 				if ltdict.get('libdir', ''):
    703 					lt_libdir = ltdict['libdir']
    704 				if not is_static and ltdict.get('library_names', ''):
    705 					dllnames=ltdict['library_names'].split()
    706 					dll=dllnames[0].lower()
    707 					dll=re.sub(r'\.dll$', '', dll)
    708 					return (lt_libdir, dll, False)
    709 				elif ltdict.get('old_library', ''):
    710 					olib=ltdict['old_library']
    711 					if os.path.exists(os.path.join(path,olib)):
    712 						return (path, olib, True)
    713 					elif lt_libdir != '' and os.path.exists(os.path.join(lt_libdir,olib)):
    714 						return (lt_libdir, olib, True)
    715 					else:
    716 						return (None, olib, True)
    717 				else:
    718 					raise self.errors.WafError('invalid libtool object file: %s' % laf)
    719 	return (None, None, None)
    720 
    721 @conf
    722 def libname_msvc(self, libname, is_static=False):
    723 	lib = libname.lower()
    724 	lib = re.sub(r'\.lib$','',lib)
    725 
    726 	if lib in g_msvc_systemlibs:
    727 		return lib
    728 
    729 	lib=re.sub('^lib','',lib)
    730 
    731 	if lib == 'm':
    732 		return None
    733 
    734 	(lt_path, lt_libname, lt_static) = self.find_lt_names_msvc(lib, is_static)
    735 
    736 	if lt_path != None and lt_libname != None:
    737 		if lt_static:
    738 			# file existence check has been made by find_lt_names
    739 			return os.path.join(lt_path,lt_libname)
    740 
    741 	if lt_path != None:
    742 		_libpaths = [lt_path] + self.env.LIBPATH
    743 	else:
    744 		_libpaths = self.env.LIBPATH
    745 
    746 	static_libs=[
    747 		'lib%ss.lib' % lib,
    748 		'lib%s.lib' % lib,
    749 		'%ss.lib' % lib,
    750 		'%s.lib' %lib,
    751 		]
    752 
    753 	dynamic_libs=[
    754 		'lib%s.dll.lib' % lib,
    755 		'lib%s.dll.a' % lib,
    756 		'%s.dll.lib' % lib,
    757 		'%s.dll.a' % lib,
    758 		'lib%s_d.lib' % lib,
    759 		'%s_d.lib' % lib,
    760 		'%s.lib' %lib,
    761 		]
    762 
    763 	libnames=static_libs
    764 	if not is_static:
    765 		libnames=dynamic_libs + static_libs
    766 
    767 	for path in _libpaths:
    768 		for libn in libnames:
    769 			if os.path.exists(os.path.join(path, libn)):
    770 				Logs.debug('msvc: lib found: %s', os.path.join(path,libn))
    771 				return re.sub(r'\.lib$', '',libn)
    772 
    773 	#if no lib can be found, just return the libname as msvc expects it
    774 	self.fatal('The library %r could not be found' % libname)
    775 	return re.sub(r'\.lib$', '', libname)
    776 
    777 @conf
    778 def check_lib_msvc(self, libname, is_static=False, uselib_store=None):
    779 	"""
    780 	Ideally we should be able to place the lib in the right env var, either STLIB or LIB,
    781 	but we don't distinguish static libs from shared libs.
    782 	This is ok since msvc doesn't have any special linker flag to select static libs (no env.STLIB_MARKER)
    783 	"""
    784 	libn = self.libname_msvc(libname, is_static)
    785 
    786 	if not uselib_store:
    787 		uselib_store = libname.upper()
    788 
    789 	if False and is_static: # disabled
    790 		self.env['STLIB_' + uselib_store] = [libn]
    791 	else:
    792 		self.env['LIB_' + uselib_store] = [libn]
    793 
    794 @conf
    795 def check_libs_msvc(self, libnames, is_static=False):
    796 	for libname in Utils.to_list(libnames):
    797 		self.check_lib_msvc(libname, is_static)
    798 
    799 def configure(conf):
    800 	"""
    801 	Configuration methods to call for detecting msvc
    802 	"""
    803 	conf.autodetect(True)
    804 	conf.find_msvc()
    805 	conf.msvc_common_flags()
    806 	conf.cc_load_tools()
    807 	conf.cxx_load_tools()
    808 	conf.cc_add_flags()
    809 	conf.cxx_add_flags()
    810 	conf.link_add_flags()
    811 	conf.visual_studio_add_flags()
    812 
    813 @conf
    814 def no_autodetect(conf):
    815 	conf.env.NO_MSVC_DETECT = 1
    816 	configure(conf)
    817 
    818 @conf
    819 def autodetect(conf, arch=False):
    820 	v = conf.env
    821 	if v.NO_MSVC_DETECT:
    822 		return
    823 
    824 	compiler, version, path, includes, libdirs, cpu = conf.detect_msvc()
    825 	if arch:
    826 		v.DEST_CPU = cpu
    827 
    828 	v.PATH = path
    829 	v.INCLUDES = includes
    830 	v.LIBPATH = libdirs
    831 	v.MSVC_COMPILER = compiler
    832 	try:
    833 		v.MSVC_VERSION = float(version)
    834 	except ValueError:
    835 		v.MSVC_VERSION = float(version[:-3])
    836 
    837 def _get_prog_names(conf, compiler):
    838 	if compiler == 'intel':
    839 		compiler_name = 'ICL'
    840 		linker_name = 'XILINK'
    841 		lib_name = 'XILIB'
    842 	else:
    843 		# assumes CL.exe
    844 		compiler_name = 'CL'
    845 		linker_name = 'LINK'
    846 		lib_name = 'LIB'
    847 	return compiler_name, linker_name, lib_name
    848 
    849 @conf
    850 def find_msvc(conf):
    851 	"""Due to path format limitations, limit operation only to native Win32. Yeah it sucks."""
    852 	if sys.platform == 'cygwin':
    853 		conf.fatal('MSVC module does not work under cygwin Python!')
    854 
    855 	# the autodetection is supposed to be performed before entering in this method
    856 	v = conf.env
    857 	path = v.PATH
    858 	compiler = v.MSVC_COMPILER
    859 	version = v.MSVC_VERSION
    860 
    861 	compiler_name, linker_name, lib_name = _get_prog_names(conf, compiler)
    862 	v.MSVC_MANIFEST = (compiler == 'msvc' and version >= 8) or (compiler == 'wsdk' and version >= 6) or (compiler == 'intel' and version >= 11)
    863 
    864 	# compiler
    865 	cxx = conf.find_program(compiler_name, var='CXX', path_list=path)
    866 
    867 	# before setting anything, check if the compiler is really msvc
    868 	env = dict(conf.environ)
    869 	if path:
    870 		env.update(PATH = ';'.join(path))
    871 	if not conf.cmd_and_log(cxx + ['/nologo', '/help'], env=env):
    872 		conf.fatal('the msvc compiler could not be identified')
    873 
    874 	# c/c++ compiler
    875 	v.CC = v.CXX = cxx
    876 	v.CC_NAME = v.CXX_NAME = 'msvc'
    877 
    878 	# linker
    879 	if not v.LINK_CXX:
    880 		conf.find_program(linker_name, path_list=path, errmsg='%s was not found (linker)' % linker_name, var='LINK_CXX')
    881 
    882 	if not v.LINK_CC:
    883 		v.LINK_CC = v.LINK_CXX
    884 
    885 	# staticlib linker
    886 	if not v.AR:
    887 		stliblink = conf.find_program(lib_name, path_list=path, var='AR')
    888 		if not stliblink:
    889 			return
    890 		v.ARFLAGS = ['/nologo']
    891 
    892 	# manifest tool. Not required for VS 2003 and below. Must have for VS 2005 and later
    893 	if v.MSVC_MANIFEST:
    894 		conf.find_program('MT', path_list=path, var='MT')
    895 		v.MTFLAGS = ['/nologo']
    896 
    897 	try:
    898 		conf.load('winres')
    899 	except Errors.ConfigurationError:
    900 		Logs.warn('Resource compiler not found. Compiling resource file is disabled')
    901 
    902 @conf
    903 def visual_studio_add_flags(self):
    904 	"""visual studio flags found in the system environment"""
    905 	v = self.env
    906 	if self.environ.get('INCLUDE'):
    907 		v.prepend_value('INCLUDES', [x for x in self.environ['INCLUDE'].split(';') if x]) # notice the 'S'
    908 	if self.environ.get('LIB'):
    909 		v.prepend_value('LIBPATH', [x for x in self.environ['LIB'].split(';') if x])
    910 
    911 @conf
    912 def msvc_common_flags(conf):
    913 	"""
    914 	Setup the flags required for executing the msvc compiler
    915 	"""
    916 	v = conf.env
    917 
    918 	v.DEST_BINFMT = 'pe'
    919 	v.append_value('CFLAGS', ['/nologo'])
    920 	v.append_value('CXXFLAGS', ['/nologo'])
    921 	v.append_value('LINKFLAGS', ['/nologo'])
    922 	v.DEFINES_ST   = '/D%s'
    923 
    924 	v.CC_SRC_F     = ''
    925 	v.CC_TGT_F     = ['/c', '/Fo']
    926 	v.CXX_SRC_F    = ''
    927 	v.CXX_TGT_F    = ['/c', '/Fo']
    928 
    929 	if (v.MSVC_COMPILER == 'msvc' and v.MSVC_VERSION >= 8) or (v.MSVC_COMPILER == 'wsdk' and v.MSVC_VERSION >= 6):
    930 		v.CC_TGT_F = ['/FC'] + v.CC_TGT_F
    931 		v.CXX_TGT_F = ['/FC'] + v.CXX_TGT_F
    932 
    933 	v.CPPPATH_ST = '/I%s' # template for adding include paths
    934 
    935 	v.AR_TGT_F = v.CCLNK_TGT_F = v.CXXLNK_TGT_F = '/OUT:'
    936 
    937 	# CRT specific flags
    938 	v.CFLAGS_CRT_MULTITHREADED     = v.CXXFLAGS_CRT_MULTITHREADED     = ['/MT']
    939 	v.CFLAGS_CRT_MULTITHREADED_DLL = v.CXXFLAGS_CRT_MULTITHREADED_DLL = ['/MD']
    940 
    941 	v.CFLAGS_CRT_MULTITHREADED_DBG     = v.CXXFLAGS_CRT_MULTITHREADED_DBG     = ['/MTd']
    942 	v.CFLAGS_CRT_MULTITHREADED_DLL_DBG = v.CXXFLAGS_CRT_MULTITHREADED_DLL_DBG = ['/MDd']
    943 
    944 	v.LIB_ST            = '%s.lib'
    945 	v.LIBPATH_ST        = '/LIBPATH:%s'
    946 	v.STLIB_ST          = '%s.lib'
    947 	v.STLIBPATH_ST      = '/LIBPATH:%s'
    948 
    949 	if v.MSVC_MANIFEST:
    950 		v.append_value('LINKFLAGS', ['/MANIFEST'])
    951 
    952 	v.CFLAGS_cshlib     = []
    953 	v.CXXFLAGS_cxxshlib = []
    954 	v.LINKFLAGS_cshlib  = v.LINKFLAGS_cxxshlib = ['/DLL']
    955 	v.cshlib_PATTERN    = v.cxxshlib_PATTERN = '%s.dll'
    956 	v.implib_PATTERN    = '%s.lib'
    957 	v.IMPLIB_ST         = '/IMPLIB:%s'
    958 
    959 	v.LINKFLAGS_cstlib  = []
    960 	v.cstlib_PATTERN    = v.cxxstlib_PATTERN = '%s.lib'
    961 
    962 	v.cprogram_PATTERN  = v.cxxprogram_PATTERN = '%s.exe'
    963 
    964 	v.def_PATTERN       = '/def:%s'
    965 
    966 
    967 #######################################################################################################
    968 ##### conf above, build below
    969 
    970 @after_method('apply_link')
    971 @feature('c', 'cxx')
    972 def apply_flags_msvc(self):
    973 	"""
    974 	Add additional flags implied by msvc, such as subsystems and pdb files::
    975 
    976 		def build(bld):
    977 			bld.stlib(source='main.c', target='bar', subsystem='gruik')
    978 	"""
    979 	if self.env.CC_NAME != 'msvc' or not getattr(self, 'link_task', None):
    980 		return
    981 
    982 	is_static = isinstance(self.link_task, ccroot.stlink_task)
    983 
    984 	subsystem = getattr(self, 'subsystem', '')
    985 	if subsystem:
    986 		subsystem = '/subsystem:%s' % subsystem
    987 		flags = is_static and 'ARFLAGS' or 'LINKFLAGS'
    988 		self.env.append_value(flags, subsystem)
    989 
    990 	if not is_static:
    991 		for f in self.env.LINKFLAGS:
    992 			d = f.lower()
    993 			if d[1:] in ('debug', 'debug:full', 'debug:fastlink'):
    994 				pdbnode = self.link_task.outputs[0].change_ext('.pdb')
    995 				self.link_task.outputs.append(pdbnode)
    996 
    997 				if getattr(self, 'install_task', None):
    998 					self.pdb_install_task = self.add_install_files(
    999 						install_to=self.install_task.install_to, install_from=pdbnode)
   1000 				break
   1001 
   1002 @feature('cprogram', 'cshlib', 'cxxprogram', 'cxxshlib')
   1003 @after_method('apply_link')
   1004 def apply_manifest(self):
   1005 	"""
   1006 	Special linker for MSVC with support for embedding manifests into DLL's
   1007 	and executables compiled by Visual Studio 2005 or probably later. Without
   1008 	the manifest file, the binaries are unusable.
   1009 	See: http://msdn2.microsoft.com/en-us/library/ms235542(VS.80).aspx
   1010 	"""
   1011 	if self.env.CC_NAME == 'msvc' and self.env.MSVC_MANIFEST and getattr(self, 'link_task', None):
   1012 		out_node = self.link_task.outputs[0]
   1013 		man_node = out_node.parent.find_or_declare(out_node.name + '.manifest')
   1014 		self.link_task.outputs.append(man_node)
   1015 		self.env.DO_MANIFEST = True
   1016 
   1017 def make_winapp(self, family):
   1018 	append = self.env.append_unique
   1019 	append('DEFINES', 'WINAPI_FAMILY=%s' % family)
   1020 	append('CXXFLAGS', ['/ZW', '/TP'])
   1021 	for lib_path in self.env.LIBPATH:
   1022 		append('CXXFLAGS','/AI%s'%lib_path)
   1023 
   1024 @feature('winphoneapp')
   1025 @after_method('process_use')
   1026 @after_method('propagate_uselib_vars')
   1027 def make_winphone_app(self):
   1028 	"""
   1029 	Insert configuration flags for windows phone applications (adds /ZW, /TP...)
   1030 	"""
   1031 	make_winapp(self, 'WINAPI_FAMILY_PHONE_APP')
   1032 	self.env.append_unique('LINKFLAGS', ['/NODEFAULTLIB:ole32.lib', 'PhoneAppModelHost.lib'])
   1033 
   1034 @feature('winapp')
   1035 @after_method('process_use')
   1036 @after_method('propagate_uselib_vars')
   1037 def make_windows_app(self):
   1038 	"""
   1039 	Insert configuration flags for windows applications (adds /ZW, /TP...)
   1040 	"""
   1041 	make_winapp(self, 'WINAPI_FAMILY_DESKTOP_APP')