1# Copyright 2019 The meson development team 2# 3# Licensed under the Apache License, Version 2.0 (the "License"); 4# you may not use this file except in compliance with the License. 5# You may obtain a copy of the License at 6# 7# http://www.apache.org/licenses/LICENSE-2.0 8# 9# Unless required by applicable law or agreed to in writing, software 10# distributed under the License is distributed on an "AS IS" BASIS, 11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12# See the License for the specific language governing permissions and 13# limitations under the License. 14 15"""Abstractions for the Intel Compiler families. 16 17Intel provides both a posix/gcc-like compiler (ICC) for MacOS and Linux, 18with Meson mixin IntelGnuLikeCompiler. 19For Windows, the Intel msvc-like compiler (ICL) Meson mixin 20is IntelVisualStudioLikeCompiler. 21""" 22 23import os 24import typing as T 25 26from ... import mesonlib 27from ..compilers import CompileCheckMode 28from .gnu import GnuLikeCompiler 29from .visualstudio import VisualStudioLikeCompiler 30 31# XXX: avoid circular dependencies 32# TODO: this belongs in a posix compiler class 33# NOTE: the default Intel optimization is -O2, unlike GNU which defaults to -O0. 34# this can be surprising, particularly for debug builds, so we specify the 35# default as -O0. 36# https://software.intel.com/en-us/cpp-compiler-developer-guide-and-reference-o 37# https://software.intel.com/en-us/cpp-compiler-developer-guide-and-reference-g 38# https://software.intel.com/en-us/fortran-compiler-developer-guide-and-reference-o 39# https://software.intel.com/en-us/fortran-compiler-developer-guide-and-reference-g 40# https://software.intel.com/en-us/fortran-compiler-developer-guide-and-reference-traceback 41# https://gcc.gnu.org/onlinedocs/gcc/Optimize-Options.html 42 43 44class IntelGnuLikeCompiler(GnuLikeCompiler): 45 """ 46 Tested on linux for ICC 14.0.3, 15.0.6, 16.0.4, 17.0.1, 19.0 47 debugoptimized: -g -O2 48 release: -O3 49 minsize: -O2 50 """ 51 52 BUILD_ARGS = { 53 'plain': [], 54 'debug': ["-g", "-traceback"], 55 'debugoptimized': ["-g", "-traceback"], 56 'release': [], 57 'minsize': [], 58 'custom': [], 59 } # type: T.Dict[str, T.List[str]] 60 61 OPTIM_ARGS = { 62 '0': ['-O0'], 63 'g': ['-O0'], 64 '1': ['-O1'], 65 '2': ['-O2'], 66 '3': ['-O3'], 67 's': ['-Os'], 68 } 69 70 def __init__(self) -> None: 71 super().__init__() 72 # As of 19.0.0 ICC doesn't have sanitizer, color, or lto support. 73 # 74 # It does have IPO, which serves much the same purpose as LOT, but 75 # there is an unfortunate rule for using IPO (you can't control the 76 # name of the output file) which break assumptions meson makes 77 self.base_options = {mesonlib.OptionKey(o) for o in [ 78 'b_pch', 'b_lundef', 'b_asneeded', 'b_pgo', 'b_coverage', 79 'b_ndebug', 'b_staticpic', 'b_pie']} 80 self.id = 'intel' 81 self.lang_header = 'none' 82 83 def get_pch_suffix(self) -> str: 84 return 'pchi' 85 86 def get_pch_use_args(self, pch_dir: str, header: str) -> T.List[str]: 87 return ['-pch', '-pch_dir', os.path.join(pch_dir), '-x', 88 self.lang_header, '-include', header, '-x', 'none'] 89 90 def get_pch_name(self, header_name: str) -> str: 91 return os.path.basename(header_name) + '.' + self.get_pch_suffix() 92 93 def openmp_flags(self) -> T.List[str]: 94 if mesonlib.version_compare(self.version, '>=15.0.0'): 95 return ['-qopenmp'] 96 else: 97 return ['-openmp'] 98 99 def get_compiler_check_args(self, mode: CompileCheckMode) -> T.List[str]: 100 extra_args = [ 101 '-diag-error', '10006', # ignoring unknown option 102 '-diag-error', '10148', # Option not supported 103 '-diag-error', '10155', # ignoring argument required 104 '-diag-error', '10156', # ignoring not argument allowed 105 '-diag-error', '10157', # Ignoring argument of the wrong type 106 '-diag-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 107 ] 108 return super().get_compiler_check_args(mode) + extra_args 109 110 def get_profile_generate_args(self) -> T.List[str]: 111 return ['-prof-gen=threadsafe'] 112 113 def get_profile_use_args(self) -> T.List[str]: 114 return ['-prof-use'] 115 116 def get_buildtype_args(self, buildtype: str) -> T.List[str]: 117 return self.BUILD_ARGS[buildtype] 118 119 def get_optimization_args(self, optimization_level: str) -> T.List[str]: 120 return self.OPTIM_ARGS[optimization_level] 121 122 def get_has_func_attribute_extra_args(self, name: str) -> T.List[str]: 123 return ['-diag-error', '1292'] 124 125 126class IntelVisualStudioLikeCompiler(VisualStudioLikeCompiler): 127 128 """Abstractions for ICL, the Intel compiler on Windows.""" 129 130 BUILD_ARGS = { 131 'plain': [], 132 'debug': ["/Zi", "/traceback"], 133 'debugoptimized': ["/Zi", "/traceback"], 134 'release': [], 135 'minsize': [], 136 'custom': [], 137 } # type: T.Dict[str, T.List[str]] 138 139 OPTIM_ARGS = { 140 '0': ['/Od'], 141 'g': ['/Od'], 142 '1': ['/O1'], 143 '2': ['/O2'], 144 '3': ['/O3'], 145 's': ['/Os'], 146 } 147 148 def __init__(self, target: str) -> None: 149 super().__init__(target) 150 self.id = 'intel-cl' 151 152 def get_compiler_check_args(self, mode: CompileCheckMode) -> T.List[str]: 153 args = super().get_compiler_check_args(mode) 154 if mode is not CompileCheckMode.LINK: 155 args.extend([ 156 '/Qdiag-error:10006', # ignoring unknown option 157 '/Qdiag-error:10148', # Option not supported 158 '/Qdiag-error:10155', # ignoring argument required 159 '/Qdiag-error:10156', # ignoring not argument allowed 160 '/Qdiag-error:10157', # Ignoring argument of the wrong type 161 '/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 162 ]) 163 return args 164 165 def get_toolset_version(self) -> T.Optional[str]: 166 # ICL provides a cl.exe that returns the version of MSVC it tries to 167 # emulate, so we'll get the version from that and pass it to the same 168 # function the real MSVC uses to calculate the toolset version. 169 _, _, err = mesonlib.Popen_safe(['cl.exe']) 170 v1, v2, *_ = mesonlib.search_version(err).split('.') 171 version = int(v1 + v2) 172 return self._calculate_toolset_version(version) 173 174 def openmp_flags(self) -> T.List[str]: 175 return ['/Qopenmp'] 176 177 def get_buildtype_args(self, buildtype: str) -> T.List[str]: 178 return self.BUILD_ARGS[buildtype] 179 180 def get_optimization_args(self, optimization_level: str) -> T.List[str]: 181 return self.OPTIM_ARGS[optimization_level] 182 183 def get_pch_base_name(self, header: str) -> str: 184 return os.path.basename(header) 185