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

# Build targets for constructing CIPD release archives.

assert(is_fuchsia)

import("//build/cipd/cipd.gni")
import("//build/config/chrome_build.gni")
import("//build/config/compiler/compiler.gni")
import("//build/util/process_version.gni")
import("//third_party/fuchsia-gn-sdk/src/build_id_dir.gni")
import("//third_party/fuchsia-gn-sdk/src/cipd.gni")

visibility = [ ":*" ]

# Allows a builder to explicitly declare the CIPD path. The base path is what
# comes after `.../p/` in the CIPD URL.
declare_args() {
  fuchsia_cipd_package_base_path = ""
}

# TODO(zijiehe): Eliminate the use of 'package_base_path' during the
# refactoring.
if (fuchsia_cipd_package_base_path == "") {
  if (is_chrome_branded) {
    package_base_path = "chrome_internal/fuchsia"
  } else {
    package_base_path = "chromium/fuchsia"
  }
} else {
  package_base_path = fuchsia_cipd_package_base_path
}

# Archives related specifically to `fuchsia.web`
_web_engine_directory = "web_engine"

# Archives of tools intended to be run on a Linux/Mac host rather than the
# Fuchsia device.
_host_tools_directory = "host_tools"

_archive_suffix = "_archive"

# Extracts the numeric Chrome version and writes it to a file in the output
# directory.
#
# To check out the repository on the commit where the version was generated,
# simply call `git checkout <version>`, and Git will check out the commit
# associated with the <version> tag.
process_version("version") {
  template_file = "version.template"
  sources = [ "//chrome/VERSION" ]
  output = "${target_gen_dir}/VERSION"
  process_only = true
}

if (target_cpu == "x64") {
  targetarch = "amd64"
} else {
  targetarch = "arm64"
}

# Prepares a CIPD archive, produces a corresponding LICENSE file,
# LICENSE.spdx.json file and generates a manifest file.
#
# Parameters:
#   package_subdirectory: Specify the subdirectory relative to
#                         |package_base_path| in which the package is put.
#   description: Sets the "description" field in CIPD package definition.
#
# Optional parameters used directly by fuchsia_cipd_package template:
#   "install_mode",
#   "sources",
#   "data",
#   "data_deps"
#   "deps",
#   "testonly",

template("cipd_archive") {
  forward_variables_from(invoker,
                         [
                           "package_subdirectory",
                           "description",
                           "install_mode",
                           "sources",
                           "data",
                           "data_deps",
                           "deps",
                           "testonly",
                         ])

  _license_path = "${target_gen_dir}/${target_name}/LICENSE"
  _invoker_dir = get_label_info(":${invoker.target_name}", "dir")
  _license_target = "${_invoker_dir}:${invoker.target_name}${_archive_suffix}"

  # GN is used by the script and is thus an input.
  if (host_os == "mac") {
    _gn_path = "//buildtools/mac/gn"
  } else if (host_os == "linux") {
    _gn_path = "//buildtools/linux64/gn"
  }

  # Produces a consolidated license file.
  action("${target_name}_license") {
    script = "//tools/licenses/licenses.py"
    inputs = [ "$_gn_path" ]
    outputs = [ _license_path ]
    args = [
      "license_file",
      rebase_path(_license_path, root_build_dir),
      "--gn-target",
      _license_target,
      "--gn-out-dir",
      ".",
    ]
  }

  # Produces a consolidated license file in spdx format.
  action("${target_name}_license_spdx") {
    _license_path_spdx = "${_license_path}.spdx.json"

    script = "//tools/licenses/licenses.py"
    inputs = [ "$_gn_path" ]
    outputs = [ _license_path_spdx ]
    args = [
      "license_file",
      rebase_path(_license_path_spdx, root_build_dir),
      "--gn-target",
      _license_target,
      "--gn-out-dir",
      ".",
      "--format",
      "spdx",
      "--spdx-doc-name",
      "${invoker.target_name}",
    ]
  }

  if (!defined(deps)) {
    deps = []
  }
  deps += [
    ":${target_name}_license",
    ":${target_name}_license_spdx",
    ":version",
  ]

  if (!defined(sources)) {
    sources = []
  }
  sources += get_target_outputs(":${target_name}_license") +
             get_target_outputs(":${target_name}_license_spdx") +
             [ "${target_gen_dir}/VERSION" ]

  fuchsia_cipd_package("${target_name}${_archive_suffix}") {
    package = "${package_base_path}/${package_subdirectory}/${targetarch}/${invoker.target_name}"
    package_root = "${target_gen_dir}/${invoker.target_name}"
    package_definition_name = "${invoker.target_name}.yaml"

    # Always use absolute path.
    use_absolute_root_path = true
  }
}

