# Copyright (C) 2022 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.

# A collection of utilities for extracting build rule information from GN
# projects.

from __future__ import print_function
import collections
import errno
import filecmp
import json
import os
import re
import shutil
import subprocess
import sys

BUILDFLAGS_TARGET = '//gn:gen_buildflags'
GEN_VERSION_TARGET = '//src/base:version_gen_h'
TARGET_TOOLCHAIN = '//gn/standalone/toolchain:gcc_like_host'
HOST_TOOLCHAIN = '//gn/standalone/toolchain:gcc_like_host'
LINKER_UNIT_TYPES = ('executable', 'shared_library', 'static_library')

# TODO(primiano): investigate these, they require further componentization.
ODR_VIOLATION_IGNORE_TARGETS = {
    '//test/cts:perfetto_cts_deps',
    '//:perfetto_integrationtests',
}


def _check_command_output(cmd, cwd):
  try:
    output = subprocess.check_output(cmd, stderr=subprocess.STDOUT, cwd=cwd)
  except subprocess.CalledProcessError as e:
    print(
        'Command "{}" failed in {}:'.format(' '.join(cmd), cwd),
        file=sys.stderr)
    print(e.output.decode(), file=sys.stderr)
    sys.exit(1)
  else:
    return output.decode()


def repo_root():
  """Returns an absolute path to the repository root."""
  return os.path.join(
      os.path.realpath(os.path.dirname(__file__)), os.path.pardir)


def _tool_path(name, system_buildtools=False):
  # Pass-through to use name if the caller requests to use the system
  # toolchain.
  if system_buildtools:
    return [name]
  wrapper = os.path.abspath(
      os.path.join(repo_root(), 'tools', 'run_buildtools_binary.py'))
  return ['python3', wrapper, name]


def prepare_out_directory(gn_args,
                          name,
                          root=repo_root(),
                          system_buildtools=False):
  """Creates the JSON build description by running GN.

    Returns (path, desc) where |path| is the location of the output directory
    and |desc| is the JSON build description.
    """
  out = os.path.join(root, 'out', name)
  try:
    os.makedirs(out)
  except OSError as e:
    if e.errno != errno.EEXIST:
      raise
  _check_command_output(
      _tool_path('gn', system_buildtools) +
      ['gen', out, '--args=%s' % gn_args],
      cwd=repo_root())
  return out


def load_build_description(out, system_buildtools=False):
  """Creates the JSON build description by running GN."""
  desc = _check_command_output(
      _tool_path('gn', system_buildtools) +
      ['desc', out, '--format=json', '--all-toolchains', '//*'],
      cwd=repo_root())
  return json.loads(desc)


def create_build_description(gn_args, root=repo_root()):
  """Prepares a GN out directory and loads the build description from it.

    The temporary out directory is automatically deleted.
    """
  out = prepare_out_directory(gn_args, 'tmp.gn_utils', root=root)
  try:
    return load_build_description(out)
  finally:
    shutil.rmtree(out)


def build_targets(out, targets, quiet=False, system_buildtools=False):
  """Runs ninja to build a list of GN targets in the given out directory.

    Compiling these targets is required so that we can include any generated
    source files in the amalgamated result.
    """
  targets = [t.replace('//', '') for t in targets]
  with open(os.devnull, 'w') as devnull:
    stdout = devnull if quiet else None
    cmd = _tool_path('ninja', system_buildtools) + targets
    subprocess.check_call(cmd, cwd=os.path.abspath(out), stdout=stdout)


def compute_source_dependencies(out, system_buildtools=False):
  """For each source file, computes a set of headers it depends on."""
  ninja_deps = _check_command_output(
      _tool_path('ninja', system_buildtools) + ['-t', 'deps'], cwd=out)
  deps = {}
  current_source = None
  for line in ninja_deps.split('\n'):
    filename = os.path.relpath(os.path.join(out, line.strip()), repo_root())
    if not line or line[0] != ' ':
      current_source = None
      continue
    elif not current_source:
      # We're assuming the source file is always listed before the
      # headers.
      assert os.path.splitext(line)[1] in ['.c', '.cc', '.cpp', '.S']
      current_source = filename
      deps[current_source] = []
    else:
      assert current_source
      deps[current_source].append(filename)
  return deps


def label_to_path(label):
  """Turn a GN output label (e.g., //some_dir/file.cc) into a path."""
  assert label.startswith('//')
  return label[2:]


def label_without_toolchain(label):
  """Strips the toolchain from a GN label.

    Return a GN label (e.g //buildtools:protobuf(//gn/standalone/toolchain:
    gcc_like_host) without the parenthesised toolchain part.
    """
  return label.split('(')[0]


