#
# Copyright (C) 2016 The Android Open Source Project
#
# 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.
#

"""Toolchains util functions."""


import glob
import os
import stat

from environment import sysroot_util
import error


# TODO(b/27386504): Consider loading these from a cached envsetup.
# Where the prebuilt toolchain can be found (relative to OS path).
EXISTING_TOOLS_FORMAT = os.path.join('prebuilts', 'gcc', '{host_arch}')
# Where, under the existing tools dir, can tools be found for each arch.
ARCH_TOOL_PREFIX = {
    'x86': 'x86/x86_64-linux-android-4.9/bin/x86_64-linux-android-',
    'arm': 'arm/arm-linux-androideabi-4.9/bin/arm-linux-androideabi-'
}
# What default flags do we want tools to run with (default none).
TOOL_FLAGS = {
    'g++': ['-std=gnu++11',
            '-fstack-protector-strong',
            '-Wformat -Werror=format-security',
            '-D_FORTIFY_SOURCE=2',
            '-Werror=implicit-function-declaration',
            '-fpie -pie',
            '-Wl,-z,now',
            '-isystem=' + os.path.join(
                os.path.sep, sysroot_util.SysrootUtil.LIBCXX_INCLUDE_DIR)]
}
# Any architecture specific flags we want to be defaults.
ARCH_TOOL_FLAGS = {
    'x86': {
        'g++': ['-m32']
    },
    'arm': {
        'g++': ['-marm']
    },
    'mips': {
        # TODO(b/27722530): get mips sysroot/toolchain working.
    }
}


class Error(error.Error):
    pass


class GenerationError(Error):
    """Raised when the toolchain fails to generate correctly."""
    description = 'Failed to generate all tools'


def _ToolFlags(tool, arch):
    """Helper to combine general and arch-specific tool flags."""
    result = []
    if tool in TOOL_FLAGS:
        result += TOOL_FLAGS[tool]
    if arch in ARCH_TOOL_FLAGS and tool in ARCH_TOOL_FLAGS[arch]:
        result += ARCH_TOOL_FLAGS[arch][tool]
    return result

def _GenerateWrapper(src, dest, flags=None):
    """Write a simple wrapper for a tool.

    dest will call src with flags. dest will be an executable file.

    Args:
        src: The original tool to wrap.
        dest: The place to put the wrapper.
        flags: (optional) Flags to include in the wrapper. Default empty list.

    Raises:
        OSError: There is an error opening or otherwise accessing dest.
        IOError: There is an error writing the wrapper file.
    """
    flags = flags or []
    with open(dest, 'w') as f:
        f.write('#!/bin/sh\n{0} {1} "$@"\n'.format(src, ' '.join(flags)))
    # Make sure the file is executable.
    st = os.stat(dest)
    os.chmod(dest, st.st_mode | stat.S_IEXEC)


def GenerateToolchain(platform, host, output_dir):
    """Generate a toolchain.

    Args:
        platform: Platform to generate toolchain for.
        host: Host architecture to generate toolchain for.
        output_dir: Where to put generated tools.

    Raises:
        Error: Not all tools generated properly.
    """
    # Make sure output dir exists.
    if not os.path.isdir(output_dir):
        os.makedirs(output_dir)

    # Put together some variables based on host and target.
    existing_tools = platform.os.path(
        EXISTING_TOOLS_FORMAT.format(host_arch=host))
    tool_prefix = os.path.join(
        existing_tools, ARCH_TOOL_PREFIX[platform.device.arch])
    prefix_len = len(tool_prefix)

    # Walk the existing tools, wrapping them all.
    errors = []
    for path in glob.iglob(tool_prefix + '*'):
        # Skip dirs, not that there should be any.
        if not os.path.isfile(path):
            continue

        # Otherwise, assume it's a tool and wrap it.
        tool = path[prefix_len:]
        try:
            output_tool = os.path.join(output_dir, tool)
            tool_flags = _ToolFlags(tool, platform.device.arch)
            # Write a simple wrapper.
            _GenerateWrapper(path, output_tool, tool_flags)
        except (IOError, OSError) as e:
            errors.append((tool, e))

    if errors:
        raise GenerationError('Failed: {}'.format(errors))
