# swift_build_support/toolchain.py ------------------------------*- python -*-
#
# This source file is part of the Swift.org open source project
#
# Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
# Licensed under Apache License v2.0 with Runtime Library Exception
#
# See https://swift.org/LICENSE.txt for license information
# See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
#
# ----------------------------------------------------------------------------
"""
Represent toolchain - the versioned executables.
"""
# ----------------------------------------------------------------------------

from __future__ import absolute_import

import platform

from . import cache_util
from . import shell
from . import xcrun
from .which import which

__all__ = [
    'host_toolchain',
]


class Toolchain(object):
    """Represents native host toolchain
    """

    def find_tool(self, *names):
        raise NotImplementedError('Subclasses must implement this method')


# Declare properties for each tools.
# These properties are loaded lazily and assignable.
def _register(name, *tool):
    def _getter(self):
        return self.find_tool(*tool)
    _getter.__name__ = name
    setattr(Toolchain, name, cache_util.reify(_getter))


if platform.system() == 'Windows':
    _register("cc", "clang-cl")
    _register("cxx", "clang-cl")
else:
    _register("cc", "clang")
    _register("cxx", "clang++")

_register("ninja", "ninja", "ninja-build")
_register("cmake", "cmake")
_register("distcc", "distcc")
_register("distcc_pump", "distcc-pump", "pump")
_register("llvm_profdata", "llvm-profdata")
_register("llvm_cov", "llvm-cov")
_register("lipo", "lipo")
_register("libtool", "libtool")


class Darwin(Toolchain):
    def __init__(self, sdk, toolchain):
        super(Darwin, self).__init__()
        self.xcrun_sdk = sdk
        self.xcrun_toolchain = toolchain

    def find_tool(self, *names):
        for name in names:
            # NOTE: xcrun searches from developer tools directory *and* from
            #       PATH. Relatively slow, but we don't need `which` for
            #       Darwin.
            found = xcrun.find(name,
                               sdk=self.xcrun_sdk,
                               toolchain=self.xcrun_toolchain)
            if found is not None:
                return found
        return None


class GenericUnix(Toolchain):
    def __init__(self, suffixes):
        super(GenericUnix, self).__init__()

        # On these platforms, search 'clang', 'clang++' unconditionally.
        # To determine the llvm_suffix.
        ret = self.find_clang(['clang', 'clang++'], suffixes)
        if ret is None:
            self.cc = None
            self.cxx = None
            # We don't have clang, then we don't have any llvm tools.
            self.llvm_suffixes = []
        else:
            found, suffix = ret
            self.cc, self.cxx = found

            if suffix == '':
                # Some platform may have `clang`, `clang++`, `llvm-cov-3.6`
                # but not `llvm-cov`. In that case, we assume `clang` is
                # corresponding to the best version of llvm tools found.
                self.llvm_suffixes = suffixes
            else:
                # Otherwise, we must have llvm tools with the same suffix as
                # `clang` or `clang++`
                self.llvm_suffixes = [suffix]

    def find_clang(self, tools, suffixes):
        for suffix in suffixes:
            ret = [which(t + suffix) for t in tools]
            if all(t is not None for t in ret):
                return (ret, suffix)
        return None

    def find_llvm_tool(self, tool):
        for suffix in self.llvm_suffixes:
            found = which(tool + suffix)
            if found is not None:
                # If we found the tool with the suffix, lock suffixes to it.
                self.llvm_suffix = [suffix]
                return found
        return None

    def find_tool(self, *names):
        for name in names:
            if name.startswith('llvm-'):
                found = self.find_llvm_tool(name)
            else:
                found = which(name)
            if found is not None:
                return found
        return None


class MacOSX(Darwin):
    def __init__(self, toolchain='default'):
        super(MacOSX, self).__init__(sdk='macosx', toolchain=toolchain)


class Linux(GenericUnix):
    def __init__(self):
        super(Linux, self).__init__(['', '-3.8', '-3.7', '-3.6', '-3.5'])


class FreeBSD(GenericUnix):
    def __init__(self):
        # For testing toolchain initializer on non-FreeBSD systems
        sys = platform.system()
        if sys != 'FreeBSD':
            suffixes = ['']
        # See: https://github.com/apple/swift/pull/169
        # Building Swift from source requires a recent version of the Clang
        # compiler with C++14 support.
        elif self._release_date and self._release_date >= 1100000:
            suffixes = ['']
        else:
            suffixes = ['38', '37', '36', '35']
        super(FreeBSD, self).__init__(suffixes)

    @cache_util.reify
    def _release_date(self):
        """Return the release date for FreeBSD operating system on this host.
        If the release date cannot be ascertained, return None.
        """
        # For details on `sysctl`, see:
        # http://www.freebsd.org/cgi/man.cgi?sysctl(8)
        out = shell.capture(['sysctl', '-n', 'kern.osreldate'],
                            dry_run=False, echo=False, optional=True)
        if out is None:
            return None
        return int(out)


class Cygwin(Linux):
    # Currently, Cygwin is considered as the same as Linux.
    pass


class Windows(Toolchain):
    def find_tool(self, *names):
        for name in names:
            found = which(name)
            if found is not None:
                return found
        return None


def host_toolchain(**kwargs):
    sys = platform.system()
    if sys == 'Darwin':
        return MacOSX(kwargs.pop('xcrun_toolchain', 'default'))
    elif sys == 'Linux':
        return Linux()
    elif sys == 'FreeBSD':
        return FreeBSD()
    elif sys.startswith('CYGWIN'):
        return Cygwin()
    elif sys == 'Windows':
        return Windows()
    else:
        raise NotImplementedError('The platform "%s" does not have a defined '
                                  'toolchain.' % sys)
