# Copyright (c) 2021 Huawei Device Co., Ltd.
# 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.

import("//build/config/python.gni")
import("//build/config/sanitizers/sanitizers.gni")
import("//build/ohos_var.gni")

# Gen module info to file
# private template
#
template("generate_module_info") {
  assert(defined(invoker.module_name),
         "module_label must be defined for ${target_name}.")
  assert(defined(invoker.module_type),
         "module_type must be defined for ${target_name}.")

  forward_variables_from(invoker,
                         [
                           "testonly",
                           "visibility",
                         ])
  forward_variables_from(invoker,
                         [
                           "module_label",
                           "module_name",
                           "module_source_dir",
                           "module_install_images",
                           "module_type",
                           "module_install_name",
                           "module_install_dir",
                           "relative_install_dir",
                           "module_output_extension",
                           "module_source",
                           "notice",
                           "shlib_type",
                           "innerapi_tags",
                           "version_script",
                           "part_name",
                           "subsystem_name",
                           "symlink_ext",
                           "symlink_path",
                           "softlink_create_path",
                         ])

  if (!defined(module_label)) {
    if (module_type == "java_library" || module_type == "none" ||
        module_type == "app" || module_type == "dex") {
      module_label = get_label_info(":$module_name", "label_no_toolchain")
    } else {
      module_label = get_label_info(":$module_name", "label_with_toolchain")
    }
  }
  module_deps = [ get_label_info(module_label, "label_no_toolchain") ]

  gen_script = "//build/templates/metadata/gen_module_info.py"

  if (!defined(module_source_dir)) {
    module_source_dir = "$root_out_dir"
  }
  if (!defined(module_install_name)) {
    module_install_name = module_name
  }
  if (!defined(module_output_extension)) {
    module_output_extension = ""
  }

  output_file = "${target_out_dir}/${module_name}_module_info.json"

  # reset module_type when module_type is lib
  if (module_type == "lib") {
    if (target_cpu == "arm64" || target_cpu == "x86_64" ||
        target_cpu == "loongarch64" || target_cpu == "riscv64") {
      module_type = "lib64"
    } else if (target_cpu == "arm" || target_cpu == "x86") {
      module_type = "lib"
    } else if (target_cpu == "riscv64" || target_cpu == "mipsel") {
      module_type = "lib"
    } else {
      assert(false, "Error: unsupported target cpu name.")
    }
  }

  if (!is_standard_system && (is_asan || is_tsan) &&
      ("${module_type}" == "lib" || "${module_type}" == "lib64" ||
       "${module_type}" == "bin")) {
    system_base_dir = "${system_base_dir}/asan"
  }

  action(target_name) {
    depfile = "${target_gen_dir}/${target_name}.d"
    args = [
      "--system-base-dir",
      system_base_dir,
      "--ramdisk-base-dir",
      ramdisk_base_dir,
      "--vendor-base-dir",
      vendor_base_dir,
      "--updater-base-dir",
      updater_base_dir,
      "--sys_prod-base-dir",
      sys_prod_base_dir,
      "--eng_system-base-dir",
      eng_system_base_dir,
      "--eng_chipset-base-dir",
      eng_chipset_base_dir,
      "--updater_vendor-base-dir",
      updater_vendor_base_dir,
      "--chip_prod-base-dir",
      chip_prod_base_dir,
      "--cloud_rom-base-dir",
      cloud_rom_base_dir,
      "--type",
      module_type,
      "--target-label",
      module_label,
      "--source-dir",
      rebase_path(module_source_dir, "$root_build_dir"),
      "--label-name",
      module_name,
      "--output-file",
      rebase_path(output_file, "$root_build_dir"),
      "--depfile",
      rebase_path(depfile, root_build_dir),
    ]

    if (module_install_name != "") {
      args += [
        "--install-name",
        module_install_name,
      ]
    }

    if (defined(invoker.module_alt_output_extension)) {
      args += [
        "--alternative-suffix",
        invoker.module_alt_output_extension,
      ]
    }

    if (defined(invoker.install_enable) && !invoker.install_enable) {
      args += [ "--install-enable" ]
    }
    if (defined(invoker.collect) && invoker.collect) {
      args += [ "--collect" ]
    }

    if (defined(module_install_images)) {
      if (defined(module_install_dir) && module_install_dir != "") {
        args += [
          "--module-install-dir",
          module_install_dir,
        ]
      }
      if (defined(relative_install_dir) && relative_install_dir != "") {
        args += [
          "--relative-install-dir",
          relative_install_dir,
        ]
      }
      args += [ "--install-images" ]
      args += module_install_images
    }

    # if prebuilt, add prebuilt=True
    if (defined(invoker.prebuilt) && invoker.prebuilt) {
      args += [
        "--prebuilt",
        "--module-source",
        module_source,
      ]
    }

    if (module_output_extension != "") {
      args += [
        "--suffix",
        module_output_extension,
      ]
    }

    if (defined(invoker.symlink_target_name)) {
      args += [ "--symlink-target" ]
      args += invoker.symlink_target_name
    }

    if (defined(invoker.output_prefix_override) &&
        invoker.output_prefix_override) {
      args += [ "--prefix-override" ]
    }
    if (defined(notice)) {
      args += [
        "--notice",
        rebase_path(notice, root_build_dir),
      ]
    }

    if (defined(part_name)) {
      args += [
        "--part-name",
        part_name,
      ]
    }
    if (defined(subsystem_name)) {
      args += [
        "--subsystem-name",
        subsystem_name,
      ]
    }
    if (defined(shlib_type)) {
      args += [
        "--shlib-type",
        shlib_type,
      ]
    }
    if (defined(innerapi_tags)) {
      args += [ "--innerapi-tags" ]
      args += innerapi_tags
    }
    if (defined(version_script)) {
      args += [
        "--version_script",
        version_script,
      ]
    }
    if (defined(symlink_ext)) {
      args += [ "--symlink-ext" ]
      args += symlink_ext
    }
    if (defined(symlink_path) && symlink_path != "") {
      args += [
        "--symlink-path",
        symlink_path,
      ]
    }
    if (defined(softlink_create_path) && softlink_create_path != "") {
      args += [
        "--softlink-create-path",
        softlink_create_path,
      ]
    }
    script = gen_script
    outputs = [ output_file ]
  }

  generated_file("${target_name}_install_info") {
    outputs = [ "${target_out_dir}/${module_name}_install_info.json" ]
    data_keys = [ "install_modules" ]
    output_conversion = "json"
    deps = module_deps
  }
}