# Prepares a CIPD test archive, which is a regular CIPD archive that generates
# test manifests for a given list of test_sets.
#
# Parameters:
#   test_sets: A list of scopes for which test manifests will be created. Each
#              set contains:
#     manifest_path: The path to the generated manifest JSON file.
#     far_sources: An optional list of CFv2 test component .far files.
#
# Required parameters used by the cipd_archive template:
#   "package_subdirectory",
#
# Optional parameters used by the cipd_archive template:
#   "description"
#   "install_mode",
#   "data",
#   "data_deps"
#   "deps",
#   "testonly",

template("cipd_test_archive") {
  forward_variables_from(invoker,
                         [
                           "package_subdirectory",
                           "description",
                           "install_mode",
                           "data",
                           "data_deps",
                           "deps",
                           "testonly",
                           "test_sets",
                         ])

  assert(defined(test_sets) && defined(testonly) && testonly == true)

  cipd_archive(target_name) {
    # Build JSON manifests for each suite of tests and include them in the
    # archive.
    sources = []
    foreach(test_set, test_sets) {
      assert(defined(test_set.far_sources))
      sources += [ test_set.manifest_path ]
      _manifest_contents = []
      if (defined(test_set.far_sources)) {
        foreach(source, test_set.far_sources) {
          package_name = get_path_info(source, "name")

          _manifest_contents += [
            {
              package = package_name
              component_name = package_name + ".cm"
            },
          ]
        }
        sources += test_set.far_sources
      }
      write_file(test_set.manifest_path, _manifest_contents, "json")
    }
  }
}

cipd_archive("web_engine") {
  package_subdirectory = _web_engine_directory
  description = "Prebuilt WebEngine binaries for Fuchsia."

  deps = [ "//fuchsia_web/webengine:web_engine" ]
  sources =
      [ "${root_gen_dir}/fuchsia_web/webengine/web_engine/web_engine.far" ]
}

cipd_archive("cast_runner") {
  package_subdirectory = _web_engine_directory
  description = "Prebuilt Cast application Runner binaries for Fuchsia."

  deps = [ "//fuchsia_web/runners:cast_runner_pkg" ]
  sources =
      [ "${root_gen_dir}/fuchsia_web/runners/cast_runner/cast_runner.far" ]
}

cipd_archive("web_engine_shell") {
  package_subdirectory = _web_engine_directory
  description = "Simple command-line embedder for WebEngine."
  testonly = true

  deps = [ "//fuchsia_web/shell:web_engine_shell_pkg" ]
  sources = [
    "${root_gen_dir}/fuchsia_web/shell/web_engine_shell/web_engine_shell.far",
  ]
}

_stripped_chromedriver_file = "${root_out_dir}/clang_x64/stripped/chromedriver"

action("strip_chromedriver_binary") {
  testonly = true

  prog_name = "${root_out_dir}/clang_x64/chromedriver"

  deps = [ "//chrome/test/chromedriver:chromedriver_server($host_toolchain)" ]
  script = "//build/gn_run_binary.py"
  sources = [
    "//buildtools/third_party/eu-strip/bin/eu-strip",
    prog_name,
  ]
  outputs = [ _stripped_chromedriver_file ]
  args = [
    rebase_path("//buildtools/third_party/eu-strip/bin/eu-strip",
                root_build_dir),
    "-o",
    rebase_path(_stripped_chromedriver_file, root_build_dir),
    rebase_path(prog_name, root_build_dir),
  ]
}

cipd_archive("chromedriver") {
  package_subdirectory = "${_host_tools_directory}/\${os}"
  description = "Prebuilt Chromedriver binary for Fuchsia host."
  install_mode = "copy"
  testonly = true

  deps = [ ":strip_chromedriver_binary" ]
  sources = [ _stripped_chromedriver_file ]
}

