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 | |
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')
-rw-r--r-- | mesonbuild/backend/ninjabackend.py | 4 | ||||
-rw-r--r-- | mesonbuild/build.py | 2 | ||||
-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 | ||||
-rw-r--r-- | mesonbuild/environment.py | 37 | ||||
-rw-r--r-- | mesonbuild/linkers.py | 18 | ||||
-rw-r--r-- | mesonbuild/modules/windows.py | 2 |
11 files changed, 271 insertions, 71 deletions
diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py index e0a6440..69682d4 100644 --- a/mesonbuild/backend/ninjabackend.py +++ b/mesonbuild/backend/ninjabackend.py @@ -221,6 +221,10 @@ class NinjaBackend(backends.Backend): Detect the search prefix to use.''' for compiler in self.build.compilers.values(): # Have to detect the dependency format + + # IFort on windows is MSVC like, but doesn't have /showincludes + if isinstance(compiler, FortranCompiler): + continue if isinstance(compiler, VisualStudioLikeCompiler): break else: diff --git a/mesonbuild/build.py b/mesonbuild/build.py index 603e0d0..bc17445 100644 --- a/mesonbuild/build.py +++ b/mesonbuild/build.py @@ -1249,7 +1249,7 @@ You probably should put it in link_with instead.''') ''' linker, _ = self.get_clink_dynamic_linker_and_stdlibs() # Mixing many languages with MSVC is not supported yet so ignore stdlibs. - if linker and linker.get_id() in ['msvc', 'clang-cl', 'llvm', 'dmd']: + if linker and linker.get_id() in {'msvc', 'clang-cl', 'intel-cl', 'llvm', 'dmd'}: return True return False 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): diff --git a/mesonbuild/environment.py b/mesonbuild/environment.py index dd1d4cf..9620639 100644 --- a/mesonbuild/environment.py +++ b/mesonbuild/environment.py @@ -15,7 +15,7 @@ import os, platform, re, sys, shlex, shutil, subprocess, typing from . import coredata -from .linkers import ArLinker, ArmarLinker, VisualStudioLinker, DLinker, CcrxLinker +from .linkers import ArLinker, ArmarLinker, VisualStudioLinker, DLinker, CcrxLinker, IntelVisualStudioLinker from . import mesonlib from .mesonlib import ( MesonException, EnvironmentException, MachineChoice, Popen_safe, @@ -60,7 +60,10 @@ from .compilers import ( ElbrusFortranCompiler, IntelCCompiler, IntelCPPCompiler, + IntelClCCompiler, + IntelClCPPCompiler, IntelFortranCompiler, + IntelClFortranCompiler, JavaCompiler, MonoCompiler, CudaCompiler, @@ -457,12 +460,18 @@ class Environment: # List of potential compilers. if mesonlib.is_windows(): # Intel C and C++ compiler is icl on Windows, but icc and icpc elsewhere. - self.default_c = ['cl', 'cc', 'gcc', 'clang', 'clang-cl', 'pgcc', 'icl'] + # Search for icl before cl, since Intel "helpfully" provides a + # cl.exe that returns *exactly the same thing* that microsofts + # cl.exe does, and if icl is present, it's almost certainly what + # you want. + self.default_c = ['icl', 'cl', 'cc', 'gcc', 'clang', 'clang-cl', 'pgcc'] # There is currently no pgc++ for Windows, only for Mac and Linux. - self.default_cpp = ['cl', 'c++', 'g++', 'clang++', 'clang-cl', 'icl'] + self.default_cpp = ['icl', 'cl', 'c++', 'g++', 'clang++', 'clang-cl'] + self.default_fortran = ['ifort', 'gfortran', 'flang', 'pgfortran', 'g95'] else: self.default_c = ['cc', 'gcc', 'clang', 'pgcc', 'icc'] self.default_cpp = ['c++', 'g++', 'clang++', 'pgc++', 'icpc'] + self.default_fortran = ['gfortran', 'flang', 'pgfortran', 'ifort', 'g95'] if mesonlib.is_windows(): self.default_cs = ['csc', 'mcs'] else: @@ -470,7 +479,6 @@ class Environment: self.default_objc = ['cc'] self.default_objcpp = ['c++'] self.default_d = ['ldc2', 'ldc', 'gdc', 'dmd'] - self.default_fortran = ['gfortran', 'flang', 'pgfortran', 'ifort', 'g95'] self.default_java = ['javac'] self.default_cuda = ['nvcc'] self.default_rust = ['rustc'] @@ -677,8 +685,12 @@ class Environment: arg = '--vsn' elif 'ccrx' in compiler[0]: arg = '-v' + elif 'icl' in compiler[0]: + # if you pass anything to icl you get stuck in a pager + arg = '' else: arg = '--version' + try: p, out, err = Popen_safe(compiler + [arg]) except OSError as e: @@ -753,6 +765,11 @@ class Environment: compiler_type = CompilerType.CLANG_STANDARD cls = ClangCCompiler if lang == 'c' else ClangCPPCompiler return cls(ccache + compiler, version, compiler_type, is_cross, exe_wrap, full_version=full_version) + if 'Intel(R) C++ Intel(R)' in err: + version = search_version(err) + target = 'x86' if 'IA-32' in err else 'x86_64' + cls = IntelClCCompiler if lang == 'c' else IntelClCPPCompiler + return cls(compiler, version, is_cross, exe_wrap, target) if 'Microsoft' in out or 'Microsoft' in err: # Latest versions of Visual Studio print version # number to stderr but earlier ones print version @@ -886,6 +903,11 @@ class Environment: version = search_version(err) return SunFortranCompiler(compiler, version, is_cross, exe_wrap, full_version=full_version) + if 'Intel(R) Visual Fortran' in err: + version = search_version(err) + target = 'x86' if 'IA-32' in err else 'x86_64' + return IntelClFortranCompiler(compiler, version, is_cross, target, exe_wrap) + if 'ifort (IFORT)' in out: return IntelFortranCompiler(compiler, version, is_cross, exe_wrap, full_version=full_version) @@ -1172,11 +1194,14 @@ class Environment: linkers = [self.vs_static_linker, self.clang_cl_static_linker, compiler.get_linker_exelist()] else: linkers = [self.default_static_linker, compiler.get_linker_exelist()] + elif isinstance(compiler, IntelClCCompiler): + # Intel has it's own linker that acts like microsoft's lib + linkers = ['xilib'] else: linkers = [self.default_static_linker] popen_exceptions = {} for linker in linkers: - if not set(['lib', 'lib.exe', 'llvm-lib', 'llvm-lib.exe']).isdisjoint(linker): + if not {'lib', 'lib.exe', 'llvm-lib', 'llvm-lib.exe', 'xilib', 'xilib.exe'}.isdisjoint(linker): arg = '/?' else: arg = '--version' @@ -1185,6 +1210,8 @@ class Environment: except OSError as e: popen_exceptions[' '.join(linker + [arg])] = e continue + if "xilib: executing 'lib'" in err: + return IntelVisualStudioLinker(linker, getattr(compiler, 'machine', None)) if '/OUT:' in out.upper() or '/OUT:' in err.upper(): return VisualStudioLinker(linker, getattr(compiler, 'machine', None)) if p.returncode == 0 and ('armar' in linker or 'armar.exe' in linker): diff --git a/mesonbuild/linkers.py b/mesonbuild/linkers.py index c6302bf..648d1ef 100644 --- a/mesonbuild/linkers.py +++ b/mesonbuild/linkers.py @@ -23,7 +23,7 @@ class StaticLinker: return mesonlib.is_windows() -class VisualStudioLinker(StaticLinker): +class VisualStudioLikeLinker: always_args = ['/NOLOGO'] def __init__(self, exelist, machine): @@ -31,7 +31,7 @@ class VisualStudioLinker(StaticLinker): self.machine = machine def get_exelist(self): - return self.exelist[:] + return self.exelist.copy() def get_std_link_args(self): return [] @@ -50,10 +50,10 @@ class VisualStudioLinker(StaticLinker): return [] def get_always_args(self): - return VisualStudioLinker.always_args[:] + return self.always_args.copy() def get_linker_always_args(self): - return VisualStudioLinker.always_args[:] + return self.always_args.copy() def build_rpath_args(self, build_dir, from_dir, rpath_paths, build_rpath, install_rpath): return [] @@ -77,6 +77,16 @@ class VisualStudioLinker(StaticLinker): return [] +class VisualStudioLinker(VisualStudioLikeLinker, StaticLinker): + + """Microsoft's lib static linker.""" + + +class IntelVisualStudioLinker(VisualStudioLikeLinker, StaticLinker): + + """Intel's xilib static linker.""" + + class ArLinker(StaticLinker): def __init__(self, exelist): diff --git a/mesonbuild/modules/windows.py b/mesonbuild/modules/windows.py index 87a83fe..e2fd9a8 100644 --- a/mesonbuild/modules/windows.py +++ b/mesonbuild/modules/windows.py @@ -51,7 +51,7 @@ class WindowsModule(ExtensionModule): if not rescomp or not rescomp.found(): comp = self.detect_compiler(state.compilers) - if comp.id == 'msvc' or comp.id == 'clang-cl': + if comp.id in {'msvc', 'clang-cl', 'intel-cl'}: rescomp = ExternalProgram('rc', silent=True) else: rescomp = ExternalProgram('windres', silent=True) |