# Copyright 2013 The Flutter 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("config/config.gni")
import("pm_tool.gni")
import("symbol_index.gni")

# Define a Fuchsia component package target.
#
# Parameters
#
#   package_name: [Optional]
#     Name of the package. Defaults to target_name.
#
#     Type: string
#
#   excluded_files: [Optional]
#     List of files to exclude from the package.
#
#     Type: list of file paths
#
#   fidl_ref_out_dir: [Optional]
#     Directory for writing out $package_name_all_fidl_refs.txt
#       that contains the paths to the internal representation (IR) of every
#       FIDL interface referenced in the package. Defaults to $root_build_dir/fidl_refs.
#
#   ids_txt_output_path: [Optional]
#     Path to write out the ids.txt file for the symbols in the binaries.
#     Defaults to `${target_gen_dir}/${package_name}/ids.txt`
#
#     Type: file path
#
#   deps
#     Required: List of fuchsia_component() targets that this
#              package contains.
#
template("fuchsia_package") {
  if (!defined(invoker.package_name)) {
    package_name = target_name
  } else {
    package_name = invoker.package_name
  }
  if (!defined(invoker.excluded_files)) {
    excluded_files = []
  } else {
    excluded_files = invoker.excluded_files
  }
  if (!defined(invoker.fidl_ref_out_dir)) {
    fidl_ref_out_dir = "$root_build_dir/fidl_refs"
  } else {
    fidl_ref_out_dir = invoker.fidl_ref_out_dir
  }

  _depfile = "${target_gen_dir}/${target_name}_stamp.d"

  # target names
  _manifest_target = "${target_name}__archive-manifest"
  _metadata_target = "${target_name}__archive-metadata"
  _packaged_components_metadata_target =
      "${target_name}__packaged_components_metadata"

  # output values
  _pkg_out_dir = "${target_gen_dir}/${package_name}"
  _runtime_deps_file = "$_pkg_out_dir/${package_name}.runtime_deps"
  _archive_manifest = "$_pkg_out_dir/${package_name}.manifest"
  _build_ids_file = "$_pkg_out_dir/ids.txt"
  if (defined(invoker.ids_txt_output_path)) {
    _build_ids_file = invoker.ids_txt_output_path
  }
  _package_file = "$_pkg_out_dir/package"
  _fidl_json_refs_file = "${fidl_ref_out_dir}/${package_name}_all_fidl_refs.txt"

  _packaged_components_metadata_file =
      "${target_gen_dir}/${package_name}_packaged_components_metadata.json"

  _package_deps = []
  if (defined(invoker.deps)) {
    _package_deps += invoker.deps
  }
  if (defined(invoker.data_deps)) {
    _package_deps += invoker.data_deps
  }

  # Generates a JSON file containing the contents of each of the
  # components being included in this package.
  generated_file(_packaged_components_metadata_target) {
    forward_variables_from(invoker, [ "testonly" ])
    outputs = [ _packaged_components_metadata_file ]
    data_keys = [ "contents" ]
    output_conversion = "json"
    deps = _package_deps
  }

  # A generated file that lists all of the .fidl.json files
  # used in this package. This is useful for tools that need
  # to decode fidl.
  generated_file("${package_name}_all_fidl_refs") {
    testonly = true
    deps = _package_deps

    outputs = [ _fidl_json_refs_file ]
    data_keys = [ "fidl_json" ]
  }

  action(_manifest_target) {
    forward_variables_from(invoker, [ "testonly" ])
    script = "//flutter/tools/fuchsia/gn-sdk/prepare_package_inputs.py"

    inputs = [
      _runtime_deps_file,
      _packaged_components_metadata_file,
    ]

    outputs = [
      _archive_manifest,
      _build_ids_file,
      _package_file,
    ]

    data_deps = _package_deps

    deps = _package_deps
    deps += [ ":${_packaged_components_metadata_target}" ]
    if (defined(invoker.deps)) {
      deps += invoker.deps
    }

    # Use a depfile to trigger package rebuilds if any of the files (static
    # assets, shared libraries, etc.) included by the package have changed.
    depfile = _depfile

    args = [
      "--root-dir",
      rebase_path("//", root_build_dir),
      "--out-dir",
      rebase_path(root_out_dir, root_build_dir),
      "--app-name",
      package_name,
      "--runtime-deps-file",
      rebase_path(_runtime_deps_file, root_build_dir),
      "--depfile-path",
      rebase_path(_depfile, root_build_dir),
      "--manifest-path",
      rebase_path(_archive_manifest, root_build_dir),
      "--build-ids-file",
      rebase_path(_build_ids_file, root_build_dir),
      "--json-file",
      rebase_path(_packaged_components_metadata_file),
    ]

    if (defined(excluded_files)) {
      foreach(filename, excluded_files) {
        args += [
          "--exclude-file",
          filename,
        ]
      }
    }
    write_runtime_deps = _runtime_deps_file

    # Allows ids.txt paths to be collected by dependent targets.
    metadata = {
      ids_txt_paths = [ _build_ids_file ]
    }
  }

  # Creates a Fuchsia metadata package.
  fuchsia_pm_tool(_metadata_target) {
    forward_variables_from(invoker, [ "testonly" ])
    package_name = package_name
    command = "build"
    archive_manifest = _archive_manifest
    public_deps = [ ":$_manifest_target" ]
  }

  fuchsia_pm_tool(target_name) {
    forward_variables_from(invoker, [ "testonly" ])
    package_name = package_name
    command = "archive"
    archive_manifest = _archive_manifest
    public_deps = [ ":$_metadata_target" ]
    if (!defined(deps)) {
      deps = []
    }
    if (defined(fuchsia_auto_index_symbols) && fuchsia_auto_index_symbols) {
      deps += [ ":${target_name}_fuchsia_auto_index_symbols" ]
    }
  }

  if (defined(fuchsia_auto_index_symbols) && fuchsia_auto_index_symbols) {
    fuchsia_symbol_index_tool("${target_name}_fuchsia_auto_index_symbols") {
      forward_variables_from(invoker, [ "testonly" ])
      symbols = _build_ids_file
      deps = [ ":$_metadata_target" ]
    }
  }
}
