aboutsummaryrefslogtreecommitdiff
path: root/mesonbuild/compilers/mixins/clang.py
diff options
context:
space:
mode:
Diffstat (limited to 'mesonbuild/compilers/mixins/clang.py')
-rw-r--r--mesonbuild/compilers/mixins/clang.py121
1 files changed, 114 insertions, 7 deletions
diff --git a/mesonbuild/compilers/mixins/clang.py b/mesonbuild/compilers/mixins/clang.py
index e9e83f2..8351672 100644
--- a/mesonbuild/compilers/mixins/clang.py
+++ b/mesonbuild/compilers/mixins/clang.py
@@ -10,15 +10,22 @@ import shutil
import typing as T
from ... import mesonlib
+from ... import options
from ...linkers.linkers import AppleDynamicLinker, ClangClDynamicLinker, LLVMDynamicLinker, GnuGoldDynamicLinker, \
- MoldDynamicLinker, MSVCDynamicLinker
-from ...mesonlib import OptionKey
+ MoldDynamicLinker, VisualStudioLikeLinkerMixin
+from ...options import OptionKey
from ..compilers import CompileCheckMode
from .gnu import GnuLikeCompiler
if T.TYPE_CHECKING:
+ from ...options import MutableKeyedOptionDictType
from ...environment import Environment
from ...dependencies import Dependency # noqa: F401
+ from ..compilers import Compiler
+
+ CompilerMixinBase = Compiler
+else:
+ CompilerMixinBase = object
clang_color_args: T.Dict[str, T.List[str]] = {
'auto': ['-fdiagnostics-color=auto'],
@@ -47,6 +54,26 @@ class ClangCompiler(GnuLikeCompiler):
id = 'clang'
+ # -fms-runtime-lib is a compilation option which sets up an automatic dependency
+ # from the .o files to the final link product
+ CRT_D_ARGS: T.Dict[str, T.List[str]] = {
+ 'none': [],
+ 'md': ['-fms-runtime-lib=dll'],
+ 'mdd': ['-fms-runtime-lib=dll_dbg'],
+ 'mt': ['-fms-runtime-lib=static'],
+ 'mtd': ['-fms-runtime-lib=static_dbg'],
+ }
+
+ # disable libcmt to avoid warnings, as that is the default and clang
+ # adds it by default.
+ CRT_ARGS: T.Dict[str, T.List[str]] = {
+ 'none': [],
+ 'md': ['-Wl,/nodefaultlib:libcmt'],
+ 'mdd': ['-Wl,/nodefaultlib:libcmt'],
+ 'mt': [],
+ 'mtd': ['-Wl,/nodefaultlib:libcmt'],
+ }
+
def __init__(self, defines: T.Optional[T.Dict[str, str]]):
super().__init__()
self.defines = defines or {}
@@ -58,9 +85,23 @@ class ClangCompiler(GnuLikeCompiler):
# linkers don't have base_options.
if isinstance(self.linker, AppleDynamicLinker):
self.base_options.add(OptionKey('b_bitcode'))
+ elif isinstance(self.linker, VisualStudioLikeLinkerMixin):
+ self.base_options.add(OptionKey('b_vscrt'))
# All Clang backends can also do LLVM IR
self.can_compile_suffixes.add('ll')
+ def get_crt_compile_args(self, crt_val: str, buildtype: str) -> T.List[str]:
+ if not isinstance(self.linker, VisualStudioLikeLinkerMixin):
+ return []
+ crt_val = self.get_crt_val(crt_val, buildtype)
+ return self.CRT_D_ARGS[crt_val]
+
+ def get_crt_link_args(self, crt_val: str, buildtype: str) -> T.List[str]:
+ if not isinstance(self.linker, VisualStudioLikeLinkerMixin):
+ return []
+ crt_val = self.get_crt_val(crt_val, buildtype)
+ return self.CRT_ARGS[crt_val]
+
def get_colorout_args(self, colortype: str) -> T.List[str]:
return clang_color_args[colortype][:]
@@ -123,7 +164,7 @@ class ClangCompiler(GnuLikeCompiler):
return super().has_function(funcname, prefix, env, extra_args=extra_args,
dependencies=dependencies)
- def openmp_flags(self) -> T.List[str]:
+ def openmp_flags(self, env: Environment) -> T.List[str]:
if mesonlib.version_compare(self.version, '>=3.8.0'):
return ['-fopenmp']
elif mesonlib.version_compare(self.version, '>=3.7.0'):
@@ -133,7 +174,7 @@ class ClangCompiler(GnuLikeCompiler):
return []
def gen_vs_module_defs_args(self, defsfile: str) -> T.List[str]:
- if isinstance(self.linker, (MSVCDynamicLinker)):
+ if isinstance(self.linker, VisualStudioLikeLinkerMixin):
# 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 ['-Wl,/DEF:' + defsfile]
@@ -146,7 +187,10 @@ class ClangCompiler(GnuLikeCompiler):
# llvm based) is retargetable, while GCC is not.
#
- # qcld: Qualcomm Snapdragon linker, based on LLVM
+ # eld: Qualcomm's opensource embedded linker
+ if linker == 'eld':
+ return ['-fuse-ld=eld']
+ # qcld: Qualcomm's deprecated linker
if linker == 'qcld':
return ['-fuse-ld=qcld']
if linker == 'mold':
@@ -184,8 +228,8 @@ class ClangCompiler(GnuLikeCompiler):
return args
def linker_to_compiler_args(self, args: T.List[str]) -> T.List[str]:
- if isinstance(self.linker, (ClangClDynamicLinker, MSVCDynamicLinker)):
- return [flag if flag.startswith('-Wl,') else f'-Wl,{flag}' for flag in args]
+ if isinstance(self.linker, VisualStudioLikeLinkerMixin):
+ return [flag if flag.startswith('-Wl,') or flag.startswith('-fuse-ld=') else f'-Wl,{flag}' for flag in args]
else:
return args
@@ -202,3 +246,66 @@ class ClangCompiler(GnuLikeCompiler):
raise mesonlib.MesonException('clang support for LTO threads requires clang >=4.0')
args.append(f'-flto-jobs={threads}')
return args
+
+
+class ClangCStds(CompilerMixinBase):
+
+ """Mixin class for clang based compilers for setting C standards.
+
+ This is used by both ClangCCompiler and ClangClCompiler, as they share
+ the same versions
+ """
+
+ _C17_VERSION = '>=6.0.0'
+ _C18_VERSION = '>=8.0.0'
+ _C2X_VERSION = '>=9.0.0'
+ _C23_VERSION = '>=18.0.0'
+ _C2Y_VERSION = '>=19.0.0'
+
+ def get_options(self) -> MutableKeyedOptionDictType:
+ opts = super().get_options()
+ stds = ['c89', 'c99', 'c11']
+ # https://releases.llvm.org/6.0.0/tools/clang/docs/ReleaseNotes.html
+ # https://en.wikipedia.org/wiki/Xcode#Latest_versions
+ if mesonlib.version_compare(self.version, self._C17_VERSION):
+ stds += ['c17']
+ if mesonlib.version_compare(self.version, self._C18_VERSION):
+ stds += ['c18']
+ if mesonlib.version_compare(self.version, self._C2X_VERSION):
+ stds += ['c2x']
+ if mesonlib.version_compare(self.version, self._C23_VERSION):
+ stds += ['c23']
+ if mesonlib.version_compare(self.version, self._C2Y_VERSION):
+ stds += ['c2y']
+ key = self.form_compileropt_key('std')
+ std_opt = opts[key]
+ assert isinstance(std_opt, options.UserStdOption), 'for mypy'
+ std_opt.set_versions(stds, gnu=True)
+ return opts
+
+
+class ClangCPPStds(CompilerMixinBase):
+
+ """Mixin class for clang based compilers for setting C++ standards.
+
+ This is used by the ClangCPPCompiler
+ """
+
+ _CPP23_VERSION = '>=12.0.0'
+ _CPP26_VERSION = '>=17.0.0'
+
+ def get_options(self) -> MutableKeyedOptionDictType:
+ opts = super().get_options()
+ stds = [
+ 'c++98', 'c++03', 'c++11', 'c++14', 'c++17', 'c++1z', 'c++2a',
+ 'c++20',
+ ]
+ if mesonlib.version_compare(self.version, self._CPP23_VERSION):
+ stds.append('c++23')
+ if mesonlib.version_compare(self.version, self._CPP26_VERSION):
+ stds.append('c++26')
+ key = self.form_compileropt_key('std')
+ std_opt = opts[key]
+ assert isinstance(std_opt, options.UserStdOption), 'for mypy'
+ std_opt.set_versions(stds, gnu=True)
+ return opts