diff options
author | Fini Jastrow <ulf.fini.jastrow@desy.de> | 2022-03-08 18:41:08 +0100 |
---|---|---|
committer | Xavier Claessens <xclaesse@gmail.com> | 2022-04-30 10:06:22 -0400 |
commit | c16fdaeecafe94461d6048b90bd337a04c25ad3c (patch) | |
tree | 7ebffc621f5ad4d75459dff1d5b5f05cc6481993 /mesonbuild/compilers | |
parent | 93ed7531c4a1e08defc5ea3b37427e59f67582db (diff) | |
download | meson-c16fdaeecafe94461d6048b90bd337a04c25ad3c.zip meson-c16fdaeecafe94461d6048b90bd337a04c25ad3c.tar.gz meson-c16fdaeecafe94461d6048b90bd337a04c25ad3c.tar.bz2 |
linkers: Add support for mold linker
[why]
Support for the relatively new mold linker is missing. If someone wants
to use mold as linker `LDFLAGS="-B/path/to/mold"` has to be added instead
of the usual `CC_LD=mold meson ...` or `CXX_LD=mold meson ...`.
[how]
Allow `mold' as linker for clang and newer GCC versions (that versions
that have support).
The error message can be a bit off, because it is generic for all GNU
like compilers, but I guess that is ok. (i.e. 'mold' is not listed as
possible linker, even if it would be possible for the given compiler.)
[note]
GCC Version 12.0.1 is not sufficient to say `mold` is supported. The
expected release with support will be 12.1.0.
On the other hand people that use the un-released 12.0.1 will probably
have built it from trunk. Allowing 12.0.1 is helping bleeding edge
developers to use mold in Meson already now.
Fixes: #9072
Signed-off-by: Fini Jastrow <ulf.fini.jastrow@desy.de>
Diffstat (limited to 'mesonbuild/compilers')
-rw-r--r-- | mesonbuild/compilers/compilers.py | 4 | ||||
-rw-r--r-- | mesonbuild/compilers/d.py | 4 | ||||
-rw-r--r-- | mesonbuild/compilers/detect.py | 60 | ||||
-rw-r--r-- | mesonbuild/compilers/mixins/clang.py | 8 | ||||
-rw-r--r-- | mesonbuild/compilers/mixins/clike.py | 4 | ||||
-rw-r--r-- | mesonbuild/compilers/mixins/gnu.py | 10 | ||||
-rw-r--r-- | mesonbuild/compilers/rust.py | 4 |
7 files changed, 51 insertions, 43 deletions
diff --git a/mesonbuild/compilers/compilers.py b/mesonbuild/compilers/compilers.py index 17c9f36..34f9a09 100644 --- a/mesonbuild/compilers/compilers.py +++ b/mesonbuild/compilers/compilers.py @@ -1,4 +1,4 @@ -# Copyright 2012-2019 The Meson development team +# Copyright 2012-2022 The Meson development team # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -1007,7 +1007,7 @@ class Compiler(HoldableObject, metaclass=abc.ABCMeta): return dep.get_link_args() @classmethod - def use_linker_args(cls, linker: str) -> T.List[str]: + def use_linker_args(cls, linker: str, version: str) -> T.List[str]: """Get a list of arguments to pass to the compiler to set the linker. """ return [] diff --git a/mesonbuild/compilers/d.py b/mesonbuild/compilers/d.py index 4e24e4e..ec0b155 100644 --- a/mesonbuild/compilers/d.py +++ b/mesonbuild/compilers/d.py @@ -1,4 +1,4 @@ -# Copyright 2012-2017 The Meson development team +# Copyright 2012-2022 The Meson development team # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -806,7 +806,7 @@ class LLVMDCompiler(DmdLikeCompilerMixin, DCompiler): return ldc_optimization_args[optimization_level] @classmethod - def use_linker_args(cls, linker: str) -> T.List[str]: + def use_linker_args(cls, linker: str, version: str) -> T.List[str]: return [f'-linker={linker}'] def get_linker_always_args(self) -> T.List[str]: diff --git a/mesonbuild/compilers/detect.py b/mesonbuild/compilers/detect.py index 53948b0..74f2f17 100644 --- a/mesonbuild/compilers/detect.py +++ b/mesonbuild/compilers/detect.py @@ -1,4 +1,4 @@ -# Copyright 2012-2021 The Meson development team +# Copyright 2012-2022 The Meson development team # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -448,7 +448,7 @@ def _detect_c_or_cpp_compiler(env: 'Environment', lang: str, for_machine: Machin version = _get_gnu_version_from_defines(defines) cls = GnuCCompiler if lang == 'c' else GnuCPPCompiler - linker = guess_nix_linker(env, compiler, cls, for_machine) + linker = guess_nix_linker(env, compiler, cls, version, for_machine) return cls( ccache + compiler, version, for_machine, is_cross, @@ -484,7 +484,7 @@ def _detect_c_or_cpp_compiler(env: 'Environment', lang: str, for_machine: Machin cls = ArmLtdClangCCompiler elif lang == 'cpp': cls = ArmLtdClangCPPCompiler - linker = guess_nix_linker(env, compiler, cls, for_machine) + linker = guess_nix_linker(env, compiler, cls, version, for_machine) return cls( ccache + compiler, version, for_machine, is_cross, info, exe_wrap, linker=linker) @@ -523,7 +523,7 @@ def _detect_c_or_cpp_compiler(env: 'Environment', lang: str, for_machine: Machin else: target = 'unknown target' cls = ClangClCCompiler if lang == 'c' else ClangClCPPCompiler - linker = guess_win_linker(env, ['lld-link'], cls, for_machine) + linker = guess_win_linker(env, ['lld-link'], cls, version, for_machine) return cls( compiler, version, for_machine, is_cross, info, target, exe_wrap, linker=linker) @@ -544,11 +544,11 @@ def _detect_c_or_cpp_compiler(env: 'Environment', lang: str, for_machine: Machin # style ld, but for clang on "real" windows we'll use # either link.exe or lld-link.exe try: - linker = guess_win_linker(env, compiler, cls, for_machine, invoked_directly=False) + linker = guess_win_linker(env, compiler, cls, version, for_machine, invoked_directly=False) except MesonException: pass if linker is None: - linker = guess_nix_linker(env, compiler, cls, for_machine) + linker = guess_nix_linker(env, compiler, cls, version, for_machine) return cls( ccache + compiler, version, for_machine, is_cross, info, @@ -582,7 +582,7 @@ def _detect_c_or_cpp_compiler(env: 'Environment', lang: str, for_machine: Machin m = f'Failed to detect MSVC compiler target architecture: \'cl /?\' output is\n{cl_signature}' raise EnvironmentException(m) cls = VisualStudioCCompiler if lang == 'c' else VisualStudioCPPCompiler - linker = guess_win_linker(env, ['link'], cls, for_machine) + linker = guess_win_linker(env, ['link'], cls, version, for_machine) # As of this writing, CCache does not support MSVC but sccache does. if 'sccache' in ccache: final_compiler = ccache + compiler @@ -607,7 +607,7 @@ def _detect_c_or_cpp_compiler(env: 'Environment', lang: str, for_machine: Machin info, exe_wrap, linker=linker) if '(ICC)' in out: cls = IntelCCompiler if lang == 'c' else IntelCPPCompiler - l = guess_nix_linker(env, compiler, cls, for_machine) + l = guess_nix_linker(env, compiler, cls, version, for_machine) return cls( ccache + compiler, version, for_machine, is_cross, info, exe_wrap, full_version=full_version, linker=l) @@ -731,14 +731,14 @@ def detect_fortran_compiler(env: 'Environment', for_machine: MachineChoice) -> C if guess_gcc_or_lcc == 'lcc': version = _get_lcc_version_from_defines(defines) cls = ElbrusFortranCompiler - linker = guess_nix_linker(env, compiler, cls, for_machine) + linker = guess_nix_linker(env, compiler, cls, version, for_machine) return cls( compiler, version, for_machine, is_cross, info, exe_wrap, defines, full_version=full_version, linker=linker) else: version = _get_gnu_version_from_defines(defines) cls = GnuFortranCompiler - linker = guess_nix_linker(env, compiler, cls, for_machine) + linker = guess_nix_linker(env, compiler, cls, version, for_machine) return cls( compiler, version, for_machine, is_cross, info, exe_wrap, defines, full_version=full_version, linker=linker) @@ -750,13 +750,13 @@ def detect_fortran_compiler(env: 'Environment', for_machine: MachineChoice) -> C arm_ver_minor = arm_ver_match.group(2) arm_ver_build = arm_ver_match.group(3) version = '.'.join([arm_ver_major, arm_ver_minor, arm_ver_build]) - linker = guess_nix_linker(env, compiler, cls, for_machine) + linker = guess_nix_linker(env, compiler, cls, version, for_machine) return cls( ccache + compiler, version, for_machine, is_cross, info, exe_wrap, linker=linker) if 'G95' in out: cls = G95FortranCompiler - linker = guess_nix_linker(env, compiler, cls, for_machine) + linker = guess_nix_linker(env, compiler, cls, version, for_machine) return G95FortranCompiler( compiler, version, for_machine, is_cross, info, exe_wrap, full_version=full_version, linker=linker) @@ -764,7 +764,7 @@ def detect_fortran_compiler(env: 'Environment', for_machine: MachineChoice) -> C if 'Sun Fortran' in err: version = search_version(err) cls = SunFortranCompiler - linker = guess_nix_linker(env, compiler, cls, for_machine) + linker = guess_nix_linker(env, compiler, cls, version, for_machine) return SunFortranCompiler( compiler, version, for_machine, is_cross, info, exe_wrap, full_version=full_version, linker=linker) @@ -780,7 +780,7 @@ def detect_fortran_compiler(env: 'Environment', for_machine: MachineChoice) -> C target, exe_wrap, linker=linker) if 'ifort (IFORT)' in out: - linker = guess_nix_linker(env, compiler, IntelFortranCompiler, for_machine) + linker = guess_nix_linker(env, compiler, IntelFortranCompiler, version, for_machine) return IntelFortranCompiler( compiler, version, for_machine, is_cross, info, exe_wrap, full_version=full_version, linker=linker) @@ -810,14 +810,14 @@ def detect_fortran_compiler(env: 'Environment', for_machine: MachineChoice) -> C if 'flang' in out or 'clang' in out: linker = guess_nix_linker(env, - compiler, FlangFortranCompiler, for_machine) + compiler, FlangFortranCompiler, version, for_machine) return FlangFortranCompiler( compiler, version, for_machine, is_cross, info, exe_wrap, full_version=full_version, linker=linker) if 'Open64 Compiler Suite' in err: linker = guess_nix_linker(env, - compiler, Open64FortranCompiler, for_machine) + compiler, Open64FortranCompiler, version, for_machine) return Open64FortranCompiler( compiler, version, for_machine, is_cross, info, exe_wrap, full_version=full_version, linker=linker) @@ -865,7 +865,7 @@ def _detect_objc_or_objcpp_compiler(env: 'Environment', for_machine: MachineChoi continue version = _get_gnu_version_from_defines(defines) comp = GnuObjCCompiler if objc else GnuObjCPPCompiler - linker = guess_nix_linker(env, compiler, comp, for_machine) + linker = guess_nix_linker(env, compiler, comp, version, for_machine) return comp( ccache + compiler, version, for_machine, is_cross, info, exe_wrap, defines, linker=linker) @@ -882,12 +882,12 @@ def _detect_objc_or_objcpp_compiler(env: 'Environment', for_machine: MachineChoi if 'windows' in out or env.machines[for_machine].is_windows(): # If we're in a MINGW context this actually will use a gnu style ld try: - linker = guess_win_linker(env, compiler, comp, for_machine) + linker = guess_win_linker(env, compiler, comp, version, for_machine) except MesonException: pass if not linker: - linker = guess_nix_linker(env, compiler, comp, for_machine) + linker = guess_nix_linker(env, compiler, comp, version, for_machine) return comp( ccache + compiler, version, for_machine, is_cross, info, exe_wrap, linker=linker, defines=defines) @@ -1032,7 +1032,7 @@ def detect_rust_compiler(env: 'Environment', for_machine: MachineChoice) -> Rust extra_args: T.Dict[str, T.Union[str, bool]] = {} always_args: T.List[str] = [] if is_link_exe: - compiler.extend(cls.use_linker_args(cc.linker.exelist[0])) + compiler.extend(cls.use_linker_args(cc.linker.exelist[0], '')) extra_args['direct'] = True extra_args['machine'] = cc.linker.machine else: @@ -1040,7 +1040,7 @@ def detect_rust_compiler(env: 'Environment', for_machine: MachineChoice) -> Rust if 'ccache' in exelist[0]: del exelist[0] c = exelist.pop(0) - compiler.extend(cls.use_linker_args(c)) + compiler.extend(cls.use_linker_args(c, '')) # Also ensure that we pass any extra arguments to the linker for l in exelist: @@ -1059,12 +1059,12 @@ def detect_rust_compiler(env: 'Environment', for_machine: MachineChoice) -> Rust **extra_args) elif 'link' in override[0]: linker = guess_win_linker(env, - override, cls, for_machine, use_linker_prefix=False) + override, cls, version, for_machine, use_linker_prefix=False) # rustc takes linker arguments without a prefix, and # inserts the correct prefix itself. assert isinstance(linker, VisualStudioLikeLinkerMixin) linker.direct = True - compiler.extend(cls.use_linker_args(linker.exelist[0])) + compiler.extend(cls.use_linker_args(linker.exelist[0], '')) else: # On linux and macos rust will invoke the c compiler for # linking, on windows it will use lld-link or link.exe. @@ -1076,7 +1076,7 @@ def detect_rust_compiler(env: 'Environment', for_machine: MachineChoice) -> Rust # Of course, we're not going to use any of that, we just # need it to get the proper arguments to pass to rustc c = linker.exelist[1] if linker.exelist[0].endswith('ccache') else linker.exelist[0] - compiler.extend(cls.use_linker_args(c)) + compiler.extend(cls.use_linker_args(c, '')) env.coredata.add_lang_args(cls.language, cls, for_machine, env) return cls( @@ -1135,7 +1135,7 @@ def detect_d_compiler(env: 'Environment', for_machine: MachineChoice) -> Compile objfile = os.path.basename(f)[:-1] + 'obj' linker = guess_win_linker(env, exelist, - LLVMDCompiler, for_machine, + LLVMDCompiler, full_version, for_machine, use_linker_prefix=True, invoked_directly=False, extra_args=[f]) else: @@ -1143,7 +1143,7 @@ def detect_d_compiler(env: 'Environment', for_machine: MachineChoice) -> Compile # Clean it up. objfile = os.path.basename(f)[:-1] + 'o' linker = guess_nix_linker(env, - exelist, LLVMDCompiler, for_machine, + exelist, LLVMDCompiler, full_version, for_machine, extra_args=[f]) finally: windows_proof_rm(f) @@ -1153,7 +1153,7 @@ def detect_d_compiler(env: 'Environment', for_machine: MachineChoice) -> Compile exelist, version, for_machine, info, arch, full_version=full_version, linker=linker, version_output=out) elif 'gdc' in out: - linker = guess_nix_linker(env, exelist, GnuDCompiler, for_machine) + linker = guess_nix_linker(env, exelist, GnuDCompiler, version, for_machine) return GnuDCompiler( exelist, version, for_machine, info, arch, exe_wrapper=exe_wrap, is_cross=is_cross, @@ -1173,12 +1173,12 @@ def detect_d_compiler(env: 'Environment', for_machine: MachineChoice) -> Compile if info.is_windows() or info.is_cygwin(): objfile = os.path.basename(f)[:-1] + 'obj' linker = guess_win_linker(env, - exelist, DmdDCompiler, for_machine, + exelist, DmdDCompiler, full_version, for_machine, invoked_directly=False, extra_args=[f, arch_arg]) else: objfile = os.path.basename(f)[:-1] + 'o' linker = guess_nix_linker(env, - exelist, DmdDCompiler, for_machine, + exelist, DmdDCompiler, full_version, for_machine, extra_args=[f, arch_arg]) finally: windows_proof_rm(f) @@ -1209,7 +1209,7 @@ def detect_swift_compiler(env: 'Environment', for_machine: MachineChoice) -> Com # As for 5.0.1 swiftc *requires* a file to check the linker: with tempfile.NamedTemporaryFile(suffix='.swift') as f: linker = guess_nix_linker(env, - exelist, SwiftCompiler, for_machine, + exelist, SwiftCompiler, version, for_machine, extra_args=[f.name]) return SwiftCompiler( exelist, version, for_machine, is_cross, info, linker=linker) diff --git a/mesonbuild/compilers/mixins/clang.py b/mesonbuild/compilers/mixins/clang.py index a823b1c..5083ace 100644 --- a/mesonbuild/compilers/mixins/clang.py +++ b/mesonbuild/compilers/mixins/clang.py @@ -1,4 +1,4 @@ -# Copyright 2019 The meson development team +# Copyright 2019-2022 The meson development team # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -118,7 +118,7 @@ class ClangCompiler(GnuLikeCompiler): return [] @classmethod - def use_linker_args(cls, linker: str) -> T.List[str]: + def use_linker_args(cls, linker: str, version: str) -> T.List[str]: # Clang additionally can use a linker specified as a path, which GCC # (and other gcc-like compilers) cannot. This is because clang (being # llvm based) is retargetable, while GCC is not. @@ -127,13 +127,15 @@ class ClangCompiler(GnuLikeCompiler): # qcld: Qualcomm Snapdragon linker, based on LLVM if linker == 'qcld': return ['-fuse-ld=qcld'] + if linker == 'mold': + return ['-fuse-ld=mold'] if shutil.which(linker): if not shutil.which(linker): raise mesonlib.MesonException( f'Cannot find linker {linker}.') return [f'-fuse-ld={linker}'] - return super().use_linker_args(linker) + return super().use_linker_args(linker, version) def get_has_func_attribute_extra_args(self, name: str) -> T.List[str]: # Clang only warns about unknown or ignored attributes, so force an diff --git a/mesonbuild/compilers/mixins/clike.py b/mesonbuild/compilers/mixins/clike.py index 162005f..4c2756e 100644 --- a/mesonbuild/compilers/mixins/clike.py +++ b/mesonbuild/compilers/mixins/clike.py @@ -1,4 +1,4 @@ -# Copyright 2012-2017 The Meson development team +# Copyright 2012-2022 The Meson development team # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -410,7 +410,7 @@ class CLikeCompiler(Compiler): if mode is CompileCheckMode.LINK: ld_value = env.lookup_binary_entry(self.for_machine, self.language + '_ld') if ld_value is not None: - largs += self.use_linker_args(ld_value[0]) + largs += self.use_linker_args(ld_value[0], self.version) # Add LDFLAGS from the env sys_ld_args = env.coredata.get_external_link_args(self.for_machine, self.language) diff --git a/mesonbuild/compilers/mixins/gnu.py b/mesonbuild/compilers/mixins/gnu.py index 91e07e5..2613038 100644 --- a/mesonbuild/compilers/mixins/gnu.py +++ b/mesonbuild/compilers/mixins/gnu.py @@ -1,4 +1,4 @@ -# Copyright 2019 The meson development team +# Copyright 2019-2022 The meson development team # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -306,7 +306,7 @@ class GnuLikeCompiler(Compiler, metaclass=abc.ABCMeta): return ['-I' + path] @classmethod - def use_linker_args(cls, linker: str) -> T.List[str]: + def use_linker_args(cls, linker: str, version: str) -> T.List[str]: if linker not in {'gold', 'bfd', 'lld'}: raise mesonlib.MesonException( f'Unsupported linker, only bfd, gold, and lld are supported, not {linker}.') @@ -389,3 +389,9 @@ class GnuCompiler(GnuLikeCompiler): elif threads > 0: return [f'-flto={threads}'] return super().get_lto_compile_args(threads=threads) + + @classmethod + def use_linker_args(cls, linker: str, version: str) -> T.List[str]: + if linker == 'mold' and mesonlib.version_compare(version, '>=12.0.1'): + return ['-fuse-ld=mold'] + return super().use_linker_args(linker, version) diff --git a/mesonbuild/compilers/rust.py b/mesonbuild/compilers/rust.py index a460b78..0967ada 100644 --- a/mesonbuild/compilers/rust.py +++ b/mesonbuild/compilers/rust.py @@ -1,4 +1,4 @@ -# Copyright 2012-2017 The Meson development team +# Copyright 2012-2022 The Meson development team # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -136,7 +136,7 @@ class RustCompiler(Compiler): return ['-o', outputname] @classmethod - def use_linker_args(cls, linker: str) -> T.List[str]: + def use_linker_args(cls, linker: str, version: str) -> T.List[str]: return ['-C', f'linker={linker}'] # Rust does not have a use_linker_args because it dispatches to a gcc-like |