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 15 (Visual Studio 2017)
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.
59 import os, sys, re, traceback
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(reversed(sorted(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:
137 Logs.debug('msvc: detecting %r - %r', version, desired_versions)
139 targets = versiondict[version]
144 for arch in platforms:
156 compiler,revision = version.rsplit(' ', 1)
157 return compiler,revision,cfg.bindirs,cfg.incdirs,cfg.libdirs,cfg.cpu
158 conf.fatal('msvc: Impossible to find a valid architecture for building %r - %r' % (desired_versions, list(versiondict.keys())))
161 def get_msvc_version(conf, compiler, version, target, vcvars):
163 Checks that an installed compiler actually runs and uses vcvars to obtain the
164 environment needed by the compiler.
166 :param compiler: compiler type, for looking up the executable name
167 :param version: compiler version, for debugging only
168 :param target: target architecture
169 :param vcvars: batch file to run to check the environment
170 :return: the location of the compiler executable, the location of include dirs, and the library paths
171 :rtype: tuple of strings
173 Logs.debug('msvc: get_msvc_version: %r %r %r', compiler, version, target)
177 except AttributeError:
179 batfile = conf.bldnode.make_node('waf-print-msvc-%d.bat' % conf.msvc_cnt)
180 batfile.write("""@echo off
185 echo INCLUDE=%%INCLUDE%%
186 echo LIB=%%LIB%%;%%LIBPATH%%
187 """ % (vcvars,target))
188 sout = conf.cmd_and_log(['cmd.exe', '/E:on', '/V:on', '/C', batfile.abspath()])
189 lines = sout.splitlines()
194 MSVC_PATH = MSVC_INCDIR = MSVC_LIBDIR = None
196 if line.startswith('PATH='):
198 MSVC_PATH = path.split(';')
199 elif line.startswith('INCLUDE='):
200 MSVC_INCDIR = [i for i in line[8:].split(';') if i]
201 elif line.startswith('LIB='):
202 MSVC_LIBDIR = [i for i in line[4:].split(';') if i]
203 if None in (MSVC_PATH, MSVC_INCDIR, MSVC_LIBDIR):
204 conf.fatal('msvc: Could not find a valid architecture for building (get_msvc_version_3)')
206 # Check if the compiler is usable at all.
207 # The detection may return 64-bit versions even on 32-bit systems, and these would fail to run.
208 env = dict(os.environ)
209 env.update(PATH = path)
210 compiler_name, linker_name, lib_name = _get_prog_names(conf, compiler)
211 cxx = conf.find_program(compiler_name, path_list=MSVC_PATH)
213 # delete CL if exists. because it could contain parameters which can change cl's behaviour rather catastrophically.
218 conf.cmd_and_log(cxx + ['/help'], env=env)
220 st = traceback.format_exc()
222 conf.logger.error(st)
223 conf.fatal('msvc: Unicode error - check the code page?')
224 except Exception as e:
225 Logs.debug('msvc: get_msvc_version: %r %r %r -> failure %s', compiler, version, target, str(e))
226 conf.fatal('msvc: cannot run the compiler in get_msvc_version (run with -v to display errors)')
228 Logs.debug('msvc: get_msvc_version: %r %r %r -> OK', compiler, version, target)
230 conf.env[compiler_name] = ''
232 return (MSVC_PATH, MSVC_INCDIR, MSVC_LIBDIR)
234 def gather_wince_supported_platforms():
236 Checks SmartPhones SDKs
238 :param versions: list to modify
241 supported_wince_platforms = []
243 ce_sdk = Utils.winreg.OpenKey(Utils.winreg.HKEY_LOCAL_MACHINE, 'SOFTWARE\\Wow6432node\\Microsoft\\Windows CE Tools\\SDKs')
246 ce_sdk = Utils.winreg.OpenKey(Utils.winreg.HKEY_LOCAL_MACHINE, 'SOFTWARE\\Microsoft\\Windows CE Tools\\SDKs')
250 return supported_wince_platforms
255 sdk_device = Utils.winreg.EnumKey(ce_sdk, index)
256 sdk = Utils.winreg.OpenKey(ce_sdk, sdk_device)
261 path,type = Utils.winreg.QueryValueEx(sdk, 'SDKRootDir')
264 path,type = Utils.winreg.QueryValueEx(sdk,'SDKInformation')
267 path,xml = os.path.split(path)
269 path,device = os.path.split(path)
271 path,device = os.path.split(path)
273 for arch,compiler in all_wince_platforms:
274 if os.path.isdir(os.path.join(path, device, 'Lib', arch)):
275 platforms.append((arch, compiler, os.path.join(path, device, 'Include', arch), os.path.join(path, device, 'Lib', arch)))
277 supported_wince_platforms.append((device, platforms))
278 return supported_wince_platforms
280 def gather_msvc_detected_versions():
281 #Detected MSVC versions!
282 version_pattern = re.compile('^(\d\d?\.\d\d?)(Exp)?$')
283 detected_versions = []
284 for vcver,vcvar in (('VCExpress','Exp'), ('VisualStudio','')):
285 prefix = 'SOFTWARE\\Wow6432node\\Microsoft\\' + vcver
287 all_versions = Utils.winreg.OpenKey(Utils.winreg.HKEY_LOCAL_MACHINE, prefix)
289 prefix = 'SOFTWARE\\Microsoft\\' + vcver
291 all_versions = Utils.winreg.OpenKey(Utils.winreg.HKEY_LOCAL_MACHINE, prefix)
298 version = Utils.winreg.EnumKey(all_versions, index)
302 match = version_pattern.match(version)
304 versionnumber = float(match.group(1))
307 detected_versions.append((versionnumber, version+vcvar, prefix+'\\'+version))
311 detected_versions.sort(key = fun)
312 return detected_versions
314 class target_compiler(object):
316 Wrap a compiler configuration; call evaluate() to determine
317 whether the configuration is usable.
319 def __init__(self, ctx, compiler, cpu, version, bat_target, bat, callback=None):
321 :param ctx: configuration context to use to eventually get the version environment
322 :param compiler: compiler name
323 :param cpu: target cpu
324 :param version: compiler version number
326 :param bat: path to the batch file to run
330 self.is_valid = False
333 self.compiler = compiler
335 self.version = version
336 self.bat_target = bat_target
338 self.callback = callback
345 vs = self.conf.get_msvc_version(self.compiler, self.version, self.bat_target, self.bat)
346 except Errors.ConfigurationError:
347 self.is_valid = False
350 vs = self.callback(self, vs)
352 (self.bindirs, self.incdirs, self.libdirs) = vs
355 return str((self.compiler, self.cpu, self.version, self.bat_target, self.bat))
358 return repr((self.compiler, self.cpu, self.version, self.bat_target, self.bat))
361 def gather_wsdk_versions(conf, versions):
363 Use winreg to add the msvc versions to the input list
365 :param versions: list to modify
368 version_pattern = re.compile('^v..?.?\...?.?')
370 all_versions = Utils.winreg.OpenKey(Utils.winreg.HKEY_LOCAL_MACHINE, 'SOFTWARE\\Wow6432node\\Microsoft\\Microsoft SDKs\\Windows')
373 all_versions = Utils.winreg.OpenKey(Utils.winreg.HKEY_LOCAL_MACHINE, 'SOFTWARE\\Microsoft\\Microsoft SDKs\\Windows')
379 version = Utils.winreg.EnumKey(all_versions, index)
383 if not version_pattern.match(version):
386 msvc_version = Utils.winreg.OpenKey(all_versions, version)
387 path,type = Utils.winreg.QueryValueEx(msvc_version,'InstallationFolder')
390 if path and os.path.isfile(os.path.join(path, 'bin', 'SetEnv.cmd')):
392 for target,arch in all_msvc_platforms:
393 targets[target] = target_compiler(conf, 'wsdk', arch, version, '/'+target, os.path.join(path, 'bin', 'SetEnv.cmd'))
394 versions['wsdk ' + version[1:]] = targets
397 def gather_msvc_targets(conf, versions, version, vc_path):
398 #Looking for normal MSVC compilers!
401 if os.path.isfile(os.path.join(vc_path, 'VC', 'Auxiliary', 'Build', 'vcvarsall.bat')):
402 for target,realtarget in all_msvc_platforms[::-1]:
403 targets[target] = target_compiler(conf, 'msvc', realtarget, version, target, os.path.join(vc_path, 'VC', 'Auxiliary', 'Build', 'vcvarsall.bat'))
404 elif os.path.isfile(os.path.join(vc_path, 'vcvarsall.bat')):
405 for target,realtarget in all_msvc_platforms[::-1]:
406 targets[target] = target_compiler(conf, 'msvc', realtarget, version, target, os.path.join(vc_path, 'vcvarsall.bat'))
407 elif os.path.isfile(os.path.join(vc_path, 'Common7', 'Tools', 'vsvars32.bat')):
408 targets['x86'] = target_compiler(conf, 'msvc', 'x86', version, 'x86', os.path.join(vc_path, 'Common7', 'Tools', 'vsvars32.bat'))
409 elif os.path.isfile(os.path.join(vc_path, 'Bin', 'vcvars32.bat')):
410 targets['x86'] = target_compiler(conf, 'msvc', 'x86', version, '', os.path.join(vc_path, 'Bin', 'vcvars32.bat'))
412 versions['msvc %s' % version] = targets
415 def gather_wince_targets(conf, versions, version, vc_path, vsvars, supported_platforms):
416 #Looking for Win CE compilers!
417 for device,platforms in supported_platforms:
419 for platform,compiler,include,lib in platforms:
420 winCEpath = os.path.join(vc_path, 'ce')
421 if not os.path.isdir(winCEpath):
424 if os.path.isdir(os.path.join(winCEpath, 'lib', platform)):
425 bindirs = [os.path.join(winCEpath, 'bin', compiler), os.path.join(winCEpath, 'bin', 'x86_'+compiler)]
426 incdirs = [os.path.join(winCEpath, 'include'), os.path.join(winCEpath, 'atlmfc', 'include'), include]
427 libdirs = [os.path.join(winCEpath, 'lib', platform), os.path.join(winCEpath, 'atlmfc', 'lib', platform), lib]
428 def combine_common(obj, compiler_env):
429 # TODO this is likely broken, remove in waf 2.1
430 (common_bindirs,_1,_2) = compiler_env
431 return (bindirs + common_bindirs, incdirs, libdirs)
432 targets[platform] = target_compiler(conf, 'msvc', platform, version, 'x86', vsvars, combine_common)
434 versions[device + ' ' + version] = targets
437 def gather_winphone_targets(conf, versions, version, vc_path, vsvars):
438 #Looking for WinPhone compilers
440 for target,realtarget in all_msvc_platforms[::-1]:
441 targets[target] = target_compiler(conf, 'winphone', realtarget, version, target, vsvars)
443 versions['winphone ' + version] = targets
446 def gather_vswhere_versions(conf, versions):
450 Logs.error('Visual Studio 2017 detection requires Python 2.6')
453 prg_path = os.environ.get('ProgramFiles(x86)', os.environ.get('ProgramFiles', 'C:\\Program Files (x86)'))
455 vswhere = os.path.join(prg_path, 'Microsoft Visual Studio', 'Installer', 'vswhere.exe')
456 args = [vswhere, '-products', '*', '-legacy', '-format', 'json']
458 txt = conf.cmd_and_log(args)
459 except Errors.WafError as e:
460 Logs.debug('msvc: vswhere.exe failed %s', e)
463 if sys.version_info[0] < 3:
465 txt = txt.decode(sys.stdout.encoding or 'cp1252')
467 txt = txt.decode('utf-8', 'replace')
468 arr = json.loads(txt)
469 arr.sort(key=lambda x: x['installationVersion'])
471 ver = entry['installationVersion']
472 ver = str('.'.join(ver.split('.')[:2]))
473 path = str(os.path.abspath(entry['installationPath']))
474 if os.path.exists(path) and ('msvc %s' % ver) not in versions:
475 conf.gather_msvc_targets(versions, ver, path)
478 def gather_msvc_versions(conf, versions):
480 for (v,version,reg) in gather_msvc_detected_versions():
483 msvc_version = Utils.winreg.OpenKey(Utils.winreg.HKEY_LOCAL_MACHINE, reg + "\\Setup\\VC")
485 msvc_version = Utils.winreg.OpenKey(Utils.winreg.HKEY_LOCAL_MACHINE, reg + "\\Setup\\Microsoft Visual C++")
486 path,type = Utils.winreg.QueryValueEx(msvc_version, 'ProductDir')
489 msvc_version = Utils.winreg.OpenKey(Utils.winreg.HKEY_LOCAL_MACHINE, "SOFTWARE\\Wow6432node\\Microsoft\\VisualStudio\\SxS\\VS7")
490 path,type = Utils.winreg.QueryValueEx(msvc_version, version)
494 vc_paths.append((version, os.path.abspath(str(path))))
497 vc_paths.append((version, os.path.abspath(str(path))))
499 wince_supported_platforms = gather_wince_supported_platforms()
501 for version,vc_path in vc_paths:
502 vs_path = os.path.dirname(vc_path)
503 vsvars = os.path.join(vs_path, 'Common7', 'Tools', 'vsvars32.bat')
504 if wince_supported_platforms and os.path.isfile(vsvars):
505 conf.gather_wince_targets(versions, version, vc_path, vsvars, wince_supported_platforms)
507 # WP80 works with 11.0Exp and 11.0, both of which resolve to the same vc_path.
508 # Stop after one is found.
509 for version,vc_path in vc_paths:
510 vs_path = os.path.dirname(vc_path)
511 vsvars = os.path.join(vs_path, 'VC', 'WPSDK', 'WP80', 'vcvarsphoneall.bat')
512 if os.path.isfile(vsvars):
513 conf.gather_winphone_targets(versions, '8.0', vc_path, vsvars)
516 for version,vc_path in vc_paths:
517 vs_path = os.path.dirname(vc_path)
518 conf.gather_msvc_targets(versions, version, vc_path)
521 def gather_icl_versions(conf, versions):
525 :param versions: list to modify
528 version_pattern = re.compile('^...?.?\....?.?')
530 all_versions = Utils.winreg.OpenKey(Utils.winreg.HKEY_LOCAL_MACHINE, 'SOFTWARE\\Wow6432node\\Intel\\Compilers\\C++')
533 all_versions = Utils.winreg.OpenKey(Utils.winreg.HKEY_LOCAL_MACHINE, 'SOFTWARE\\Intel\\Compilers\\C++')
539 version = Utils.winreg.EnumKey(all_versions, index)
543 if not version_pattern.match(version):
546 for target,arch in all_icl_platforms:
547 if target=='intel64':
548 targetDir='EM64T_NATIVE'
552 Utils.winreg.OpenKey(all_versions,version+'\\'+targetDir)
553 icl_version=Utils.winreg.OpenKey(all_versions,version)
554 path,type=Utils.winreg.QueryValueEx(icl_version,'ProductDir')
558 batch_file=os.path.join(path,'bin','iclvars.bat')
559 if os.path.isfile(batch_file):
560 targets[target] = target_compiler(conf, 'intel', arch, version, target, batch_file)
561 for target,arch in all_icl_platforms:
563 icl_version = Utils.winreg.OpenKey(all_versions, version+'\\'+target)
564 path,type = Utils.winreg.QueryValueEx(icl_version,'ProductDir')
568 batch_file=os.path.join(path,'bin','iclvars.bat')
569 if os.path.isfile(batch_file):
570 targets[target] = target_compiler(conf, 'intel', arch, version, target, batch_file)
572 versions['intel ' + major] = targets
575 def gather_intel_composer_versions(conf, versions):
577 Checks ICL compilers that are part of Intel Composer Suites
579 :param versions: list to modify
582 version_pattern = re.compile('^...?.?\...?.?.?')
584 all_versions = Utils.winreg.OpenKey(Utils.winreg.HKEY_LOCAL_MACHINE, 'SOFTWARE\\Wow6432node\\Intel\\Suites')
587 all_versions = Utils.winreg.OpenKey(Utils.winreg.HKEY_LOCAL_MACHINE, 'SOFTWARE\\Intel\\Suites')
593 version = Utils.winreg.EnumKey(all_versions, index)
597 if not version_pattern.match(version):
600 for target,arch in all_icl_platforms:
601 if target=='intel64':
602 targetDir='EM64T_NATIVE'
607 defaults = Utils.winreg.OpenKey(all_versions,version+'\\Defaults\\C++\\'+targetDir)
609 if targetDir == 'EM64T_NATIVE':
610 defaults = Utils.winreg.OpenKey(all_versions,version+'\\Defaults\\C++\\EM64T')
613 uid,type = Utils.winreg.QueryValueEx(defaults, 'SubKey')
614 Utils.winreg.OpenKey(all_versions,version+'\\'+uid+'\\C++\\'+targetDir)
615 icl_version=Utils.winreg.OpenKey(all_versions,version+'\\'+uid+'\\C++')
616 path,type=Utils.winreg.QueryValueEx(icl_version,'ProductDir')
620 batch_file=os.path.join(path,'bin','iclvars.bat')
621 if os.path.isfile(batch_file):
622 targets[target] = target_compiler(conf, 'intel', arch, version, target, batch_file)
623 # The intel compilervar_arch.bat is broken when used with Visual Studio Express 2012
624 # http://software.intel.com/en-us/forums/topic/328487
625 compilervars_warning_attr = '_compilervars_warning_key'
626 if version[0:2] == '13' and getattr(conf, compilervars_warning_attr, True):
627 setattr(conf, compilervars_warning_attr, False)
628 patch_url = 'http://software.intel.com/en-us/forums/topic/328487'
629 compilervars_arch = os.path.join(path, 'bin', 'compilervars_arch.bat')
630 for vscomntool in ('VS110COMNTOOLS', 'VS100COMNTOOLS'):
631 if vscomntool in os.environ:
632 vs_express_path = os.environ[vscomntool] + r'..\IDE\VSWinExpress.exe'
633 dev_env_path = os.environ[vscomntool] + r'..\IDE\devenv.exe'
634 if (r'if exist "%VS110COMNTOOLS%..\IDE\VSWinExpress.exe"' in Utils.readf(compilervars_arch) and
635 not os.path.exists(vs_express_path) and not os.path.exists(dev_env_path)):
636 Logs.warn(('The Intel compilervar_arch.bat only checks for one Visual Studio SKU '
637 '(VSWinExpress.exe) but it does not seem to be installed at %r. '
638 'The intel command line set up will fail to configure unless the file %r'
639 'is patched. See: %s') % (vs_express_path, compilervars_arch, patch_url))
641 versions['intel ' + major] = targets
644 def detect_msvc(self):
645 return self.setup_msvc(self.get_msvc_versions())
648 def get_msvc_versions(self):
650 :return: platform to compiler configurations
653 dct = Utils.ordered_iter_dict()
654 self.gather_icl_versions(dct)
655 self.gather_intel_composer_versions(dct)
656 self.gather_wsdk_versions(dct)
657 self.gather_msvc_versions(dct)
658 self.gather_vswhere_versions(dct)
659 Logs.debug('msvc: detected versions %r', list(dct.keys()))
663 def find_lt_names_msvc(self, libname, is_static=False):
665 Win32/MSVC specific code to glean out information from libtool la files.
666 this function is not attached to the task_gen class. Returns a triplet:
667 (library absolute path, library name without extension, whether the library is static)
670 'lib%s.la' % libname,
674 for path in self.env.LIBPATH:
676 laf=os.path.join(path,la)
678 if os.path.exists(laf):
679 ltdict = Utils.read_la_file(laf)
681 if ltdict.get('libdir', ''):
682 lt_libdir = ltdict['libdir']
683 if not is_static and ltdict.get('library_names', ''):
684 dllnames=ltdict['library_names'].split()
685 dll=dllnames[0].lower()
686 dll=re.sub('\.dll$', '', dll)
687 return (lt_libdir, dll, False)
688 elif ltdict.get('old_library', ''):
689 olib=ltdict['old_library']
690 if os.path.exists(os.path.join(path,olib)):
691 return (path, olib, True)
692 elif lt_libdir != '' and os.path.exists(os.path.join(lt_libdir,olib)):
693 return (lt_libdir, olib, True)
695 return (None, olib, True)
697 raise self.errors.WafError('invalid libtool object file: %s' % laf)
698 return (None, None, None)
701 def libname_msvc(self, libname, is_static=False):
702 lib = libname.lower()
703 lib = re.sub('\.lib$','',lib)
705 if lib in g_msvc_systemlibs:
708 lib=re.sub('^lib','',lib)
713 (lt_path, lt_libname, lt_static) = self.find_lt_names_msvc(lib, is_static)
715 if lt_path != None and lt_libname != None:
717 # file existence check has been made by find_lt_names
718 return os.path.join(lt_path,lt_libname)
721 _libpaths = [lt_path] + self.env.LIBPATH
723 _libpaths = self.env.LIBPATH
733 'lib%s.dll.lib' % lib,
744 libnames=dynamic_libs + static_libs
746 for path in _libpaths:
747 for libn in libnames:
748 if os.path.exists(os.path.join(path, libn)):
749 Logs.debug('msvc: lib found: %s', os.path.join(path,libn))
750 return re.sub('\.lib$', '',libn)
752 #if no lib can be found, just return the libname as msvc expects it
753 self.fatal('The library %r could not be found' % libname)
754 return re.sub('\.lib$', '', libname)
757 def check_lib_msvc(self, libname, is_static=False, uselib_store=None):
759 Ideally we should be able to place the lib in the right env var, either STLIB or LIB,
760 but we don't distinguish static libs from shared libs.
761 This is ok since msvc doesn't have any special linker flag to select static libs (no env.STLIB_MARKER)
763 libn = self.libname_msvc(libname, is_static)
766 uselib_store = libname.upper()
768 if False and is_static: # disabled
769 self.env['STLIB_' + uselib_store] = [libn]
771 self.env['LIB_' + uselib_store] = [libn]
774 def check_libs_msvc(self, libnames, is_static=False):
775 for libname in Utils.to_list(libnames):
776 self.check_lib_msvc(libname, is_static)
780 Configuration methods to call for detecting msvc
782 conf.autodetect(True)
784 conf.msvc_common_flags()
786 conf.cxx_load_tools()
789 conf.link_add_flags()
790 conf.visual_studio_add_flags()
793 def no_autodetect(conf):
794 conf.env.NO_MSVC_DETECT = 1
798 def autodetect(conf, arch=False):
803 compiler, version, path, includes, libdirs, cpu = conf.detect_msvc()
808 v.INCLUDES = includes
810 v.MSVC_COMPILER = compiler
812 v.MSVC_VERSION = float(version)
814 v.MSVC_VERSION = float(version[:-3])
816 def _get_prog_names(conf, compiler):
817 if compiler == 'intel':
818 compiler_name = 'ICL'
819 linker_name = 'XILINK'
826 return compiler_name, linker_name, lib_name
830 """Due to path format limitations, limit operation only to native Win32. Yeah it sucks."""
831 if sys.platform == 'cygwin':
832 conf.fatal('MSVC module does not work under cygwin Python!')
834 # the autodetection is supposed to be performed before entering in this method
837 compiler = v.MSVC_COMPILER
838 version = v.MSVC_VERSION
840 compiler_name, linker_name, lib_name = _get_prog_names(conf, compiler)
841 v.MSVC_MANIFEST = (compiler == 'msvc' and version >= 8) or (compiler == 'wsdk' and version >= 6) or (compiler == 'intel' and version >= 11)
844 cxx = conf.find_program(compiler_name, var='CXX', path_list=path)
846 # before setting anything, check if the compiler is really msvc
847 env = dict(conf.environ)
849 env.update(PATH = ';'.join(path))
850 if not conf.cmd_and_log(cxx + ['/nologo', '/help'], env=env):
851 conf.fatal('the msvc compiler could not be identified')
855 v.CC_NAME = v.CXX_NAME = 'msvc'
859 conf.find_program(linker_name, path_list=path, errmsg='%s was not found (linker)' % linker_name, var='LINK_CXX')
862 v.LINK_CC = v.LINK_CXX
866 stliblink = conf.find_program(lib_name, path_list=path, var='AR')
869 v.ARFLAGS = ['/nologo']
871 # manifest tool. Not required for VS 2003 and below. Must have for VS 2005 and later
873 conf.find_program('MT', path_list=path, var='MT')
874 v.MTFLAGS = ['/nologo']
878 except Errors.ConfigurationError:
879 Logs.warn('Resource compiler not found. Compiling resource file is disabled')
882 def visual_studio_add_flags(self):
883 """visual studio flags found in the system environment"""
885 if self.environ.get('INCLUDE'):
886 v.prepend_value('INCLUDES', [x for x in self.environ['INCLUDE'].split(';') if x]) # notice the 'S'
887 if self.environ.get('LIB'):
888 v.prepend_value('LIBPATH', [x for x in self.environ['LIB'].split(';') if x])
891 def msvc_common_flags(conf):
893 Setup the flags required for executing the msvc compiler
898 v.append_value('CFLAGS', ['/nologo'])
899 v.append_value('CXXFLAGS', ['/nologo'])
900 v.append_value('LINKFLAGS', ['/nologo'])
901 v.DEFINES_ST = '/D%s'
904 v.CC_TGT_F = ['/c', '/Fo']
906 v.CXX_TGT_F = ['/c', '/Fo']
908 if (v.MSVC_COMPILER == 'msvc' and v.MSVC_VERSION >= 8) or (v.MSVC_COMPILER == 'wsdk' and v.MSVC_VERSION >= 6):
909 v.CC_TGT_F = ['/FC'] + v.CC_TGT_F
910 v.CXX_TGT_F = ['/FC'] + v.CXX_TGT_F
912 v.CPPPATH_ST = '/I%s' # template for adding include paths
914 v.AR_TGT_F = v.CCLNK_TGT_F = v.CXXLNK_TGT_F = '/OUT:'
917 v.CFLAGS_CRT_MULTITHREADED = v.CXXFLAGS_CRT_MULTITHREADED = ['/MT']
918 v.CFLAGS_CRT_MULTITHREADED_DLL = v.CXXFLAGS_CRT_MULTITHREADED_DLL = ['/MD']
920 v.CFLAGS_CRT_MULTITHREADED_DBG = v.CXXFLAGS_CRT_MULTITHREADED_DBG = ['/MTd']
921 v.CFLAGS_CRT_MULTITHREADED_DLL_DBG = v.CXXFLAGS_CRT_MULTITHREADED_DLL_DBG = ['/MDd']
924 v.LIBPATH_ST = '/LIBPATH:%s'
925 v.STLIB_ST = '%s.lib'
926 v.STLIBPATH_ST = '/LIBPATH:%s'
929 v.append_value('LINKFLAGS', ['/MANIFEST'])
932 v.CXXFLAGS_cxxshlib = []
933 v.LINKFLAGS_cshlib = v.LINKFLAGS_cxxshlib = ['/DLL']
934 v.cshlib_PATTERN = v.cxxshlib_PATTERN = '%s.dll'
935 v.implib_PATTERN = '%s.lib'
936 v.IMPLIB_ST = '/IMPLIB:%s'
938 v.LINKFLAGS_cstlib = []
939 v.cstlib_PATTERN = v.cxxstlib_PATTERN = '%s.lib'
941 v.cprogram_PATTERN = v.cxxprogram_PATTERN = '%s.exe'
944 #######################################################################################################
945 ##### conf above, build below
947 @after_method('apply_link')
949 def apply_flags_msvc(self):
951 Add additional flags implied by msvc, such as subsystems and pdb files::
954 bld.stlib(source='main.c', target='bar', subsystem='gruik')
956 if self.env.CC_NAME != 'msvc' or not getattr(self, 'link_task', None):
959 is_static = isinstance(self.link_task, ccroot.stlink_task)
961 subsystem = getattr(self, 'subsystem', '')
963 subsystem = '/subsystem:%s' % subsystem
964 flags = is_static and 'ARFLAGS' or 'LINKFLAGS'
965 self.env.append_value(flags, subsystem)
968 for f in self.env.LINKFLAGS:
971 pdbnode = self.link_task.outputs[0].change_ext('.pdb')
972 self.link_task.outputs.append(pdbnode)
974 if getattr(self, 'install_task', None):
975 self.pdb_install_task = self.add_install_files(
976 install_to=self.install_task.install_to, install_from=pdbnode)
979 @feature('cprogram', 'cshlib', 'cxxprogram', 'cxxshlib')
980 @after_method('apply_link')
981 def apply_manifest(self):
983 Special linker for MSVC with support for embedding manifests into DLL's
984 and executables compiled by Visual Studio 2005 or probably later. Without
985 the manifest file, the binaries are unusable.
986 See: http://msdn2.microsoft.com/en-us/library/ms235542(VS.80).aspx
988 if self.env.CC_NAME == 'msvc' and self.env.MSVC_MANIFEST and getattr(self, 'link_task', None):
989 out_node = self.link_task.outputs[0]
990 man_node = out_node.parent.find_or_declare(out_node.name + '.manifest')
991 self.link_task.outputs.append(man_node)
992 self.env.DO_MANIFEST = True
994 def make_winapp(self, family):
995 append = self.env.append_unique
996 append('DEFINES', 'WINAPI_FAMILY=%s' % family)
997 append('CXXFLAGS', ['/ZW', '/TP'])
998 for lib_path in self.env.LIBPATH:
999 append('CXXFLAGS','/AI%s'%lib_path)
1001 @feature('winphoneapp')
1002 @after_method('process_use')
1003 @after_method('propagate_uselib_vars')
1004 def make_winphone_app(self):
1006 Insert configuration flags for windows phone applications (adds /ZW, /TP...)
1008 make_winapp(self, 'WINAPI_FAMILY_PHONE_APP')
1009 self.env.append_unique('LINKFLAGS', ['/NODEFAULTLIB:ole32.lib', 'PhoneAppModelHost.lib'])
1012 @after_method('process_use')
1013 @after_method('propagate_uselib_vars')
1014 def make_windows_app(self):
1016 Insert configuration flags for windows applications (adds /ZW, /TP...)
1018 make_winapp(self, 'WINAPI_FAMILY_DESKTOP_APP')