# 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.
# 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.
from __future__ import annotations

"""Abstractions for the LLVM/Clang compiler family."""

import os
import shutil
import typing as T

from ... import mesonlib
from ...linkers.linkers import AppleDynamicLinker, ClangClDynamicLinker, LLVMDynamicLinker, GnuGoldDynamicLinker, \
    MoldDynamicLinker
from ...mesonlib import OptionKey
from ..compilers import CompileCheckMode
from .gnu import GnuLikeCompiler

if T.TYPE_CHECKING:
    from ...environment import Environment
    from ...dependencies import Dependency  # noqa: F401

clang_color_args = {
    'auto': ['-fcolor-diagnostics'],
    'always': ['-fcolor-diagnostics'],
    'never': ['-fno-color-diagnostics'],
}  # type: T.Dict[str, T.List[str]]

clang_optimization_args = {
    'plain': [],
    '0': ['-O0'],
    'g': ['-Og'],
    '1': ['-O1'],
    '2': ['-O2'],
    '3': ['-O3'],
    's': ['-Oz'],
}  # type: T.Dict[str, T.List[str]]

class ClangCompiler(GnuLikeCompiler):

    id = 'clang'

    def __init__(self, defines: T.Optional[T.Dict[str, str]]):
        super().__init__()
        self.defines = defines or {}
        self.base_options.update(
            {OptionKey('b_colorout'), OptionKey('b_lto_threads'), OptionKey('b_lto_mode'), OptionKey('b_thinlto_cache'),
             OptionKey('b_thinlto_cache_dir')})

        # TODO: this really should be part of the linker base_options, but
        # linkers don't have base_options.
        if isinstance(self.linker, AppleDynamicLinker):
            self.base_options.add(OptionKey('b_bitcode'))
        # All Clang backends can also do LLVM IR
        self.can_compile_suffixes.add('ll')

    def get_colorout_args(self, colortype: str) -> T.List[str]:
        return clang_color_args[colortype][:]

    def has_builtin_define(self, define: str) -> bool:
        return define in self.defines

    def get_builtin_define(self, define: str) -> T.Optional[str]:
        return self.defines.get(define)

    def get_optimization_args(self, optimization_level: str) -> T.List[str]:
        return clang_optimization_args[optimization_level]

    def get_pch_suffix(self) -> str:
        return 'pch'

    def get_pch_use_args(self, pch_dir: str, header: str) -> T.List[str]:
        # Workaround for Clang bug http://llvm.org/bugs/show_bug.cgi?id=15136
        # This flag is internal to Clang (or at least not documented on the man page)
        # so it might change semantics at any time.
        return ['-include-pch', os.path.join(pch_dir, self.get_pch_name(header))]

    def get_compiler_check_args(self, mode: CompileCheckMode) -> T.List[str]:
        # Clang is different than GCC, it will return True when a symbol isn't
        # defined in a header. Specifically this seems to have something to do
        # with functions that may be in a header on some systems, but not all of
        # them. `strlcat` specifically with can trigger this.
        myargs: T.List[str] = ['-Werror=implicit-function-declaration']
        if mode is CompileCheckMode.COMPILE:
            myargs.extend(['-Werror=unknown-warning-option', '-Werror=unused-command-line-argument'])
            if mesonlib.version_compare(self.version, '>=3.6.0'):
                myargs.append('-Werror=ignored-optimization-argument')
        return super().get_compiler_check_args(mode) + myargs

    def has_function(self, funcname: str, prefix: str, env: 'Environment', *,
                     extra_args: T.Optional[T.List[str]] = None,
                     dependencies: T.Optional[T.List['Dependency']] = None) -> T.Tuple[bool, bool]:
        if extra_args is None:
            extra_args = []
        # Starting with XCode 8, we need to pass this to force linker
        # visibility to obey OS X/iOS/tvOS minimum version targets with
        # -mmacosx-version-min, -miphoneos-version-min, -mtvos-version-min etc.
        # https://github.com/Homebrew/homebrew-core/issues/3727
        # TODO: this really should be communicated by the linker
        if isinstance(self.linker, AppleDynamicLinker) and mesonlib.version_compare(self.version, '>=8.0'):
            extra_args.append('-Wl,-no_weak_imports')
        return super().has_function(funcname, prefix, env, extra_args=extra_args,
                                    dependencies=dependencies)

    def openmp_flags(self) -> T.List[str]:
        if mesonlib.version_compare(self.version, '>=3.8.0'):
            return ['-fopenmp']
        elif mesonlib.version_compare(self.version, '>=3.7.0'):
            return ['-fopenmp=libomp']
        else:
            # Shouldn't work, but it'll be checked explicitly in the OpenMP dependency.
            return []

    @classmethod
    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.
        #

        # 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, 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
        # error.
        return ['-Werror=attributes']

    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':
            # ThinLTO requires the use of gold, lld, ld64, lld-link or mold 1.1+
            if isinstance(self.linker, (MoldDynamicLinker)):
                # https://github.com/rui314/mold/commit/46995bcfc3e3113133620bf16445c5f13cd76a18
                if not mesonlib.version_compare(self.linker.version, '>=1.1'):
                    raise mesonlib.MesonException("LLVM's ThinLTO requires mold 1.1+")
            elif not isinstance(self.linker, (AppleDynamicLinker, ClangClDynamicLinker, LLVMDynamicLinker, GnuGoldDynamicLinker)):
                raise mesonlib.MesonException(f"LLVM's ThinLTO only works with gold, lld, lld-link, ld64 or mold, 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))
        return args

    def get_lto_link_args(self, *, threads: int = 0, mode: str = 'default',
                          thinlto_cache_dir: T.Optional[str] = None) -> T.List[str]:
        args = self.get_lto_compile_args(threads=threads, mode=mode)
        if mode == 'thin' and thinlto_cache_dir is not None:
            # We check for ThinLTO linker support above in get_lto_compile_args, and all of them support
            # get_thinlto_cache_args as well
            args.extend(self.linker.get_thinlto_cache_args(thinlto_cache_dir))
        # In clang -flto-jobs=0 means auto, and is the default if unspecified, just like in meson
        if threads > 0:
            if not mesonlib.version_compare(self.version, '>=4.0.0'):
                raise mesonlib.MesonException('clang support for LTO threads requires clang >=4.0')
            args.append(f'-flto-jobs={threads}')
        return args
