diff options
Diffstat (limited to 'third_party/waf/waflib/Tools/msvc.py')
-rw-r--r-- | third_party/waf/waflib/Tools/msvc.py | 204 |
1 files changed, 121 insertions, 83 deletions
diff --git a/third_party/waf/waflib/Tools/msvc.py b/third_party/waf/waflib/Tools/msvc.py index 7cc2fef17a2..9ee7eadcdbe 100644 --- a/third_party/waf/waflib/Tools/msvc.py +++ b/third_party/waf/waflib/Tools/msvc.py @@ -42,7 +42,7 @@ Supported platforms: ia64, x64, x86, x86_amd64, x86_ia64, x86_arm, amd64_x86, am Compilers supported: -* msvc => Visual Studio, versions 6.0 (VC 98, VC .NET 2002) to 12.0 (Visual Studio 2013) +* msvc => Visual Studio, versions 6.0 (VC 98, VC .NET 2002) to 15 (Visual Studio 2017) * wsdk => Windows SDK, versions 6.0, 6.1, 7.0, 7.1, 8.0 * icl => Intel compiler, versions 9, 10, 11, 13 * winphone => Visual Studio to target Windows Phone 8 native (version 8.0 for now) @@ -56,7 +56,7 @@ cmd.exe /C "chcp 1252 & set PYTHONUNBUFFERED=true && set && waf configure" Setting PYTHONUNBUFFERED gives the unbuffered output. """ -import os, sys, re +import os, sys, re, traceback from waflib import Utils, Logs, Options, Errors from waflib.TaskGen import after_method, feature @@ -117,7 +117,7 @@ def setup_msvc(conf, versiondict): platforms=Utils.to_list(conf.env.MSVC_TARGETS) or [i for i,j in all_msvc_platforms+all_icl_platforms+all_wince_platforms] desired_versions = getattr(Options.options, 'msvc_version', '').split(',') if desired_versions == ['']: - desired_versions = conf.env.MSVC_VERSIONS or list(versiondict.keys()) + desired_versions = conf.env.MSVC_VERSIONS or list(reversed(sorted(versiondict.keys()))) # Override lazy detection by evaluating after the fact. lazy_detect = getattr(Options.options, 'msvc_lazy', True) @@ -134,15 +134,23 @@ def setup_msvc(conf, versiondict): conf.env.MSVC_INSTALLED_VERSIONS = versiondict for version in desired_versions: + Logs.debug('msvc: detecting %r - %r', version, desired_versions) try: targets = versiondict[version] except KeyError: continue + + seen = set() for arch in platforms: + if arch in seen: + continue + else: + seen.add(arch) try: cfg = targets[arch] except KeyError: continue + cfg.evaluate() if cfg.is_valid: compiler,revision = version.rsplit(' ', 1) @@ -209,11 +217,11 @@ echo LIB=%%LIB%%;%%LIBPATH%% try: conf.cmd_and_log(cxx + ['/help'], env=env) except UnicodeError: - st = Utils.ex_stack() + st = traceback.format_exc() if conf.logger: conf.logger.error(st) conf.fatal('msvc: Unicode error - check the code page?') - except Exception ,e: + except Exception as e: Logs.debug('msvc: get_msvc_version: %r %r %r -> failure %s', compiler, version, target, str(e)) conf.fatal('msvc: cannot run the compiler in get_msvc_version (run with -v to display errors)') else: @@ -223,42 +231,6 @@ echo LIB=%%LIB%%;%%LIBPATH%% return (MSVC_PATH, MSVC_INCDIR, MSVC_LIBDIR) -@conf -def gather_wsdk_versions(conf, versions): - """ - Use winreg to add the msvc versions to the input list - - :param versions: list to modify - :type versions: list - """ - version_pattern = re.compile('^v..?.?\...?.?') - try: - all_versions = Utils.winreg.OpenKey(Utils.winreg.HKEY_LOCAL_MACHINE, 'SOFTWARE\\Wow6432node\\Microsoft\\Microsoft SDKs\\Windows') - except WindowsError: - try: - all_versions = Utils.winreg.OpenKey(Utils.winreg.HKEY_LOCAL_MACHINE, 'SOFTWARE\\Microsoft\\Microsoft SDKs\\Windows') - except WindowsError: - return - index = 0 - while 1: - try: - version = Utils.winreg.EnumKey(all_versions, index) - except WindowsError: - break - index += 1 - if not version_pattern.match(version): - continue - try: - msvc_version = Utils.winreg.OpenKey(all_versions, version) - path,type = Utils.winreg.QueryValueEx(msvc_version,'InstallationFolder') - except WindowsError: - continue - if path and os.path.isfile(os.path.join(path, 'bin', 'SetEnv.cmd')): - targets = {} - for target,arch in all_msvc_platforms: - targets[target] = target_compiler(conf, 'wsdk', arch, version, '/'+target, os.path.join(path, 'bin', 'SetEnv.cmd')) - versions['wsdk ' + version[1:]] = targets - def gather_wince_supported_platforms(): """ Checks SmartPhones SDKs @@ -269,10 +241,10 @@ def gather_wince_supported_platforms(): supported_wince_platforms = [] try: ce_sdk = Utils.winreg.OpenKey(Utils.winreg.HKEY_LOCAL_MACHINE, 'SOFTWARE\\Wow6432node\\Microsoft\\Windows CE Tools\\SDKs') - except WindowsError: + except OSError: try: ce_sdk = Utils.winreg.OpenKey(Utils.winreg.HKEY_LOCAL_MACHINE, 'SOFTWARE\\Microsoft\\Windows CE Tools\\SDKs') - except WindowsError: + except OSError: ce_sdk = '' if not ce_sdk: return supported_wince_platforms @@ -282,15 +254,15 @@ def gather_wince_supported_platforms(): try: sdk_device = Utils.winreg.EnumKey(ce_sdk, index) sdk = Utils.winreg.OpenKey(ce_sdk, sdk_device) - except WindowsError: + except OSError: break index += 1 try: path,type = Utils.winreg.QueryValueEx(sdk, 'SDKRootDir') - except WindowsError: + except OSError: try: path,type = Utils.winreg.QueryValueEx(sdk,'SDKInformation') - except WindowsError: + except OSError: continue path,xml = os.path.split(path) path = str(path) @@ -313,18 +285,18 @@ def gather_msvc_detected_versions(): prefix = 'SOFTWARE\\Wow6432node\\Microsoft\\' + vcver try: all_versions = Utils.winreg.OpenKey(Utils.winreg.HKEY_LOCAL_MACHINE, prefix) - except WindowsError: + except OSError: prefix = 'SOFTWARE\\Microsoft\\' + vcver try: all_versions = Utils.winreg.OpenKey(Utils.winreg.HKEY_LOCAL_MACHINE, prefix) - except WindowsError: + except OSError: continue index = 0 while 1: try: version = Utils.winreg.EnumKey(all_versions, index) - except WindowsError: + except OSError: break index += 1 match = version_pattern.match(version) @@ -352,7 +324,6 @@ class target_compiler(object): :param version: compiler version number :param bat_target: ? :param bat: path to the batch file to run - :param callback: optional function to take the realized environment variables tup and map it (e.g. to combine other constant paths) """ self.conf = ctx self.name = None @@ -381,10 +352,46 @@ class target_compiler(object): (self.bindirs, self.incdirs, self.libdirs) = vs def __str__(self): - return str((self.bindirs, self.incdirs, self.libdirs)) + return str((self.compiler, self.cpu, self.version, self.bat_target, self.bat)) def __repr__(self): - return repr((self.bindirs, self.incdirs, self.libdirs)) + return repr((self.compiler, self.cpu, self.version, self.bat_target, self.bat)) + +@conf +def gather_wsdk_versions(conf, versions): + """ + Use winreg to add the msvc versions to the input list + + :param versions: list to modify + :type versions: list + """ + version_pattern = re.compile('^v..?.?\...?.?') + try: + all_versions = Utils.winreg.OpenKey(Utils.winreg.HKEY_LOCAL_MACHINE, 'SOFTWARE\\Wow6432node\\Microsoft\\Microsoft SDKs\\Windows') + except OSError: + try: + all_versions = Utils.winreg.OpenKey(Utils.winreg.HKEY_LOCAL_MACHINE, 'SOFTWARE\\Microsoft\\Microsoft SDKs\\Windows') + except OSError: + return + index = 0 + while 1: + try: + version = Utils.winreg.EnumKey(all_versions, index) + except OSError: + break + index += 1 + if not version_pattern.match(version): + continue + try: + msvc_version = Utils.winreg.OpenKey(all_versions, version) + path,type = Utils.winreg.QueryValueEx(msvc_version,'InstallationFolder') + except OSError: + continue + if path and os.path.isfile(os.path.join(path, 'bin', 'SetEnv.cmd')): + targets = {} + for target,arch in all_msvc_platforms: + targets[target] = target_compiler(conf, 'wsdk', arch, version, '/'+target, os.path.join(path, 'bin', 'SetEnv.cmd')) + versions['wsdk ' + version[1:]] = targets @conf def gather_msvc_targets(conf, versions, version, vc_path): @@ -402,7 +409,7 @@ def gather_msvc_targets(conf, versions, version, vc_path): elif os.path.isfile(os.path.join(vc_path, 'Bin', 'vcvars32.bat')): targets['x86'] = target_compiler(conf, 'msvc', 'x86', version, '', os.path.join(vc_path, 'Bin', 'vcvars32.bat')) if targets: - versions['msvc ' + version] = targets + versions['msvc %s' % version] = targets @conf def gather_wince_targets(conf, versions, version, vc_path, vsvars, supported_platforms): @@ -419,6 +426,7 @@ def gather_wince_targets(conf, versions, version, vc_path, vsvars, supported_pla incdirs = [os.path.join(winCEpath, 'include'), os.path.join(winCEpath, 'atlmfc', 'include'), include] libdirs = [os.path.join(winCEpath, 'lib', platform), os.path.join(winCEpath, 'atlmfc', 'lib', platform), lib] def combine_common(obj, compiler_env): + # TODO this is likely broken, remove in waf 2.1 (common_bindirs,_1,_2) = compiler_env return (bindirs + common_bindirs, incdirs, libdirs) targets[platform] = target_compiler(conf, 'msvc', platform, version, 'x86', vsvars, combine_common) @@ -435,20 +443,52 @@ def gather_winphone_targets(conf, versions, version, vc_path, vsvars): versions['winphone ' + version] = targets @conf +def gather_vswhere_versions(conf, versions): + try: + import json + except ImportError: + Logs.error('Visual Studio 2017 detection requires Python 2.6') + return + + prg_path = os.environ.get('ProgramFiles(x86)', os.environ.get('ProgramFiles', 'C:\\Program Files (x86)')) + + vswhere = os.path.join(prg_path, 'Microsoft Visual Studio', 'Installer', 'vswhere.exe') + args = [vswhere, '-products', '*', '-legacy', '-format', 'json'] + try: + txt = conf.cmd_and_log(args) + except Errors.WafError as e: + Logs.debug('msvc: vswhere.exe failed %s', e) + return + + if sys.version_info[0] < 3: + try: + txt = txt.decode(sys.stdout.encoding or 'cp1252') + except UnicodeError: + txt = txt.decode('utf-8', 'replace') + arr = json.loads(txt) + arr.sort(key=lambda x: x['installationVersion']) + for entry in arr: + ver = entry['installationVersion'] + ver = str('.'.join(ver.split('.')[:2])) + path = str(os.path.abspath(entry['installationPath'])) + if os.path.exists(path) and ('msvc %s' % ver) not in versions: + conf.gather_msvc_targets(versions, ver, path) + +@conf def gather_msvc_versions(conf, versions): vc_paths = [] for (v,version,reg) in gather_msvc_detected_versions(): try: try: msvc_version = Utils.winreg.OpenKey(Utils.winreg.HKEY_LOCAL_MACHINE, reg + "\\Setup\\VC") - except WindowsError: + except OSError: msvc_version = Utils.winreg.OpenKey(Utils.winreg.HKEY_LOCAL_MACHINE, reg + "\\Setup\\Microsoft Visual C++") path,type = Utils.winreg.QueryValueEx(msvc_version, 'ProductDir') - except WindowsError: + except OSError: try: msvc_version = Utils.winreg.OpenKey(Utils.winreg.HKEY_LOCAL_MACHINE, "SOFTWARE\\Wow6432node\\Microsoft\\VisualStudio\\SxS\\VS7") path,type = Utils.winreg.QueryValueEx(msvc_version, version) - except WindowsError: + except OSError: continue else: vc_paths.append((version, os.path.abspath(str(path)))) @@ -488,29 +528,31 @@ def gather_icl_versions(conf, versions): version_pattern = re.compile('^...?.?\....?.?') try: all_versions = Utils.winreg.OpenKey(Utils.winreg.HKEY_LOCAL_MACHINE, 'SOFTWARE\\Wow6432node\\Intel\\Compilers\\C++') - except WindowsError: + except OSError: try: all_versions = Utils.winreg.OpenKey(Utils.winreg.HKEY_LOCAL_MACHINE, 'SOFTWARE\\Intel\\Compilers\\C++') - except WindowsError: + except OSError: return index = 0 while 1: try: version = Utils.winreg.EnumKey(all_versions, index) - except WindowsError: + except OSError: break index += 1 if not version_pattern.match(version): continue targets = {} for target,arch in all_icl_platforms: - if target=='intel64': targetDir='EM64T_NATIVE' - else: targetDir=target + if target=='intel64': + targetDir='EM64T_NATIVE' + else: + targetDir=target try: Utils.winreg.OpenKey(all_versions,version+'\\'+targetDir) icl_version=Utils.winreg.OpenKey(all_versions,version) path,type=Utils.winreg.QueryValueEx(icl_version,'ProductDir') - except WindowsError: + except OSError: pass else: batch_file=os.path.join(path,'bin','iclvars.bat') @@ -520,7 +562,7 @@ def gather_icl_versions(conf, versions): try: icl_version = Utils.winreg.OpenKey(all_versions, version+'\\'+target) path,type = Utils.winreg.QueryValueEx(icl_version,'ProductDir') - except WindowsError: + except OSError: continue else: batch_file=os.path.join(path,'bin','iclvars.bat') @@ -540,28 +582,30 @@ def gather_intel_composer_versions(conf, versions): version_pattern = re.compile('^...?.?\...?.?.?') try: all_versions = Utils.winreg.OpenKey(Utils.winreg.HKEY_LOCAL_MACHINE, 'SOFTWARE\\Wow6432node\\Intel\\Suites') - except WindowsError: + except OSError: try: all_versions = Utils.winreg.OpenKey(Utils.winreg.HKEY_LOCAL_MACHINE, 'SOFTWARE\\Intel\\Suites') - except WindowsError: + except OSError: return index = 0 while 1: try: version = Utils.winreg.EnumKey(all_versions, index) - except WindowsError: + except OSError: break index += 1 if not version_pattern.match(version): continue targets = {} for target,arch in all_icl_platforms: - if target=='intel64': targetDir='EM64T_NATIVE' - else: targetDir=target + if target=='intel64': + targetDir='EM64T_NATIVE' + else: + targetDir=target try: try: defaults = Utils.winreg.OpenKey(all_versions,version+'\\Defaults\\C++\\'+targetDir) - except WindowsError: + except OSError: if targetDir == 'EM64T_NATIVE': defaults = Utils.winreg.OpenKey(all_versions,version+'\\Defaults\\C++\\EM64T') else: @@ -570,7 +614,7 @@ def gather_intel_composer_versions(conf, versions): Utils.winreg.OpenKey(all_versions,version+'\\'+uid+'\\C++\\'+targetDir) icl_version=Utils.winreg.OpenKey(all_versions,version+'\\'+uid+'\\C++') path,type=Utils.winreg.QueryValueEx(icl_version,'ProductDir') - except WindowsError: + except OSError: pass else: batch_file=os.path.join(path,'bin','iclvars.bat') @@ -611,6 +655,7 @@ def get_msvc_versions(self): self.gather_intel_composer_versions(dct) self.gather_wsdk_versions(dct) self.gather_msvc_versions(dct) + self.gather_vswhere_versions(dct) Logs.debug('msvc: detected versions %r', list(dct.keys())) return dct @@ -668,7 +713,7 @@ def libname_msvc(self, libname, is_static=False): (lt_path, lt_libname, lt_static) = self.find_lt_names_msvc(lib, is_static) if lt_path != None and lt_libname != None: - if lt_static == True: + if lt_static: # file existence check has been made by find_lt_names return os.path.join(lt_path,lt_libname) @@ -765,7 +810,7 @@ def autodetect(conf, arch=False): v.MSVC_COMPILER = compiler try: v.MSVC_VERSION = float(version) - except TypeError: + except ValueError: v.MSVC_VERSION = float(version[:-3]) def _get_prog_names(conf, compiler): @@ -800,7 +845,8 @@ def find_msvc(conf): # before setting anything, check if the compiler is really msvc env = dict(conf.environ) - if path: env.update(PATH = ';'.join(path)) + if path: + env.update(PATH = ';'.join(path)) if not conf.cmd_and_log(cxx + ['/nologo', '/help'], env=env): conf.fatal('the msvc compiler could not be identified') @@ -810,8 +856,7 @@ def find_msvc(conf): # linker if not v.LINK_CXX: - # TODO: var=LINK_CXX to let so that LINK_CXX can be overridden? - v.LINK_CXX = conf.find_program(linker_name, path_list=path, errmsg='%s was not found (linker)' % linker_name) + conf.find_program(linker_name, path_list=path, errmsg='%s was not found (linker)' % linker_name, var='LINK_CXX') if not v.LINK_CC: v.LINK_CC = v.LINK_CXX @@ -868,13 +913,6 @@ def msvc_common_flags(conf): v.AR_TGT_F = v.CCLNK_TGT_F = v.CXXLNK_TGT_F = '/OUT:' - # Subsystem specific flags - v.CFLAGS_CONSOLE = v.CXXFLAGS_CONSOLE = ['/SUBSYSTEM:CONSOLE'] - v.CFLAGS_NATIVE = v.CXXFLAGS_NATIVE = ['/SUBSYSTEM:NATIVE'] - v.CFLAGS_POSIX = v.CXXFLAGS_POSIX = ['/SUBSYSTEM:POSIX'] - v.CFLAGS_WINDOWS = v.CXXFLAGS_WINDOWS = ['/SUBSYSTEM:WINDOWS'] - v.CFLAGS_WINDOWSCE = v.CXXFLAGS_WINDOWSCE = ['/SUBSYSTEM:WINDOWSCE'] - # CRT specific flags v.CFLAGS_CRT_MULTITHREADED = v.CXXFLAGS_CRT_MULTITHREADED = ['/MT'] v.CFLAGS_CRT_MULTITHREADED_DLL = v.CXXFLAGS_CRT_MULTITHREADED_DLL = ['/MD'] @@ -968,7 +1006,7 @@ def make_winphone_app(self): Insert configuration flags for windows phone applications (adds /ZW, /TP...) """ make_winapp(self, 'WINAPI_FAMILY_PHONE_APP') - conf.env.append_unique('LINKFLAGS', ['/NODEFAULTLIB:ole32.lib', 'PhoneAppModelHost.lib']) + self.env.append_unique('LINKFLAGS', ['/NODEFAULTLIB:ole32.lib', 'PhoneAppModelHost.lib']) @feature('winapp') @after_method('process_use') |