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

# GN template to generate static library for the given mojom files.
# How to use:
# [platform2/pkg/BUILD.gn]
# generate_mojom_bindings("foo_mojo_bindings") {
#   mojo_root = "${platform2_root}"
#   sources = [
#     "mojo/foo.mojom",
#     "mojo/foo_sub.mojom",
#   ]
# }
#
# Then this generates static library for the mojom files and the header files
# under ${root_gen_dir}/include,. E.g.
# ${root_gen_dir}/include/pkg/mojo/foo.mojom.h etc., where "mojo" directory
# comes from "sources", and "pkg" comes from the target path relative to
# |mojo_root|.
#
# If you'd like to generate binding source code and headers, but not to
# create static library, you can use generate_mojom_bindings_gen template,
# instead.
#
# Parameters:
#   sources
#       The .mojom file paths.
#   mojo_extra_args (optional)
#       Extra additional arguments passed to mojom_bindings_generator.py.
#   mojo_root (optional)
#       Root directory used when referring across .mojom or generated files.
#       "." by default.
#   standalone (optional)
#       If true, generates a library that can be referred from other packages.
#       Otherwise it generates a thin archive assuming it's used inside the same package only.
#   use_pic (optional)
#       If true, generates a position independent code instead of position independent executable.
#   mojom_bindings_generator (optional)
#       Path to the mojom_bindings_generator.py script. This is useful if
#       the script is not yet installed to the system, but the repository
#       contains it.
#       If not given, /usr/src/libmojo-${libbase_ver}/mojo/mojom_bindings_generator.py
#       is used.
#   All flags which can be interpreted by static_library target:
#       The values are used as if static_library does. Note that some flags
#       may be modified in order to reflect the parameters described above
#       and build mojom generated files.

import("//common-mk/pkg_config.gni")

# This gn generates header files under ${root_gen_dir}/include.
_mojo_output_base = "${root_gen_dir}/include"

# Path to the directory which contains mojo template files.
_mojo_templates_dir = "${root_gen_dir}/templates"

# Thin wrapper to launch mojom_bindings_generator.py.
_mojom_bindings_generator_wrapper =
    "${platform2_root}/common-mk/mojom_bindings_generator_wrapper.py"

# Generates C++ mojo bindings source code and headers.
template("generate_mojom_bindings_gen") {
  forward_variables_from(invoker,
                         [
                           "mojo_extra_args",
                           "mojo_root",
                           "mojom_bindings_generator",
                         ])

  if (defined(mojom_bindings_generator)) {
    mojom_bindings_generator = rebase_path(mojom_bindings_generator)
  } else {
    mojom_bindings_generator = "${sysroot}/usr/src/libmojo-${libbase_ver}/mojo/mojom_bindings_generator.py"
  }

  if (!defined(mojo_extra_args)) {
    mojo_extra_args = []
  }

  if (!defined(mojo_root)) {
    mojo_root = "."
  }
  mojo_root = rebase_path(mojo_root)

  action("mojo_templates_dir") {
    inputs = []
    outputs = [
      _mojo_templates_dir,
    ]
    print("Creating mojo C++ templates dir")
    script = "//common-mk/file_generator_wrapper.py"
    args = [
      "mkdir",
      "-p",
      _mojo_templates_dir,
    ]
  }

  action("mojo_templates") {
    inputs = [
      mojom_bindings_generator,
      _mojo_templates_dir,
    ]
    outputs = [
      "${_mojo_templates_dir}/cpp_templates.zip",
    ]
    print("Generating mojo C++ templates")
    script = mojom_bindings_generator
    args = [
      "--use_bundled_pylibs",
      "precompile",
      "-o",
      _mojo_templates_dir,
    ]
    deps = [
      ":mojo_templates_dir",
    ]
  }

  action_foreach(target_name) {
    forward_variables_from(invoker, [ "sources" ])
    inputs = [
               _mojom_bindings_generator_wrapper,
               mojom_bindings_generator,
             ] + get_target_outputs(":mojo_templates")

    # Generated files are referred using relative path from |mojo_root|,
    # separated from this target's path.
    # for example, if foo_pkg is a child of |mojo_root|,
    # "#include <foo_pkg/mojom/bar.mojom.h>"
    # even when this target itself is under foo_pkg/.
    mojo_output_dir = _mojo_output_base + "/" + rebase_path(".", mojo_root)
    outputs = [
      "${mojo_output_dir}/{{source_target_relative}}-internal.h",
      "${mojo_output_dir}/{{source_target_relative}}-shared.cc",
      "${mojo_output_dir}/{{source_target_relative}}-shared.h",
      "${mojo_output_dir}/{{source_target_relative}}.cc",
      "${mojo_output_dir}/{{source_target_relative}}.h",
    ]
    print("Generating mojo C++ bindings")
    script = _mojom_bindings_generator_wrapper
    args = [
             mojom_bindings_generator,
             "--use_bundled_pylibs",
             "generate",
             "{{source}}",
             "--output_dir",
             _mojo_output_base,
             "--bytecode_path",
             _mojo_templates_dir,
             "-I",
             mojo_root,  # Mojo include path.
             "-d",
             mojo_root,  # Mojo depth.
             "--generators",
             "c++",
           ] + mojo_extra_args
    deps = [
      ":mojo_templates",
    ]
  }
}

# Generates a static library for the given mojom files.
template("generate_mojom_bindings") {
  target_gen_name = target_name + "_gen"
  generate_mojom_bindings_gen(target_gen_name) {
    forward_variables_from(invoker,
                           [
                             "mojo_extra_args",
                             "mojo_root",
                             "mojom_bindings_generator",
                             "sources",
                           ])
  }

  pkg_config("generate_mojom_bindings_pkg_deps") {
    pkg_deps = [
      "libchrome-${libbase_ver}",
      "libmojo-${libbase_ver}",
    ]
  }

  static_library(target_name) {
    forward_variables_from(invoker,
                           "*",
                           [
                             # Exclude mojo related inputs.
                             "mojo_extra_args",
                             "mojo_root",
                             "mojom_bindings_generator",
                             "sources",

                             # Exclude fields, which are manually handled.
                             "all_dependent_configs",
                             "configs",
                             "deps",
                             "include_dirs",

                             # Additional fields for this rule.
                             "standalone",
                             "use_pic",
                           ])
    all_dependent_configs = [ ":generate_mojom_bindings_pkg_deps" ]
    if (defined(invoker.all_dependent_configs)) {
      all_dependent_configs += invoker.all_dependent_configs
    }

    include_dirs = [ _mojo_output_base ]
    if (defined(invoker.include_dirs)) {
      include_dirs += invoker.include_dirs
    }

    if (defined(invoker.configs)) {
      configs += invoker.configs
    }
    if (defined(invoker.use_pic) && invoker.use_pic) {
      configs -= [ "//common-mk:pie" ]
      configs += [ "//common-mk:pic" ]
    }
    if (defined(invoker.standalone) && invoker.standalone) {
      configs -= [ "//common-mk:use_thin_archive" ]
      configs += [ "//common-mk:nouse_thin_archive" ]
    }
    deps = [
      ":${target_gen_name}",
    ]
    if (defined(invoker.deps)) {
      deps += invoker.deps
    }

    sources = get_target_outputs(":${target_gen_name}")
  }
}
