aboutsummaryrefslogtreecommitdiff
path: root/mesonbuild
diff options
context:
space:
mode:
authorDylan Baker <dylan@pnwbakers.com>2019-07-02 11:24:44 -0700
committerDylan Baker <dylan@pnwbakers.com>2019-07-15 10:59:22 -0700
commit214ab455d3a16215ffdca5a4235148f06e7b22fd (patch)
tree83b048d9b74ecc1052a0bfd0b704c955549b4e68 /mesonbuild
parent51c66752a9561b1c444dc36cf9edd1fe0431bef8 (diff)
downloadmeson-214ab455d3a16215ffdca5a4235148f06e7b22fd.zip
meson-214ab455d3a16215ffdca5a4235148f06e7b22fd.tar.gz
meson-214ab455d3a16215ffdca5a4235148f06e7b22fd.tar.bz2
compilers: Move the VisualStudioLikeCompiler class into mixins
Diffstat (limited to 'mesonbuild')
-rw-r--r--mesonbuild/compilers/__init__.py2
-rw-r--r--mesonbuild/compilers/c.py2
-rw-r--r--mesonbuild/compilers/compilers.py387
-rw-r--r--mesonbuild/compilers/cpp.py2
-rw-r--r--mesonbuild/compilers/mixins/clike.py5
-rw-r--r--mesonbuild/compilers/mixins/visualstudio.py411
6 files changed, 418 insertions, 391 deletions
diff --git a/mesonbuild/compilers/__init__.py b/mesonbuild/compilers/__init__.py
index 0f0db44..98241a6 100644
--- a/mesonbuild/compilers/__init__.py
+++ b/mesonbuild/compilers/__init__.py
@@ -123,7 +123,6 @@ from .compilers import (
CompilerArgs,
GnuCompiler,
IntelGnuLikeCompiler,
- VisualStudioLikeCompiler,
IntelVisualStudioLikeCompiler,
)
from .c import (
@@ -190,3 +189,4 @@ from .objcpp import (
from .rust import RustCompiler
from .swift import SwiftCompiler
from .vala import ValaCompiler
+from .mixins.visualstudio import VisualStudioLikeCompiler
diff --git a/mesonbuild/compilers/c.py b/mesonbuild/compilers/c.py
index 90dd51f..2effec6 100644
--- a/mesonbuild/compilers/c.py
+++ b/mesonbuild/compilers/c.py
@@ -21,6 +21,7 @@ from .c_function_attributes import C_FUNC_ATTRIBUTES
from .mixins.clike import CLikeCompiler
from .mixins.ccrx import CcrxCompiler
from .mixins.arm import ArmCompiler
+from .mixins.visualstudio import VisualStudioLikeCompiler
from .compilers import (
gnu_winlibs,
msvc_winlibs,
@@ -33,7 +34,6 @@ from .compilers import (
IntelGnuLikeCompiler,
IntelVisualStudioLikeCompiler,
PGICompiler,
- VisualStudioLikeCompiler,
)
diff --git a/mesonbuild/compilers/compilers.py b/mesonbuild/compilers/compilers.py
index 7304954..0b06072 100644
--- a/mesonbuild/compilers/compilers.py
+++ b/mesonbuild/compilers/compilers.py
@@ -29,6 +29,7 @@ from ..mesonlib import (
from ..envconfig import (
Properties,
)
+from .mixins.visualstudio import VisualStudioLikeCompiler
"""This file contains the data files of all compilers Meson knows
about. To support a new compiler, add its information below.
@@ -160,14 +161,6 @@ cuda_buildtype_args = {'plain': [],
'release': [],
'minsize': [],
}
-msvc_buildtype_args = {'plain': [],
- 'debug': ["/ZI", "/Ob0", "/Od", "/RTC1"],
- 'debugoptimized': ["/Zi", "/Ob1"],
- 'release': ["/Ob2", "/Gw"],
- 'minsize': ["/Zi", "/Gw"],
- 'custom': [],
- }
-
pgi_buildtype_args = {'plain': [],
'debug': [],
'debugoptimized': [],
@@ -200,17 +193,6 @@ pgi_buildtype_linker_args = {'plain': [],
'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': [],
- }
-
java_buildtype_args = {'plain': [],
'debug': ['-g'],
'debugoptimized': ['-g'],
@@ -308,14 +290,6 @@ gnu_optimization_args = {'0': [],
's': ['-Os'],
}
-msvc_optimization_args = {'0': [],
- 'g': ['/O0'],
- '1': ['/O1'],
- '2': ['/O2'],
- '3': ['/O2'],
- 's': ['/O1'], # Implies /Os.
- }
-
cuda_optimization_args = {'0': [],
'g': ['-O0'],
'1': ['-O1'],
@@ -330,9 +304,6 @@ cuda_debug_args = {False: [],
clike_debug_args = {False: [],
True: ['-g']}
-msvc_debug_args = {False: [],
- True: []} # Fixme!
-
base_options = {'b_pch': coredata.UserBooleanOption('Use precompiled headers', True),
'b_lto': coredata.UserBooleanOption('Use link time optimization', False),
'b_sanitize': coredata.UserComboOption('Code sanitizer to use',
@@ -373,30 +344,6 @@ gnulike_instruction_set_args = {'mmx': ['-mmmx'],
'neon': ['-mfpu=neon'],
}
-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,
- }
-
-# 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,
- }
-
gnu_symbol_visibility_args = {'': [],
'default': ['-fvisibility=default'],
'internal': ['-fvisibility=internal'],
@@ -1486,338 +1433,6 @@ def gnulike_default_include_dirs(compiler, lang):
return paths
-class VisualStudioLikeCompiler(metaclass=abc.ABCMeta):
-
- """A common interface for all compilers implementing an MSVC-style
- interface.
-
- A number of compilers attempt to mimic MSVC, with varying levels of
- success, such as Clang-CL and ICL (the Intel C/C++ Compiler for Windows).
- This classs implements as much common logic as possible.
- """
-
- std_warn_args = ['/W3']
- std_opt_args = ['/O2']
- ignore_libs = unixy_compiler_internal_libs
- internal_libs = ()
-
- crt_args = {'none': [],
- 'md': ['/MD'],
- 'mdd': ['/MDd'],
- 'mt': ['/MT'],
- 'mtd': ['/MTd'],
- }
- # /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'],
- }
-
- def __init__(self, target: str):
- self.base_options = ['b_pch', 'b_ndebug', 'b_vscrt'] # FIXME add lto, pgo and the like
- self.target = target
- self.is_64 = ('x64' in target) or ('x86_64' in target)
- # do some canonicalization of target machine
- if 'x86_64' in target:
- self.machine = 'x64'
- elif '86' in target:
- self.machine = 'x86'
- else:
- self.machine = target
-
- # Override CCompiler.get_always_args
- def get_always_args(self):
- return self.always_args
-
- def get_linker_debug_crt_args(self):
- """
- Arguments needed to select a debug crt for the linker
-
- Sometimes we need to manually select the CRT (C runtime) to use with
- MSVC. One example is when trying to link with static libraries since
- MSVC won't auto-select a CRT for us in that case and will error out
- asking us to select one.
- """
- return ['/MDd']
-
- def get_buildtype_args(self, buildtype):
- args = msvc_buildtype_args[buildtype]
- if self.id == 'msvc' and version_compare(self.version, '<18.0'):
- args = [arg for arg in args if arg != '/Gw']
- return args
-
- def get_buildtype_linker_args(self, buildtype):
- return msvc_buildtype_linker_args[buildtype]
-
- def get_pch_suffix(self):
- return 'pch'
-
- def get_pch_name(self, header):
- 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):
- 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):
- return ['/EP']
-
- def get_compile_only_args(self):
- return ['/c']
-
- def get_no_optimization_args(self):
- return ['/Od']
-
- def get_output_args(self, target):
- if target.endswith('.exe'):
- return ['/Fe' + target]
- return ['/Fo' + target]
-
- def get_optimization_args(self, optimization_level):
- return msvc_optimization_args[optimization_level]
-
- def get_debug_args(self, is_debug):
- return msvc_debug_args[is_debug]
-
- def get_dependency_gen_args(self, outtarget, outfile):
- return []
-
- def get_linker_exelist(self):
- # FIXME, should have same path as compiler.
- # FIXME, should be controllable via cross-file.
- if self.id == 'clang-cl':
- return ['lld-link']
- else:
- return ['link']
-
- def get_linker_always_args(self):
- return ['/nologo']
-
- def get_linker_output_args(self, outputname):
- return ['/MACHINE:' + self.machine, '/OUT:' + outputname]
-
- def get_linker_search_args(self, dirname):
- return ['/LIBPATH:' + dirname]
-
- def linker_to_compiler_args(self, args):
- return ['/link'] + args
-
- def get_gui_app_args(self, value):
- # the default is for the linker to guess the subsystem based on presence
- # of main or WinMain symbols, so always be explicit
- if value:
- return ['/SUBSYSTEM:WINDOWS']
- else:
- return ['/SUBSYSTEM:CONSOLE']
-
- def get_pic_args(self):
- return [] # PIC is handled by the loader on Windows
-
- def gen_export_dynamic_link_args(self, env):
- return [] # Not applicable with MSVC
-
- def get_std_shared_lib_link_args(self):
- return ['/DLL']
-
- def gen_vs_module_defs_args(self, defsfile):
- 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):
- objname = os.path.splitext(pchname)[0] + '.obj'
- return objname, ['/Yc' + header, '/Fp' + pchname, '/Fo' + objname]
-
- def gen_import_library_args(self, implibname):
- "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):
- return []
-
- def openmp_flags(self):
- return ['/openmp']
-
- # FIXME, no idea what these should be.
- def thread_flags(self, env):
- return []
-
- def thread_link_flags(self, env):
- return []
-
- @classmethod
- def unix_args_to_native(cls, args):
- result = []
- for i in args:
- # -mms-bitfields is specific to MinGW-GCC
- # -pthread is only valid for GCC
- if i in ('-mms-bitfields', '-pthread'):
- continue
- if i.startswith('-L'):
- i = '/LIBPATH:' + i[2:]
- # Translate GNU-style -lfoo library name to the import library
- elif i.startswith('-l'):
- name = i[2:]
- if name in cls.ignore_libs:
- # With MSVC, these are provided by the C runtime which is
- # linked in by default
- continue
- else:
- i = name + '.lib'
- # -pthread in link flags is only used on Linux
- elif i == '-pthread':
- continue
- result.append(i)
- return result
-
- def get_werror_args(self):
- return ['/WX']
-
- def get_include_args(self, path, is_system):
- 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):
- 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:]))
- elif i[:9] == '/LIBPATH:':
- parameter_list[idx] = i[:9] + os.path.normpath(os.path.join(build_dir, i[9:]))
-
- return parameter_list
-
- # 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):
- warning_text = '4044' if mode == 'link' else '9002'
- if self.id == 'clang-cl' and mode != 'link':
- args = args + ['-Werror=unknown-argument']
- with self._build_wrapper(code, env, extra_args=args, mode=mode) as p:
- if p.returncode != 0:
- 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):
- pdbarr = rel_obj.split('.')[:-1]
- pdbarr += ['pdb']
- args = ['/Fd' + '.'.join(pdbarr)]
- # When generating a PDB file with PCH, all compile commands write
- # to the same PDB file. Hence, we need to serialize the PDB
- # writes using /FS since we do parallel builds. This slows down the
- # build obviously, which is why we only do this when PCH is on.
- # This was added in Visual Studio 2013 (MSVC 18.0). Before that it was
- # always on: https://msdn.microsoft.com/en-us/library/dn502518.aspx
- if pch and self.id == 'msvc' and version_compare(self.version, '>=18.0'):
- args = ['/FS'] + args
- return args
-
- def get_link_debugfile_args(self, targetfile):
- pdbarr = targetfile.split('.')[:-1]
- pdbarr += ['pdb']
- return ['/DEBUG', '/PDB:' + '.'.join(pdbarr)]
-
- def get_link_whole_for(self, args):
- # Only since VS2015
- args = mesonlib.listify(args)
- return ['/WHOLEARCHIVE:' + x for x in args]
-
- def get_instruction_set_args(self, instruction_set):
- 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':
- # VS documentation says that this exists and should work, but
- # it does not. The headers do not contain AVX intrinsics
- # and the can not be called.
- return None
- return vs32_instruction_set_args.get(instruction_set, None)
-
- def _calculate_toolset_version(self, version: int) -> Optional[str]:
- if version < 1310:
- return '7.0'
- elif version < 1400:
- return '7.1' # (Visual Studio 2003)
- elif version < 1500:
- return '8.0' # (Visual Studio 2005)
- elif version < 1600:
- return '9.0' # (Visual Studio 2008)
- elif version < 1700:
- return '10.0' # (Visual Studio 2010)
- elif version < 1800:
- return '11.0' # (Visual Studio 2012)
- elif version < 1900:
- return '12.0' # (Visual Studio 2013)
- elif version < 1910:
- return '14.0' # (Visual Studio 2015)
- elif version < 1920:
- return '14.1' # (Visual Studio 2017)
- elif version < 1930:
- return '14.2' # (Visual Studio 2019)
- mlog.warning('Could not find toolset for version {!r}'.format(self.version))
- return None
-
- def get_toolset_version(self):
- if self.id == 'clang-cl':
- # I have no idea
- return '14.1'
-
- # See boost/config/compiler/visualc.cpp for up to date mapping
- try:
- version = int(''.join(self.version.split('.')[0:2]))
- except ValueError:
- return None
- return self._calculate_toolset_version(version)
-
- def get_default_include_dirs(self):
- if 'INCLUDE' not in os.environ:
- return []
- return os.environ['INCLUDE'].split(os.pathsep)
-
- def get_crt_compile_args(self, crt_val, buildtype):
- if crt_val in self.crt_args:
- return self.crt_args[crt_val]
- assert(crt_val == 'from_buildtype')
- # Match what build type flags used to do.
- if buildtype == 'plain':
- return []
- elif buildtype == 'debug':
- return self.crt_args['mdd']
- elif buildtype == 'debugoptimized':
- return self.crt_args['md']
- elif buildtype == 'release':
- return self.crt_args['md']
- elif buildtype == 'minsize':
- return self.crt_args['md']
- else:
- assert(buildtype == 'custom')
- raise mesonlib.EnvironmentException('Requested C runtime based on buildtype, but buildtype is "custom".')
-
- def has_func_attribute(self, name, env):
- # 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):
- return 'msvc'
-
- def get_allow_undefined_link_args(self):
- # link.exe
- return ['/FORCE:UNRESOLVED']
-
-
class GnuLikeCompiler(abc.ABC):
"""
GnuLikeCompiler is a common interface to all compilers implementing
diff --git a/mesonbuild/compilers/cpp.py b/mesonbuild/compilers/cpp.py
index 15edea0..cf893b9 100644
--- a/mesonbuild/compilers/cpp.py
+++ b/mesonbuild/compilers/cpp.py
@@ -32,12 +32,12 @@ from .compilers import (
PGICompiler,
ArmclangCompiler,
Compiler,
- VisualStudioLikeCompiler,
)
from .c_function_attributes import CXX_FUNC_ATTRIBUTES, C_FUNC_ATTRIBUTES
from .mixins.clike import CLikeCompiler
from .mixins.ccrx import CcrxCompiler
from .mixins.arm import ArmCompiler
+from .mixins.visualstudio import VisualStudioLikeCompiler
def non_msvc_eh_options(eh, args):
diff --git a/mesonbuild/compilers/mixins/clike.py b/mesonbuild/compilers/mixins/clike.py
index 3097603..b378252 100644
--- a/mesonbuild/compilers/mixins/clike.py
+++ b/mesonbuild/compilers/mixins/clike.py
@@ -33,6 +33,7 @@ from ... import mesonlib
from ...mesonlib import LibType
from ... import mlog
from .. import compilers
+from .visualstudio import VisualStudioLikeCompiler
class CLikeCompiler:
@@ -872,7 +873,7 @@ class CLikeCompiler:
# people depend on it. Also, some people use prebuilt `foo.so` instead
# of `libfoo.so` for unknown reasons, and may also want to create
# `foo.so` by setting name_prefix to ''
- if strict and not isinstance(self, compilers.VisualStudioLikeCompiler): # lib prefix is not usually used with msvc
+ if strict and not isinstance(self, VisualStudioLikeCompiler): # lib prefix is not usually used with msvc
prefixes = ['lib']
else:
prefixes = ['lib', '']
@@ -882,7 +883,7 @@ class CLikeCompiler:
elif env.machines[self.for_machine].is_windows():
# FIXME: .lib files can be import or static so we should read the
# file, figure out which one it is, and reject the wrong kind.
- if isinstance(self, compilers.VisualStudioLikeCompiler):
+ if isinstance(self, VisualStudioLikeCompiler):
shlibext = ['lib']
else:
shlibext = ['dll.a', 'lib', 'dll']
diff --git a/mesonbuild/compilers/mixins/visualstudio.py b/mesonbuild/compilers/mixins/visualstudio.py
new file mode 100644
index 0000000..4c5eec9
--- /dev/null
+++ b/mesonbuild/compilers/mixins/visualstudio.py
@@ -0,0 +1,411 @@
+# Copyright 2019 The meson development team
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+"""Abstractions to simplify compilers that implement an MSVC compatible
+interface.
+"""
+
+import abc
+import os
+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,
+ }
+
+# 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,
+ }
+
+
+class VisualStudioLikeCompiler(metaclass=abc.ABCMeta):
+
+ """A common interface for all compilers implementing an MSVC-style
+ interface.
+
+ A number of compilers attempt to mimic MSVC, with varying levels of
+ success, such as Clang-CL and ICL (the Intel C/C++ Compiler for Windows).
+ This classs implements as much common logic as possible.
+ """
+
+ std_warn_args = ['/W3']
+ std_opt_args = ['/O2']
+ # XXX: this is copied in this patch only to avoid circular dependencies
+ #ignore_libs = unixy_compiler_internal_libs
+ ignore_libs = ('m', 'c', 'pthread', 'dl', 'rt', 'execinfo')
+ internal_libs = ()
+
+ crt_args = {'none': [],
+ 'md': ['/MD'],
+ 'mdd': ['/MDd'],
+ 'mt': ['/MT'],
+ 'mtd': ['/MTd'],
+ }
+ # /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'],
+ }
+
+ def __init__(self, target: str):
+ self.base_options = ['b_pch', 'b_ndebug', 'b_vscrt'] # FIXME add lto, pgo and the like
+ self.target = target
+ self.is_64 = ('x64' in target) or ('x86_64' in target)
+ # do some canonicalization of target machine
+ if 'x86_64' in target:
+ self.machine = 'x64'
+ elif '86' in target:
+ self.machine = 'x86'
+ else:
+ self.machine = target
+
+ # Override CCompiler.get_always_args
+ def get_always_args(self):
+ return self.always_args
+
+ def get_linker_debug_crt_args(self):
+ """
+ Arguments needed to select a debug crt for the linker
+
+ Sometimes we need to manually select the CRT (C runtime) to use with
+ MSVC. One example is when trying to link with static libraries since
+ MSVC won't auto-select a CRT for us in that case and will error out
+ asking us to select one.
+ """
+ return ['/MDd']
+
+ def get_buildtype_args(self, buildtype):
+ 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):
+ return msvc_buildtype_linker_args[buildtype]
+
+ def get_pch_suffix(self):
+ return 'pch'
+
+ def get_pch_name(self, header):
+ 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):
+ 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):
+ return ['/EP']
+
+ def get_compile_only_args(self):
+ return ['/c']
+
+ def get_no_optimization_args(self):
+ return ['/Od']
+
+ def get_output_args(self, target):
+ if target.endswith('.exe'):
+ return ['/Fe' + target]
+ return ['/Fo' + target]
+
+ def get_optimization_args(self, optimization_level):
+ return msvc_optimization_args[optimization_level]
+
+ def get_debug_args(self, is_debug):
+ return msvc_debug_args[is_debug]
+
+ def get_dependency_gen_args(self, outtarget, outfile):
+ return []
+
+ def get_linker_exelist(self):
+ # FIXME, should have same path as compiler.
+ # FIXME, should be controllable via cross-file.
+ if self.id == 'clang-cl':
+ return ['lld-link']
+ else:
+ return ['link']
+
+ def get_linker_always_args(self):
+ return ['/nologo']
+
+ def get_linker_output_args(self, outputname):
+ return ['/MACHINE:' + self.machine, '/OUT:' + outputname]
+
+ def get_linker_search_args(self, dirname):
+ return ['/LIBPATH:' + dirname]
+
+ def linker_to_compiler_args(self, args):
+ return ['/link'] + args
+
+ def get_gui_app_args(self, value):
+ # the default is for the linker to guess the subsystem based on presence
+ # of main or WinMain symbols, so always be explicit
+ if value:
+ return ['/SUBSYSTEM:WINDOWS']
+ else:
+ return ['/SUBSYSTEM:CONSOLE']
+
+ def get_pic_args(self):
+ return [] # PIC is handled by the loader on Windows
+
+ def gen_export_dynamic_link_args(self, env):
+ return [] # Not applicable with MSVC
+
+ def get_std_shared_lib_link_args(self):
+ return ['/DLL']
+
+ def gen_vs_module_defs_args(self, defsfile):
+ 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):
+ objname = os.path.splitext(pchname)[0] + '.obj'
+ return objname, ['/Yc' + header, '/Fp' + pchname, '/Fo' + objname]
+
+ def gen_import_library_args(self, implibname):
+ "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):
+ return []
+
+ def openmp_flags(self):
+ return ['/openmp']
+
+ # FIXME, no idea what these should be.
+ def thread_flags(self, env):
+ return []
+
+ def thread_link_flags(self, env):
+ return []
+
+ @classmethod
+ def unix_args_to_native(cls, args):
+ result = []
+ for i in args:
+ # -mms-bitfields is specific to MinGW-GCC
+ # -pthread is only valid for GCC
+ if i in ('-mms-bitfields', '-pthread'):
+ continue
+ if i.startswith('-L'):
+ i = '/LIBPATH:' + i[2:]
+ # Translate GNU-style -lfoo library name to the import library
+ elif i.startswith('-l'):
+ name = i[2:]
+ if name in cls.ignore_libs:
+ # With MSVC, these are provided by the C runtime which is
+ # linked in by default
+ continue
+ else:
+ i = name + '.lib'
+ # -pthread in link flags is only used on Linux
+ elif i == '-pthread':
+ continue
+ result.append(i)
+ return result
+
+ def get_werror_args(self):
+ return ['/WX']
+
+ def get_include_args(self, path, is_system):
+ 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):
+ 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:]))
+ elif i[:9] == '/LIBPATH:':
+ parameter_list[idx] = i[:9] + os.path.normpath(os.path.join(build_dir, i[9:]))
+
+ return parameter_list
+
+ # 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):
+ warning_text = '4044' if mode == 'link' else '9002'
+ if self.id == 'clang-cl' and mode != 'link':
+ args = args + ['-Werror=unknown-argument']
+ with self._build_wrapper(code, env, extra_args=args, mode=mode) as p:
+ if p.returncode != 0:
+ 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):
+ pdbarr = rel_obj.split('.')[:-1]
+ pdbarr += ['pdb']
+ args = ['/Fd' + '.'.join(pdbarr)]
+ # When generating a PDB file with PCH, all compile commands write
+ # to the same PDB file. Hence, we need to serialize the PDB
+ # writes using /FS since we do parallel builds. This slows down the
+ # build obviously, which is why we only do this when PCH is on.
+ # This was added in Visual Studio 2013 (MSVC 18.0). Before that it was
+ # always on: https://msdn.microsoft.com/en-us/library/dn502518.aspx
+ if pch and self.id == 'msvc' and mesonlib.version_compare(self.version, '>=18.0'):
+ args = ['/FS'] + args
+ return args
+
+ def get_link_debugfile_args(self, targetfile):
+ pdbarr = targetfile.split('.')[:-1]
+ pdbarr += ['pdb']
+ return ['/DEBUG', '/PDB:' + '.'.join(pdbarr)]
+
+ def get_link_whole_for(self, args):
+ # Only since VS2015
+ args = mesonlib.listify(args)
+ return ['/WHOLEARCHIVE:' + x for x in args]
+
+ def get_instruction_set_args(self, instruction_set):
+ 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':
+ # VS documentation says that this exists and should work, but
+ # it does not. The headers do not contain AVX intrinsics
+ # and the can not be called.
+ return None
+ return vs32_instruction_set_args.get(instruction_set, None)
+
+ def _calculate_toolset_version(self, version: int) -> typing.Optional[str]:
+ if version < 1310:
+ return '7.0'
+ elif version < 1400:
+ return '7.1' # (Visual Studio 2003)
+ elif version < 1500:
+ return '8.0' # (Visual Studio 2005)
+ elif version < 1600:
+ return '9.0' # (Visual Studio 2008)
+ elif version < 1700:
+ return '10.0' # (Visual Studio 2010)
+ elif version < 1800:
+ return '11.0' # (Visual Studio 2012)
+ elif version < 1900:
+ return '12.0' # (Visual Studio 2013)
+ elif version < 1910:
+ return '14.0' # (Visual Studio 2015)
+ elif version < 1920:
+ return '14.1' # (Visual Studio 2017)
+ elif version < 1930:
+ return '14.2' # (Visual Studio 2019)
+ mlog.warning('Could not find toolset for version {!r}'.format(self.version))
+ return None
+
+ def get_toolset_version(self):
+ if self.id == 'clang-cl':
+ # I have no idea
+ return '14.1'
+
+ # See boost/config/compiler/visualc.cpp for up to date mapping
+ try:
+ version = int(''.join(self.version.split('.')[0:2]))
+ except ValueError:
+ return None
+ return self._calculate_toolset_version(version)
+
+ def get_default_include_dirs(self):
+ if 'INCLUDE' not in os.environ:
+ return []
+ return os.environ['INCLUDE'].split(os.pathsep)
+
+ def get_crt_compile_args(self, crt_val, buildtype):
+ if crt_val in self.crt_args:
+ return self.crt_args[crt_val]
+ assert(crt_val == 'from_buildtype')
+ # Match what build type flags used to do.
+ if buildtype == 'plain':
+ return []
+ elif buildtype == 'debug':
+ return self.crt_args['mdd']
+ elif buildtype == 'debugoptimized':
+ return self.crt_args['md']
+ elif buildtype == 'release':
+ return self.crt_args['md']
+ elif buildtype == 'minsize':
+ return self.crt_args['md']
+ else:
+ assert(buildtype == 'custom')
+ raise mesonlib.EnvironmentException('Requested C runtime based on buildtype, but buildtype is "custom".')
+
+ def has_func_attribute(self, name, env):
+ # 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):
+ return 'msvc'
+
+ def get_allow_undefined_link_args(self):
+ # link.exe
+ return ['/FORCE:UNRESOLVED']