aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--docs/markdown/Builtin-options.md3
-rw-r--r--docs/markdown/snippets/lto_mode.md5
-rw-r--r--mesonbuild/compilers/compilers.py8
-rw-r--r--mesonbuild/compilers/mixins/clang.py17
-rw-r--r--mesonbuild/compilers/mixins/gnu.py4
-rwxr-xr-xrun_unittests.py25
6 files changed, 54 insertions, 8 deletions
diff --git a/docs/markdown/Builtin-options.md b/docs/markdown/Builtin-options.md
index f57755c..2d7c01c 100644
--- a/docs/markdown/Builtin-options.md
+++ b/docs/markdown/Builtin-options.md
@@ -128,6 +128,7 @@ available on all platforms or with all compilers:
| b_lundef | true | true, false | Don't allow undefined symbols when linking |
| b_lto | false | true, false | Use link time optimization |
| b_lto_threads | 0 | Any integer* | Use multiple threads for lto. *(Added in 0.57.0)* |
+| b_lto_mode | default | default, thin | Select between lto modes, thin and default. *(Added in 0.57.0)* |
| b_ndebug | false | true, false, if-release | Disable asserts |
| b_pch | true | true, false | Use precompiled headers |
| b_pgo | off | off, generate, use | Use profile guided optimization |
@@ -141,6 +142,8 @@ The value of `b_sanitize` can be one of: `none`, `address`, `thread`,
* < 0 means disable, == 0 means automatic selection, > 0 sets a specific number to use
+LLVM supports `thin` lto, for more discussion see [LLVM's documentation](https://clang.llvm.org/docs/ThinLTO.html)
+
<a name="b_vscrt-from_buildtype"></a>
The default value of `b_vscrt` is `from_buildtype`. The following table is
used internally to pick the CRT compiler arguments for `from_buildtype` or
diff --git a/docs/markdown/snippets/lto_mode.md b/docs/markdown/snippets/lto_mode.md
new file mode 100644
index 0000000..c1df066
--- /dev/null
+++ b/docs/markdown/snippets/lto_mode.md
@@ -0,0 +1,5 @@
+## Support added for LLVM's thinLTO
+
+A new `b_lto_mode` option has been added, which may be set to `default` or
+`thin`. Thin only works for clang, and only with gnu gold, lld variants, or
+ld64.
diff --git a/mesonbuild/compilers/compilers.py b/mesonbuild/compilers/compilers.py
index 07569a7..08db6d7 100644
--- a/mesonbuild/compilers/compilers.py
+++ b/mesonbuild/compilers/compilers.py
@@ -270,6 +270,9 @@ base_options: 'KeyedOptionDictType' = {
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'),
@@ -320,7 +323,8 @@ def get_base_compile_args(options: 'KeyedOptionDictType', compiler: 'Compiler')
try:
if options[OptionKey('b_lto')].value:
args.extend(compiler.get_lto_compile_args(
- threads=get_option_value(options, OptionKey('b_lto_threads'), 0)))
+ threads=get_option_value(options, OptionKey('b_lto_threads'), 0),
+ mode=get_option_value(options, OptionKey('b_lto_mode'), 'default')))
except KeyError:
pass
try:
@@ -942,7 +946,7 @@ class Compiler(metaclass=abc.ABCMeta):
ret.append(arg)
return ret
- def get_lto_compile_args(self, *, threads: int = 0) -> 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 9c17a55..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,8 @@ class ClangCompiler(GnuLikeCompiler):
super().__init__()
self.id = 'clang'
self.defines = defines or {}
- self.base_options.update({OptionKey('b_colorout'), OptionKey('b_lto_threads')})
+ 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.
@@ -137,8 +138,16 @@ class ClangCompiler(GnuLikeCompiler):
def get_coverage_link_args(self) -> T.List[str]:
return ['--coverage']
- def get_lto_compile_args(self, *, threads: int = 0) -> T.List[str]:
- args = super().get_lto_compile_args(threads=threads)
+ 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}')
diff --git a/mesonbuild/compilers/mixins/gnu.py b/mesonbuild/compilers/mixins/gnu.py
index 5afbb83..464c664 100644
--- a/mesonbuild/compilers/mixins/gnu.py
+++ b/mesonbuild/compilers/mixins/gnu.py
@@ -282,7 +282,7 @@ class GnuLikeCompiler(Compiler, metaclass=abc.ABCMeta):
return self._split_fetch_real_dirs(line.split('=', 1)[1])
return []
- def get_lto_compile_args(self, *, threads: int = 0) -> 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']
@@ -387,7 +387,7 @@ 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) -> T.List[str]:
+ 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']
diff --git a/run_unittests.py b/run_unittests.py
index aff94c4..2b8812a 100755
--- a/run_unittests.py
+++ b/run_unittests.py
@@ -2864,6 +2864,31 @@ class AllPlatformTests(BasePlatformTests):
for e in expected:
self.assertIn(e, s['parameters'])
+ @skip_if_not_base_option('b_lto_mode')
+ @skip_if_not_base_option('b_lto_threads')
+ def test_lto_mode(self):
+ testdir = os.path.join(self.common_test_dir, '6 linkshared')
+
+ env = get_fake_env(testdir, self.builddir, self.prefix)
+ cc = env.detect_c_compiler(MachineChoice.HOST)
+ if cc.get_id() != 'clang':
+ raise unittest.SkipTest('Only clang currently supports thinLTO')
+ if cc.linker.id not in {'ld.lld', 'ld.gold', 'ld64', 'lld-link'}:
+ raise unittest.SkipTest('thinLTO requires ld.lld, ld.gold, ld64, or lld-link')
+ elif is_windows():
+ raise unittest.SkipTest('LTO not (yet) supported by windows clang')
+
+ self.init(testdir, extra_args=['-Db_lto=true', '-Db_lto_mode=thin', '-Db_lto_threads=8'])
+ self.build()
+ self.run_tests()
+
+ expected = set(cc.get_lto_compile_args(threads=8, mode='thin'))
+ targets = self.introspect('--targets')
+ # This assumes all of the targets support lto
+ for t in targets:
+ for s in t['target_sources']:
+ assert expected.issubset(set(s['parameters'])), f'Incorrect values for {t["name"]}'
+
def test_dist_git(self):
if not shutil.which('git'):
raise unittest.SkipTest('Git not found')