#!/usr/bin/env python
#
# Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file
# for details. All rights reserved. Use of this source code is governed by a
# BSD-style license that can be found in the LICENSE file.

import io
import json
import multiprocessing
import optparse
import os
import subprocess
import sys
import time
import utils

HOST_OS = utils.GuessOS()
HOST_CPUS = utils.GuessCpus()
SCRIPT_DIR = os.path.dirname(sys.argv[0])
DART_ROOT = os.path.realpath(os.path.join(SCRIPT_DIR, '..'))
AVAILABLE_ARCHS = utils.ARCH_FAMILY.keys()

usage = """\
usage: %%prog [options] [targets]

This script invokes ninja to build Dart.
"""


def BuildOptions():
    result = optparse.OptionParser(usage=usage)
    result.add_option(
        "-a",
        "--arch",
        help='Target architectures (comma-separated).',
        metavar='[all,' + ','.join(AVAILABLE_ARCHS) + ']',
        default=utils.GuessArchitecture())
    result.add_option(
        "-b",
        "--bytecode",
        help='Build with the kernel bytecode interpreter. DEPRECATED.',
        default=False,
        action='store_true')
    result.add_option(
        "-j", type=int, help='Ninja -j option for Goma builds.', default=1000)
    result.add_option(
        "-l", type=int, help='Ninja -l option for Goma builds.', default=64)
    result.add_option(
        "-m",
        "--mode",
        help='Build variants (comma-separated).',
        metavar='[all,debug,release,product]',
        default='debug')
    result.add_option(
        "--no-start-goma",
        help="Don't try to start goma",
        default=False,
        action='store_true')
    result.add_option(
        "--os",
        help='Target OSs (comma-separated).',
        metavar='[all,host,android]',
        default='host')
    result.add_option(
        "--sanitizer",
        type=str,
        help='Build variants (comma-separated).',
        metavar='[all,none,asan,lsan,msan,tsan,ubsan]',
        default='none')
    # TODO(38701): Remove this option once the NNBD SDK is stable/performant
    # and there is no need to build a legacy version of the SDK for comparison
    # purposes.
    result.add_option(
        "--no-nnbd",
        help='Build the Legacy (pre NNBD) version of the SDK.',
        default=False,
        action='store_true')
    result.add_option(
        "-v",
        "--verbose",
        help='Verbose output.',
        default=False,
        action="store_true")
    return result


def ProcessOsOption(os_name):
    if os_name == 'host':
        return HOST_OS
    return os_name


def ProcessOptions(options, args):
    if options.arch == 'all':
        options.arch = 'ia32,x64,simarm,simarm64'
    if options.mode == 'all':
        options.mode = 'debug,release,product'
    if options.os == 'all':
        options.os = 'host,android'
    if options.sanitizer == 'all':
        options.sanitizer = 'none,asan,lsan,msan,tsan,ubsan'
    options.mode = options.mode.split(',')
    options.arch = options.arch.split(',')
    options.os = options.os.split(',')
    options.sanitizer = options.sanitizer.split(',')
    for mode in options.mode:
        if not mode in ['debug', 'release', 'product']:
            print("Unknown mode %s" % mode)
            return False
    for i, arch in enumerate(options.arch):
        if not arch in AVAILABLE_ARCHS:
            # Normalise to lower case form to make it less case-picky.
            arch_lower = arch.lower()
            if arch_lower in AVAILABLE_ARCHS:
                options.arch[i] = arch_lower
                continue
            print("Unknown arch %s" % arch)
            return False
    options.os = [ProcessOsOption(os_name) for os_name in options.os]
    for os_name in options.os:
        if not os_name in ['android', 'freebsd', 'linux', 'macos', 'win32']:
            print("Unknown os %s" % os_name)
            return False
        if os_name != HOST_OS:
            if os_name != 'android':
                print("Unsupported target os %s" % os_name)
                return False
            if not HOST_OS in ['linux', 'macos']:
                print("Cross-compilation to %s is not supported on host os %s."
                      % (os_name, HOST_OS))
                return False
            if not arch in [
                    'ia32', 'x64', 'arm', 'arm_x64', 'armv6', 'arm64'
            ]:
                print(
                    "Cross-compilation to %s is not supported for architecture %s."
                    % (os_name, arch))
                return False
            # We have not yet tweaked the v8 dart build to work with the Android
            # NDK/SDK, so don't try to build it.
            if not args:
                print(
                    "For android builds you must specify a target, such as 'runtime'."
                )
                return False
    return True


