# Copyright (c) 2020 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/lite/config/subsystem/aafwk/path.gni")

template("generate_lite_notice") {
  action_with_pydeps(target_name) {
    assert(defined(invoker.module_name), "module_name in required.")
    assert(target_name != "")
    forward_variables_from(invoker,
                           [
                             "module_name",
                             "module_source_dir",
                             "deps",
                             "license_file",
                             "module_type",
                             "outputs",

                             # Some license file are generated in gn gen.
                             # Such notices should not be used as sources.
                             "license_as_sources",
                           ])
    script = rebase_path("//build/ohos/notice/collect_module_notice_file.py")
    depfile = "${target_gen_dir}/$target_name.d"
    module_name = invoker.module_name

    if (!defined(outputs)) {
      outputs = []

      # _notice_subdir = "${invoker.subsystem_name}/${invoker.part_name}"
      if (defined(module_type) && module_type == "static_library") {
        outputs +=
            [ "$root_build_dir/NOTICE_FILES/rootfs/libs/$module_name.a.txt" ]
      } else if (defined(module_type) && module_type == "shared_library") {
        outputs += [
          "$root_build_dir/NOTICE_FILES/rootfs/usr/lib/$module_name.so.txt",
        ]
      } else if (defined(module_type) && module_type == "executable") {
        outputs +=
            [ "$root_build_dir/NOTICE_FILES/rootfs/bin/$module_name.bin.txt" ]
      }
    }

    args = [
      "--module-source-dir",
      rebase_path(module_source_dir, root_build_dir),
      "--depfile",
      rebase_path(depfile, root_build_dir),
    ]
    foreach(o, outputs) {
      args += [
        "--output",
        rebase_path(o, root_build_dir),
      ]
    }

    if (defined(license_file)) {
      _license_as_sources = true
      if (defined(license_as_sources)) {
        _license_as_sources = license_as_sources
      }
      if (_license_as_sources) {
        inputs = [ license_file ]
      }
      args += [
        "--license-file",
        rebase_path(license_file, root_build_dir),
      ]
    }
  }
}

template("lite_library") {
  assert(defined(invoker.target_type), "Library target_type is required.")
  assert(defined(invoker.sources), "Library sources is required.")
  target_type = invoker.target_type
  shared_lib = target_type == "shared_library"

  if (shared_lib &&
      (ohos_kernel_type == "liteos_m" || ohos_kernel_type == "uniproton")) {
    group(target_name) {
      if (defined(invoker.sources)) {
        assert(invoker.sources != "")
      }
      if (defined(invoker.public_configs)) {
        assert(invoker.public_configs != "")
      }
      if (defined(invoker.public_deps)) {
        assert(invoker.public_deps != "")
      }
      if (defined(invoker.output_name)) {
        assert(invoker.output_name != "")
      }
    }
  } else {
    notice_target_type = invoker.target_type
    if (notice_target_type == "shared_library" ||
        notice_target_type == "static_library" ||
        notice_target_type == "executable") {
      _notice_target = "${target_name}__notice"
      _main_target_name = target_name
      generate_lite_notice(_notice_target) {
        module_type = notice_target_type
        module_name = _main_target_name
        module_source_dir = get_label_info(":${_main_target_name}", "dir")
      }
    }

    target(target_type, target_name) {
      forward_variables_from(invoker, "*", [ "remove_configs" ])
      cflags = []
      cflags_cc = []
      ldflags = []
      if (defined(invoker.cflags)) {
        cflags += invoker.cflags
      }
      if (defined(invoker.cflags_cc)) {
        cflags_cc += invoker.cflags_cc
        ldflags += [ "-lstdc++" ]
      }
      if (defined(invoker.ldflags)) {
        ldflags += invoker.ldflags
      }
      if (defined(invoker.remove_configs)) {
        configs -= invoker.remove_configs
      }
      shared_lib = target_type == "shared_library"
      if (shared_lib) {
        cflags += [ "-fPIC" ]
        cflags_cc += [ "-fPIC" ]
      } else if (!shared_lib && (ohos_kernel_type != "liteos_m" &&
                                 ohos_kernel_type != "uniproton")) {
        cflags += [ "-fPIE" ]
        cflags_cc += [ "-fPIE" ]
      }
      if (!defined(deps)) {
        deps = []
      }
      if (defined(invoker.target_type)) {
        notice_target_type = invoker.target_type
        if (notice_target_type == "shared_library" ||
            notice_target_type == "static_library" ||
            notice_target_type == "executable") {
          _notice_target = "${target_name}__notice"
          deps += [ ":$_notice_target" ]
        }
      }
    }
  }
}