def label_to_target_name_with_path(label):
  """
  Turn a GN label into a target name involving the full path.
  e.g., //src/perfetto:tests -> src_perfetto_tests
  """
  name = re.sub(r'^//:?', '', label)
  name = re.sub(r'[^a-zA-Z0-9_]', '_', name)
  return name


def gen_buildflags(gn_args, target_file):
  """Generates the perfetto_build_flags.h for the given config.

    target_file: the path, relative to the repo root, where the generated
        buildflag header will be copied into.
    """
  tmp_out = prepare_out_directory(gn_args, 'tmp.gen_buildflags')
  build_targets(tmp_out, [BUILDFLAGS_TARGET], quiet=True)
  src = os.path.join(tmp_out, 'gen', 'build_config', 'perfetto_build_flags.h')
  shutil.copy(src, os.path.join(repo_root(), target_file))
  shutil.rmtree(tmp_out)


def check_or_commit_generated_files(tmp_files, check):
  """Checks that gen files are unchanged or renames them to the final location

    Takes in input a list of 'xxx.swp' files that have been written.
    If check == False, it renames xxx.swp -> xxx.
    If check == True, it just checks that the contents of 'xxx.swp' == 'xxx'.
    Returns 0 if no diff was detected, 1 otherwise (to be used as exit code).
    """
  res = 0
  for tmp_file in tmp_files:
    assert (tmp_file.endswith('.swp'))
    target_file = os.path.relpath(tmp_file[:-4])
    if check:
      if not filecmp.cmp(tmp_file, target_file):
        sys.stderr.write('%s needs to be regenerated\n' % target_file)
        res = 1
      os.unlink(tmp_file)
    else:
      os.rename(tmp_file, target_file)
  return res


class ODRChecker(object):
  """Detects ODR violations in linker units

  When we turn GN source sets into Soong & Bazel file groups, there is the risk
  to create ODR violations by including the same file group into different
  linker unit (this is because other build systems don't have a concept
  equivalent to GN's source_set). This class navigates the transitive
  dependencies (mostly static libraries) of a target and detects if multiple
  paths end up including the same file group. This is to avoid situations like:

  traced.exe -> base(file group)
  traced.exe -> libperfetto(static lib) -> base(file group)
  """

  def __init__(self, gn, target_name):
    self.gn = gn
    self.root = gn.get_target(target_name)
    self.source_sets = collections.defaultdict(set)
    self.deps_visited = set()
    self.source_set_hdr_only = {}

    self._visit(target_name)
    num_violations = 0
    if target_name in ODR_VIOLATION_IGNORE_TARGETS:
      return
    for sset, paths in self.source_sets.items():
      if self.is_header_only(sset):
        continue
      if len(paths) != 1:
        num_violations += 1
        print(
            'ODR violation in target %s, multiple paths include %s:\n  %s' %
            (target_name, sset, '\n  '.join(paths)),
            file=sys.stderr)
    if num_violations > 0:
      raise Exception('%d ODR violations detected. Build generation aborted' %
                      num_violations)

  def _visit(self, target_name, parent_path=''):
    target = self.gn.get_target(target_name)
    path = ((parent_path + ' > ') if parent_path else '') + target_name
    if not target:
      raise Exception('Cannot find target %s' % target_name)
    for ssdep in target.source_set_deps:
      name_and_path = '%s (via %s)' % (target_name, path)
      self.source_sets[ssdep].add(name_and_path)
    deps = set(target.deps).union(
        target.transitive_proto_deps) - self.deps_visited
    for dep_name in deps:
      dep = self.gn.get_target(dep_name)
      if dep.type == 'executable':
        continue  # Execs are strong boundaries and don't cause ODR violations.
      # static_library dependencies should reset the path. It doesn't matter if
      # we get to a source file via:
      # source_set1 > static_lib > source.cc OR
      # source_set1 > source_set2 > static_lib > source.cc
      # This is NOT an ODR violation because source.cc is linked from the same
      # static library
      next_parent_path = path if dep.type != 'static_library' else ''
      self.deps_visited.add(dep_name)
      self._visit(dep_name, next_parent_path)

  def is_header_only(self, source_set_name):
    cached = self.source_set_hdr_only.get(source_set_name)
    if cached is not None:
      return cached
    target = self.gn.get_target(source_set_name)
    if target.type != 'source_set':
      raise TypeError('%s is not a source_set' % source_set_name)
    res = all(src.endswith('.h') for src in target.sources)
    self.source_set_hdr_only[source_set_name] = res
    return res