def NotifyBuildDone(build_config, success, start):
    if not success:
        print("BUILD FAILED")

    sys.stdout.flush()

    # Display a notification if build time exceeded DART_BUILD_NOTIFICATION_DELAY.
    notification_delay = float(
        os.getenv('DART_BUILD_NOTIFICATION_DELAY', sys.float_info.max))
    if (time.time() - start) < notification_delay:
        return

    if success:
        message = 'Build succeeded.'
    else:
        message = 'Build failed.'
    title = build_config

    command = None
    if HOST_OS == 'macos':
        # Use AppleScript to display a UI non-modal notification.
        script = 'display notification  "%s" with title "%s" sound name "Glass"' % (
            message, title)
        command = "osascript -e '%s' &" % script
    elif HOST_OS == 'linux':
        if success:
            icon = 'dialog-information'
        else:
            icon = 'dialog-error'
        command = "notify-send -i '%s' '%s' '%s' &" % (icon, message, title)
    elif HOST_OS == 'win32':
        if success:
            icon = 'info'
        else:
            icon = 'error'
        command = (
            "powershell -command \""
            "[reflection.assembly]::loadwithpartialname('System.Windows.Forms')"
            "| Out-Null;"
            "[reflection.assembly]::loadwithpartialname('System.Drawing')"
            "| Out-Null;"
            "$n = new-object system.windows.forms.notifyicon;"
            "$n.icon = [system.drawing.systemicons]::information;"
            "$n.visible = $true;"
            "$n.showballoontip(%d, '%s', '%s', "
            "[system.windows.forms.tooltipicon]::%s);\"") % (
                5000,  # Notification stays on for this many milliseconds
                message,
                title,
                icon)

    if command:
        # Ignore return code, if this command fails, it doesn't matter.
        os.system(command)


def GenerateBuildfilesIfNeeded():
    if os.path.exists(utils.GetBuildDir(HOST_OS)):
        return True
    command = [
        'python',
        os.path.join(DART_ROOT, 'tools', 'generate_buildfiles.py')
    ]
    print("Running " + ' '.join(command))
    process = subprocess.Popen(command)
    process.wait()
    if process.returncode != 0:
        print("Tried to generate missing buildfiles, but failed. "
              "Try running manually:\n\t$ " + ' '.join(command))
        return False
    return True


def RunGNIfNeeded(out_dir, target_os, mode, arch, dont_use_nnbd, sanitizer):
    if os.path.isfile(os.path.join(out_dir, 'args.gn')):
        return
    gn_os = 'host' if target_os == HOST_OS else target_os
    gn_command = [
        'python',
        os.path.join(DART_ROOT, 'tools', 'gn.py'),
        '--sanitizer',
        sanitizer,
        '-m',
        mode,
        '-a',
        arch,
        '--os',
        gn_os,
        '-v',
    ]
    if dont_use_nnbd:
        gn_command.append('--no-nnbd')

    process = subprocess.Popen(gn_command)
    process.wait()
    if process.returncode != 0:
        print("Tried to run GN, but it failed. Try running it manually: \n\t$ "
              + ' '.join(gn_command))


def UseGoma(out_dir):
    args_gn = os.path.join(out_dir, 'args.gn')
    return 'use_goma = true' in open(args_gn, 'r').read()


# Try to start goma, but don't bail out if we can't. Instead print an error
# message, and let the build fail with its own error messages as well.
goma_started = False


def EnsureGomaStarted(out_dir):
    global goma_started
    if goma_started:
        return True
    args_gn_path = os.path.join(out_dir, 'args.gn')
    goma_dir = None
    with open(args_gn_path, 'r') as fp:
        for line in fp:
            if 'goma_dir' in line:
                words = line.split()
                goma_dir = words[2][1:-1]  # goma_dir = "/path/to/goma"
    if not goma_dir:
        print('Could not find goma for ' + out_dir)
        return False
    if not os.path.exists(goma_dir) or not os.path.isdir(goma_dir):
        print('Could not find goma at ' + goma_dir)
        return False
    goma_ctl = os.path.join(goma_dir, 'goma_ctl.py')
    goma_ctl_command = [
        'python',
        goma_ctl,
        'ensure_start',
    ]
    process = subprocess.Popen(goma_ctl_command)
    process.wait()
    if process.returncode != 0:
        print(
            "Tried to run goma_ctl.py, but it failed. Try running it manually: "
            + "\n\t" + ' '.join(goma_ctl_command))
        return False
    goma_started = True
    return True

