From a1ef957e349583f9affdce5b5a4f094860e91037 Mon Sep 17 00:00:00 2001 From: Eli Schwartz Date: Mon, 6 Feb 2023 23:29:27 -0500 Subject: [PATCH] linkers: delay implementations import until detect is run This saves on a 1500-line import at startup and may be skipped entirely if no compiled languages are used. In exchange, we move the implementation to a new file that is imported instead. Followup to commit ab20eb5bbc21ae855bcd211131132d2778602bcf. --- mesonbuild/arglist.py | 2 +- mesonbuild/backend/backends.py | 2 +- mesonbuild/backend/ninjabackend.py | 2 +- mesonbuild/build.py | 2 +- mesonbuild/compilers/asm.py | 2 +- mesonbuild/compilers/c.py | 2 +- mesonbuild/compilers/compilers.py | 3 +- mesonbuild/compilers/cpp.py | 2 +- mesonbuild/compilers/cuda.py | 2 +- mesonbuild/compilers/d.py | 2 +- mesonbuild/compilers/detect.py | 2 +- mesonbuild/compilers/fortran.py | 2 +- mesonbuild/compilers/mixins/arm.py | 2 +- mesonbuild/compilers/mixins/clang.py | 2 +- mesonbuild/compilers/mixins/clike.py | 2 +- mesonbuild/compilers/objc.py | 2 +- mesonbuild/compilers/objcpp.py | 2 +- mesonbuild/compilers/rust.py | 2 +- mesonbuild/compilers/swift.py | 2 +- mesonbuild/linkers/__init__.py | 130 +----------------- mesonbuild/linkers/base.py | 50 +++++++ mesonbuild/linkers/detect.py | 46 +++---- mesonbuild/linkers/linkers.py | 36 +---- .../unit/113 empty project/expected_mods.json | 2 +- unittests/allplatformstests.py | 29 ++-- unittests/internaltests.py | 7 +- 26 files changed, 117 insertions(+), 222 deletions(-) create mode 100644 mesonbuild/linkers/base.py diff --git a/mesonbuild/arglist.py b/mesonbuild/arglist.py index cb74d3185..c44728ab7 100644 --- a/mesonbuild/arglist.py +++ b/mesonbuild/arglist.py @@ -22,7 +22,7 @@ import re import typing as T if T.TYPE_CHECKING: - from .linkers import StaticLinker + from .linkers.linkers import StaticLinker from .compilers import Compiler # execinfo is a compiler lib on BSD diff --git a/mesonbuild/backend/backends.py b/mesonbuild/backend/backends.py index 14f03b137..dec1e68cc 100644 --- a/mesonbuild/backend/backends.py +++ b/mesonbuild/backend/backends.py @@ -46,7 +46,7 @@ if T.TYPE_CHECKING: from ..compilers import Compiler from ..environment import Environment from ..interpreter import Interpreter, Test - from ..linkers import StaticLinker + from ..linkers.linkers import StaticLinker from ..mesonlib import FileMode, FileOrString from typing_extensions import TypedDict diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py index b6b8599f1..c91830470 100644 --- a/mesonbuild/backend/ninjabackend.py +++ b/mesonbuild/backend/ninjabackend.py @@ -52,7 +52,7 @@ if T.TYPE_CHECKING: from .._typing import ImmutableListProtocol from ..build import ExtractedObjects, LibTypes from ..interpreter import Interpreter - from ..linkers import DynamicLinker, StaticLinker + from ..linkers.linkers import DynamicLinker, StaticLinker from ..compilers.cs import CsCompiler from ..compilers.fortran import FortranCompiler diff --git a/mesonbuild/build.py b/mesonbuild/build.py index 7254f7578..b9525987d 100644 --- a/mesonbuild/build.py +++ b/mesonbuild/build.py @@ -52,7 +52,7 @@ if T.TYPE_CHECKING: from .compilers import Compiler from .interpreter.interpreter import Test, SourceOutputs, Interpreter from .interpreterbase import SubProject - from .linkers import StaticLinker + from .linkers.linkers import StaticLinker from .mesonlib import FileMode, FileOrString from .modules import ModuleState from .mparser import BaseNode diff --git a/mesonbuild/compilers/asm.py b/mesonbuild/compilers/asm.py index 17b11ba4c..e34b4a671 100644 --- a/mesonbuild/compilers/asm.py +++ b/mesonbuild/compilers/asm.py @@ -7,7 +7,7 @@ from .mixins.metrowerks import MetrowerksCompiler, mwasmarm_instruction_set_args if T.TYPE_CHECKING: from ..environment import Environment - from ..linkers import DynamicLinker + from ..linkers.linkers import DynamicLinker from ..mesonlib import MachineChoice from ..envconfig import MachineInfo diff --git a/mesonbuild/compilers/c.py b/mesonbuild/compilers/c.py index c1dafd0fe..d514650de 100644 --- a/mesonbuild/compilers/c.py +++ b/mesonbuild/compilers/c.py @@ -47,7 +47,7 @@ if T.TYPE_CHECKING: from ..dependencies import Dependency from ..envconfig import MachineInfo from ..environment import Environment - from ..linkers import DynamicLinker + from ..linkers.linkers import DynamicLinker from ..mesonlib import MachineChoice from ..programs import ExternalProgram from .compilers import CompileCheckMode diff --git a/mesonbuild/compilers/compilers.py b/mesonbuild/compilers/compilers.py index 76f9e0e34..3fd58968f 100644 --- a/mesonbuild/compilers/compilers.py +++ b/mesonbuild/compilers/compilers.py @@ -36,7 +36,8 @@ if T.TYPE_CHECKING: from ..coredata import MutableKeyedOptionDictType, KeyedOptionDictType from ..envconfig import MachineInfo from ..environment import Environment - from ..linkers import DynamicLinker, RSPFileSyntax + from ..linkers import RSPFileSyntax + from ..linkers.linkers import DynamicLinker from ..mesonlib import MachineChoice from ..dependencies import Dependency diff --git a/mesonbuild/compilers/cpp.py b/mesonbuild/compilers/cpp.py index dbdcb2fa2..3f8bf00ec 100644 --- a/mesonbuild/compilers/cpp.py +++ b/mesonbuild/compilers/cpp.py @@ -48,7 +48,7 @@ if T.TYPE_CHECKING: from ..dependencies import Dependency from ..envconfig import MachineInfo from ..environment import Environment - from ..linkers import DynamicLinker + from ..linkers.linkers import DynamicLinker from ..mesonlib import MachineChoice from ..programs import ExternalProgram CompilerMixinBase = CLikeCompiler diff --git a/mesonbuild/compilers/cuda.py b/mesonbuild/compilers/cuda.py index bbc2fc8fc..8ed7fa41c 100644 --- a/mesonbuild/compilers/cuda.py +++ b/mesonbuild/compilers/cuda.py @@ -34,7 +34,7 @@ if T.TYPE_CHECKING: from ..dependencies import Dependency from ..environment import Environment # noqa: F401 from ..envconfig import MachineInfo - from ..linkers import DynamicLinker + from ..linkers.linkers import DynamicLinker from ..mesonlib import MachineChoice from ..programs import ExternalProgram diff --git a/mesonbuild/compilers/d.py b/mesonbuild/compilers/d.py index 4cdda0093..c6e70b252 100644 --- a/mesonbuild/compilers/d.py +++ b/mesonbuild/compilers/d.py @@ -43,7 +43,7 @@ if T.TYPE_CHECKING: from ..programs import ExternalProgram from ..envconfig import MachineInfo from ..environment import Environment - from ..linkers import DynamicLinker + from ..linkers.linkers import DynamicLinker from ..mesonlib import MachineChoice CompilerMixinBase = Compiler diff --git a/mesonbuild/compilers/detect.py b/mesonbuild/compilers/detect.py index f6d1c427c..5ac19c952 100644 --- a/mesonbuild/compilers/detect.py +++ b/mesonbuild/compilers/detect.py @@ -36,7 +36,7 @@ if T.TYPE_CHECKING: from .cpp import CPPCompiler from .fortran import FortranCompiler from .rust import RustCompiler - from ..linkers import StaticLinker, DynamicLinker + from ..linkers.linkers import StaticLinker, DynamicLinker from ..environment import Environment from ..programs import ExternalProgram diff --git a/mesonbuild/compilers/fortran.py b/mesonbuild/compilers/fortran.py index e767dcd97..7c836b74a 100644 --- a/mesonbuild/compilers/fortran.py +++ b/mesonbuild/compilers/fortran.py @@ -40,7 +40,7 @@ if T.TYPE_CHECKING: from ..dependencies import Dependency from ..envconfig import MachineInfo from ..environment import Environment - from ..linkers import DynamicLinker + from ..linkers.linkers import DynamicLinker from ..mesonlib import MachineChoice from ..programs import ExternalProgram from .compilers import CompileCheckMode diff --git a/mesonbuild/compilers/mixins/arm.py b/mesonbuild/compilers/mixins/arm.py index e8efae122..7c5332739 100644 --- a/mesonbuild/compilers/mixins/arm.py +++ b/mesonbuild/compilers/mixins/arm.py @@ -19,7 +19,7 @@ import os import typing as T from ... import mesonlib -from ...linkers import ArmClangDynamicLinker +from ...linkers.linkers import ArmClangDynamicLinker from ...mesonlib import OptionKey from ..compilers import clike_debug_args from .clang import clang_color_args diff --git a/mesonbuild/compilers/mixins/clang.py b/mesonbuild/compilers/mixins/clang.py index cdb4c2300..b43b2465e 100644 --- a/mesonbuild/compilers/mixins/clang.py +++ b/mesonbuild/compilers/mixins/clang.py @@ -20,7 +20,7 @@ import shutil import typing as T from ... import mesonlib -from ...linkers import AppleDynamicLinker, ClangClDynamicLinker, LLVMDynamicLinker, GnuGoldDynamicLinker, \ +from ...linkers.linkers import AppleDynamicLinker, ClangClDynamicLinker, LLVMDynamicLinker, GnuGoldDynamicLinker, \ MoldDynamicLinker from ...mesonlib import OptionKey from ..compilers import CompileCheckMode diff --git a/mesonbuild/compilers/mixins/clike.py b/mesonbuild/compilers/mixins/clike.py index 4ebec3f8e..2649cae71 100644 --- a/mesonbuild/compilers/mixins/clike.py +++ b/mesonbuild/compilers/mixins/clike.py @@ -35,7 +35,7 @@ from pathlib import Path from ... import arglist from ... import mesonlib from ... import mlog -from ...linkers import GnuLikeDynamicLinkerMixin, SolarisDynamicLinker, CompCertDynamicLinker +from ...linkers.linkers import GnuLikeDynamicLinkerMixin, SolarisDynamicLinker, CompCertDynamicLinker from ...mesonlib import LibType from ...coredata import OptionKey from .. import compilers diff --git a/mesonbuild/compilers/objc.py b/mesonbuild/compilers/objc.py index 83dcaadf3..cb8eb9e1f 100644 --- a/mesonbuild/compilers/objc.py +++ b/mesonbuild/compilers/objc.py @@ -27,7 +27,7 @@ if T.TYPE_CHECKING: from ..programs import ExternalProgram from ..envconfig import MachineInfo from ..environment import Environment - from ..linkers import DynamicLinker + from ..linkers.linkers import DynamicLinker from ..mesonlib import MachineChoice diff --git a/mesonbuild/compilers/objcpp.py b/mesonbuild/compilers/objcpp.py index 1f9f75635..530bc7cb6 100644 --- a/mesonbuild/compilers/objcpp.py +++ b/mesonbuild/compilers/objcpp.py @@ -27,7 +27,7 @@ if T.TYPE_CHECKING: from ..programs import ExternalProgram from ..envconfig import MachineInfo from ..environment import Environment - from ..linkers import DynamicLinker + from ..linkers.linkers import DynamicLinker from ..mesonlib import MachineChoice class ObjCPPCompiler(CLikeCompiler, Compiler): diff --git a/mesonbuild/compilers/rust.py b/mesonbuild/compilers/rust.py index 4fc3a49b7..13674ed15 100644 --- a/mesonbuild/compilers/rust.py +++ b/mesonbuild/compilers/rust.py @@ -26,7 +26,7 @@ if T.TYPE_CHECKING: from ..coredata import MutableKeyedOptionDictType, KeyedOptionDictType from ..envconfig import MachineInfo from ..environment import Environment # noqa: F401 - from ..linkers import DynamicLinker + from ..linkers.linkers import DynamicLinker from ..mesonlib import MachineChoice from ..programs import ExternalProgram from ..dependencies import Dependency diff --git a/mesonbuild/compilers/swift.py b/mesonbuild/compilers/swift.py index ebf29f8e6..19866e2c0 100644 --- a/mesonbuild/compilers/swift.py +++ b/mesonbuild/compilers/swift.py @@ -23,7 +23,7 @@ from .compilers import Compiler, swift_buildtype_args, clike_debug_args if T.TYPE_CHECKING: from ..envconfig import MachineInfo from ..environment import Environment - from ..linkers import DynamicLinker + from ..linkers.linkers import DynamicLinker from ..mesonlib import MachineChoice swift_optimization_args = { diff --git a/mesonbuild/linkers/__init__.py b/mesonbuild/linkers/__init__.py index b9df8d7af..7c3569400 100644 --- a/mesonbuild/linkers/__init__.py +++ b/mesonbuild/linkers/__init__.py @@ -12,139 +12,21 @@ # See the License for the specific language governing permissions and # limitations under the License. + +from .base import ArLikeLinker, RSPFileSyntax from .detect import ( defaults, guess_win_linker, guess_nix_linker, ) -from .linkers import ( - RSPFileSyntax, - - StaticLinker, - VisualStudioLikeLinker, - VisualStudioLinker, - IntelVisualStudioLinker, - AppleArLinker, - ArLikeLinker, - ArLinker, - ArmarLinker, - DLinker, - CcrxLinker, - Xc16Linker, - CompCertLinker, - C2000Linker, - TILinker, - AIXArLinker, - PGIStaticLinker, - NvidiaHPC_StaticLinker, - MetrowerksStaticLinker, - MetrowerksStaticLinkerARM, - MetrowerksStaticLinkerEmbeddedPowerPC, - - DynamicLinker, - PosixDynamicLinkerMixin, - GnuLikeDynamicLinkerMixin, - AppleDynamicLinker, - GnuDynamicLinker, - GnuGoldDynamicLinker, - GnuBFDDynamicLinker, - LLVMDynamicLinker, - MoldDynamicLinker, - WASMDynamicLinker, - CcrxDynamicLinker, - Xc16DynamicLinker, - CompCertDynamicLinker, - C2000DynamicLinker, - TIDynamicLinker, - ArmDynamicLinker, - ArmClangDynamicLinker, - QualcommLLVMDynamicLinker, - PGIDynamicLinker, - NvidiaHPC_DynamicLinker, - NAGDynamicLinker, - MetrowerksLinker, - MetrowerksLinkerARM, - MetrowerksLinkerEmbeddedPowerPC, - - VisualStudioLikeLinkerMixin, - MSVCDynamicLinker, - ClangClDynamicLinker, - XilinkDynamicLinker, - SolarisDynamicLinker, - AIXDynamicLinker, - OptlinkDynamicLinker, - CudaLinker, - - prepare_rpaths, - order_rpaths, - evaluate_rpath, -) __all__ = [ + # base.py + 'ArLikeLinker', + 'RSPFileSyntax', + # detect.py 'defaults', 'guess_win_linker', 'guess_nix_linker', - - # linkers.py - 'RSPFileSyntax', - - 'StaticLinker', - 'VisualStudioLikeLinker', - 'VisualStudioLinker', - 'IntelVisualStudioLinker', - 'ArLikeLinker', - 'ArLinker', - 'ArmarLinker', - 'DLinker', - 'CcrxLinker', - 'Xc16Linker', - 'CompCertLinker', - 'C2000Linker', - 'TILinker', - 'AIXArLinker', - 'AppleArLinker', - 'PGIStaticLinker', - 'NvidiaHPC_StaticLinker', - 'MetrowerksStaticLinker', - 'MetrowerksStaticLinkerARM', - 'MetrowerksStaticLinkerEmbeddedPowerPC', - - 'DynamicLinker', - 'PosixDynamicLinkerMixin', - 'GnuLikeDynamicLinkerMixin', - 'AppleDynamicLinker', - 'GnuDynamicLinker', - 'GnuGoldDynamicLinker', - 'GnuBFDDynamicLinker', - 'LLVMDynamicLinker', - 'MoldDynamicLinker', - 'WASMDynamicLinker', - 'CcrxDynamicLinker', - 'Xc16DynamicLinker', - 'CompCertDynamicLinker', - 'C2000DynamicLinker', - 'TIDynamicLinker', - 'ArmDynamicLinker', - 'ArmClangDynamicLinker', - 'QualcommLLVMDynamicLinker', - 'PGIDynamicLinker', - 'NvidiaHPC_DynamicLinker', - 'NAGDynamicLinker', - 'MetrowerksLinker', - 'MetrowerksLinkerARM', - 'MetrowerksLinkerEmbeddedPowerPC', - - 'VisualStudioLikeLinkerMixin', - 'MSVCDynamicLinker', - 'ClangClDynamicLinker', - 'XilinkDynamicLinker', - 'SolarisDynamicLinker', - 'AIXDynamicLinker', - 'OptlinkDynamicLinker', - 'CudaLinker', - - 'prepare_rpaths', - 'order_rpaths', - 'evaluate_rpath', ] diff --git a/mesonbuild/linkers/base.py b/mesonbuild/linkers/base.py new file mode 100644 index 000000000..a656bb40c --- /dev/null +++ b/mesonbuild/linkers/base.py @@ -0,0 +1,50 @@ +# Copyright 2012-2023 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. +# You may obtain a copy of the License at + +# https://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Core public classes for linkers. +from __future__ import annotations + +import enum +import typing as T + +if T.TYPE_CHECKING: + from ..environment import Environment + + +@enum.unique +class RSPFileSyntax(enum.Enum): + + """Which RSP file syntax the compiler supports.""" + + MSVC = enum.auto() + GCC = enum.auto() + + +class ArLikeLinker: + # POSIX requires supporting the dash, GNU permits omitting it + std_args = ['-csr'] + + def can_linker_accept_rsp(self) -> bool: + # armar / AIX can't accept arguments using the @rsp syntax + # in fact, only the 'ar' id can + return False + + def get_std_link_args(self, env: 'Environment', is_thin: bool) -> T.List[str]: + return self.std_args + + def get_output_args(self, target: str) -> T.List[str]: + return [target] + + def rsp_file_syntax(self) -> RSPFileSyntax: + return RSPFileSyntax.GCC diff --git a/mesonbuild/linkers/detect.py b/mesonbuild/linkers/detect.py index 3f8de0570..60be10fde 100644 --- a/mesonbuild/linkers/detect.py +++ b/mesonbuild/linkers/detect.py @@ -19,20 +19,6 @@ from ..mesonlib import ( EnvironmentException, Popen_safe, Popen_safe_logged, join_args, search_version ) -from .linkers import ( - AppleDynamicLinker, - LLVMLD64DynamicLinker, - GnuGoldDynamicLinker, - GnuBFDDynamicLinker, - MoldDynamicLinker, - LLVMDynamicLinker, - QualcommLLVMDynamicLinker, - MSVCDynamicLinker, - ClangClDynamicLinker, - SolarisDynamicLinker, - AIXDynamicLinker, - OptlinkDynamicLinker, -) import re import shlex @@ -62,6 +48,7 @@ def guess_win_linker(env: 'Environment', compiler: T.List[str], comp_class: T.Ty comp_version: str, for_machine: MachineChoice, *, use_linker_prefix: bool = True, invoked_directly: bool = True, extra_args: T.Optional[T.List[str]] = None) -> 'DynamicLinker': + from . import linkers env.coredata.add_lang_args(comp_class.language, comp_class, for_machine, env) # Explicitly pass logo here so that we can get the version of link.exe @@ -86,11 +73,11 @@ def guess_win_linker(env: 'Environment', compiler: T.List[str], comp_class: T.Ty p, o, _ = Popen_safe(compiler + check_args) if 'LLD' in o.split('\n', maxsplit=1)[0]: if '(compatible with GNU linkers)' in o: - return LLVMDynamicLinker( + return linkers.LLVMDynamicLinker( compiler, for_machine, comp_class.LINKER_PREFIX, override, version=search_version(o)) elif not invoked_directly: - return ClangClDynamicLinker( + return linkers.ClangClDynamicLinker( for_machine, override, exelist=compiler, prefix=comp_class.LINKER_PREFIX, version=search_version(o), direct=False, machine=None) @@ -100,13 +87,13 @@ def guess_win_linker(env: 'Environment', compiler: T.List[str], comp_class: T.Ty p, o, e = Popen_safe(compiler + check_args) if 'LLD' in o.split('\n', maxsplit=1)[0]: - return ClangClDynamicLinker( + return linkers.ClangClDynamicLinker( for_machine, [], prefix=comp_class.LINKER_PREFIX if use_linker_prefix else [], exelist=compiler, version=search_version(o), direct=invoked_directly) elif 'OPTLINK' in o: # Optlink's stdout *may* begin with a \r character. - return OptlinkDynamicLinker(compiler, for_machine, version=search_version(o)) + return linkers.OptlinkDynamicLinker(compiler, for_machine, version=search_version(o)) elif o.startswith('Microsoft') or e.startswith('Microsoft'): out = o or e match = re.search(r'.*(X86|X64|ARM|ARM64).*', out) @@ -115,7 +102,7 @@ def guess_win_linker(env: 'Environment', compiler: T.List[str], comp_class: T.Ty else: target = 'x86' - return MSVCDynamicLinker( + return linkers.MSVCDynamicLinker( for_machine, [], machine=target, exelist=compiler, prefix=comp_class.LINKER_PREFIX if use_linker_prefix else [], version=search_version(out), direct=invoked_directly) @@ -139,6 +126,7 @@ def guess_nix_linker(env: 'Environment', compiler: T.List[str], comp_class: T.Ty :for_machine: which machine this linker targets :extra_args: Any additional arguments required (such as a source file) """ + from . import linkers env.coredata.add_lang_args(comp_class.language, comp_class, for_machine, env) extra_args = extra_args or [] @@ -170,14 +158,14 @@ def guess_nix_linker(env: 'Environment', compiler: T.List[str], comp_class: T.Ty lld_cls: T.Type[DynamicLinker] if 'ld64.lld' in newerr: - lld_cls = LLVMLD64DynamicLinker + lld_cls = linkers.LLVMLD64DynamicLinker else: - lld_cls = LLVMDynamicLinker + lld_cls = linkers.LLVMDynamicLinker linker = lld_cls( compiler, for_machine, comp_class.LINKER_PREFIX, override, version=v) elif 'Snapdragon' in e and 'LLVM' in e: - linker = QualcommLLVMDynamicLinker( + linker = linkers.QualcommLLVMDynamicLinker( compiler, for_machine, comp_class.LINKER_PREFIX, override, version=v) elif e.startswith('lld-link: '): # The LLD MinGW frontend didn't respond to --version before version 9.0.0, @@ -196,7 +184,7 @@ def guess_nix_linker(env: 'Environment', compiler: T.List[str], comp_class: T.Ty _, o, e = Popen_safe([linker_cmd, '--version']) v = search_version(o) - linker = LLVMDynamicLinker(compiler, for_machine, comp_class.LINKER_PREFIX, override, version=v) + linker = linkers.LLVMDynamicLinker(compiler, for_machine, comp_class.LINKER_PREFIX, override, version=v) # first might be apple clang, second is for real gcc, the third is icc elif e.endswith('(use -v to see invocation)\n') or 'macosx_version' in e or 'ld: unknown option:' in e: if isinstance(comp_class.LINKER_PREFIX, str): @@ -211,17 +199,17 @@ def guess_nix_linker(env: 'Environment', compiler: T.List[str], comp_class: T.Ty break else: __failed_to_detect_linker(compiler, check_args, o, e) - linker = AppleDynamicLinker(compiler, for_machine, comp_class.LINKER_PREFIX, override, version=v) + linker = linkers.AppleDynamicLinker(compiler, for_machine, comp_class.LINKER_PREFIX, override, version=v) elif 'GNU' in o or 'GNU' in e: gnu_cls: T.Type[GnuDynamicLinker] # this is always the only thing on stdout, except for swift # which may or may not redirect the linker stdout to stderr if o.startswith('GNU gold') or e.startswith('GNU gold'): - gnu_cls = GnuGoldDynamicLinker + gnu_cls = linkers.GnuGoldDynamicLinker elif o.startswith('mold') or e.startswith('mold'): - gnu_cls = MoldDynamicLinker + gnu_cls = linkers.MoldDynamicLinker else: - gnu_cls = GnuBFDDynamicLinker + gnu_cls = linkers.GnuBFDDynamicLinker linker = gnu_cls(compiler, for_machine, comp_class.LINKER_PREFIX, override, version=v) elif 'Solaris' in e or 'Solaris' in o: for line in (o+e).split('\n'): @@ -230,7 +218,7 @@ def guess_nix_linker(env: 'Environment', compiler: T.List[str], comp_class: T.Ty break else: v = 'unknown version' - linker = SolarisDynamicLinker( + linker = linkers.SolarisDynamicLinker( compiler, for_machine, comp_class.LINKER_PREFIX, override, version=v) elif 'ld: 0706-012 The -- flag is not recognized' in e: @@ -238,7 +226,7 @@ def guess_nix_linker(env: 'Environment', compiler: T.List[str], comp_class: T.Ty _, _, e = Popen_safe(compiler + [comp_class.LINKER_PREFIX + '-V'] + extra_args) else: _, _, e = Popen_safe(compiler + comp_class.LINKER_PREFIX + ['-V'] + extra_args) - linker = AIXDynamicLinker( + linker = linkers.AIXDynamicLinker( compiler, for_machine, comp_class.LINKER_PREFIX, override, version=search_version(e)) else: diff --git a/mesonbuild/linkers/linkers.py b/mesonbuild/linkers/linkers.py index 21e0eebc0..d7868f260 100644 --- a/mesonbuild/linkers/linkers.py +++ b/mesonbuild/linkers/linkers.py @@ -14,10 +14,10 @@ from __future__ import annotations import abc -import enum import os import typing as T +from .base import ArLikeLinker, RSPFileSyntax from .. import mesonlib from ..mesonlib import EnvironmentException, MesonException from ..arglist import CompilerArgs @@ -28,15 +28,6 @@ if T.TYPE_CHECKING: from ..mesonlib import MachineChoice -@enum.unique -class RSPFileSyntax(enum.Enum): - - """Which RSP file syntax the compiler supports.""" - - MSVC = enum.auto() - GCC = enum.auto() - - class StaticLinker: id: str @@ -168,26 +159,7 @@ class IntelVisualStudioLinker(VisualStudioLikeLinker, StaticLinker): VisualStudioLikeLinker.__init__(self, machine) -class ArLikeLinker(StaticLinker): - # POSIX requires supporting the dash, GNU permits omitting it - std_args = ['-csr'] - - def can_linker_accept_rsp(self) -> bool: - # armar / AIX can't accept arguments using the @rsp syntax - # in fact, only the 'ar' id can - return False - - def get_std_link_args(self, env: 'Environment', is_thin: bool) -> T.List[str]: - return self.std_args - - def get_output_args(self, target: str) -> T.List[str]: - return [target] - - def rsp_file_syntax(self) -> RSPFileSyntax: - return RSPFileSyntax.GCC - - -class ArLinker(ArLikeLinker): +class ArLinker(ArLikeLinker, StaticLinker): id = 'ar' def __init__(self, for_machine: mesonlib.MachineChoice, exelist: T.List[str]): @@ -227,7 +199,7 @@ class AppleArLinker(ArLinker): id = 'applear' -class ArmarLinker(ArLikeLinker): +class ArmarLinker(ArLikeLinker, StaticLinker): id = 'armar' @@ -322,7 +294,7 @@ class C2000Linker(TILinker): id = 'ar2000' -class AIXArLinker(ArLikeLinker): +class AIXArLinker(ArLikeLinker, StaticLinker): id = 'aixar' std_args = ['-csr', '-Xany'] diff --git a/test cases/unit/113 empty project/expected_mods.json b/test cases/unit/113 empty project/expected_mods.json index 05f4cb6a9..1a0e8a13f 100644 --- a/test cases/unit/113 empty project/expected_mods.json +++ b/test cases/unit/113 empty project/expected_mods.json @@ -216,8 +216,8 @@ "mesonbuild.interpreterbase.interpreterbase", "mesonbuild.interpreterbase.operator", "mesonbuild.linkers", + "mesonbuild.linkers.base", "mesonbuild.linkers.detect", - "mesonbuild.linkers.linkers", "mesonbuild.mesonlib", "mesonbuild.mesonmain", "mesonbuild.mintro", diff --git a/unittests/allplatformstests.py b/unittests/allplatformstests.py index 2d0b054d1..f270e51c5 100644 --- a/unittests/allplatformstests.py +++ b/unittests/allplatformstests.py @@ -55,6 +55,7 @@ from mesonbuild.compilers import ( detect_static_linker, detect_c_compiler, compiler_from_language, detect_compiler_for ) +from mesonbuild.linkers import linkers from mesonbuild.dependencies.pkgconfig import PkgConfigDependency from mesonbuild.build import Target, ConfigurationData, Executable, SharedLibrary, StaticLibrary @@ -354,7 +355,7 @@ class AllPlatformTests(BasePlatformTests): static_linker = detect_static_linker(env, cc) if is_windows(): raise SkipTest('https://github.com/mesonbuild/meson/issues/1526') - if not isinstance(static_linker, mesonbuild.linkers.ArLinker): + if not isinstance(static_linker, linkers.ArLinker): raise SkipTest('static linker is not `ar`') # Configure self.init(testdir) @@ -983,8 +984,8 @@ class AllPlatformTests(BasePlatformTests): intel = IntelGnuLikeCompiler msvc = (VisualStudioCCompiler, VisualStudioCPPCompiler) clangcl = (ClangClCCompiler, ClangClCPPCompiler) - ar = mesonbuild.linkers.ArLinker - lib = mesonbuild.linkers.VisualStudioLinker + ar = linkers.ArLinker + lib = linkers.VisualStudioLinker langs = [('c', 'CC'), ('cpp', 'CXX')] if not is_windows() and platform.machine().lower() != 'e2k': langs += [('objc', 'OBJC'), ('objcpp', 'OBJCXX')] @@ -1028,39 +1029,39 @@ class AllPlatformTests(BasePlatformTests): if isinstance(cc, gnu): self.assertIsInstance(linker, ar) if is_osx(): - self.assertIsInstance(cc.linker, mesonbuild.linkers.AppleDynamicLinker) + self.assertIsInstance(cc.linker, linkers.AppleDynamicLinker) elif is_sunos(): - self.assertIsInstance(cc.linker, (mesonbuild.linkers.SolarisDynamicLinker, mesonbuild.linkers.GnuLikeDynamicLinkerMixin)) + self.assertIsInstance(cc.linker, (linkers.SolarisDynamicLinker, linkers.GnuLikeDynamicLinkerMixin)) else: - self.assertIsInstance(cc.linker, mesonbuild.linkers.GnuLikeDynamicLinkerMixin) + self.assertIsInstance(cc.linker, linkers.GnuLikeDynamicLinkerMixin) if isinstance(cc, clangcl): self.assertIsInstance(linker, lib) - self.assertIsInstance(cc.linker, mesonbuild.linkers.ClangClDynamicLinker) + self.assertIsInstance(cc.linker, linkers.ClangClDynamicLinker) if isinstance(cc, clang): self.assertIsInstance(linker, ar) if is_osx(): - self.assertIsInstance(cc.linker, mesonbuild.linkers.AppleDynamicLinker) + self.assertIsInstance(cc.linker, linkers.AppleDynamicLinker) elif is_windows(): # This is clang, not clang-cl. This can be either an # ld-like linker of link.exe-like linker (usually the # former for msys2, the latter otherwise) - self.assertIsInstance(cc.linker, (mesonbuild.linkers.MSVCDynamicLinker, mesonbuild.linkers.GnuLikeDynamicLinkerMixin)) + self.assertIsInstance(cc.linker, (linkers.MSVCDynamicLinker, linkers.GnuLikeDynamicLinkerMixin)) else: - self.assertIsInstance(cc.linker, mesonbuild.linkers.GnuLikeDynamicLinkerMixin) + self.assertIsInstance(cc.linker, linkers.GnuLikeDynamicLinkerMixin) if isinstance(cc, intel): self.assertIsInstance(linker, ar) if is_osx(): - self.assertIsInstance(cc.linker, mesonbuild.linkers.AppleDynamicLinker) + self.assertIsInstance(cc.linker, linkers.AppleDynamicLinker) elif is_windows(): - self.assertIsInstance(cc.linker, mesonbuild.linkers.XilinkDynamicLinker) + self.assertIsInstance(cc.linker, linkers.XilinkDynamicLinker) else: - self.assertIsInstance(cc.linker, mesonbuild.linkers.GnuDynamicLinker) + self.assertIsInstance(cc.linker, linkers.GnuDynamicLinker) if isinstance(cc, msvc): self.assertTrue(is_windows()) self.assertIsInstance(linker, lib) self.assertEqual(cc.id, 'msvc') self.assertTrue(hasattr(cc, 'is_64')) - self.assertIsInstance(cc.linker, mesonbuild.linkers.MSVCDynamicLinker) + self.assertIsInstance(cc.linker, linkers.MSVCDynamicLinker) # If we're on Windows CI, we know what the compiler will be if 'arch' in os.environ: if os.environ['arch'] == 'x64': diff --git a/unittests/internaltests.py b/unittests/internaltests.py index 6f04d9415..f22adb2f9 100644 --- a/unittests/internaltests.py +++ b/unittests/internaltests.py @@ -38,6 +38,7 @@ from mesonbuild import coredata from mesonbuild.compilers.c import ClangCCompiler, GnuCCompiler from mesonbuild.compilers.cpp import VisualStudioCPPCompiler from mesonbuild.compilers.d import DmdDCompiler +from mesonbuild.linkers import linkers from mesonbuild.interpreterbase import typed_pos_args, InvalidArguments, ObjectHolder from mesonbuild.interpreterbase import typed_pos_args, InvalidArguments, typed_kwargs, ContainerTypeInfo, KwargInfo from mesonbuild.mesonlib import ( @@ -223,7 +224,7 @@ class InternalTests(unittest.TestCase): def test_compiler_args_class_visualstudio(self): - linker = mesonbuild.linkers.MSVCDynamicLinker(MachineChoice.HOST, []) + linker = linkers.MSVCDynamicLinker(MachineChoice.HOST, []) # Version just needs to be > 19.0.0 cc = VisualStudioCPPCompiler([], [], '20.00', MachineChoice.HOST, False, mock.Mock(), 'x64', linker=linker) @@ -245,7 +246,7 @@ class InternalTests(unittest.TestCase): def test_compiler_args_class_gnuld(self): ## Test --start/end-group - linker = mesonbuild.linkers.GnuBFDDynamicLinker([], MachineChoice.HOST, '-Wl,', []) + linker = linkers.GnuBFDDynamicLinker([], MachineChoice.HOST, '-Wl,', []) gcc = GnuCCompiler([], [], 'fake', False, MachineChoice.HOST, mock.Mock(), linker=linker) ## Ensure that the fake compiler is never called by overriding the relevant function gcc.get_default_include_dirs = lambda: ['/usr/include', '/usr/share/include', '/usr/local/include'] @@ -273,7 +274,7 @@ class InternalTests(unittest.TestCase): def test_compiler_args_remove_system(self): ## Test --start/end-group - linker = mesonbuild.linkers.GnuBFDDynamicLinker([], MachineChoice.HOST, '-Wl,', []) + linker = linkers.GnuBFDDynamicLinker([], MachineChoice.HOST, '-Wl,', []) gcc = GnuCCompiler([], [], 'fake', False, MachineChoice.HOST, mock.Mock(), linker=linker) ## Ensure that the fake compiler is never called by overriding the relevant function gcc.get_default_include_dirs = lambda: ['/usr/include', '/usr/share/include', '/usr/local/include']