#!/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 = [
  '//src/protozero:libprotozero',
  '//src/trace_processor:trace_processor',
  '//src/trace_processor:trace_processor_shell_host(//gn/standalone/toolchain:gcc_like_host)',
  '//tools/trace_to_text:trace_to_text_host(//gn/standalone/toolchain:gcc_like_host)',
  '//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',
  '//src/trace_processor:trace_processor_shell_host': 'trace_processor_shell',
  '//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'))
  module.deps.add(Label('//third_party/protobuf'))


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'))


def disable_module(module):
  pass


# Internal equivalents for third-party libraries that the upstream project
# depends on.
builtin_deps = {
    '//gn:jsoncpp_deps': enable_jsoncpp,
    '//buildtools:linenoise': enable_linenoise,
    '//buildtools:protobuf_lite': disable_module,
    '//buildtools:protobuf_full': enable_protobuf_full,
    '//buildtools:protoc': disable_module,
    '//buildtools:sqlite': enable_sqlite,
    '//buildtools:zlib': enable_zlib,
    '//gn:default_deps': disable_module,
    '//gn:protoc_lib_deps': 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())