class GnParser(object):
  """A parser with some cleverness for GN json desc files

    The main goals of this parser are:
    1) Deal with the fact that other build systems don't have an equivalent
       notion to GN's source_set. Conversely to Bazel's and Soong's filegroups,
       GN source_sets expect that dependencies, cflags and other source_set
       properties propagate up to the linker unit (static_library, executable or
       shared_library). This parser simulates the same behavior: when a
       source_set is encountered, some of its variables (cflags and such) are
       copied up to the dependent targets. This is to allow gen_xxx to create
       one filegroup for each source_set and then squash all the other flags
       onto the linker unit.
    2) Detect and special-case protobuf targets, figuring out the protoc-plugin
       being used.
    """

  class Target(object):
    """Reperesents A GN target.

        Maked properties are propagated up the dependency chain when a
        source_set dependency is encountered.
        """

    def __init__(self, name, type):
      self.name = name  # e.g. //src/ipc:ipc

      VALID_TYPES = ('static_library', 'shared_library', 'executable', 'group',
                     'action', 'source_set', 'proto_library')
      assert (type in VALID_TYPES)
      self.type = type
      self.testonly = False
      self.toolchain = None

      # These are valid only for type == proto_library.
      # This is typically: 'proto', 'protozero', 'ipc'.
      self.proto_plugin = None
      self.proto_paths = set()
      self.proto_exports = set()

      self.sources = set()
      # TODO(primiano): consider whether the public section should be part of
      # bubbled-up sources.
      self.public_headers = set()  # 'public'

      # These are valid only for type == 'action'
      self.inputs = set()
      self.outputs = set()
      self.script = None
      self.args = []

      # These variables are propagated up when encountering a dependency
      # on a source_set target.
      self.cflags = set()
      self.defines = set()
      self.deps = set()
      self.libs = set()
      self.include_dirs = set()
      self.ldflags = set()
      self.source_set_deps = set()  # Transitive set of source_set deps.
      self.proto_deps = set()
      self.transitive_proto_deps = set()

      # Deps on //gn:xxx have this flag set to True. These dependencies
      # are special because they pull third_party code from buildtools/.
      # We don't want to keep recursing into //buildtools in generators,
      # this flag is used to stop the recursion and create an empty
      # placeholder target once we hit //gn:protoc or similar.
      self.is_third_party_dep_ = False

    def __lt__(self, other):
      if isinstance(other, self.__class__):
        return self.name < other.name
      raise TypeError(
          '\'<\' not supported between instances of \'%s\' and \'%s\'' %
          (type(self).__name__, type(other).__name__))

    def __repr__(self):
      return json.dumps({
          k: (list(sorted(v)) if isinstance(v, set) else v)
          for (k, v) in self.__dict__.items()
      },
                        indent=4,
                        sort_keys=True)

    def update(self, other):
      for key in ('cflags', 'defines', 'deps', 'include_dirs', 'ldflags',
                  'source_set_deps', 'proto_deps', 'transitive_proto_deps',
                  'libs', 'proto_paths'):
        self.__dict__[key].update(other.__dict__.get(key, []))

  def __init__(self, gn_desc):
    self.gn_desc_ = gn_desc
    self.all_targets = {}
    self.linker_units = {}  # Executables, shared or static libraries.
    self.source_sets = {}
    self.actions = {}
    self.proto_libs = {}

  def get_target(self, gn_target_name):
    """Returns a Target object from the fully qualified GN target name.

        It bubbles up variables from source_set dependencies as described in the
        class-level comments.
        """
    target = self.all_targets.get(gn_target_name)
    if target is not None:
      return target  # Target already processed.

    desc = self.gn_desc_[gn_target_name]
    target = GnParser.Target(gn_target_name, desc['type'])
    target.testonly = desc.get('testonly', False)
    target.toolchain = desc.get('toolchain', None)
    self.all_targets[gn_target_name] = target

    # We should never have GN targets directly depend on buidtools. They
    # should hop via //gn:xxx, so we can give generators an opportunity to
    # override them.
    assert (not gn_target_name.startswith('//buildtools'))

    # Don't descend further into third_party targets. Genrators are supposed
    # to either ignore them or route to other externally-provided targets.
    if gn_target_name.startswith('//gn'):
      target.is_third_party_dep_ = True
      return target

    proto_target_type, proto_desc = self.get_proto_target_type(target)
    if proto_target_type is not None:
      self.proto_libs[target.name] = target
      target.type = 'proto_library'
      target.proto_plugin = proto_target_type
      target.proto_paths.update(self.get_proto_paths(proto_desc))
      target.proto_exports.update(self.get_proto_exports(proto_desc))
      target.sources.update(proto_desc.get('sources', []))
      assert (all(x.endswith('.proto') for x in target.sources))
    elif target.type == 'source_set':
      self.source_sets[gn_target_name] = target
      target.sources.update(desc.get('sources', []))
    elif target.type in LINKER_UNIT_TYPES:
      self.linker_units[gn_target_name] = target
      target.sources.update(desc.get('sources', []))
    elif target.type == 'action':
      self.actions[gn_target_name] = target
      target.inputs.update(desc.get('inputs', []))
      target.sources.update(desc.get('sources', []))
      outs = [re.sub('^//out/.+?/gen/', '', x) for x in desc['outputs']]
      target.outputs.update(outs)
      target.script = desc['script']
      # Args are typically relative to the root build dir (../../xxx)
      # because root build dir is typically out/xxx/).
      target.args = [re.sub('^../../', '//', x) for x in desc['args']]

    # Default for 'public' is //* - all headers in 'sources' are public.
    # TODO(primiano): if a 'public' section is specified (even if empty), then
    # the rest of 'sources' is considered inaccessible by gn. Consider
    # emulating that, so that generated build files don't end up with overly
    # accessible headers.
    public_headers = [x for x in desc.get('public', []) if x != '*']
    target.public_headers.update(public_headers)

    target.cflags.update(desc.get('cflags', []) + desc.get('cflags_cc', []))
    target.libs.update(desc.get('libs', []))
    target.ldflags.update(desc.get('ldflags', []))
    target.defines.update(desc.get('defines', []))
    target.include_dirs.update(desc.get('include_dirs', []))

    # Recurse in dependencies.
    for dep_name in desc.get('deps', []):
      dep = self.get_target(dep_name)
      if dep.is_third_party_dep_:
        target.deps.add(dep_name)
      elif dep.type == 'proto_library':
        target.proto_deps.add(dep_name)
        target.transitive_proto_deps.add(dep_name)
        target.proto_paths.update(dep.proto_paths)
        target.transitive_proto_deps.update(dep.transitive_proto_deps)
      elif dep.type == 'source_set':
        target.source_set_deps.add(dep_name)
        target.update(dep)  # Bubble up source set's cflags/ldflags etc.
      elif dep.type == 'group':
        target.update(dep)  # Bubble up groups's cflags/ldflags etc.
      elif dep.type == 'action':
        if proto_target_type is None:
          target.deps.add(dep_name)
      elif dep.type in LINKER_UNIT_TYPES:
        target.deps.add(dep_name)

    return target

  def get_proto_exports(self, proto_desc):
    # exports in metadata will be available for source_set targets.
    metadata = proto_desc.get('metadata', {})
    return metadata.get('exports', [])

  def get_proto_paths(self, proto_desc):
    # import_dirs in metadata will be available for source_set targets.
    metadata = proto_desc.get('metadata', {})
    return metadata.get('import_dirs', [])

  def get_proto_target_type(self, target):
    """ Checks if the target is a proto library and return the plugin.

        Returns:
            (None, None): if the target is not a proto library.
            (plugin, proto_desc) where |plugin| is 'proto' in the default (lite)
            case or 'protozero' or 'ipc' or 'descriptor'; |proto_desc| is the GN
            json desc of the target with the .proto sources (_gen target for
            non-descriptor types or the target itself for descriptor type).
        """
    parts = target.name.split('(', 1)
    name = parts[0]
    toolchain = '(' + parts[1] if len(parts) > 1 else ''

    # Descriptor targets don't have a _gen target; instead we look for the
    # characteristic flag in the args of the target itself.
    desc = self.gn_desc_.get(target.name)
    if '--descriptor_set_out' in desc.get('args', []):
      return 'descriptor', desc

    # Source set proto targets have a non-empty proto_library_sources in the
    # metadata of the description.
    metadata = desc.get('metadata', {})
    if 'proto_library_sources' in metadata:
      return 'source_set', desc

    # In all other cases, we want to look at the _gen target as that has the
    # important information.
    gen_desc = self.gn_desc_.get('%s_gen%s' % (name, toolchain))
    if gen_desc is None or gen_desc['type'] != 'action':
      return None, None
    args = gen_desc.get('args', [])
    if '/protoc' not in args[0]:
      return None, None
    plugin = 'proto'
    for arg in (arg for arg in args if arg.startswith('--plugin=')):
      # |arg| at this point looks like:
      #  --plugin=protoc-gen-plugin=gcc_like_host/protozero_plugin
      # or
      #  --plugin=protoc-gen-plugin=protozero_plugin
      plugin = arg.split('=')[-1].split('/')[-1].replace('_plugin', '')
    return plugin, gen_desc
