diff options
Diffstat (limited to 'mesonbuild/compilers')
-rw-r--r-- | mesonbuild/compilers/compilers.py | 24 | ||||
-rw-r--r-- | mesonbuild/compilers/mixins/clang.py | 21 | ||||
-rw-r--r-- | mesonbuild/compilers/mixins/gnu.py | 17 |
3 files changed, 56 insertions, 6 deletions
diff --git a/mesonbuild/compilers/compilers.py b/mesonbuild/compilers/compilers.py index 0f83f4c..08db6d7 100644 --- a/mesonbuild/compilers/compilers.py +++ b/mesonbuild/compilers/compilers.py @@ -268,6 +268,11 @@ clike_debug_args = {False: [], base_options: 'KeyedOptionDictType' = { OptionKey('b_pch'): coredata.UserBooleanOption('Use precompiled headers', True), OptionKey('b_lto'): coredata.UserBooleanOption('Use link time optimization', False), + OptionKey('b_lto'): coredata.UserBooleanOption('Use link time optimization', False), + OptionKey('b_lto_threads'): coredata.UserIntegerOption('Use multiple threads for Link Time Optimization', (None, None,0)), + OptionKey('b_lto_mode'): coredata.UserComboOption('Select between different LTO modes.', + ['default', 'thin'], + 'default'), OptionKey('b_sanitize'): coredata.UserComboOption('Code sanitizer to use', ['none', 'address', 'thread', 'undefined', 'memory', 'address,undefined'], 'none'), @@ -300,11 +305,26 @@ def option_enabled(boptions: T.Set[OptionKey], options: 'KeyedOptionDictType', except KeyError: return False + +def get_option_value(options: 'KeyedOptionDictType', opt: OptionKey, fallback: '_T') -> '_T': + """Get the value of an option, or the fallback value.""" + try: + v: '_T' = options[opt].value + except KeyError: + return fallback + + assert isinstance(v, type(fallback)), f'Should have {type(fallback)!r} but was {type(v)!r}' + # Mypy doesn't understand that the above assert ensures that v is type _T + return v + + def get_base_compile_args(options: 'KeyedOptionDictType', compiler: 'Compiler') -> T.List[str]: args = [] # type T.List[str] try: if options[OptionKey('b_lto')].value: - args.extend(compiler.get_lto_compile_args()) + args.extend(compiler.get_lto_compile_args( + threads=get_option_value(options, OptionKey('b_lto_threads'), 0), + mode=get_option_value(options, OptionKey('b_lto_mode'), 'default'))) except KeyError: pass try: @@ -926,7 +946,7 @@ class Compiler(metaclass=abc.ABCMeta): ret.append(arg) return ret - def get_lto_compile_args(self) -> T.List[str]: + def get_lto_compile_args(self, *, threads: int = 0, mode: str = 'default') -> T.List[str]: return [] def get_lto_link_args(self) -> T.List[str]: diff --git a/mesonbuild/compilers/mixins/clang.py b/mesonbuild/compilers/mixins/clang.py index fcb2225..1778c31 100644 --- a/mesonbuild/compilers/mixins/clang.py +++ b/mesonbuild/compilers/mixins/clang.py @@ -19,7 +19,7 @@ import shutil import typing as T from ... import mesonlib -from ...linkers import AppleDynamicLinker +from ...linkers import AppleDynamicLinker, ClangClDynamicLinker, LLVMDynamicLinker, GnuGoldDynamicLinker from ...mesonlib import OptionKey from ..compilers import CompileCheckMode from .gnu import GnuLikeCompiler @@ -49,7 +49,9 @@ class ClangCompiler(GnuLikeCompiler): super().__init__() self.id = 'clang' self.defines = defines or {} - self.base_options.add(OptionKey('b_colorout')) + self.base_options.update( + {OptionKey('b_colorout'), OptionKey('b_lto_threads'), OptionKey('b_lto_mode')}) + # TODO: this really should be part of the linker base_options, but # linkers don't have base_options. if isinstance(self.linker, AppleDynamicLinker): @@ -135,3 +137,18 @@ class ClangCompiler(GnuLikeCompiler): def get_coverage_link_args(self) -> T.List[str]: return ['--coverage'] + + def get_lto_compile_args(self, *, threads: int = 0, mode: str = 'default') -> T.List[str]: + args: T.List[str] = [] + if mode == 'thin': + # Thin LTO requires the use of gold, lld, ld64, or lld-link + if not isinstance(self.linker, (AppleDynamicLinker, ClangClDynamicLinker, LLVMDynamicLinker, GnuGoldDynamicLinker)): + raise mesonlib.MesonException(f"LLVM's thinLTO only works with gnu gold, lld, lld-link, and ld64, not {self.linker.id}") + args.append(f'-flto={mode}') + else: + assert mode == 'default', 'someone forgot to wire something up' + args.extend(super().get_lto_compile_args(threads=threads)) + # In clang -flto=0 means auto + if threads >= 0: + args.append(f'-flto-jobs={threads}') + return args diff --git a/mesonbuild/compilers/mixins/gnu.py b/mesonbuild/compilers/mixins/gnu.py index 95bcd7c..464c664 100644 --- a/mesonbuild/compilers/mixins/gnu.py +++ b/mesonbuild/compilers/mixins/gnu.py @@ -17,6 +17,7 @@ import abc import functools import os +import multiprocessing import pathlib import re import subprocess @@ -281,7 +282,9 @@ class GnuLikeCompiler(Compiler, metaclass=abc.ABCMeta): return self._split_fetch_real_dirs(line.split('=', 1)[1]) return [] - def get_lto_compile_args(self) -> T.List[str]: + def get_lto_compile_args(self, *, threads: int = 0, mode: str = 'default') -> T.List[str]: + # This provides a base for many compilers, GCC and Clang override this + # for their specific arguments return ['-flto'] def sanitizer_compile_args(self, value: str) -> T.List[str]: @@ -330,7 +333,7 @@ class GnuCompiler(GnuLikeCompiler): super().__init__() self.id = 'gcc' self.defines = defines or {} - self.base_options.add(OptionKey('b_colorout')) + self.base_options.update({OptionKey('b_colorout'), OptionKey('b_lto_threads')}) def get_colorout_args(self, colortype: str) -> T.List[str]: if mesonlib.version_compare(self.version, '>=4.9.0'): @@ -383,3 +386,13 @@ class GnuCompiler(GnuLikeCompiler): def get_prelink_args(self, prelink_name: str, obj_list: T.List[str]) -> T.List[str]: return ['-r', '-o', prelink_name] + obj_list + + def get_lto_compile_args(self, *, threads: int = 0, mode: str = 'default') -> T.List[str]: + if threads == 0: + if mesonlib.version_compare(self.version, '>= 10.0'): + return ['-flto=auto'] + # This matches clang's behavior of using the number of cpus + return [f'-flto={multiprocessing.cpu_count()}'] + elif threads > 0: + return [f'-flto={threads}'] + return super().get_lto_compile_args(threads=threads) |