# Copyright 2019 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
#
#     http://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.

"""Mixins for compilers that *are* linkers.

While many compilers (such as gcc and clang) are used by meson to dispatch
linker commands and other (like MSVC) are not, a few (such as DMD) actually
are both the linker and compiler in one binary. This module provides mixin
classes for those cases.
"""

import typing as T

from ...mesonlib import EnvironmentException, MesonException, is_windows

if T.TYPE_CHECKING:
    from ...coredata import KeyedOptionDictType
    from ...environment import Environment
    from ...compilers.compilers import Compiler
else:
    # This is a bit clever, for mypy we pretend that these mixins descend from
    # Compiler, so we get all of the methods and attributes defined for us, but
    # for runtime we make them descend from object (which all classes normally
    # do). This gives up DRYer type checking, with no runtime impact
    Compiler = object


class BasicLinkerIsCompilerMixin(Compiler):

    """Provides a baseline of methods that a linker would implement.

    In every case this provides a "no" or "empty" answer. If a compiler
    implements any of these it needs a different mixin or to override that
    functionality itself.
    """

    def sanitizer_link_args(self, value: str) -> T.List[str]:
        return []

    def get_lto_link_args(self, *, threads: int = 0, mode: str = 'default',
                          thinlto_cache_dir: T.Optional[str] = None) -> T.List[str]:
        return []

    def can_linker_accept_rsp(self) -> bool:
        return is_windows()

    def get_linker_exelist(self) -> T.List[str]:
        return self.exelist.copy()

    def get_linker_output_args(self, outputname: str) -> T.List[str]:
        return []

    def get_linker_always_args(self) -> T.List[str]:
        return []

    def get_linker_lib_prefix(self) -> str:
        return ''

    def get_option_link_args(self, options: 'KeyedOptionDictType') -> T.List[str]:
        return []

    def has_multi_link_args(self, args: T.List[str], env: 'Environment') -> T.Tuple[bool, bool]:
        return False, False

    def get_link_debugfile_args(self, targetfile: str) -> T.List[str]:
        return []

    def get_std_shared_lib_link_args(self) -> T.List[str]:
        return []

    def get_std_shared_module_args(self, options: 'KeyedOptionDictType') -> T.List[str]:
        return self.get_std_shared_lib_link_args()

    def get_link_whole_for(self, args: T.List[str]) -> T.List[str]:
        raise EnvironmentException(f'Linker {self.id} does not support link_whole')

    def get_allow_undefined_link_args(self) -> T.List[str]:
        raise EnvironmentException(f'Linker {self.id} does not support allow undefined')

    def get_pie_link_args(self) -> T.List[str]:
        raise EnvironmentException(f'Linker {self.id} does not support position-independent executable')

    def get_undefined_link_args(self) -> T.List[str]:
        return []

    def get_coverage_link_args(self) -> T.List[str]:
        return []

    def no_undefined_link_args(self) -> T.List[str]:
        return []

    def bitcode_args(self) -> T.List[str]:
        raise MesonException("This linker doesn't support bitcode bundles")

    def get_soname_args(self, env: 'Environment', prefix: str, shlib_name: str,
                        suffix: str, soversion: str,
                        darwin_versions: T.Tuple[str, str]) -> T.List[str]:
        raise MesonException("This linker doesn't support soname args")

    def build_rpath_args(self, env: 'Environment', build_dir: str, from_dir: str,
                         rpath_paths: T.Tuple[str, ...], build_rpath: str,
                         install_rpath: str) -> T.Tuple[T.List[str], T.Set[bytes]]:
        return ([], set())

    def get_asneeded_args(self) -> T.List[str]:
        return []

    def get_buildtype_linker_args(self, buildtype: str) -> T.List[str]:
        return []

    def get_link_debugfile_name(self, targetfile: str) -> str:
        return ''

    def thread_flags(self, env: 'Environment') -> T.List[str]:
        return []

    def thread_link_flags(self, env: 'Environment') -> T.List[str]:
        return []