# Defines a component
#
# The lite_component template defines all the modules contained in a subsystem
#
# Parameters
#
#   features (required)
#     [list of scopes] Defines all features in the component.
template("lite_component") {
  assert(defined(invoker.features), "Component features is required.")

  if (!defined(invoker.target_type)) {
    target_type = "group"
  } else if (invoker.target_type == "static_library") {
    target_type = "group"
  } else {
    target_type = invoker.target_type
  }
  assert(target_type != "")

  target(target_type, target_name) {
    deps = []

    forward_variables_from(invoker, "*")

    # add component deps
    if (defined(invoker.deps)) {
      deps += invoker.deps
    }

    # add component features
    foreach(feature_label, features) {
      deps += [ feature_label ]
    }
  }
}

template("build_ext_component") {
  forward_variables_from(invoker, [ "testonly" ])
  if (defined(invoker.version)) {
    print(invoker.version)
  }
  action(target_name) {
    forward_variables_from(invoker,
                           [
                             "no_default_deps",
                             "deps",
                           ])
    args = []
    if (defined(invoker.exec_path)) {
      args += [ "--path=${invoker.exec_path}" ]
    }
    if (defined(invoker.enable)) {
      args += [ "--enable=${invoker.enable}" ]
    }
    if (defined(invoker.prebuilts)) {
      args += [ "--prebuilts=${invoker.prebuilts}" ]
    }
    if (defined(invoker.command)) {
      args += [ "--command=${invoker.command}" ]
    }

    # external component build log
    target_dir = rebase_path("${target_out_dir}/build.log")
    args += [ "--target_dir=${target_dir}" ]

    # external component error log if compile failed
    out_dir = rebase_path("${root_out_dir}/error.log")
    args += [ "--out_dir=${out_dir}" ]
    script = "//build/lite/build_ext_components.py"
    outputs = [ "$target_out_dir/${target_name}_build_ext_components.txt" ]
    if (defined(invoker.outputs)) {
      outputs += invoker.outputs
    }
  }
}

template("ohos_tools") {
  target(invoker.target_type, target_name) {
    forward_variables_from(invoker, "*")
    output_dir = "$root_out_dir/tools/$target_name"
    if (ohos_kernel_type == "liteos_a" || ohos_kernel_type == "linux") {
      configs -= [ "//build/lite/config:ohos" ]
    } else if (ohos_kernel_type == "liteos_m") {
      configs -= [ "//build/lite/config:liteos" ]
    }
    configs -= [ "//build/lite/config:pie_executable_config" ]
    configs -= [ "//build/lite/config:static_pie_config" ]
    configs += [ "//build/lite/config:tools" ]
  }
}

template("generate_notice_file") {
  assert(defined(invoker.module_name), "module_name in required.")
  assert(defined(invoker.module_source_dir_list),
         "module_source_dir_list in required.")
  assert(target_name != "")
  forward_variables_from(invoker,
                         [
                           "module_name",
                           "module_source_dir_list",
                         ])
  gen_script = rebase_path("//build/lite/gen_module_notice_file.py")

  foreach(module_source_dir, module_source_dir_list) {
    arguments = []
    arguments = [
      "--root-out-dir",
      rebase_path(root_out_dir),
      "--module-source-dir",
      rebase_path(module_source_dir),
      "--module-relative-source-dir",
      rebase_path(module_source_dir, "//"),
      "--target-name",
      module_name,
    ]
    ret_msg = ""
    ret_msg = exec_script(gen_script, arguments, "list lines")
    if (ret_msg != "") {
      foreach(msg, ret_msg) {
        print(msg)
      }
    }
  }
}