From d68969f1691515b45f0f9d438aebb120059872d9 Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Tue, 2 Jul 2019 11:38:36 -0700 Subject: [PATCH] compilers/mixins/visualstudio: Add type annotations --- mesonbuild/compilers/mixins/visualstudio.py | 225 +++++++++++--------- 1 file changed, 119 insertions(+), 106 deletions(-) diff --git a/mesonbuild/compilers/mixins/visualstudio.py b/mesonbuild/compilers/mixins/visualstudio.py index 4c5eec9bb..edb104d0c 100644 --- a/mesonbuild/compilers/mixins/visualstudio.py +++ b/mesonbuild/compilers/mixins/visualstudio.py @@ -23,58 +23,68 @@ import typing from ... import mesonlib from ... import mlog -msvc_buildtype_args = {'plain': [], - 'debug': ["/ZI", "/Ob0", "/Od", "/RTC1"], - 'debugoptimized': ["/Zi", "/Ob1"], - 'release': ["/Ob2", "/Gw"], - 'minsize': ["/Zi", "/Gw"], - 'custom': [], - } - -msvc_buildtype_linker_args = {'plain': [], - 'debug': [], - 'debugoptimized': [], - # The otherwise implicit REF and ICF linker - # optimisations are disabled by /DEBUG. - # REF implies ICF. - 'release': ['/OPT:REF'], - 'minsize': ['/INCREMENTAL:NO', '/OPT:REF'], - 'custom': [], - } - -msvc_optimization_args = {'0': [], - 'g': ['/O0'], - '1': ['/O1'], - '2': ['/O2'], - '3': ['/O2'], - 's': ['/O1'], # Implies /Os. - } -msvc_debug_args = {False: [], - True: []} # Fixme! - -vs32_instruction_set_args = {'mmx': ['/arch:SSE'], # There does not seem to be a flag just for MMX - 'sse': ['/arch:SSE'], - 'sse2': ['/arch:SSE2'], - 'sse3': ['/arch:AVX'], # VS leaped from SSE2 directly to AVX. - 'sse41': ['/arch:AVX'], - 'sse42': ['/arch:AVX'], - 'avx': ['/arch:AVX'], - 'avx2': ['/arch:AVX2'], - 'neon': None, - } +if typing.TYPE_CHECKING: + from ...environment import Environment + +vs32_instruction_set_args = { + 'mmx': ['/arch:SSE'], # There does not seem to be a flag just for MMX + 'sse': ['/arch:SSE'], + 'sse2': ['/arch:SSE2'], + 'sse3': ['/arch:AVX'], # VS leaped from SSE2 directly to AVX. + 'sse41': ['/arch:AVX'], + 'sse42': ['/arch:AVX'], + 'avx': ['/arch:AVX'], + 'avx2': ['/arch:AVX2'], + 'neon': None, +} # typing.Dicst[str, typing.Optional[typing.List[str]]] # The 64 bit compiler defaults to /arch:avx. -vs64_instruction_set_args = {'mmx': ['/arch:AVX'], - 'sse': ['/arch:AVX'], - 'sse2': ['/arch:AVX'], - 'sse3': ['/arch:AVX'], - 'ssse3': ['/arch:AVX'], - 'sse41': ['/arch:AVX'], - 'sse42': ['/arch:AVX'], - 'avx': ['/arch:AVX'], - 'avx2': ['/arch:AVX2'], - 'neon': None, - } +vs64_instruction_set_args = { + 'mmx': ['/arch:AVX'], + 'sse': ['/arch:AVX'], + 'sse2': ['/arch:AVX'], + 'sse3': ['/arch:AVX'], + 'ssse3': ['/arch:AVX'], + 'sse41': ['/arch:AVX'], + 'sse42': ['/arch:AVX'], + 'avx': ['/arch:AVX'], + 'avx2': ['/arch:AVX2'], + 'neon': None, +} # typing.Dicst[str, typing.Optional[typing.List[str]]] + +msvc_buildtype_args = { + 'plain': [], + 'debug': ["/ZI", "/Ob0", "/Od", "/RTC1"], + 'debugoptimized': ["/Zi", "/Ob1"], + 'release': ["/Ob2", "/Gw"], + 'minsize': ["/Zi", "/Gw"], + 'custom': [], +} # type: typing.Dict[str, typing.List[str]] + +msvc_buildtype_linker_args = { + 'plain': [], + 'debug': [], + 'debugoptimized': [], + # The otherwise implicit REF and ICF linker optimisations are disabled by + # /DEBUG. REF implies ICF. + 'release': ['/OPT:REF'], + 'minsize': ['/INCREMENTAL:NO', '/OPT:REF'], + 'custom': [], +} # type: typing.Dict[str, typing.List[str]] + +msvc_optimization_args = { + '0': [], + 'g': ['/O0'], + '1': ['/O1'], + '2': ['/O2'], + '3': ['/O2'], + 's': ['/O1'], # Implies /Os. +} # type: typing.Dict[str, typing.List[str]] + +msvc_debug_args = { + False: [], + True: [] # Fixme! +} # type: typing.Dict[bool, typing.List[str]] class VisualStudioLikeCompiler(metaclass=abc.ABCMeta): @@ -94,20 +104,23 @@ class VisualStudioLikeCompiler(metaclass=abc.ABCMeta): ignore_libs = ('m', 'c', 'pthread', 'dl', 'rt', 'execinfo') internal_libs = () - crt_args = {'none': [], - 'md': ['/MD'], - 'mdd': ['/MDd'], - 'mt': ['/MT'], - 'mtd': ['/MTd'], - } + crt_args = { + 'none': [], + 'md': ['/MD'], + 'mdd': ['/MDd'], + 'mt': ['/MT'], + 'mtd': ['/MTd'], + } # type: typing.Dict[str, typing.List[str]] + # /showIncludes is needed for build dependency tracking in Ninja # See: https://ninja-build.org/manual.html#_deps always_args = ['/nologo', '/showIncludes'] - warn_args = {'0': ['/W1'], - '1': ['/W2'], - '2': ['/W3'], - '3': ['/W4'], - } + warn_args = { + '0': ['/W1'], + '1': ['/W2'], + '2': ['/W3'], + '3': ['/W4'], + } # type: typing.Dict[str, typing.List[str]] def __init__(self, target: str): self.base_options = ['b_pch', 'b_ndebug', 'b_vscrt'] # FIXME add lto, pgo and the like @@ -122,10 +135,10 @@ class VisualStudioLikeCompiler(metaclass=abc.ABCMeta): self.machine = target # Override CCompiler.get_always_args - def get_always_args(self): + def get_always_args(self) -> typing.List[str]: return self.always_args - def get_linker_debug_crt_args(self): + def get_linker_debug_crt_args(self) -> typing.List[str]: """ Arguments needed to select a debug crt for the linker @@ -136,55 +149,55 @@ class VisualStudioLikeCompiler(metaclass=abc.ABCMeta): """ return ['/MDd'] - def get_buildtype_args(self, buildtype): + def get_buildtype_args(self, buildtype: str) -> typing.List[str]: args = msvc_buildtype_args[buildtype] if self.id == 'msvc' and mesonlib.version_compare(self.version, '<18.0'): args = [arg for arg in args if arg != '/Gw'] return args - def get_buildtype_linker_args(self, buildtype): + def get_buildtype_linker_args(self, buildtype: str) -> typing.List[str]: return msvc_buildtype_linker_args[buildtype] - def get_pch_suffix(self): + def get_pch_suffix(self) -> str: return 'pch' - def get_pch_name(self, header): + def get_pch_name(self, header: str) -> str: chopped = os.path.basename(header).split('.')[:-1] chopped.append(self.get_pch_suffix()) pchname = '.'.join(chopped) return pchname - def get_pch_use_args(self, pch_dir, header): + def get_pch_use_args(self, pch_dir: str, header: str) -> typing.List[str]: base = os.path.basename(header) if self.id == 'clang-cl': base = header pchname = self.get_pch_name(header) return ['/FI' + base, '/Yu' + base, '/Fp' + os.path.join(pch_dir, pchname)] - def get_preprocess_only_args(self): + def get_preprocess_only_args(self) -> typing.List[str]: return ['/EP'] - def get_compile_only_args(self): + def get_compile_only_args(self) -> typing.List[str]: return ['/c'] - def get_no_optimization_args(self): + def get_no_optimization_args(self) -> typing.List[str]: return ['/Od'] - def get_output_args(self, target): + def get_output_args(self, target: str) -> typing.List[str]: if target.endswith('.exe'): return ['/Fe' + target] return ['/Fo' + target] - def get_optimization_args(self, optimization_level): + def get_optimization_args(self, optimization_level: str) -> typing.List[str]: return msvc_optimization_args[optimization_level] - def get_debug_args(self, is_debug): + def get_debug_args(self, is_debug: bool) -> typing.List[str]: return msvc_debug_args[is_debug] - def get_dependency_gen_args(self, outtarget, outfile): + def get_dependency_gen_args(self, outtarget: str, outfile: str) -> typing.List[str]: return [] - def get_linker_exelist(self): + def get_linker_exelist(self) -> typing.List[str]: # FIXME, should have same path as compiler. # FIXME, should be controllable via cross-file. if self.id == 'clang-cl': @@ -192,19 +205,19 @@ class VisualStudioLikeCompiler(metaclass=abc.ABCMeta): else: return ['link'] - def get_linker_always_args(self): + def get_linker_always_args(self) -> typing.List[str]: return ['/nologo'] - def get_linker_output_args(self, outputname): + def get_linker_output_args(self, outputname: str) -> typing.List[str]: return ['/MACHINE:' + self.machine, '/OUT:' + outputname] - def get_linker_search_args(self, dirname): + def get_linker_search_args(self, dirname: str) -> typing.List[str]: return ['/LIBPATH:' + dirname] - def linker_to_compiler_args(self, args): + def linker_to_compiler_args(self, args: typing.List[str]) -> typing.List[str]: return ['/link'] + args - def get_gui_app_args(self, value): + def get_gui_app_args(self, value: bool) -> typing.List[str]: # the default is for the linker to guess the subsystem based on presence # of main or WinMain symbols, so always be explicit if value: @@ -212,45 +225,45 @@ class VisualStudioLikeCompiler(metaclass=abc.ABCMeta): else: return ['/SUBSYSTEM:CONSOLE'] - def get_pic_args(self): + def get_pic_args(self) -> typing.List[str]: return [] # PIC is handled by the loader on Windows - def gen_export_dynamic_link_args(self, env): + def gen_export_dynamic_link_args(self, env: 'Environment') -> typing.List[str]: return [] # Not applicable with MSVC - def get_std_shared_lib_link_args(self): + def get_std_shared_lib_link_args(self) -> typing.List[str]: return ['/DLL'] - def gen_vs_module_defs_args(self, defsfile): + def gen_vs_module_defs_args(self, defsfile: str) -> typing.List[str]: if not isinstance(defsfile, str): raise RuntimeError('Module definitions file should be str') # With MSVC, DLLs only export symbols that are explicitly exported, # so if a module defs file is specified, we use that to export symbols return ['/DEF:' + defsfile] - def gen_pch_args(self, header, source, pchname): + def gen_pch_args(self, header: str, source: str, pchname: str) -> typing.Tuple[str, typing.List[str]]: objname = os.path.splitext(pchname)[0] + '.obj' return objname, ['/Yc' + header, '/Fp' + pchname, '/Fo' + objname] - def gen_import_library_args(self, implibname): + def gen_import_library_args(self, implibname: str) -> typing.List[str]: "The name of the outputted import library" return ['/IMPLIB:' + implibname] - def build_rpath_args(self, build_dir, from_dir, rpath_paths, build_rpath, install_rpath): + def build_rpath_args(self, build_dir: str, from_dir: str, rpath_paths: str, build_rpath: str, install_rpath: str) -> typing.List[str]: return [] - def openmp_flags(self): + def openmp_flags(self) -> typing.List[str]: return ['/openmp'] # FIXME, no idea what these should be. - def thread_flags(self, env): + def thread_flags(self, env: 'Environment') -> typing.List[str]: return [] - def thread_link_flags(self, env): + def thread_link_flags(self, env: 'Environment') -> typing.List[str]: return [] @classmethod - def unix_args_to_native(cls, args): + def unix_args_to_native(cls, args: typing.List[str]) -> typing.List[str]: result = [] for i in args: # -mms-bitfields is specific to MinGW-GCC @@ -274,16 +287,16 @@ class VisualStudioLikeCompiler(metaclass=abc.ABCMeta): result.append(i) return result - def get_werror_args(self): + def get_werror_args(self) -> typing.List[str]: return ['/WX'] - def get_include_args(self, path, is_system): + def get_include_args(self, path: str, is_system: bool) -> typing.List[str]: if path == '': path = '.' # msvc does not have a concept of system header dirs. return ['-I' + path] - def compute_parameters_with_absolute_paths(self, parameter_list, build_dir): + def compute_parameters_with_absolute_paths(self, parameter_list: typing.List[str], build_dir: str) -> typing.List[str]: for idx, i in enumerate(parameter_list): if i[:2] == '-I' or i[:2] == '/I': parameter_list[idx] = i[:2] + os.path.normpath(os.path.join(build_dir, i[2:])) @@ -295,7 +308,7 @@ class VisualStudioLikeCompiler(metaclass=abc.ABCMeta): # Visual Studio is special. It ignores some arguments it does not # understand and you can't tell it to error out on those. # http://stackoverflow.com/questions/15259720/how-can-i-make-the-microsoft-c-compiler-treat-unknown-flags-as-errors-rather-t - def has_arguments(self, args, env, code, mode): + def has_arguments(self, args: typing.List[str], env: 'Environment', code, mode: str) -> typing.Tuple[bool, bool]: warning_text = '4044' if mode == 'link' else '9002' if self.id == 'clang-cl' and mode != 'link': args = args + ['-Werror=unknown-argument'] @@ -304,7 +317,7 @@ class VisualStudioLikeCompiler(metaclass=abc.ABCMeta): return False, p.cached return not(warning_text in p.stde or warning_text in p.stdo), p.cached - def get_compile_debugfile_args(self, rel_obj, pch=False): + def get_compile_debugfile_args(self, rel_obj: str, pch: bool = False) -> typing.List[str]: pdbarr = rel_obj.split('.')[:-1] pdbarr += ['pdb'] args = ['/Fd' + '.'.join(pdbarr)] @@ -318,17 +331,17 @@ class VisualStudioLikeCompiler(metaclass=abc.ABCMeta): args = ['/FS'] + args return args - def get_link_debugfile_args(self, targetfile): + def get_link_debugfile_args(self, targetfile: str) -> typing.List[str]: pdbarr = targetfile.split('.')[:-1] pdbarr += ['pdb'] return ['/DEBUG', '/PDB:' + '.'.join(pdbarr)] - def get_link_whole_for(self, args): + def get_link_whole_for(self, args: typing.List[str]) -> typing.List[str]: # Only since VS2015 args = mesonlib.listify(args) return ['/WHOLEARCHIVE:' + x for x in args] - def get_instruction_set_args(self, instruction_set): + def get_instruction_set_args(self, instruction_set: str) -> typing.Optional[typing.List[str]]: if self.is_64: return vs64_instruction_set_args.get(instruction_set, None) if self.id == 'msvc' and self.version.split('.')[0] == '16' and instruction_set == 'avx': @@ -362,7 +375,7 @@ class VisualStudioLikeCompiler(metaclass=abc.ABCMeta): mlog.warning('Could not find toolset for version {!r}'.format(self.version)) return None - def get_toolset_version(self): + def get_toolset_version(self) -> typing.Optional[str]: if self.id == 'clang-cl': # I have no idea return '14.1' @@ -374,12 +387,12 @@ class VisualStudioLikeCompiler(metaclass=abc.ABCMeta): return None return self._calculate_toolset_version(version) - def get_default_include_dirs(self): + def get_default_include_dirs(self) -> typing.List[str]: if 'INCLUDE' not in os.environ: return [] return os.environ['INCLUDE'].split(os.pathsep) - def get_crt_compile_args(self, crt_val, buildtype): + def get_crt_compile_args(self, crt_val: str, buildtype: str) -> typing.List[str]: if crt_val in self.crt_args: return self.crt_args[crt_val] assert(crt_val == 'from_buildtype') @@ -398,14 +411,14 @@ class VisualStudioLikeCompiler(metaclass=abc.ABCMeta): assert(buildtype == 'custom') raise mesonlib.EnvironmentException('Requested C runtime based on buildtype, but buildtype is "custom".') - def has_func_attribute(self, name, env): + def has_func_attribute(self, name: str, env: 'Environment') -> typing.Tuple[bool, bool]: # MSVC doesn't have __attribute__ like Clang and GCC do, so just return # false without compiling anything return name in ['dllimport', 'dllexport'], False - def get_argument_syntax(self): + def get_argument_syntax(self) -> str: return 'msvc' - def get_allow_undefined_link_args(self): + def get_allow_undefined_link_args(self) -> typing.List[str]: # link.exe return ['/FORCE:UNRESOLVED']