# Returns a tuple (build_config, command to run, whether goma is used)
def BuildOneConfig(options, targets, target_os, mode, arch, sanitizer):
    build_config = utils.GetBuildConf(mode, arch, target_os, sanitizer,
                                      options.no_nnbd)
    out_dir = utils.GetBuildRoot(HOST_OS, mode, arch, target_os, sanitizer,
                                 options.no_nnbd)
    using_goma = False
    # TODO(zra): Remove auto-run of gn, replace with prompt for user to run
    # gn.py manually.
    RunGNIfNeeded(out_dir, target_os, mode, arch, options.no_nnbd, sanitizer)
    command = ['ninja', '-C', out_dir]
    if options.verbose:
        command += ['-v']
    if UseGoma(out_dir):
        if options.no_start_goma or EnsureGomaStarted(out_dir):
            using_goma = True
            command += [('-j%s' % str(options.j))]
            command += [('-l%s' % str(options.l))]
        else:
            # If we couldn't ensure that goma is started, let the build start, but
            # slowly so we can see any helpful error messages that pop out.
            command += ['-j1']
    command += targets
    return (build_config, command, using_goma)


def RunOneBuildCommand(build_config, args, env):
    start_time = time.time()
    print(' '.join(args))
    process = subprocess.Popen(args, env=env, stdin=None)
    process.wait()
    if process.returncode != 0:
        NotifyBuildDone(build_config, success=False, start=start_time)
        return 1
    else:
        NotifyBuildDone(build_config, success=True, start=start_time)

    return 0


def RunOneGomaBuildCommand(options):
    (env, args) = options
    try:
        print(' '.join(args))
        process = subprocess.Popen(args, env=env, stdin=None)
        process.wait()
        print(' '.join(args) + " done.")
        return process.returncode
    except KeyboardInterrupt:
        return 1


def SanitizerEnvironmentVariables():
    with io.open('tools/bots/test_matrix.json', encoding='utf-8') as fd:
        config = json.loads(fd.read())
        env = dict()
        for k, v in config['sanitizer_options'].items():
            env[str(k)] = str(v)
        symbolizer_path = config['sanitizer_symbolizer'].get(HOST_OS, None)
        if symbolizer_path:
            symbolizer_path = str(os.path.join(DART_ROOT, symbolizer_path))
            env['ASAN_SYMBOLIZER_PATH'] = symbolizer_path
            env['LSAN_SYMBOLIZER_PATH'] = symbolizer_path
            env['MSAN_SYMBOLIZER_PATH'] = symbolizer_path
            env['TSAN_SYMBOLIZER_PATH'] = symbolizer_path
            env['UBSAN_SYMBOLIZER_PATH'] = symbolizer_path
        return env


def Main():
    starttime = time.time()
    # Parse the options.
    parser = BuildOptions()
    (options, args) = parser.parse_args()
    if not ProcessOptions(options, args):
        parser.print_help()
        return 1
    # Determine which targets to build. By default we build the "all" target.
    if len(args) == 0:
        targets = ['all']
    else:
        targets = args

    if not GenerateBuildfilesIfNeeded():
        return 1

    # If binaries are built with sanitizers we should use those flags.
    # If the binaries are not built with sanitizers the flag should have no
    # effect.
    env = dict(os.environ)
    env.update(SanitizerEnvironmentVariables())

    # Build all targets for each requested configuration.
    configs = []
    for target_os in options.os:
        for mode in options.mode:
            for arch in options.arch:
                for sanitizer in options.sanitizer:
                    configs.append(
                        BuildOneConfig(options, targets, target_os, mode, arch,
                                       sanitizer))

    # Build regular configs.
    goma_builds = []
    for (build_config, args, goma) in configs:
        if args is None:
            return 1
        if goma:
            goma_builds.append([env, args])
        elif RunOneBuildCommand(build_config, args, env=env) != 0:
            return 1

    # Run goma builds in parallel.
    pool = multiprocessing.Pool(multiprocessing.cpu_count())
    results = pool.map(RunOneGomaBuildCommand, goma_builds, chunksize=1)
    for r in results:
        if r != 0:
            return 1

    endtime = time.time()
    print("The build took %.3f seconds" % (endtime - starttime))
    return 0


if __name__ == '__main__':
    sys.exit(Main())