template("write_meta_data") {
  assert(defined(invoker.meta_data), "meta_data must be defined")
  assert(defined(invoker.type), "type must be defined")
  forward_variables_from(invoker, [ "testonly" ])

  action_with_pydeps(target_name) {
    forward_variables_from(invoker,
                           [
                             "deps",
                             "meta_data",
                             "type",
                             "resources",
                             "hap_path",
                             "app_profile",
                             "hap_profile",
                             "package_name",
                             "raw_assets",
                             "js_assets",
                             "ets_assets",
                             "js2abc",
                             "unresolved_assets",
                           ])
    if (type != "js_assets" && type != "ets_assets" &&
        type != "unresolved_assets" && type != "assets" &&
        type != "resources" && type != "hap" && type != "app_profile") {
      assert(
          false,
          "type must be one of [js_assets, ets_assets, unresolved_assets, assets, resources, hap, app_profile]")
    }
    if (type != "hap") {
      _parent_invoker = invoker.invoker
      _caller_target_name = get_label_info(":${_parent_invoker.target_name}",
                                           "label_no_toolchain")
      sources = [ _caller_target_name ]
      sources = filter_exclude(sources, app_target_allowlist)
      if (sources != []) {
        if (type == "js_assets" || type == "ets_assets" ||
            type == "unresolved_assets" || type == "assets") {
          assert(
              false,
              "Illegal target name: \"${_caller_target_name}\", target name of ohos_js_assets or ohos_assets must endswith assets or asset ")
        } else if (type == "resources") {
          assert(
              false,
              "Illegal target name: \"${_caller_target_name}\", target name of ohos_resources must endswith res or resources or resource")
        }
      }
    }

    script = "//build/templates/metadata/write_meta_data.py"
    outputs = [ meta_data ]
    depfile = "$target_gen_dir/$target_name.d"

    args = [
      "--output",
      rebase_path(meta_data, root_build_dir),
      "--type",
      type,
      "--depfile",
      rebase_path(depfile, root_build_dir),
    ]

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

    _possible_deps = []
    if (defined(invoker.possible_deps)) {
      _possible_deps = invoker.possible_deps
    }

    _deps_metadata = []
    inputs = []
    foreach(d, _possible_deps) {
      sources_raw = []
      _target_label = get_label_info(d, "label_no_toolchain")
      sources_raw += [ _target_label ]
      sources = filter_exclude(sources_raw, app_target_allowlist)
      if (sources == []) {
        _deps_metadata += [ get_label_info(d, "target_gen_dir") + "/" +
                            get_label_info(d, "name") + ".metadata" ]
        deps += [ "${_target_label}__metadata" ]
      }
    }

    if (_deps_metadata != []) {
      args += [ "--deps-metadata" ]
      foreach(d, _deps_metadata) {
        args += [ rebase_path(d, root_build_dir) ]
      }
      inputs += _deps_metadata
    }

    if (defined(resources)) {
      args += [ "--resources" ]
      foreach(res, resources) {
        args += [ rebase_path(res, root_build_dir) ]
      }
      if (defined(package_name)) {
        args += [
          "--package-name",
          package_name,
        ]
      }
    }

    if (defined(app_profile)) {
      args += [
        "--app-profile",
        rebase_path(app_profile, root_build_dir),
      ]
    }

    if (defined(hap_profile)) {
      args += [
        "--hap-profile",
        rebase_path(hap_profile, root_build_dir),
      ]
    }

    if (defined(raw_assets)) {
      args += [ "--raw-assets" ]
      foreach(asset, raw_assets) {
        args += [ rebase_path(asset, root_build_dir) ]
      }
    }

    if (defined(js_assets)) {
      args += [ "--js-assets" ]
      foreach(asset, js_assets) {
        args += [ rebase_path(asset, root_build_dir) ]
      }
    }

    if (defined(ets_assets)) {
      args += [ "--ets-assets" ]
      foreach(asset, ets_assets) {
        args += [ rebase_path(asset, root_build_dir) ]
      }
    }

    if (defined(unresolved_assets)) {
      args += [ "--unresolved-assets" ]
      foreach(asset, unresolved_assets) {
        args += [ rebase_path(asset, root_build_dir) ]
      }
    }

    if (defined(js2abc) && js2abc) {
      args += [ "--js2abc" ]
    }

    if (defined(hap_path)) {
      args += [
        "--hap-path",
        rebase_path(hap_path, root_build_dir),
      ]
    }
  }
}