diff options
author | Jussi Pakkanen <jpakkane@gmail.com> | 2019-05-14 00:24:48 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-05-14 00:24:48 +0300 |
commit | 7b8ef78bc0002d0327626c6218b793f87c2a5eb8 (patch) | |
tree | 44ffa3b3c11e8e154615d65e79f9c79f5334648d /mesonbuild/compilers | |
parent | b849f6f935787055834ed3745faf7203c22c982b (diff) | |
parent | 523c7beefc170395fd3f49cf4609aadb8e986ad1 (diff) | |
download | meson-7b8ef78bc0002d0327626c6218b793f87c2a5eb8.zip meson-7b8ef78bc0002d0327626c6218b793f87c2a5eb8.tar.gz meson-7b8ef78bc0002d0327626c6218b793f87c2a5eb8.tar.bz2 |
Merge pull request #5331 from dcbaker/icl
ICL (Intel for Windows) support
Diffstat (limited to 'mesonbuild/compilers')
-rw-r--r-- | mesonbuild/compilers/__init__.py | 12 | ||||
-rw-r--r-- | mesonbuild/compilers/c.py | 39 | ||||
-rw-r--r-- | mesonbuild/compilers/clike.py | 4 | ||||
-rw-r--r-- | mesonbuild/compilers/compilers.py | 75 | ||||
-rw-r--r-- | mesonbuild/compilers/cpp.py | 111 | ||||
-rw-r--r-- | mesonbuild/compilers/fortran.py | 38 |
6 files changed, 219 insertions, 60 deletions
diff --git a/mesonbuild/compilers/__init__.py b/mesonbuild/compilers/__init__.py index 3c06f38..ea65c21 100644 --- a/mesonbuild/compilers/__init__.py +++ b/mesonbuild/compilers/__init__.py @@ -65,10 +65,14 @@ __all__ = [ 'FlangFortranCompiler', 'GnuObjCCompiler', 'GnuObjCPPCompiler', - 'IntelCompiler', + 'IntelGnuLikeCompiler', + 'IntelVisualStudioLikeCompiler', 'IntelCCompiler', 'IntelCPPCompiler', + 'IntelClCCompiler', + 'IntelClCPPCompiler', 'IntelFortranCompiler', + 'IntelClFortranCompiler', 'JavaCompiler', 'LLVMDCompiler', 'MonoCompiler', @@ -119,9 +123,10 @@ from .compilers import ( ClangCompiler, CompilerArgs, GnuCompiler, - IntelCompiler, + IntelGnuLikeCompiler, CcrxCompiler, VisualStudioLikeCompiler, + IntelVisualStudioLikeCompiler, ) from .c import ( CCompiler, @@ -132,6 +137,7 @@ from .c import ( GnuCCompiler, ElbrusCCompiler, IntelCCompiler, + IntelClCCompiler, PGICCompiler, CcrxCCompiler, VisualStudioCCompiler, @@ -145,6 +151,7 @@ from .cpp import ( GnuCPPCompiler, ElbrusCPPCompiler, IntelCPPCompiler, + IntelClCPPCompiler, PGICPPCompiler, CcrxCPPCompiler, VisualStudioCPPCompiler, @@ -164,6 +171,7 @@ from .fortran import ( ElbrusFortranCompiler, FlangFortranCompiler, IntelFortranCompiler, + IntelClFortranCompiler, NAGFortranCompiler, Open64FortranCompiler, PathScaleFortranCompiler, diff --git a/mesonbuild/compilers/c.py b/mesonbuild/compilers/c.py index 73a4083..0cfcbc3 100644 --- a/mesonbuild/compilers/c.py +++ b/mesonbuild/compilers/c.py @@ -16,7 +16,7 @@ import os.path import typing from .. import coredata -from ..mesonlib import MesonException, version_compare +from ..mesonlib import MesonException, version_compare, mlog from .c_function_attributes import C_FUNC_ATTRIBUTES from .clike import CLikeCompiler @@ -30,7 +30,8 @@ from .compilers import ( CompilerType, GnuCompiler, ElbrusCompiler, - IntelCompiler, + IntelGnuLikeCompiler, + IntelVisualStudioLikeCompiler, PGICompiler, CcrxCompiler, VisualStudioLikeCompiler, @@ -221,10 +222,10 @@ class ElbrusCCompiler(GnuCCompiler, ElbrusCompiler): dependencies=dependencies) -class IntelCCompiler(IntelCompiler, CCompiler): +class IntelCCompiler(IntelGnuLikeCompiler, CCompiler): def __init__(self, exelist, version, compiler_type, is_cross, exe_wrapper=None, **kwargs): CCompiler.__init__(self, exelist, version, is_cross, exe_wrapper, **kwargs) - IntelCompiler.__init__(self, compiler_type) + IntelGnuLikeCompiler.__init__(self, compiler_type) self.lang_header = 'c-header' default_warn_args = ['-Wall', '-w3', '-diag-disable:remark'] self.warn_args = {'0': [], @@ -279,6 +280,36 @@ class ClangClCCompiler(VisualStudioLikeCompiler, VisualStudioLikeCCompilerMixin, self.id = 'clang-cl' +class IntelClCCompiler(IntelVisualStudioLikeCompiler, VisualStudioLikeCCompilerMixin, CCompiler): + + """Intel "ICL" compiler abstraction.""" + + __have_warned = False + + def __init__(self, exelist, version, is_cross, exe_wrap, target): + CCompiler.__init__(self, exelist, version, is_cross, exe_wrap) + IntelVisualStudioLikeCompiler.__init__(self, target) + + def get_options(self): + opts = super().get_options() + c_stds = ['none', 'c89', 'c99', 'c11'] + opts.update({'c_std': coredata.UserComboOption('c_std', 'C language standard to use', + c_stds, + 'none')}) + return opts + + def get_option_compile_args(self, options): + args = [] + std = options['c_std'] + if std.value == 'c89': + if not self.__have_warned: + self.__have_warned = True + mlog.warning("ICL doesn't explicitly implement c89, setting the standard to 'none', which is close.") + elif std.value != 'none': + args.append('/Qstd:' + std.value) + return args + + class ArmCCompiler(ArmCompiler, CCompiler): def __init__(self, exelist, version, compiler_type, is_cross, exe_wrapper=None, **kwargs): CCompiler.__init__(self, exelist, version, is_cross, exe_wrapper, **kwargs) diff --git a/mesonbuild/compilers/clike.py b/mesonbuild/compilers/clike.py index e9d5d1d..3d29b75 100644 --- a/mesonbuild/compilers/clike.py +++ b/mesonbuild/compilers/clike.py @@ -776,7 +776,7 @@ class CLikeCompiler: return True, cached # MSVC does not have compiler __builtin_-s. - if self.get_id() == 'msvc': + if self.get_id() in {'msvc', 'intel-cl'}: return False, False # Detect function as a built-in @@ -849,7 +849,7 @@ class CLikeCompiler: ''' args = self.get_compiler_check_args() n = 'symbols_have_underscore_prefix' - with self.compile(code, args, 'compile', want_output=True) as p: + with self.compile(code, extra_args=args, mode='compile', want_output=True) as p: if p.returncode != 0: m = 'BUG: Unable to compile {!r} check: {}' raise RuntimeError(m.format(n, p.stdo)) diff --git a/mesonbuild/compilers/compilers.py b/mesonbuild/compilers/compilers.py index bafb023..dacf75d 100644 --- a/mesonbuild/compilers/compilers.py +++ b/mesonbuild/compilers/compilers.py @@ -1146,7 +1146,7 @@ class Compiler: return os.path.join(dirname, 'output.' + suffix) @contextlib.contextmanager - def compile(self, code, extra_args=None, mode='link', want_output=False): + def compile(self, code, extra_args=None, *, mode='link', want_output=False): if extra_args is None: extra_args = [] try: @@ -1199,7 +1199,7 @@ class Compiler: pass @contextlib.contextmanager - def cached_compile(self, code, cdata: coredata.CoreData, extra_args=None, mode: str = 'link'): + def cached_compile(self, code, cdata: coredata.CoreData, *, extra_args=None, mode: str = 'link'): assert(isinstance(cdata, coredata.CoreData)) # Calculate the key @@ -1465,14 +1465,14 @@ def get_compiler_uses_gnuld(c): # FIXME: Perhaps we should detect the linker in the environment? # FIXME: Assumes that *BSD use GNU ld, but they might start using lld soon compiler_type = getattr(c, 'compiler_type', None) - return compiler_type in ( + return compiler_type in { CompilerType.GCC_STANDARD, CompilerType.GCC_MINGW, CompilerType.GCC_CYGWIN, CompilerType.CLANG_STANDARD, CompilerType.CLANG_MINGW, CompilerType.ICC_STANDARD, - CompilerType.ICC_WIN) + } def get_largefile_args(compiler): ''' @@ -1791,16 +1791,7 @@ class VisualStudioLikeCompiler(metaclass=abc.ABCMeta): return None return vs32_instruction_set_args.get(instruction_set, 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 + def _calculate_toolset_version(self, version: int) -> Optional[str]: if version < 1310: return '7.0' elif version < 1400: @@ -1824,6 +1815,18 @@ class VisualStudioLikeCompiler(metaclass=abc.ABCMeta): 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 [] @@ -2288,7 +2291,7 @@ class ArmclangCompiler: # Tested on linux for ICC 14.0.3, 15.0.6, 16.0.4, 17.0.1, 19.0.0 -class IntelCompiler(GnuLikeCompiler): +class IntelGnuLikeCompiler(GnuLikeCompiler): def __init__(self, compiler_type): super().__init__(compiler_type) @@ -2344,6 +2347,48 @@ class IntelCompiler(GnuLikeCompiler): return ['-prof-use'] +class IntelVisualStudioLikeCompiler(VisualStudioLikeCompiler): + + """Abstractions for ICL, the Intel compiler on Windows.""" + + def __init__(self, target: str): + super().__init__(target) + self.compiler_type = CompilerType.ICC_WIN + self.id = 'intel-cl' + + def compile(self, code, *, extra_args=None, **kwargs): + # This covers a case that .get('foo', []) doesn't, that extra_args is + if kwargs.get('mode', 'compile') != 'link': + extra_args = extra_args.copy() if extra_args is not None else [] + extra_args.extend([ + '/Qdiag-error:10006', # ignoring unknown option + '/Qdiag-error:10148', # Option not supported + '/Qdiag-error:10155', # ignoring argument required + '/Qdiag-error:10156', # ignoring not argument allowed + '/Qdiag-error:10157', # Ignoring argument of the wrong type + '/Qdiag-error:10158', # Argument must be separate. Can be hit by trying an option like -foo-bar=foo when -foo=bar is a valid option but -foo-bar isn't + ]) + return super().compile(code, extra_args, **kwargs) + + def get_toolset_version(self) -> Optional[str]: + # Avoid circular dependencies.... + from ..environment import search_version + + # ICL provides a cl.exe that returns the version of MSVC it tries to + # emulate, so we'll get the version from that and pass it to the same + # function the real MSVC uses to calculate the toolset version. + _, _, err = Popen_safe(['cl.exe']) + v1, v2, *_ = search_version(err).split('.') + version = int(v1 + v2) + return self._calculate_toolset_version(version) + + def get_linker_exelist(self): + return ['xilink'] + + def openmp_flags(self): + return ['/Qopenmp'] + + class ArmCompiler: # Functionality that is common to all ARM family compilers. def __init__(self, compiler_type): diff --git a/mesonbuild/compilers/cpp.py b/mesonbuild/compilers/cpp.py index 988eac6..9fae22c 100644 --- a/mesonbuild/compilers/cpp.py +++ b/mesonbuild/compilers/cpp.py @@ -12,6 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. +import copy import functools import os.path import typing @@ -26,7 +27,8 @@ from .compilers import ( ClangCompiler, GnuCompiler, ElbrusCompiler, - IntelCompiler, + IntelGnuLikeCompiler, + IntelVisualStudioLikeCompiler, PGICompiler, ArmCompiler, ArmclangCompiler, @@ -104,7 +106,7 @@ class CPPCompiler(CLikeCompiler, Compiler): # 2. even if it did have an env object, that might contain another more # recent -std= argument, which might lead to a cascaded failure. CPP_TEST = 'int i = static_cast<int>(0);' - with self.compile(code=CPP_TEST, extra_args=[cpp_std_value], mode='compile') as p: + with self.compile(CPP_TEST, extra_args=[cpp_std_value], mode='compile') as p: if p.returncode == 0: mlog.debug('Compiler accepts {}:'.format(cpp_std_value), 'YES') return True @@ -310,10 +312,10 @@ class ElbrusCPPCompiler(GnuCPPCompiler, ElbrusCompiler): dependencies=dependencies) -class IntelCPPCompiler(IntelCompiler, CPPCompiler): +class IntelCPPCompiler(IntelGnuLikeCompiler, CPPCompiler): def __init__(self, exelist, version, compiler_type, is_cross, exe_wrap, **kwargs): CPPCompiler.__init__(self, exelist, version, is_cross, exe_wrap, **kwargs) - IntelCompiler.__init__(self, compiler_type) + IntelGnuLikeCompiler.__init__(self, compiler_type) self.lang_header = 'c++-header' default_warn_args = ['-Wall', '-w3', '-diag-disable:remark', '-Wpch-messages', '-Wnon-virtual-dtor'] @@ -371,6 +373,16 @@ class VisualStudioLikeCPPCompilerMixin: """Mixin for C++ specific method overrides in MSVC-like compilers.""" + VC_VERSION_MAP = { + 'none': (True, None), + 'vc++11': (True, 11), + 'vc++14': (True, 14), + 'vc++17': (True, 17), + 'c++11': (False, 11), + 'c++14': (False, 14), + 'c++17': (False, 17), + } + def get_option_link_args(self, options): return options['cpp_winlibs'].value[:] @@ -397,34 +409,12 @@ class VisualStudioLikeCPPCompilerMixin: elif eh.value != 'none': args.append('/EH' + eh.value) - vc_version_map = { - 'none': (True, None), - 'vc++11': (True, 11), - 'vc++14': (True, 14), - 'vc++17': (True, 17), - 'c++11': (False, 11), - 'c++14': (False, 14), - 'c++17': (False, 17)} - - permissive, ver = vc_version_map[options['cpp_std'].value] - - if ver is None: - pass - elif ver == 11: - # Note: there is no explicit flag for supporting C++11; we attempt to do the best we can - # which means setting the C++ standard version to C++14, in compilers that support it - # (i.e., after VS2015U3) - # if one is using anything before that point, one cannot set the standard. - if self.id == 'clang-cl' or version_compare(self.version, '>=19.00.24210'): - mlog.warning('MSVC does not support C++11; ' - 'attempting best effort; setting the standard to C++14') - args.append('/std:c++14') - else: - mlog.warning('This version of MSVC does not support cpp_std arguments') - else: + permissive, ver = self.VC_VERSION_MAP[options['cpp_std'].value] + + if ver is not None: args.append('/std:c++{}'.format(ver)) - if not permissive and version_compare(self.version, '>=19.11'): + if not permissive: args.append('/permissive-') return args @@ -434,7 +424,33 @@ class VisualStudioLikeCPPCompilerMixin: return CLikeCompiler.get_compiler_check_args(self) -class VisualStudioCPPCompiler(VisualStudioLikeCPPCompilerMixin, VisualStudioLikeCompiler, CPPCompiler): +class CPP11AsCPP14Mixin: + + """Mixin class for VisualStudio and ClangCl to replace C++11 std with C++14. + + This is a limitation of Clang and MSVC that ICL doesn't share. + """ + + def get_option_compile_args(self, options): + # Note: there is no explicit flag for supporting C++11; we attempt to do the best we can + # which means setting the C++ standard version to C++14, in compilers that support it + # (i.e., after VS2015U3) + # if one is using anything before that point, one cannot set the standard. + if options['cpp_std'].value in {'vc++11', 'c++11'}: + mlog.warning(self.id, 'does not support C++11;', + 'attempting best effort; setting the standard to C++14') + # Don't mutate anything we're going to change, we need to use + # deepcopy since we're messing with members, and we can't simply + # copy the members because the option proxy doesn't support it. + options = copy.deepcopy(options) + if options['cpp_std'].value == 'vc++11': + options['cpp_std'].value = 'vc++14' + else: + options['cpp_std'].value = 'c++14' + return super().get_option_compile_args(options) + + +class VisualStudioCPPCompiler(CPP11AsCPP14Mixin, VisualStudioLikeCPPCompilerMixin, VisualStudioLikeCompiler, CPPCompiler): def __init__(self, exelist, version, is_cross, exe_wrap, target): CPPCompiler.__init__(self, exelist, version, is_cross, exe_wrap) VisualStudioLikeCompiler.__init__(self, target) @@ -445,14 +461,29 @@ class VisualStudioCPPCompiler(VisualStudioLikeCPPCompilerMixin, VisualStudioLike cpp_stds = ['none', 'c++11', 'vc++11'] # Visual Studio 2015 and later if version_compare(self.version, '>=19'): - cpp_stds.extend(['c++14', 'vc++14', 'c++latest', 'vc++latest']) + cpp_stds.extend(['c++14', 'c++latest', 'vc++latest']) # Visual Studio 2017 and later if version_compare(self.version, '>=19.11'): - cpp_stds.extend(['c++17', 'vc++17']) + cpp_stds.extend(['vc++14', 'c++17', 'vc++17']) return self._get_options_impl(super().get_options(), cpp_stds) + def get_option_compile_args(self, options): + if options['cpp_std'].value != 'none' and version_compare(self.version, '<19.00.24210'): + mlog.warning('This version of MSVC does not support cpp_std arguments') + options = copy.copy(options) + options['cpp_std'].value = 'none' + + args = super().get_option_compile_args(options) + + if version_compare(self.version, '<19.11'): + try: + i = args.index('/permissive-') + except ValueError: + return args + del args[i] + return args -class ClangClCPPCompiler(VisualStudioLikeCPPCompilerMixin, VisualStudioLikeCompiler, CPPCompiler): +class ClangClCPPCompiler(CPP11AsCPP14Mixin, VisualStudioLikeCPPCompilerMixin, VisualStudioLikeCompiler, CPPCompiler): def __init__(self, exelist, version, is_cross, exe_wrap, target): CPPCompiler.__init__(self, exelist, version, is_cross, exe_wrap) VisualStudioLikeCompiler.__init__(self, target) @@ -463,6 +494,18 @@ class ClangClCPPCompiler(VisualStudioLikeCPPCompilerMixin, VisualStudioLikeCompi return self._get_options_impl(super().get_options(), cpp_stds) +class IntelClCPPCompiler(VisualStudioLikeCPPCompilerMixin, IntelVisualStudioLikeCompiler, CPPCompiler): + + def __init__(self, exelist, version, is_cross, exe_wrap, target): + CPPCompiler.__init__(self, exelist, version, is_cross, exe_wrap) + IntelVisualStudioLikeCompiler.__init__(self, target) + + def get_options(self): + # This has only been tested with verison 19.0, + cpp_stds = ['none', 'c++11', 'vc++11', 'c++14', 'vc++14', 'c++17', 'vc++17', 'c++latest'] + return self._get_options_impl(super().get_options(), cpp_stds) + + class ArmCPPCompiler(ArmCompiler, CPPCompiler): def __init__(self, exelist, version, compiler_type, is_cross, exe_wrap=None, **kwargs): CPPCompiler.__init__(self, exelist, version, is_cross, exe_wrap, **kwargs) diff --git a/mesonbuild/compilers/fortran.py b/mesonbuild/compilers/fortran.py index 3fee43b..06e01d0 100644 --- a/mesonbuild/compilers/fortran.py +++ b/mesonbuild/compilers/fortran.py @@ -26,8 +26,9 @@ from .compilers import ( GnuCompiler, ClangCompiler, ElbrusCompiler, - IntelCompiler, + IntelGnuLikeCompiler, PGICompiler, + IntelVisualStudioLikeCompiler, ) from .clike import CLikeCompiler @@ -66,6 +67,7 @@ class FortranCompiler(CLikeCompiler, Compiler): for_machine = MachineChoice.HOST extra_flags = environment.coredata.get_external_args(for_machine, self.language) extra_flags += environment.coredata.get_external_link_args(for_machine, self.language) + extra_flags += self.get_always_args() # %% build the test executable pc = subprocess.Popen(self.exelist + extra_flags + [str(source_name), '-o', str(binary_name)]) pc.wait() @@ -213,13 +215,13 @@ class SunFortranCompiler(FortranCompiler): return ['-xopenmp'] -class IntelFortranCompiler(IntelCompiler, FortranCompiler): +class IntelFortranCompiler(IntelGnuLikeCompiler, FortranCompiler): def __init__(self, exelist, version, is_cross, exe_wrapper=None, **kwags): self.file_suffixes = ('f90', 'f', 'for', 'ftn', 'fpp') FortranCompiler.__init__(self, exelist, version, is_cross, exe_wrapper, **kwags) # FIXME: Add support for OS X and Windows in detect_fortran_compiler so # we are sent the type of compiler - IntelCompiler.__init__(self, CompilerType.ICC_STANDARD) + IntelGnuLikeCompiler.__init__(self, CompilerType.ICC_STANDARD) self.id = 'intel' default_warn_args = ['-warn', 'general', '-warn', 'truncated_source'] self.warn_args = {'0': [], @@ -239,6 +241,36 @@ class IntelFortranCompiler(IntelCompiler, FortranCompiler): def language_stdlib_only_link_flags(self): return ['-lifcore', '-limf'] +class IntelClFortranCompiler(IntelVisualStudioLikeCompiler, FortranCompiler): + + file_suffixes = ['f90', 'f', 'for', 'ftn', 'fpp'] + always_args = ['/nologo'] + + BUILD_ARGS = { + 'plain': [], + 'debug': ["/Zi", "/Od"], + 'debugoptimized': ["/Zi", "/O1"], + 'release': ["/O2"], + 'minsize': ["/Os"], + 'custom': [], + } + + def __init__(self, exelist, version, is_cross, target: str, exe_wrapper=None): + FortranCompiler.__init__(self, exelist, version, is_cross, exe_wrapper) + IntelVisualStudioLikeCompiler.__init__(self, target) + + default_warn_args = ['/warn:general', '/warn:truncated_source'] + self.warn_args = {'0': [], + '1': default_warn_args, + '2': default_warn_args + ['/warn:unused'], + '3': ['/warn:all']} + + def get_module_outdir_args(self, path) -> List[str]: + return ['/module:' + path] + + def get_buildtype_args(self, buildtype: str) -> List[str]: + return self.BUILD_ARGS[buildtype] + class PathScaleFortranCompiler(FortranCompiler): def __init__(self, exelist, version, is_cross, exe_wrapper=None, **kwags): |