#!/usr/bin/env python
# Copyright (C) 2018 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.

# This tool translates a collection of BUILD.gn files into a mostly equivalent
# BUILD file for the Bazel build system. The input to the tool is a
# JSON description of the GN build definition generated with the following
# command:
#
#   gn desc out --format=json --all-toolchains "//*" > desc.json
#
# The tool is then given a list of GN labels for which to generate Bazel
# build rules.

from __future__ import print_function
import argparse
import functools
import json
import os
import re
import sys
import textwrap

import gn_utils

# Copyright header for generated code.
header = """# Copyright (C) 2019 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.
#
# This file is automatically generated by {}. Do not edit.
""".format(__file__)

# Arguments for the GN output directory.
# host_os="linux" is to generate the right build files from Mac OS.
gn_args = 'target_os="linux" is_debug=false host_os="linux"'

# Default targets to translate to the blueprint file.
default_targets = [
  '//:trace_processor_shell',
  '//src/protozero:libprotozero',
  '//src/trace_processor:trace_processor',
  '//tools/trace_to_text:trace_to_text_host(//gn/standalone/toolchain:gcc_like_host)',
  '//tools/trace_to_text:libpprofbuilder',
  '//protos/perfetto/config:merged_config_gen',
  '//protos/perfetto/trace:merged_trace_gen',
  '//protos/perfetto/trace_processor:lite_gen',
  '//protos/perfetto/metrics:lite_gen'
]

# Aliases to add to the BUILD file
alias_targets = {
  '//src/protozero:libprotozero': 'libprotozero',
  '//src/trace_processor:trace_processor': 'trace_processor',
  '//tools/trace_to_text:trace_to_text_host': 'trace_to_text',
}


def enable_sqlite(module):
  module.deps.add(Label('//third_party/sqlite'))
  module.deps.add(Label('//third_party/sqlite:sqlite_ext_percentile'))


def enable_jsoncpp(module):
  module.deps.add(Label('//third_party/perfetto/google:jsoncpp'))


def enable_linenoise(module):
  module.deps.add(Label('//third_party/perfetto/google:linenoise'))


def enable_gtest_prod(module):
  module.deps.add(Label('//third_party/perfetto/google:gtest_prod'))


def enable_protobuf_full(module):
  module.deps.add(Label('//third_party/protobuf:libprotoc_legacy'))
  module.deps.add(Label('//third_party/protobuf:protobuf_legacy'))


def enable_perfetto_version(module):
  module.deps.add(Label('//third_party/perfetto/google:perfetto_version'))


def enable_zlib(module):
  module.deps.add(Label('//third_party/zlib:zlibsystem'))


def disable_module(module):
  pass


# Internal equivalents for third-party libraries that the upstream project
# depends on.
builtin_deps = {
    '//buildtools:linenoise': enable_linenoise,
    '//buildtools:protobuf_full': enable_protobuf_full,
    '//buildtools:protobuf_lite': disable_module,
    '//buildtools:protoc': disable_module,
    '//buildtools:sqlite': enable_sqlite,
    '//buildtools:zlib': enable_zlib,
    '//gn:default_deps': disable_module,
    '//gn:jsoncpp': enable_jsoncpp,
    '//gn:protoc_lib': enable_protobuf_full,
    '//gn/standalone:gen_git_revision': enable_perfetto_version,
}

# ----------------------------------------------------------------------------
# End of configuration.
# ----------------------------------------------------------------------------


class Error(Exception):
  pass


def is_public_header(label):
  """
  Returns if this is a c++ header file that is part of the API.
  Args:
      label: Label to evaluate
  """
  return label.endswith('.h') and label.startswith('//include/perfetto/')


