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

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

import os
import shutil
import typing as T

from ... import mesonlib
from ...linkers import AppleDynamicLinker, ClangClDynamicLinker, LLVMDynamicLinker, GnuGoldDynamicLinker
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 = {
    '0': ['-O0'],
    'g': ['-Og'],
    '1': ['-O1'],
    '2': ['-O2'],
    '3': ['-O3'],
    's': ['-Oz'],
}  # type: T.Dict[str, T.List[str]]

class ClangCompiler(GnuLikeCompiler):

    def __init__(self, defines: T.Optional[T.Dict[str, str]]):
        super().__init__()
        self.id = 'clang'
        self.defines = defines or {}
        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.
        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) -> 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 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)

    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':
            # 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))
        return args

    def get_lto_link_args(self, *, threads: int = 0, mode: str = 'default') -> T.List[str]:
        args = self.get_lto_compile_args(threads=threads, mode=mode)
        # 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
