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