3 # WARNING! Do not edit! https://waf.io/book/index.html#_obtaining_the_waf_file
7 # Carlos Rafael Giani, 2006 (dv)
8 # Tamas Pal, 2007 (folti)
9 # Nicolas Mercier, 2009
13 Microsoft Visual C++/Intel C++ compiler support
17 $ waf configure --msvc_version="msvc 10.0,msvc 9.0" --msvc_target="x64"
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']
29 conf.load('msvc', funs='no_autodetect')
30 conf.check_lib_msvc('gdi32')
31 conf.check_libs_msvc('kernel32 user32')
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
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.
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
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"""
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')
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:
128 for val
in versiondict
.values():
129 for arch
in list(val
.keys()):
134 conf
.env
.MSVC_INSTALLED_VERSIONS
= versiondict
136 for version
in desired_versions
:
138 targets
= versiondict
[version
]
141 for arch
in platforms
:
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())))
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
)
169 except AttributeError:
171 batfile
= conf
.bldnode
.make_node('waf-print-msvc-%d.bat' % conf
.msvc_cnt
)
172 batfile
.write("""@echo off
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()
186 MSVC_PATH
= MSVC_INCDIR
= MSVC_LIBDIR
= None
188 if line
.startswith('PATH='):
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.
210 conf
.cmd_and_log(cxx
+ ['/help'], env
=env
)
212 st
= Utils
.ex_stack()
214 conf
.logger
.error(st
)
215 conf
.fatal('msvc: Unicode error - check the code page?')
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)')
220 Logs
.debug('msvc: get_msvc_version: %r %r %r -> OK', compiler
, version
, target
)
222 conf
.env
[compiler_name
] = ''
224 return (MSVC_PATH
, MSVC_INCDIR
, MSVC_LIBDIR
)
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
234 version_pattern
= re
.compile('^v..?.?\...?.?')
236 all_versions
= Utils
.winreg
.OpenKey(Utils
.winreg
.HKEY_LOCAL_MACHINE
, 'SOFTWARE\\Wow6432node\\Microsoft\\Microsoft SDKs\\Windows')
239 all_versions
= Utils
.winreg
.OpenKey(Utils
.winreg
.HKEY_LOCAL_MACHINE
, 'SOFTWARE\\Microsoft\\Microsoft SDKs\\Windows')
245 version
= Utils
.winreg
.EnumKey(all_versions
, index
)
249 if not version_pattern
.match(version
):
252 msvc_version
= Utils
.winreg
.OpenKey(all_versions
, version
)
253 path
,type = Utils
.winreg
.QueryValueEx(msvc_version
,'InstallationFolder')
256 if path
and os
.path
.isfile(os
.path
.join(path
, 'bin', 'SetEnv.cmd')):
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
269 supported_wince_platforms
= []
271 ce_sdk
= Utils
.winreg
.OpenKey(Utils
.winreg
.HKEY_LOCAL_MACHINE
, 'SOFTWARE\\Wow6432node\\Microsoft\\Windows CE Tools\\SDKs')
274 ce_sdk
= Utils
.winreg
.OpenKey(Utils
.winreg
.HKEY_LOCAL_MACHINE
, 'SOFTWARE\\Microsoft\\Windows CE Tools\\SDKs')
278 return supported_wince_platforms
283 sdk_device
= Utils
.winreg
.EnumKey(ce_sdk
, index
)
284 sdk
= Utils
.winreg
.OpenKey(ce_sdk
, sdk_device
)
289 path
,type = Utils
.winreg
.QueryValueEx(sdk
, 'SDKRootDir')
292 path
,type = Utils
.winreg
.QueryValueEx(sdk
,'SDKInformation')
295 path
,xml
= os
.path
.split(path
)
297 path
,device
= os
.path
.split(path
)
299 path
,device
= os
.path
.split(path
)
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
)))
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
315 all_versions
= Utils
.winreg
.OpenKey(Utils
.winreg
.HKEY_LOCAL_MACHINE
, prefix
)
317 prefix
= 'SOFTWARE\\Microsoft\\' + vcver
319 all_versions
= Utils
.winreg
.OpenKey(Utils
.winreg
.HKEY_LOCAL_MACHINE
, prefix
)
326 version
= Utils
.winreg
.EnumKey(all_versions
, index
)
330 match
= version_pattern
.match(version
)
332 versionnumber
= float(match
.group(1))
335 detected_versions
.append((versionnumber
, version
+vcvar
, prefix
+'\\'+version
))
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
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)
359 self
.is_valid
= False
362 self
.compiler
= compiler
364 self
.version
= version
365 self
.bat_target
= bat_target
367 self
.callback
= callback
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
379 vs
= self
.callback(self
, vs
)
381 (self
.bindirs
, self
.incdirs
, self
.libdirs
) = vs
384 return str((self
.bindirs
, self
.incdirs
, self
.libdirs
))
387 return repr((self
.bindirs
, self
.incdirs
, self
.libdirs
))
390 def gather_msvc_targets(conf
, versions
, version
, vc_path
):
391 #Looking for normal MSVC compilers!
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'))
405 versions
['msvc ' + version
] = targets
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
:
412 for platform
,compiler
,include
,lib
in platforms
:
413 winCEpath
= os
.path
.join(vc_path
, 'ce')
414 if not os
.path
.isdir(winCEpath
):
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
)
426 versions
[device
+ ' ' + version
] = targets
429 def gather_winphone_targets(conf
, versions
, version
, vc_path
, vsvars
):
430 #Looking for WinPhone compilers
432 for target
,realtarget
in all_msvc_platforms
[::-1]:
433 targets
[target
] = target_compiler(conf
, 'winphone', realtarget
, version
, target
, vsvars
)
435 versions
['winphone ' + version
] = targets
438 def gather_msvc_versions(conf
, versions
):
440 for (v
,version
,reg
) in gather_msvc_detected_versions():
443 msvc_version
= Utils
.winreg
.OpenKey(Utils
.winreg
.HKEY_LOCAL_MACHINE
, reg
+ "\\Setup\\VC")
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')
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
)
454 vc_paths
.append((version
, os
.path
.abspath(str(path
))))
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
)
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
)
481 def gather_icl_versions(conf
, versions
):
485 :param versions: list to modify
488 version_pattern
= re
.compile('^...?.?\....?.?')
490 all_versions
= Utils
.winreg
.OpenKey(Utils
.winreg
.HKEY_LOCAL_MACHINE
, 'SOFTWARE\\Wow6432node\\Intel\\Compilers\\C++')
493 all_versions
= Utils
.winreg
.OpenKey(Utils
.winreg
.HKEY_LOCAL_MACHINE
, 'SOFTWARE\\Intel\\Compilers\\C++')
499 version
= Utils
.winreg
.EnumKey(all_versions
, index
)
503 if not version_pattern
.match(version
):
506 for target
,arch
in all_icl_platforms
:
507 if target
=='intel64': targetDir
='EM64T_NATIVE'
508 else: targetDir
=target
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')
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
:
521 icl_version
= Utils
.winreg
.OpenKey(all_versions
, version
+'\\'+target
)
522 path
,type = Utils
.winreg
.QueryValueEx(icl_version
,'ProductDir')
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
)
530 versions
['intel ' + major
] = targets
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
540 version_pattern
= re
.compile('^...?.?\...?.?.?')
542 all_versions
= Utils
.winreg
.OpenKey(Utils
.winreg
.HKEY_LOCAL_MACHINE
, 'SOFTWARE\\Wow6432node\\Intel\\Suites')
545 all_versions
= Utils
.winreg
.OpenKey(Utils
.winreg
.HKEY_LOCAL_MACHINE
, 'SOFTWARE\\Intel\\Suites')
551 version
= Utils
.winreg
.EnumKey(all_versions
, index
)
555 if not version_pattern
.match(version
):
558 for target
,arch
in all_icl_platforms
:
559 if target
=='intel64': targetDir
='EM64T_NATIVE'
560 else: targetDir
=target
563 defaults
= Utils
.winreg
.OpenKey(all_versions
,version
+'\\Defaults\\C++\\'+targetDir
)
565 if targetDir
== 'EM64T_NATIVE':
566 defaults
= Utils
.winreg
.OpenKey(all_versions
,version
+'\\Defaults\\C++\\EM64T')
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')
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
))
597 versions
['intel ' + major
] = targets
600 def detect_msvc(self
):
601 return self
.setup_msvc(self
.get_msvc_versions())
604 def get_msvc_versions(self
):
606 :return: platform to compiler configurations
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()))
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)
625 'lib%s.la' % libname
,
629 for path
in self
.env
.LIBPATH
:
631 laf
=os
.path
.join(path
,la
)
633 if os
.path
.exists(laf
):
634 ltdict
= Utils
.read_la_file(laf
)
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)
650 return (None, olib
, True)
652 raise self
.errors
.WafError('invalid libtool object file: %s' % laf
)
653 return (None, None, None)
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
:
663 lib
=re
.sub('^lib','',lib
)
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
)
676 _libpaths
= [lt_path
] + self
.env
.LIBPATH
678 _libpaths
= self
.env
.LIBPATH
688 'lib%s.dll.lib' % lib
,
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
)
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
)
721 uselib_store
= libname
.upper()
723 if False and is_static
: # disabled
724 self
.env
['STLIB_' + uselib_store
] = [libn
]
726 self
.env
['LIB_' + uselib_store
] = [libn
]
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
)
735 Configuration methods to call for detecting msvc
737 conf
.autodetect(True)
739 conf
.msvc_common_flags()
741 conf
.cxx_load_tools()
744 conf
.link_add_flags()
745 conf
.visual_studio_add_flags()
748 def no_autodetect(conf
):
749 conf
.env
.NO_MSVC_DETECT
= 1
753 def autodetect(conf
, arch
=False):
758 compiler
, version
, path
, includes
, libdirs
, cpu
= conf
.detect_msvc()
763 v
.INCLUDES
= includes
765 v
.MSVC_COMPILER
= compiler
767 v
.MSVC_VERSION
= float(version
)
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'
781 return compiler_name
, linker_name
, lib_name
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
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)
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')
809 v
.CC_NAME
= v
.CXX_NAME
= 'msvc'
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
)
817 v
.LINK_CC
= v
.LINK_CXX
821 stliblink
= conf
.find_program(lib_name
, path_list
=path
, var
='AR')
824 v
.ARFLAGS
= ['/nologo']
826 # manifest tool. Not required for VS 2003 and below. Must have for VS 2005 and later
828 conf
.find_program('MT', path_list
=path
, var
='MT')
829 v
.MTFLAGS
= ['/nologo']
833 except Errors
.ConfigurationError
:
834 Logs
.warn('Resource compiler not found. Compiling resource file is disabled')
837 def visual_studio_add_flags(self
):
838 """visual studio flags found in the system environment"""
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
])
846 def msvc_common_flags(conf
):
848 Setup the flags required for executing the msvc compiler
853 v
.append_value('CFLAGS', ['/nologo'])
854 v
.append_value('CXXFLAGS', ['/nologo'])
855 v
.append_value('LINKFLAGS', ['/nologo'])
856 v
.DEFINES_ST
= '/D%s'
859 v
.CC_TGT_F
= ['/c', '/Fo']
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']
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']
886 v
.LIBPATH_ST
= '/LIBPATH:%s'
887 v
.STLIB_ST
= '%s.lib'
888 v
.STLIBPATH_ST
= '/LIBPATH:%s'
891 v
.append_value('LINKFLAGS', ['/MANIFEST'])
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')
911 def apply_flags_msvc(self
):
913 Add additional flags implied by msvc, such as subsystems and pdb files::
916 bld.stlib(source='main.c', target='bar', subsystem='gruik')
918 if self
.env
.CC_NAME
!= 'msvc' or not getattr(self
, 'link_task', None):
921 is_static
= isinstance(self
.link_task
, ccroot
.stlink_task
)
923 subsystem
= getattr(self
, 'subsystem', '')
925 subsystem
= '/subsystem:%s' % subsystem
926 flags
= is_static
and 'ARFLAGS' or 'LINKFLAGS'
927 self
.env
.append_value(flags
, subsystem
)
930 for f
in self
.env
.LINKFLAGS
:
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
)
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'])
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')