@functools.total_ordering
class Label(object):
  """Represents a label in BUILD file terminology. This class wraps a string
  label to allow for correct comparision of labels for sorting.

  Args:
      label: The string rerepsentation of the label.
  """

  def __init__(self, label):
    self.label = label

  def is_absolute(self):
    return self.label.startswith('//')

  def dirname(self):
    return self.label.split(':')[0] if ':' in self.label else self.label

  def basename(self):
    return self.label.split(':')[1] if ':' in self.label else ''

  def __eq__(self, other):
    return self.label == other.label

  def __lt__(self, other):
    return (
        self.is_absolute(),
        self.dirname(),
        self.basename()
    ) < (
        other.is_absolute(),
        other.dirname(),
        other.basename()
    )

  def __str__(self):
    return self.label

  def __hash__(self):
    return hash(self.label)


class Writer(object):
  def __init__(self, output, width=79):
    self.output = output
    self.width = width

  def comment(self, text):
    for line in textwrap.wrap(text,
                              self.width - 2,
                              break_long_words=False,
                              break_on_hyphens=False):
      self.output.write('# {}\n'.format(line))

  def newline(self):
    self.output.write('\n')

  def line(self, s, indent=0):
    self.output.write('    ' * indent + s + '\n')

  def variable(self, key, value, sort=True):
    if value is None:
      return
    if isinstance(value, set) or isinstance(value, list):
      if len(value) == 0:
        return
      self.line('{} = ['.format(key), indent=1)
      for v in sorted(list(value)) if sort else value:
        self.line('"{}",'.format(v), indent=2)
      self.line('],', indent=1)
    elif isinstance(value, basestring):
      self.line('{} = "{}",'.format(key, value), indent=1)
    else:
      self.line('{} = {},'.format(key, value), indent=1)

  def header(self):
    self.output.write(header)


class Target(object):
  """In-memory representation of a BUILD target."""

  def __init__(self, type, name, gn_name=None):
    assert type in ('cc_binary', 'cc_library', 'cc_proto_library',
                    'proto_library', 'filegroup', 'alias',
                    'pbzero_cc_proto_library', 'genrule',
                    'transitive_descriptor_set', 'java_proto_library' )
    self.type = type
    self.name = name
    self.srcs = set()
    self.hdrs = set()
    self.deps = set()
    self.visibility = set()
    self.gn_name = gn_name
    self.cc_proto_fields = False
    self.src_proto_library = None
    self.outs = set()
    self.cmd = None
    self.tools = set()

  def write(self, writer):
    if self.gn_name:
      writer.comment('GN target: {}'.format(self.gn_name))

    writer.line('{}('.format(self.type))
    writer.variable('name', self.name)
    writer.variable('srcs', self.srcs)
    writer.variable('hdrs', self.hdrs)

    if self.cc_proto_fields:
      assert(self.type == 'proto_library')
      if self.srcs:
        writer.variable('has_services', 1)
      writer.variable('cc_api_version', 2)
      if self.srcs:
        writer.variable('cc_generic_services', 1)

    writer.variable('src_proto_library', self.src_proto_library)

    writer.variable('outs', self.outs)
    writer.variable('cmd', self.cmd)
    writer.variable('tools', self.tools)

    # Keep visibility and deps last.
    writer.variable('visibility', self.visibility)

    if type != 'filegroup':
      writer.variable('deps', self.deps)

    writer.line(')')


class Build(object):
  """In-memory representation of a BUILD file."""

  def __init__(self, public, header_lines=[]):
    self.targets = {}
    self.public = public
    self.header_lines = header_lines

  def add_target(self, target):
    self.targets[target.name] = target

  def write(self, writer):
    writer.header()
    writer.newline()
    for line in self.header_lines:
      writer.line(line)
    if self.header_lines:
      writer.newline()
    if self.public:
      writer.line(
          'package(default_visibility = ["//visibility:public"])')
    else:
      writer.line(
          'package(default_visibility = ["//third_party/perfetto:__subpackages__"])')
    writer.newline()
    writer.line('licenses(["notice"])  # Apache 2.0')
    writer.newline()
    writer.line('exports_files(["LICENSE"])')
    writer.newline()

    sorted_targets = sorted(
        self.targets.itervalues(), key=lambda m: m.name)
    for target in sorted_targets[:-1]:
      target.write(writer)
      writer.newline()

    # BUILD files shouldn't have a trailing new line.
    sorted_targets[-1].write(writer)


