1#! /usr/bin/env python
2# encoding: utf-8
3# WARNING! Do not edit! https://waf.io/book/index.html#_obtaining_the_waf_file
4
5import os,sys,re,traceback
6from waflib import Utils,Logs,Options,Errors
7from waflib.TaskGen import after_method,feature
8from waflib.Configure import conf
9from waflib.Tools import ccroot,c,cxx,ar
10g_msvc_systemlibs='''
11aclui activeds ad1 adptif adsiid advapi32 asycfilt authz bhsupp bits bufferoverflowu cabinet
12cap certadm certidl ciuuid clusapi comctl32 comdlg32 comsupp comsuppd comsuppw comsuppwd comsvcs
13credui crypt32 cryptnet cryptui d3d8thk daouuid dbgeng dbghelp dciman32 ddao35 ddao35d
14ddao35u ddao35ud delayimp dhcpcsvc dhcpsapi dlcapi dnsapi dsprop dsuiext dtchelp
15faultrep fcachdll fci fdi framedyd framedyn gdi32 gdiplus glauxglu32 gpedit gpmuuid
16gtrts32w gtrtst32hlink htmlhelp httpapi icm32 icmui imagehlp imm32 iphlpapi iprop
17kernel32 ksguid ksproxy ksuser libcmt libcmtd libcpmt libcpmtd loadperf lz32 mapi
18mapi32 mgmtapi minidump mmc mobsync mpr mprapi mqoa mqrt msacm32 mscms mscoree
19msdasc msimg32 msrating mstask msvcmrt msvcurt msvcurtd mswsock msxml2 mtx mtxdm
20netapi32 nmapinmsupp npptools ntdsapi ntdsbcli ntmsapi ntquery odbc32 odbcbcp
21odbccp32 oldnames ole32 oleacc oleaut32 oledb oledlgolepro32 opends60 opengl32
22osptk parser pdh penter pgobootrun pgort powrprof psapi ptrustm ptrustmd ptrustu
23ptrustud qosname rasapi32 rasdlg rassapi resutils riched20 rpcndr rpcns4 rpcrt4 rtm
24rtutils runtmchk scarddlg scrnsave scrnsavw secur32 sensapi setupapi sfc shell32
25shfolder shlwapi sisbkup snmpapi sporder srclient sti strsafe svcguid tapi32 thunk32
26traffic unicows url urlmon user32 userenv usp10 uuid uxtheme vcomp vcompd vdmdbg
27version vfw32 wbemuuid  webpost wiaguid wininet winmm winscard winspool winstrm
28wintrust wldap32 wmiutils wow32 ws2_32 wsnmp32 wsock32 wst wtsapi32 xaswitch xolehlp
29'''.split()
30all_msvc_platforms=[('x64','amd64'),('x86','x86'),('ia64','ia64'),('x86_amd64','amd64'),('x86_ia64','ia64'),('x86_arm','arm'),('x86_arm64','arm64'),('amd64_x86','x86'),('amd64_arm','arm'),('amd64_arm64','arm64')]
31all_wince_platforms=[('armv4','arm'),('armv4i','arm'),('mipsii','mips'),('mipsii_fp','mips'),('mipsiv','mips'),('mipsiv_fp','mips'),('sh4','sh'),('x86','cex86')]
32all_icl_platforms=[('intel64','amd64'),('em64t','amd64'),('ia32','x86'),('Itanium','ia64')]
33def options(opt):
34	opt.add_option('--msvc_version',type='string',help='msvc version, eg: "msvc 10.0,msvc 9.0"',default='')
35	opt.add_option('--msvc_targets',type='string',help='msvc targets, eg: "x64,arm"',default='')
36	opt.add_option('--no-msvc-lazy',action='store_false',help='lazily check msvc target environments',default=True,dest='msvc_lazy')
37@conf
38def setup_msvc(conf,versiondict):
39	platforms=getattr(Options.options,'msvc_targets','').split(',')
40	if platforms==['']:
41		platforms=Utils.to_list(conf.env.MSVC_TARGETS)or[i for i,j in all_msvc_platforms+all_icl_platforms+all_wince_platforms]
42	desired_versions=getattr(Options.options,'msvc_version','').split(',')
43	if desired_versions==['']:
44		desired_versions=conf.env.MSVC_VERSIONS or list(reversed(sorted(versiondict.keys())))
45	lazy_detect=getattr(Options.options,'msvc_lazy',True)
46	if conf.env.MSVC_LAZY_AUTODETECT is False:
47		lazy_detect=False
48	if not lazy_detect:
49		for val in versiondict.values():
50			for arch in list(val.keys()):
51				cfg=val[arch]
52				cfg.evaluate()
53				if not cfg.is_valid:
54					del val[arch]
55		conf.env.MSVC_INSTALLED_VERSIONS=versiondict
56	for version in desired_versions:
57		Logs.debug('msvc: detecting %r - %r',version,desired_versions)
58		try:
59			targets=versiondict[version]
60		except KeyError:
61			continue
62		seen=set()
63		for arch in platforms:
64			if arch in seen:
65				continue
66			else:
67				seen.add(arch)
68			try:
69				cfg=targets[arch]
70			except KeyError:
71				continue
72			cfg.evaluate()
73			if cfg.is_valid:
74				compiler,revision=version.rsplit(' ',1)
75				return compiler,revision,cfg.bindirs,cfg.incdirs,cfg.libdirs,cfg.cpu
76	conf.fatal('msvc: Impossible to find a valid architecture for building %r - %r'%(desired_versions,list(versiondict.keys())))
77@conf
78def get_msvc_version(conf,compiler,version,target,vcvars):
79	Logs.debug('msvc: get_msvc_version: %r %r %r',compiler,version,target)
80	try:
81		conf.msvc_cnt+=1
82	except AttributeError:
83		conf.msvc_cnt=1
84	batfile=conf.bldnode.make_node('waf-print-msvc-%d.bat'%conf.msvc_cnt)
85	batfile.write("""@echo off
86set INCLUDE=
87set LIB=
88call "%s" %s
89echo PATH=%%PATH%%
90echo INCLUDE=%%INCLUDE%%
91echo LIB=%%LIB%%;%%LIBPATH%%
92"""%(vcvars,target))
93	sout=conf.cmd_and_log(['cmd.exe','/E:on','/V:on','/C',batfile.abspath()])
94	lines=sout.splitlines()
95	if not lines[0]:
96		lines.pop(0)
97	MSVC_PATH=MSVC_INCDIR=MSVC_LIBDIR=None
98	for line in lines:
99		if line.startswith('PATH='):
100			path=line[5:]
101			MSVC_PATH=path.split(';')
102		elif line.startswith('INCLUDE='):
103			MSVC_INCDIR=[i for i in line[8:].split(';')if i]
104		elif line.startswith('LIB='):
105			MSVC_LIBDIR=[i for i in line[4:].split(';')if i]
106	if None in(MSVC_PATH,MSVC_INCDIR,MSVC_LIBDIR):
107		conf.fatal('msvc: Could not find a valid architecture for building (get_msvc_version_3)')
108	env=dict(os.environ)
109	env.update(PATH=path)
110	compiler_name,linker_name,lib_name=_get_prog_names(conf,compiler)
111	cxx=conf.find_program(compiler_name,path_list=MSVC_PATH)
112	if'CL'in env:
113		del(env['CL'])
114	try:
115		conf.cmd_and_log(cxx+['/help'],env=env)
116	except UnicodeError:
117		st=traceback.format_exc()
118		if conf.logger:
119			conf.logger.error(st)
120		conf.fatal('msvc: Unicode error - check the code page?')
121	except Exception as e:
122		Logs.debug('msvc: get_msvc_version: %r %r %r -> failure %s',compiler,version,target,str(e))
123		conf.fatal('msvc: cannot run the compiler in get_msvc_version (run with -v to display errors)')
124	else:
125		Logs.debug('msvc: get_msvc_version: %r %r %r -> OK',compiler,version,target)
126	finally:
127		conf.env[compiler_name]=''
128	return(MSVC_PATH,MSVC_INCDIR,MSVC_LIBDIR)
129def gather_wince_supported_platforms():
130	supported_wince_platforms=[]
131	try:
132		ce_sdk=Utils.winreg.OpenKey(Utils.winreg.HKEY_LOCAL_MACHINE,'SOFTWARE\\Wow6432node\\Microsoft\\Windows CE Tools\\SDKs')
133	except OSError:
134		try:
135			ce_sdk=Utils.winreg.OpenKey(Utils.winreg.HKEY_LOCAL_MACHINE,'SOFTWARE\\Microsoft\\Windows CE Tools\\SDKs')
136		except OSError:
137			ce_sdk=''
138	if not ce_sdk:
139		return supported_wince_platforms
140	index=0
141	while 1:
142		try:
143			sdk_device=Utils.winreg.EnumKey(ce_sdk,index)
144			sdk=Utils.winreg.OpenKey(ce_sdk,sdk_device)
145		except OSError:
146			break
147		index+=1
148		try:
149			path,type=Utils.winreg.QueryValueEx(sdk,'SDKRootDir')
150		except OSError:
151			try:
152				path,type=Utils.winreg.QueryValueEx(sdk,'SDKInformation')
153			except OSError:
154				continue
155			path,xml=os.path.split(path)
156		path=str(path)
157		path,device=os.path.split(path)
158		if not device:
159			path,device=os.path.split(path)
160		platforms=[]
161		for arch,compiler in all_wince_platforms:
162			if os.path.isdir(os.path.join(path,device,'Lib',arch)):
163				platforms.append((arch,compiler,os.path.join(path,device,'Include',arch),os.path.join(path,device,'Lib',arch)))
164		if platforms:
165			supported_wince_platforms.append((device,platforms))
166	return supported_wince_platforms
167def gather_msvc_detected_versions():
168	version_pattern=re.compile('^(\d\d?\.\d\d?)(Exp)?$')
169	detected_versions=[]
170	for vcver,vcvar in(('VCExpress','Exp'),('VisualStudio','')):
171		prefix='SOFTWARE\\Wow6432node\\Microsoft\\'+vcver
172		try:
173			all_versions=Utils.winreg.OpenKey(Utils.winreg.HKEY_LOCAL_MACHINE,prefix)
174		except OSError:
175			prefix='SOFTWARE\\Microsoft\\'+vcver
176			try:
177				all_versions=Utils.winreg.OpenKey(Utils.winreg.HKEY_LOCAL_MACHINE,prefix)
178			except OSError:
179				continue
180		index=0
181		while 1:
182			try:
183				version=Utils.winreg.EnumKey(all_versions,index)
184			except OSError:
185				break
186			index+=1
187			match=version_pattern.match(version)
188			if match:
189				versionnumber=float(match.group(1))
190			else:
191				continue
192			detected_versions.append((versionnumber,version+vcvar,prefix+'\\'+version))
193	def fun(tup):
194		return tup[0]
195	detected_versions.sort(key=fun)
196	return detected_versions
197class target_compiler(object):
198	def __init__(self,ctx,compiler,cpu,version,bat_target,bat,callback=None):
199		self.conf=ctx
200		self.name=None
201		self.is_valid=False
202		self.is_done=False
203		self.compiler=compiler
204		self.cpu=cpu
205		self.version=version
206		self.bat_target=bat_target
207		self.bat=bat
208		self.callback=callback
209	def evaluate(self):
210		if self.is_done:
211			return
212		self.is_done=True
213		try:
214			vs=self.conf.get_msvc_version(self.compiler,self.version,self.bat_target,self.bat)
215		except Errors.ConfigurationError:
216			self.is_valid=False
217			return
218		if self.callback:
219			vs=self.callback(self,vs)
220		self.is_valid=True
221		(self.bindirs,self.incdirs,self.libdirs)=vs
222	def __str__(self):
223		return str((self.compiler,self.cpu,self.version,self.bat_target,self.bat))
224	def __repr__(self):
225		return repr((self.compiler,self.cpu,self.version,self.bat_target,self.bat))
226@conf
227def gather_wsdk_versions(conf,versions):
228	version_pattern=re.compile('^v..?.?\...?.?')
229	try:
230		all_versions=Utils.winreg.OpenKey(Utils.winreg.HKEY_LOCAL_MACHINE,'SOFTWARE\\Wow6432node\\Microsoft\\Microsoft SDKs\\Windows')
231	except OSError:
232		try:
233			all_versions=Utils.winreg.OpenKey(Utils.winreg.HKEY_LOCAL_MACHINE,'SOFTWARE\\Microsoft\\Microsoft SDKs\\Windows')
234		except OSError:
235			return
236	index=0
237	while 1:
238		try:
239			version=Utils.winreg.EnumKey(all_versions,index)
240		except OSError:
241			break
242		index+=1
243		if not version_pattern.match(version):
244			continue
245		try:
246			msvc_version=Utils.winreg.OpenKey(all_versions,version)
247			path,type=Utils.winreg.QueryValueEx(msvc_version,'InstallationFolder')
248		except OSError:
249			continue
250		if path and os.path.isfile(os.path.join(path,'bin','SetEnv.cmd')):
251			targets={}
252			for target,arch in all_msvc_platforms:
253				targets[target]=target_compiler(conf,'wsdk',arch,version,'/'+target,os.path.join(path,'bin','SetEnv.cmd'))
254			versions['wsdk '+version[1:]]=targets
255@conf
256def gather_msvc_targets(conf,versions,version,vc_path):
257	targets={}
258	if os.path.isfile(os.path.join(vc_path,'VC','Auxiliary','Build','vcvarsall.bat')):
259		for target,realtarget in all_msvc_platforms[::-1]:
260			targets[target]=target_compiler(conf,'msvc',realtarget,version,target,os.path.join(vc_path,'VC','Auxiliary','Build','vcvarsall.bat'))
261	elif os.path.isfile(os.path.join(vc_path,'vcvarsall.bat')):
262		for target,realtarget in all_msvc_platforms[::-1]:
263			targets[target]=target_compiler(conf,'msvc',realtarget,version,target,os.path.join(vc_path,'vcvarsall.bat'))
264	elif os.path.isfile(os.path.join(vc_path,'Common7','Tools','vsvars32.bat')):
265		targets['x86']=target_compiler(conf,'msvc','x86',version,'x86',os.path.join(vc_path,'Common7','Tools','vsvars32.bat'))
266	elif os.path.isfile(os.path.join(vc_path,'Bin','vcvars32.bat')):
267		targets['x86']=target_compiler(conf,'msvc','x86',version,'',os.path.join(vc_path,'Bin','vcvars32.bat'))
268	if targets:
269		versions['msvc %s'%version]=targets
270@conf
271def gather_wince_targets(conf,versions,version,vc_path,vsvars,supported_platforms):
272	for device,platforms in supported_platforms:
273		targets={}
274		for platform,compiler,include,lib in platforms:
275			winCEpath=os.path.join(vc_path,'ce')
276			if not os.path.isdir(winCEpath):
277				continue
278			if os.path.isdir(os.path.join(winCEpath,'lib',platform)):
279				bindirs=[os.path.join(winCEpath,'bin',compiler),os.path.join(winCEpath,'bin','x86_'+compiler)]
280				incdirs=[os.path.join(winCEpath,'include'),os.path.join(winCEpath,'atlmfc','include'),include]
281				libdirs=[os.path.join(winCEpath,'lib',platform),os.path.join(winCEpath,'atlmfc','lib',platform),lib]
282				def combine_common(obj,compiler_env):
283					(common_bindirs,_1,_2)=compiler_env
284					return(bindirs+common_bindirs,incdirs,libdirs)
285				targets[platform]=target_compiler(conf,'msvc',platform,version,'x86',vsvars,combine_common)
286		if targets:
287			versions[device+' '+version]=targets
288@conf
289def gather_winphone_targets(conf,versions,version,vc_path,vsvars):
290	targets={}
291	for target,realtarget in all_msvc_platforms[::-1]:
292		targets[target]=target_compiler(conf,'winphone',realtarget,version,target,vsvars)
293	if targets:
294		versions['winphone '+version]=targets
295@conf
296def gather_vswhere_versions(conf,versions):
297	try:
298		import json
299	except ImportError:
300		Logs.error('Visual Studio 2017 detection requires Python 2.6')
301		return
302	prg_path=os.environ.get('ProgramFiles(x86)',os.environ.get('ProgramFiles','C:\\Program Files (x86)'))
303	vswhere=os.path.join(prg_path,'Microsoft Visual Studio','Installer','vswhere.exe')
304	args=[vswhere,'-products','*','-legacy','-format','json']
305	try:
306		txt=conf.cmd_and_log(args)
307	except Errors.WafError as e:
308		Logs.debug('msvc: vswhere.exe failed %s',e)
309		return
310	if sys.version_info[0]<3:
311		txt=txt.decode(Utils.console_encoding())
312	arr=json.loads(txt)
313	arr.sort(key=lambda x:x['installationVersion'])
314	for entry in arr:
315		ver=entry['installationVersion']
316		ver=str('.'.join(ver.split('.')[:2]))
317		path=str(os.path.abspath(entry['installationPath']))
318		if os.path.exists(path)and('msvc %s'%ver)not in versions:
319			conf.gather_msvc_targets(versions,ver,path)
320@conf
321def gather_msvc_versions(conf,versions):
322	vc_paths=[]
323	for(v,version,reg)in gather_msvc_detected_versions():
324		try:
325			try:
326				msvc_version=Utils.winreg.OpenKey(Utils.winreg.HKEY_LOCAL_MACHINE,reg+"\\Setup\\VC")
327			except OSError:
328				msvc_version=Utils.winreg.OpenKey(Utils.winreg.HKEY_LOCAL_MACHINE,reg+"\\Setup\\Microsoft Visual C++")
329			path,type=Utils.winreg.QueryValueEx(msvc_version,'ProductDir')
330		except OSError:
331			try:
332				msvc_version=Utils.winreg.OpenKey(Utils.winreg.HKEY_LOCAL_MACHINE,"SOFTWARE\\Wow6432node\\Microsoft\\VisualStudio\\SxS\\VS7")
333				path,type=Utils.winreg.QueryValueEx(msvc_version,version)
334			except OSError:
335				continue
336			else:
337				vc_paths.append((version,os.path.abspath(str(path))))
338			continue
339		else:
340			vc_paths.append((version,os.path.abspath(str(path))))
341	wince_supported_platforms=gather_wince_supported_platforms()
342	for version,vc_path in vc_paths:
343		vs_path=os.path.dirname(vc_path)
344		vsvars=os.path.join(vs_path,'Common7','Tools','vsvars32.bat')
345		if wince_supported_platforms and os.path.isfile(vsvars):
346			conf.gather_wince_targets(versions,version,vc_path,vsvars,wince_supported_platforms)
347	for version,vc_path in vc_paths:
348		vs_path=os.path.dirname(vc_path)
349		vsvars=os.path.join(vs_path,'VC','WPSDK','WP80','vcvarsphoneall.bat')
350		if os.path.isfile(vsvars):
351			conf.gather_winphone_targets(versions,'8.0',vc_path,vsvars)
352			break
353	for version,vc_path in vc_paths:
354		vs_path=os.path.dirname(vc_path)
355		conf.gather_msvc_targets(versions,version,vc_path)
356@conf
357def gather_icl_versions(conf,versions):
358	version_pattern=re.compile('^...?.?\....?.?')
359	try:
360		all_versions=Utils.winreg.OpenKey(Utils.winreg.HKEY_LOCAL_MACHINE,'SOFTWARE\\Wow6432node\\Intel\\Compilers\\C++')
361	except OSError:
362		try:
363			all_versions=Utils.winreg.OpenKey(Utils.winreg.HKEY_LOCAL_MACHINE,'SOFTWARE\\Intel\\Compilers\\C++')
364		except OSError:
365			return
366	index=0
367	while 1:
368		try:
369			version=Utils.winreg.EnumKey(all_versions,index)
370		except OSError:
371			break
372		index+=1
373		if not version_pattern.match(version):
374			continue
375		targets={}
376		for target,arch in all_icl_platforms:
377			if target=='intel64':
378				targetDir='EM64T_NATIVE'
379			else:
380				targetDir=target
381			try:
382				Utils.winreg.OpenKey(all_versions,version+'\\'+targetDir)
383				icl_version=Utils.winreg.OpenKey(all_versions,version)
384				path,type=Utils.winreg.QueryValueEx(icl_version,'ProductDir')
385			except OSError:
386				pass
387			else:
388				batch_file=os.path.join(path,'bin','iclvars.bat')
389				if os.path.isfile(batch_file):
390					targets[target]=target_compiler(conf,'intel',arch,version,target,batch_file)
391		for target,arch in all_icl_platforms:
392			try:
393				icl_version=Utils.winreg.OpenKey(all_versions,version+'\\'+target)
394				path,type=Utils.winreg.QueryValueEx(icl_version,'ProductDir')
395			except OSError:
396				continue
397			else:
398				batch_file=os.path.join(path,'bin','iclvars.bat')
399				if os.path.isfile(batch_file):
400					targets[target]=target_compiler(conf,'intel',arch,version,target,batch_file)
401		major=version[0:2]
402		versions['intel '+major]=targets
403@conf
404def gather_intel_composer_versions(conf,versions):
405	version_pattern=re.compile('^...?.?\...?.?.?')
406	try:
407		all_versions=Utils.winreg.OpenKey(Utils.winreg.HKEY_LOCAL_MACHINE,'SOFTWARE\\Wow6432node\\Intel\\Suites')
408	except OSError:
409		try:
410			all_versions=Utils.winreg.OpenKey(Utils.winreg.HKEY_LOCAL_MACHINE,'SOFTWARE\\Intel\\Suites')
411		except OSError:
412			return
413	index=0
414	while 1:
415		try:
416			version=Utils.winreg.EnumKey(all_versions,index)
417		except OSError:
418			break
419		index+=1
420		if not version_pattern.match(version):
421			continue
422		targets={}
423		for target,arch in all_icl_platforms:
424			if target=='intel64':
425				targetDir='EM64T_NATIVE'
426			else:
427				targetDir=target
428			try:
429				try:
430					defaults=Utils.winreg.OpenKey(all_versions,version+'\\Defaults\\C++\\'+targetDir)
431				except OSError:
432					if targetDir=='EM64T_NATIVE':
433						defaults=Utils.winreg.OpenKey(all_versions,version+'\\Defaults\\C++\\EM64T')
434					else:
435						raise
436				uid,type=Utils.winreg.QueryValueEx(defaults,'SubKey')
437				Utils.winreg.OpenKey(all_versions,version+'\\'+uid+'\\C++\\'+targetDir)
438				icl_version=Utils.winreg.OpenKey(all_versions,version+'\\'+uid+'\\C++')
439				path,type=Utils.winreg.QueryValueEx(icl_version,'ProductDir')
440			except OSError:
441				pass
442			else:
443				batch_file=os.path.join(path,'bin','iclvars.bat')
444				if os.path.isfile(batch_file):
445					targets[target]=target_compiler(conf,'intel',arch,version,target,batch_file)
446				compilervars_warning_attr='_compilervars_warning_key'
447				if version[0:2]=='13'and getattr(conf,compilervars_warning_attr,True):
448					setattr(conf,compilervars_warning_attr,False)
449					patch_url='http://software.intel.com/en-us/forums/topic/328487'
450					compilervars_arch=os.path.join(path,'bin','compilervars_arch.bat')
451					for vscomntool in('VS110COMNTOOLS','VS100COMNTOOLS'):
452						if vscomntool in os.environ:
453							vs_express_path=os.environ[vscomntool]+r'..\IDE\VSWinExpress.exe'
454							dev_env_path=os.environ[vscomntool]+r'..\IDE\devenv.exe'
455							if(r'if exist "%VS110COMNTOOLS%..\IDE\VSWinExpress.exe"'in Utils.readf(compilervars_arch)and not os.path.exists(vs_express_path)and not os.path.exists(dev_env_path)):
456								Logs.warn(('The Intel compilervar_arch.bat only checks for one Visual Studio SKU ''(VSWinExpress.exe) but it does not seem to be installed at %r. ''The intel command line set up will fail to configure unless the file %r''is patched. See: %s')%(vs_express_path,compilervars_arch,patch_url))
457		major=version[0:2]
458		versions['intel '+major]=targets
459@conf
460def detect_msvc(self):
461	return self.setup_msvc(self.get_msvc_versions())
462@conf
463def get_msvc_versions(self):
464	dct=Utils.ordered_iter_dict()
465	self.gather_icl_versions(dct)
466	self.gather_intel_composer_versions(dct)
467	self.gather_wsdk_versions(dct)
468	self.gather_msvc_versions(dct)
469	self.gather_vswhere_versions(dct)
470	Logs.debug('msvc: detected versions %r',list(dct.keys()))
471	return dct
472@conf
473def find_lt_names_msvc(self,libname,is_static=False):
474	lt_names=['lib%s.la'%libname,'%s.la'%libname,]
475	for path in self.env.LIBPATH:
476		for la in lt_names:
477			laf=os.path.join(path,la)
478			dll=None
479			if os.path.exists(laf):
480				ltdict=Utils.read_la_file(laf)
481				lt_libdir=None
482				if ltdict.get('libdir',''):
483					lt_libdir=ltdict['libdir']
484				if not is_static and ltdict.get('library_names',''):
485					dllnames=ltdict['library_names'].split()
486					dll=dllnames[0].lower()
487					dll=re.sub('\.dll$','',dll)
488					return(lt_libdir,dll,False)
489				elif ltdict.get('old_library',''):
490					olib=ltdict['old_library']
491					if os.path.exists(os.path.join(path,olib)):
492						return(path,olib,True)
493					elif lt_libdir!=''and os.path.exists(os.path.join(lt_libdir,olib)):
494						return(lt_libdir,olib,True)
495					else:
496						return(None,olib,True)
497				else:
498					raise self.errors.WafError('invalid libtool object file: %s'%laf)
499	return(None,None,None)
500@conf
501def libname_msvc(self,libname,is_static=False):
502	lib=libname.lower()
503	lib=re.sub('\.lib$','',lib)
504	if lib in g_msvc_systemlibs:
505		return lib
506	lib=re.sub('^lib','',lib)
507	if lib=='m':
508		return None
509	(lt_path,lt_libname,lt_static)=self.find_lt_names_msvc(lib,is_static)
510	if lt_path!=None and lt_libname!=None:
511		if lt_static:
512			return os.path.join(lt_path,lt_libname)
513	if lt_path!=None:
514		_libpaths=[lt_path]+self.env.LIBPATH
515	else:
516		_libpaths=self.env.LIBPATH
517	static_libs=['lib%ss.lib'%lib,'lib%s.lib'%lib,'%ss.lib'%lib,'%s.lib'%lib,]
518	dynamic_libs=['lib%s.dll.lib'%lib,'lib%s.dll.a'%lib,'%s.dll.lib'%lib,'%s.dll.a'%lib,'lib%s_d.lib'%lib,'%s_d.lib'%lib,'%s.lib'%lib,]
519	libnames=static_libs
520	if not is_static:
521		libnames=dynamic_libs+static_libs
522	for path in _libpaths:
523		for libn in libnames:
524			if os.path.exists(os.path.join(path,libn)):
525				Logs.debug('msvc: lib found: %s',os.path.join(path,libn))
526				return re.sub('\.lib$','',libn)
527	self.fatal('The library %r could not be found'%libname)
528	return re.sub('\.lib$','',libname)
529@conf
530def check_lib_msvc(self,libname,is_static=False,uselib_store=None):
531	libn=self.libname_msvc(libname,is_static)
532	if not uselib_store:
533		uselib_store=libname.upper()
534	if False and is_static:
535		self.env['STLIB_'+uselib_store]=[libn]
536	else:
537		self.env['LIB_'+uselib_store]=[libn]
538@conf
539def check_libs_msvc(self,libnames,is_static=False):
540	for libname in Utils.to_list(libnames):
541		self.check_lib_msvc(libname,is_static)
542def configure(conf):
543	conf.autodetect(True)
544	conf.find_msvc()
545	conf.msvc_common_flags()
546	conf.cc_load_tools()
547	conf.cxx_load_tools()
548	conf.cc_add_flags()
549	conf.cxx_add_flags()
550	conf.link_add_flags()
551	conf.visual_studio_add_flags()
552@conf
553def no_autodetect(conf):
554	conf.env.NO_MSVC_DETECT=1
555	configure(conf)
556@conf
557def autodetect(conf,arch=False):
558	v=conf.env
559	if v.NO_MSVC_DETECT:
560		return
561	compiler,version,path,includes,libdirs,cpu=conf.detect_msvc()
562	if arch:
563		v.DEST_CPU=cpu
564	v.PATH=path
565	v.INCLUDES=includes
566	v.LIBPATH=libdirs
567	v.MSVC_COMPILER=compiler
568	try:
569		v.MSVC_VERSION=float(version)
570	except ValueError:
571		v.MSVC_VERSION=float(version[:-3])
572def _get_prog_names(conf,compiler):
573	if compiler=='intel':
574		compiler_name='ICL'
575		linker_name='XILINK'
576		lib_name='XILIB'
577	else:
578		compiler_name='CL'
579		linker_name='LINK'
580		lib_name='LIB'
581	return compiler_name,linker_name,lib_name
582@conf
583def find_msvc(conf):
584	if sys.platform=='cygwin':
585		conf.fatal('MSVC module does not work under cygwin Python!')
586	v=conf.env
587	path=v.PATH
588	compiler=v.MSVC_COMPILER
589	version=v.MSVC_VERSION
590	compiler_name,linker_name,lib_name=_get_prog_names(conf,compiler)
591	v.MSVC_MANIFEST=(compiler=='msvc'and version>=8)or(compiler=='wsdk'and version>=6)or(compiler=='intel'and version>=11)
592	cxx=conf.find_program(compiler_name,var='CXX',path_list=path)
593	env=dict(conf.environ)
594	if path:
595		env.update(PATH=';'.join(path))
596	if not conf.cmd_and_log(cxx+['/nologo','/help'],env=env):
597		conf.fatal('the msvc compiler could not be identified')
598	v.CC=v.CXX=cxx
599	v.CC_NAME=v.CXX_NAME='msvc'
600	if not v.LINK_CXX:
601		conf.find_program(linker_name,path_list=path,errmsg='%s was not found (linker)'%linker_name,var='LINK_CXX')
602	if not v.LINK_CC:
603		v.LINK_CC=v.LINK_CXX
604	if not v.AR:
605		stliblink=conf.find_program(lib_name,path_list=path,var='AR')
606		if not stliblink:
607			return
608		v.ARFLAGS=['/nologo']
609	if v.MSVC_MANIFEST:
610		conf.find_program('MT',path_list=path,var='MT')
611		v.MTFLAGS=['/nologo']
612	try:
613		conf.load('winres')
614	except Errors.ConfigurationError:
615		Logs.warn('Resource compiler not found. Compiling resource file is disabled')
616@conf
617def visual_studio_add_flags(self):
618	v=self.env
619	if self.environ.get('INCLUDE'):
620		v.prepend_value('INCLUDES',[x for x in self.environ['INCLUDE'].split(';')if x])
621	if self.environ.get('LIB'):
622		v.prepend_value('LIBPATH',[x for x in self.environ['LIB'].split(';')if x])
623@conf
624def msvc_common_flags(conf):
625	v=conf.env
626	v.DEST_BINFMT='pe'
627	v.append_value('CFLAGS',['/nologo'])
628	v.append_value('CXXFLAGS',['/nologo'])
629	v.append_value('LINKFLAGS',['/nologo'])
630	v.DEFINES_ST='/D%s'
631	v.CC_SRC_F=''
632	v.CC_TGT_F=['/c','/Fo']
633	v.CXX_SRC_F=''
634	v.CXX_TGT_F=['/c','/Fo']
635	if(v.MSVC_COMPILER=='msvc'and v.MSVC_VERSION>=8)or(v.MSVC_COMPILER=='wsdk'and v.MSVC_VERSION>=6):
636		v.CC_TGT_F=['/FC']+v.CC_TGT_F
637		v.CXX_TGT_F=['/FC']+v.CXX_TGT_F
638	v.CPPPATH_ST='/I%s'
639	v.AR_TGT_F=v.CCLNK_TGT_F=v.CXXLNK_TGT_F='/OUT:'
640	v.CFLAGS_CRT_MULTITHREADED=v.CXXFLAGS_CRT_MULTITHREADED=['/MT']
641	v.CFLAGS_CRT_MULTITHREADED_DLL=v.CXXFLAGS_CRT_MULTITHREADED_DLL=['/MD']
642	v.CFLAGS_CRT_MULTITHREADED_DBG=v.CXXFLAGS_CRT_MULTITHREADED_DBG=['/MTd']
643	v.CFLAGS_CRT_MULTITHREADED_DLL_DBG=v.CXXFLAGS_CRT_MULTITHREADED_DLL_DBG=['/MDd']
644	v.LIB_ST='%s.lib'
645	v.LIBPATH_ST='/LIBPATH:%s'
646	v.STLIB_ST='%s.lib'
647	v.STLIBPATH_ST='/LIBPATH:%s'
648	if v.MSVC_MANIFEST:
649		v.append_value('LINKFLAGS',['/MANIFEST'])
650	v.CFLAGS_cshlib=[]
651	v.CXXFLAGS_cxxshlib=[]
652	v.LINKFLAGS_cshlib=v.LINKFLAGS_cxxshlib=['/DLL']
653	v.cshlib_PATTERN=v.cxxshlib_PATTERN='%s.dll'
654	v.implib_PATTERN='%s.lib'
655	v.IMPLIB_ST='/IMPLIB:%s'
656	v.LINKFLAGS_cstlib=[]
657	v.cstlib_PATTERN=v.cxxstlib_PATTERN='%s.lib'
658	v.cprogram_PATTERN=v.cxxprogram_PATTERN='%s.exe'
659	v.def_PATTERN='/def:%s'
660@after_method('apply_link')
661@feature('c','cxx')
662def apply_flags_msvc(self):
663	if self.env.CC_NAME!='msvc'or not getattr(self,'link_task',None):
664		return
665	is_static=isinstance(self.link_task,ccroot.stlink_task)
666	subsystem=getattr(self,'subsystem','')
667	if subsystem:
668		subsystem='/subsystem:%s'%subsystem
669		flags=is_static and'ARFLAGS'or'LINKFLAGS'
670		self.env.append_value(flags,subsystem)
671	if not is_static:
672		for f in self.env.LINKFLAGS:
673			d=f.lower()
674			if d[1:]=='debug':
675				pdbnode=self.link_task.outputs[0].change_ext('.pdb')
676				self.link_task.outputs.append(pdbnode)
677				if getattr(self,'install_task',None):
678					self.pdb_install_task=self.add_install_files(install_to=self.install_task.install_to,install_from=pdbnode)
679				break
680@feature('cprogram','cshlib','cxxprogram','cxxshlib')
681@after_method('apply_link')
682def apply_manifest(self):
683	if self.env.CC_NAME=='msvc'and self.env.MSVC_MANIFEST and getattr(self,'link_task',None):
684		out_node=self.link_task.outputs[0]
685		man_node=out_node.parent.find_or_declare(out_node.name+'.manifest')
686		self.link_task.outputs.append(man_node)
687		self.env.DO_MANIFEST=True
688def make_winapp(self,family):
689	append=self.env.append_unique
690	append('DEFINES','WINAPI_FAMILY=%s'%family)
691	append('CXXFLAGS',['/ZW','/TP'])
692	for lib_path in self.env.LIBPATH:
693		append('CXXFLAGS','/AI%s'%lib_path)
694@feature('winphoneapp')
695@after_method('process_use')
696@after_method('propagate_uselib_vars')
697def make_winphone_app(self):
698	make_winapp(self,'WINAPI_FAMILY_PHONE_APP')
699	self.env.append_unique('LINKFLAGS',['/NODEFAULTLIB:ole32.lib','PhoneAppModelHost.lib'])
700@feature('winapp')
701@after_method('process_use')
702@after_method('propagate_uselib_vars')
703def make_windows_app(self):
704	make_winapp(self,'WINAPI_FAMILY_DESKTOP_APP')
705