# Copyright 2020 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

import multiprocessing
import sys

from recipe_engine import recipe_api

# The default latency (seconds) to collect RBE logs.
COLLECT_RBE_LOGS_LATENCY_SECS = 1800


class BuildUtilApi(recipe_api.RecipeApi):
  """Gn and Ninja wrapper functions."""

  def __init__(self, *args, **kwargs):
    super(BuildUtilApi, self).__init__(*args, **kwargs)
    self.use_goma = True
    self.use_rbe = False

  def run_gn(self, gn_args, checkout_path):
    """Run a gn command with the given arguments.

    Args:
      gn_args(list): A list of strings to be passed to the gn command.
      checkout_path(Path): A path object with the checkout location.
    """
    gn_cmd = ['python3', checkout_path.join('flutter/tools/gn')]
    self.use_goma = '--no-goma' not in gn_args
    self.use_rbe = '--no-rbe' not in gn_args
    if self.m.properties.get('no_lto', False) and '--no-lto' not in gn_args:
      gn_args += ('--no-lto',)
    gn_cmd.extend(gn_args)
    if self.use_goma:
      env = {'GOMA_DIR': self.m.goma.goma_dir}
      # Some gn configurations expect depot_tools in path. e.g. vs_studio
      # tool_chain update script.
      with self.m.goma(), self.m.context(env=env), self.m.depot_tools.on_path():
        self.m.step('gn %s' % ' '.join(gn_args), gn_cmd)
    else:
      with self.m.depot_tools.on_path():
        self.m.step('gn %s' % ' '.join(gn_args), gn_cmd)

  def _calculate_j_value(self):
    """Calculates concurrent jobs value for the current machine."""
    cores = multiprocessing.cpu_count()

    # For non goma builds, set -j to the number of cores.
    if not self.use_goma:
      return 5 if self._test_data.enabled else cores

    # Assume simultaneous multithreading and therefore half as many cores as
    # logical processors.
    cores //= 2
    default_core_multiplier = 80
    j_value = cores * default_core_multiplier
    if self.m.platform.is_win:
      # On windows, j value higher than 1000 does not improve build
      # performance.
      j_value = min(j_value, 1000)
    elif self.m.platform.is_mac:
      # On macOS, j value higher than 800 causes 'Too many open files' error
      # (crbug.com/936864).
      j_value = min(j_value, 800)
    return 200 if self._test_data.enabled else j_value

  def _build_rbe(
      self, config, checkout_path, targets, tool, rbe_working_path, env
  ):
    """Builds using ninja and rbe.

    Args:
      config(str): A string with the configuration to build.
      checkout_path(Path): A path object with the checkout location.
      targets(list): A list of strings with the ninja targets to build.
      tool(path): Path to the ninja tool.
      rbe_working_path(path): Path to the rbe working directory.
    """
    assert rbe_working_path
    build_dir = checkout_path.join('out/%s' % config)
    rbe_jobs = self.m.properties.get('rbe_jobs') or self._calculate_j_value()
    ninja_args = [tool, '-j', rbe_jobs, '-C', build_dir]
    ninja_args.extend(targets)
    with self.m.rbe(
        working_path=rbe_working_path,
        collect_rbe_logs_latency=self.m.properties.get(
            'collect_rbe_logs_latency',
            COLLECT_RBE_LOGS_LATENCY_SECS)), self.m.depot_tools.on_path():
      try:
        name = 'build %s' % ' '.join([config] + list(targets))
        self.m.step(name, ninja_args)
      except self.m.step.StepFailure:
        self._upload_crash_reproducer(env)
        raise

  def _build_goma(self, config, checkout_path, targets, tool, env):
    """Builds using ninja and goma.

    Args:
      config(str): A string with the configuration to build.
      checkout_path(Path): A path object with the checkout location.
      targets(list): A list of strings with the ninja targets to build.
    """
    build_dir = checkout_path.join('out/%s' % config)
    goma_jobs = self.m.properties.get('goma_jobs') or self._calculate_j_value()
    ninja_args = [tool, '-j', goma_jobs, '-C', build_dir]
    ninja_args.extend(targets)
    with self.m.goma(), self.m.depot_tools.on_path():
      try:
        name = 'build %s' % ' '.join([config] + list(targets))
        self.m.step(name, ninja_args)
      except self.m.step.StepFailure:
        self._upload_crash_reproducer(env)
        raise

  def _build_no_goma_rbe(self, config, checkout_path, targets, tool, env):
    """Builds using ninja without goma/rbe.

    Args:
      config(str): A string with the configuration to build.
      checkout_path(Path): A path object with the checkout location.
      targets(list): A list of string with the ninja targets to build.
    """
    build_dir = checkout_path.join('out/%s' % config)
    concurrent_jobs = self.m.properties.get('concurrent_jobs'
                                           ) or self._calculate_j_value()
    ninja_args = [tool, '-C', build_dir, '-j', concurrent_jobs]
    ninja_args.extend(targets)
    with self.m.depot_tools.on_path():
      try:
        name = 'build %s' % ' '.join([config] + list(targets))
        self.m.step(name, ninja_args)
      except self.m.step.StepFailure:
        self._upload_crash_reproducer(env)
        raise

  def _upload_crash_reproducer(self, env):
    """Uploads crash reproducer files to GCS when clang crash happens."""
    clang_crash_diagnostics_dir = env['CLANG_CRASH_DIAGNOSTICS_DIR']
    flutter_logs_dir = env['FLUTTER_LOGS_DIR']
    with self.m.step.nest("upload crash reproducer"), self.m.context(
        infra_steps=True):
      reproducers = self.m.file.glob_paths(
          "find reproducers",
          clang_crash_diagnostics_dir,
          "*.sh",
          test_data=(clang_crash_diagnostics_dir.join("foo.sh"),),
      )
      for reproducer in reproducers:
        base = self.m.path.splitext(self.m.path.basename(reproducer))[0]
        files = self.m.file.glob_paths(
            f"find {base} files",
            clang_crash_diagnostics_dir,
            base + ".*",
            test_data=(clang_crash_diagnostics_dir.join("foo.sh"),),
        )
        for f in files:
          self.m.file.copy(
              'Copy crash reproduce file %s' % f, f, flutter_logs_dir
          )

  def build(self, config, checkout_path, targets, env, rbe_working_path=None):
    """Builds using ninja.

    Args:
      config(str): A string with the configuration to build.
      checkout_path(Path): A path object with the checkout location.
      targets(list): A list of string with the ninja targets to build.
      rbe_working_path(path): Path to rbe working directory.
    """
    ninja_path = checkout_path.join('flutter', 'third_party', 'ninja', 'ninja')

    if self.use_goma:
      self._build_goma(config, checkout_path, targets, ninja_path, env)
    else:
      if self.use_rbe:
        self._build_rbe(
            config, checkout_path, targets, ninja_path, rbe_working_path, env
        )
      else:
        self._build_no_goma_rbe(config, checkout_path, targets, ninja_path, env)