class BuildGenerator(object):
  def __init__(self, desc):
    self.desc = desc
    self.action_generated_files = set()

    for target in self.desc.itervalues():
      if target['type'] == 'action':
        self.action_generated_files.update(target['outputs'])


  def create_build_for_targets(self, targets):
    """Generate a BUILD for a list of GN targets and aliases."""
    self.build = Build(public=True)

    proto_cc_import = 'load("//tools/build_defs/proto/cpp:cc_proto_library.bzl", "cc_proto_library")'
    descriptor_set_import = 'load("//tools/build_defs/proto:descriptor_set.bzl", "transitive_descriptor_set")'
    pbzero_cc_import = 'load("//third_party/perfetto/google:build_defs.bzl", "pbzero_cc_proto_library")'
    self.proto_build = Build(public=False,
                             header_lines=[
                               proto_cc_import,
                               descriptor_set_import,
                               pbzero_cc_import,
                             ])

    for target in targets:
      self.create_target(target)

    return (self.build, self.proto_build)


  def resolve_dependencies(self, target_name):
    """Return the set of direct dependent-on targets for a GN target.

    Args:
        desc: JSON GN description.
        target_name: Name of target

    Returns:
        A set of transitive dependencies in the form of GN targets.
    """

    if gn_utils.label_without_toolchain(target_name) in builtin_deps:
      return set()
    target = self.desc[target_name]
    resolved_deps = set()
    for dep in target.get('deps', []):
      resolved_deps.add(dep)
    return resolved_deps


  def apply_module_sources_to_target(self, target, module_desc):
    """
    Args:
        target: Module to which dependencies should be added.
        module_desc: JSON GN description of the module.
        visibility: Whether the module is visible with respect to the target.
    """
    for src in module_desc.get('sources', []):
      label = Label(gn_utils.label_to_path(src))
      if target.type == 'cc_library' and is_public_header(src):
        target.hdrs.add(label)
      else:
        target.srcs.add(label)


  def apply_module_dependency(self, target, dep_name):
    """
    Args:
        build: BUILD instance which is being generated.
        proto_build: BUILD instance which is being generated to hold protos.
        desc: JSON GN description.
        target: Module to which dependencies should be added.
        dep_name: GN target of the dependency.
    """
    # If the dependency refers to a library which we can replace with an internal
    # equivalent, stop recursing and patch the dependency in.
    dep_name_no_toolchain = gn_utils.label_without_toolchain(dep_name)
    if dep_name_no_toolchain in builtin_deps:
      builtin_deps[dep_name_no_toolchain](target)
      return

    dep_desc = self.desc[dep_name]
    if dep_desc['type'] == 'source_set':
      for inner_name in self.resolve_dependencies(dep_name):
        self.apply_module_dependency(target, inner_name)

      # Any source set which has a source generated by an action doesn't need
      # to be depended on as we will depend on the action directly.
      sources = dep_desc.get('sources', [])
      if any(src in self.action_generated_files for src in sources):
        return

      self.apply_module_sources_to_target(target, dep_desc)
    elif dep_desc['type'] == 'action':
      args = dep_desc['args']
      if "gen_merged_sql_metrics" in dep_name:
        dep_target = self.create_merged_sql_metrics_target(dep_name)
        target.deps.add(Label("//third_party/perfetto:" + dep_target.name))

        if target.type == 'cc_library' or target.type == 'cc_binary':
          target.srcs.update(dep_target.outs)
      elif args[0].endswith('/protoc'):
        result = self.create_proto_target(dep_name);
        if result is None:
          return
        (proto_target, cc_target) = result
        if target.type == 'proto_library':
          dep_target_name = proto_target.name
        else:
          dep_target_name = cc_target.name
        target.deps.add(
            Label("//third_party/perfetto/protos:" + dep_target_name))
      else:
        raise Error('Unsupported action in target %s: %s' % (dep_target_name,
                                                            args))
    elif dep_desc['type'] == 'static_library':
      dep_target = self.create_target(dep_name)
      target.deps.add(Label("//third_party/perfetto:" + dep_target.name))
    elif dep_desc['type'] == 'group':
      for inner_name in self.resolve_dependencies(dep_name):
        self.apply_module_dependency(target, inner_name)
    elif dep_desc['type'] == 'executable':
      # Just create the dep target but don't add it as a dep because it's an
      # executable.
      self.create_target(dep_name)
    else:
      raise Error('Unknown target name %s with type: %s' %
                  (dep_name, dep_desc['type']))

  def create_merged_sql_metrics_target(self, gn_target_name):
    target_desc = self.desc[gn_target_name]
    gn_target_name_no_toolchain = gn_utils.label_without_toolchain(
        gn_target_name)
    target = Target(
      'genrule',
      'gen_merged_sql_metrics',
      gn_name=gn_target_name_no_toolchain,
    )
    target.outs.update(
      Label(src[src.index('gen/') + len('gen/'):])
      for src in target_desc.get('outputs', [])
    )
    target.cmd = '$(location gen_merged_sql_metrics_py) --cpp_out=$@ $(SRCS)'
    target.tools.update([
      'gen_merged_sql_metrics_py',
    ])
    target.srcs.update(
      Label(gn_utils.label_to_path(src))
      for src in target_desc.get('inputs', [])
      if src not in self.action_generated_files
    )
    self.build.add_target(target)
    return target

  def create_proto_target(self, gn_target_name):
    target_desc = self.desc[gn_target_name]
    args = target_desc['args']

    gn_target_name_no_toolchain = gn_utils.label_without_toolchain(
        gn_target_name)
    stripped_path = gn_target_name_no_toolchain.replace("protos/perfetto/", "")

    is_descriptor = any('descriptor_set_out' in arg for arg in args)
    if is_descriptor:
      return None

    is_pbzero = any("pbzero" in arg for arg in args)
    is_proto_lite = not is_pbzero and not is_descriptor

    pretty_target_name = gn_utils.label_to_target_name_with_path(stripped_path)
    pretty_target_name = pretty_target_name.replace("_lite_gen", "")
    pretty_target_name = pretty_target_name.replace("_zero_gen", "_zero")
    proto_target_name = pretty_target_name

    proto_target = Target(
      'proto_library',
      proto_target_name,
      gn_name=gn_target_name_no_toolchain
    )
    proto_target.cc_proto_fields = is_proto_lite
    proto_target.srcs.update([
      Label(gn_utils.label_to_path(src).replace('protos/', ''))
      for src in target_desc.get('sources', [])
    ])
    if is_proto_lite:
      proto_target.visibility.add("//visibility:public")
    self.proto_build.add_target(proto_target)

    for dep_name in self.resolve_dependencies(gn_target_name):
      self.apply_module_dependency(proto_target, dep_name)

    if is_pbzero:
      # Remove all the protozero srcs from the proto_library.
      proto_target.srcs.difference_update(
          [src for src in proto_target.srcs if not src.label.endswith('.proto')])

      # Remove all the non-proto deps from the proto_library and add to the cc
      # library.
      cc_deps = [
        dep for dep in proto_target.deps
        if not dep.label.startswith('//third_party/perfetto/protos')
      ]
      proto_target.deps.difference_update(cc_deps)

      cc_target_name = proto_target.name + "_cc_proto"
      cc_target = Target('pbzero_cc_proto_library', cc_target_name,
                         gn_name=gn_target_name_no_toolchain)

      cc_target.deps.add(Label('//third_party/perfetto:libprotozero'))
      cc_target.deps.update(cc_deps)

      # Add the proto_library to the cc_target.
      cc_target.src_proto_library = \
          "//third_party/perfetto/protos:" + proto_target.name

      self.proto_build.add_target(cc_target)
    else:
      cc_target_name = proto_target.name + "_cc_proto"
      cc_target = Target('cc_proto_library',
                        cc_target_name, gn_name=gn_target_name_no_toolchain)
      cc_target.visibility.add("//visibility:public")
      cc_target.deps.add(
          Label("//third_party/perfetto/protos:" + proto_target.name))
      self.proto_build.add_target(cc_target)

      java_target_name = proto_target.name + "_java_proto"
      java_target = Target('java_proto_library',
                           java_target_name,
                           gn_name=gn_target_name_no_toolchain)
      java_target.visibility.add("//visibility:public")
      java_target.deps.add(
          Label("//third_party/perfetto/protos:" + proto_target.name))
      self.proto_build.add_target(java_target)

    return (proto_target, cc_target)


  def create_target(self, gn_target_name):
    """Generate module(s) for a given GN target.

    Given a GN target name, generate one or more corresponding modules into a
    build file.

    Args:
        build: Build instance which is being generated.
        desc: JSON GN description.
        gn_target_name: GN target name for module generation.
    """

    target_desc = self.desc[gn_target_name]
    if target_desc['type'] == 'action':
      args = target_desc['args']
      if args[0].endswith('/protoc'):
        return self.create_proto_target(gn_target_name)
      else:
        raise Error('Unsupported action in target %s: %s' % (gn_target_name,
                                                            args))
    elif target_desc['type'] == 'executable':
      target_type = 'cc_binary'
    elif target_desc['type'] == 'static_library':
      target_type = 'cc_library'
    elif target_desc['type'] == 'source_set':
      target_type = 'filegroup'
    else:
      raise Error('Unknown target type: %s' % target_desc['type'])

    label_no_toolchain = gn_utils.label_without_toolchain(gn_target_name)
    target_name_path = gn_utils.label_to_target_name_with_path(label_no_toolchain)
    target_name = alias_targets.get(label_no_toolchain, target_name_path)
    target = Target(target_type, target_name, gn_name=label_no_toolchain)
    target.srcs.update(
        Label(gn_utils.label_to_path(src))
        for src in target_desc.get('sources', [])
        if src not in self.action_generated_files
    )

    for dep_name in self.resolve_dependencies(gn_target_name):
      self.apply_module_dependency(target, dep_name)

    self.build.add_target(target)
    return target