cipd_test_archive("tests") {
  package_subdirectory = _web_engine_directory
  description = "Prebuilt Chromium tests for Fuchsia."
  testonly = true

  _common_tests = [
    "${root_gen_dir}/base/base_unittests/base_unittests.far",
    "${root_gen_dir}/ipc/ipc_tests/ipc_tests.far",
    "${root_gen_dir}/media/media_unittests/media_unittests.far",
    "${root_gen_dir}/mojo/mojo_unittests/mojo_unittests.far",
    "${root_gen_dir}/skia/skia_unittests/skia_unittests.far",
    "${root_gen_dir}/third_party/blink/common/blink_common_unittests/blink_common_unittests.far",
  ]
  deps = [
    "//base:base_unittests_pkg",
    "//ipc:ipc_tests_pkg",
    "//media:media_unittests_pkg",
    "//mojo:mojo_unittests_pkg",
    "//skia:skia_unittests_pkg",
    "//third_party/blink/common:blink_common_unittests_pkg",
  ]

  _web_engine_tests = [ "${root_gen_dir}/fuchsia_web/webengine/web_engine_integration_tests/web_engine_integration_tests.far" ]
  deps += [ "//fuchsia_web/webengine:web_engine_integration_tests_pkg" ]

  _cast_runner_tests = [ "${root_gen_dir}/fuchsia_web/runners/cast_runner_integration_tests/cast_runner_integration_tests.far" ]
  deps += [ "//fuchsia_web/runners:cast_runner_integration_tests_pkg" ]

  _all_tests = _common_tests + _web_engine_tests + _cast_runner_tests

  test_sets = [
    {
      manifest_path = "${target_gen_dir}/test_manifest.json"
      far_sources = _all_tests
    },
    {
      manifest_path = "${target_gen_dir}/common_tests_manifest.json"
      far_sources = _common_tests
    },
    {
      manifest_path = "${target_gen_dir}/web_engine_tests_manifest.json"
      far_sources = _web_engine_tests
    },
    {
      manifest_path = "${target_gen_dir}/cast_runner_tests_manifest.json"
      far_sources = _cast_runner_tests
    },
  ]
}

# Construct a consolidated directory of web_engine debugging symbols using the
# GNU .build_id structure for CIPD archival.
_web_engine_build_ids_target = "web_engine_debug_symbol_directory"
_web_engine_debug_symbols_archive_name = "web_engine_debug_symbols"
_web_engine_debug_symbols_outdir = "${target_gen_dir}/${_web_engine_debug_symbols_archive_name}/${_web_engine_build_ids_target}"

build_id_dir(_web_engine_build_ids_target) {
  testonly = true  # Some of the archives contain test packages.
  output_path = _web_engine_debug_symbols_outdir
  deps = [ ":web_engine_archives_with_tests" ]
}

fuchsia_cipd_package(_web_engine_debug_symbols_archive_name) {
  testonly = true
  package = "${package_base_path}/${_web_engine_directory}/${targetarch}/debug-symbols"
  package_root = _web_engine_debug_symbols_outdir
  package_definition_name = "${target_name}.yaml"
  package_definition_dir = "${target_gen_dir}/${target_name}"
  description = "Debugging symbols for prebuilt binaries from Chromium."
  use_absolute_root_path = true

  directories = [ "." ]
  deps = [ ":${_web_engine_build_ids_target}" ]
}

# A group for production archives to ensure nothing is testonly.
group("web_engine_production_archives") {
  deps = [
    ":cast_runner${_archive_suffix}",
    ":web_engine${_archive_suffix}",
  ]
}

# Used by both the main group as well as :debug_symbols.
group("web_engine_archives_with_tests") {
  testonly = true  # tests and web_engine_shell are testonly.
  deps = [
    ":tests${_archive_suffix}",
    ":web_engine_production_archives",
    ":web_engine_shell${_archive_suffix}",
  ]
}

# TODO(zijiehe): Rename to "cipd_yaml" when possible.
# This target only creates yaml files and related archives for cipd rather
# than executing the cipd instance to upload them.
# Currently it's named as "cipd" to match the folder name which introduces
# confusions.
group("cipd") {
  testonly = true  # Some archives are testonly.
  deps = [
    ":web_engine_archives_with_tests",

    # Symbols are not uploaded for the following.
    ":chromedriver${_archive_suffix}",
    ":web_engine_debug_symbols",
  ]
  visibility = []  # Required to replace the file default.
  visibility = [ "//:gn_all" ]
}