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