def main():
  parser = argparse.ArgumentParser(
      description='Generate BUILD from a GN description.')
  parser.add_argument(
      '--desc',
      help='GN description (e.g., gn desc out --format=json --all-toolchains "//*"'
  )
  parser.add_argument(
      '--repo-root',
      help='Standalone Perfetto repository to generate a GN description',
      default=gn_utils.repo_root(),
  )
  parser.add_argument(
      '--extras',
      help='Extra targets to include at the end of the BUILD file',
      default=os.path.join(gn_utils.repo_root(), 'BUILD.extras'),
  )
  parser.add_argument(
      '--output',
      help='BUILD file to create',
      default=os.path.join(gn_utils.repo_root(), 'BUILD'),
  )
  parser.add_argument(
      '--output-proto',
      help='Proto BUILD file to create',
      default=os.path.join(gn_utils.repo_root(), 'protos', 'BUILD'),
  )
  parser.add_argument(
      'targets',
      nargs=argparse.REMAINDER,
      help='Targets to include in the BUILD file (e.g., "//:perfetto_tests")')
  args = parser.parse_args()

  if args.desc:
    with open(args.desc) as f:
      desc = json.load(f)
  else:
    desc = gn_utils.create_build_description(gn_args, args.repo_root)

  build_generator = BuildGenerator(desc)
  build, proto_build = build_generator.create_build_for_targets(
      args.targets or default_targets)
  with open(args.output, 'w') as f:
    writer = Writer(f)
    build.write(writer)
    writer.newline()

    with open(args.extras, 'r') as r:
      for line in r:
        writer.line(line.rstrip("\n\r"))

  with open(args.output_proto, 'w') as f:
    proto_build.write(Writer(f))

  return 0


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