%YAML 1.2
--- |
  # GRPC Fuchsia GN build file

  # This file has been automatically generated from a template file.
  # Please look at the templates directory instead.
  # This file can be regenerated from the template by running
  # tools/buildgen/generate_projects.sh

  # Copyright 2019 gRPC authors.
  #
  # 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.

  config("grpc_config") {
    include_dirs = [
      ".",
      "include/",
    ]
    defines = [
      "GRPC_USE_PROTO_LITE",
      "GPR_SUPPORT_CHANNELS_FROM_FD",
      "PB_FIELD_16BIT",
    ]
  }
  <%!
  def get_deps(target_dict):
    deps = []
    if target_dict.get("secure", False):
      deps = ["//third_party/boringssl"]
    if target_dict.get("build", None) == "protoc":
      deps.append("//third_party/protobuf:protoc_lib")
    name = target_dict.get("name", None)
    if name in ("grpc++", "grpc++_codegen_lib"):
      deps.append("//third_party/protobuf:protobuf_lite")
    elif name in ("grpc", "grpc_unsecure"):
      deps.append("//third_party/zlib")
    for d in target_dict.get("deps", []):
      if d.startswith(("//", ":")):
        deps.append(d)
      else:
        deps.append(":%s" % d)
    if needs_ares(target_dict.src):
      deps.append("//third_party/cares")
      deps.append(":address_sorting")
    if needs_nanopb(target_dict.src) and target_dict.name != "nanopb":
      deps.append(":nanopb")
    if needs_health_proto(target_dict.src) and target_dict.name != "health_proto":
      deps.append(":health_proto")
    return deps

  %><%!
  def needs_ares(srcs):
    return any("/c_ares/" in f for f in srcs) if srcs else False

  %><%!
  def needs_nanopb(srcs):
    return any(f.startswith("third_party/nanopb")
               or f.endswith(".pb.h")
               or f.endswith(".pb.c")
               or f.endswith(".pb.cc")
               or f.endswith("load_balancer_api.h")
               or f.endswith("load_balancer_api.c")
               for f in srcs)

  %><%!
  def needs_address_sorting(sources):
    return needs_ares(sources) or any("address_sorting" in s for s in sources)

  %><%!
  def needs_health_proto(srcs):
    return any("health.pb" in f for f in srcs)

  %><%!
  def get_include_dirs(sources):
    dirs = []
    if needs_ares(sources):
      dirs = ["third_party/cares"]
    if needs_address_sorting(sources):
      dirs.append("third_party/address_sorting/include")
    if needs_nanopb(sources):
      dirs.append("third_party/nanopb")
    return dirs

  %><%!
  def strip_sources(sources, name):
    return [f for f in sources
            if "ruby_generator" not in f
            and ("third_party/nanopb" not in f or name == "nanopb")
            and ("health.pb" not in f or name == "health_proto")]

  %><%!
  def get_sources(target):
    return ((target.public_headers or []) +
            (target.headers or []) +
            (target.src or []))

  %><%!
  def get_extra_configs(target_dict):
    if target_dict.get("name", "") == "grpc_cpp_plugin":
      return ["//third_party/protobuf:protobuf_config"]
    return []

  %><%!
  def wanted_lib(lib):
    wanted_libs = ("gpr", "grpc", "grpc++", "grpc_plugin_support", "address_sorting")
    return lib.build in ("all", "protoc") and lib.get("name", "") in wanted_libs

  %><%!
  def wanted_binary(tgt):
    wanted_binaries = ("grpc_cpp_plugin",)
    return tgt.build == "protoc" and tgt.get("name", "") in wanted_binaries

  %><%!
  def only_on_host_toolchain(tgt):
    return tgt.get("name", "") in ("grpc_plugin_support", "grpc_cpp_plugin")

  %>
  % for lib in filegroups:
    % if lib.name in ("nanopb", "health_proto"):
      ${cc_library(lib)}
    %endif
  %endfor
  % for lib in libs:
    % if wanted_lib(lib):
      % if only_on_host_toolchain(lib):
        # Only compile the plugin for the host architecture.
        if (current_toolchain == host_toolchain) {
          ${cc_library(lib)}
        }
      % else:
        ${cc_library(lib)}
      % endif
    % endif
  % endfor
  % for tgt in targets:
    % if wanted_binary(tgt):
      % if only_on_host_toolchain(tgt):
        # Only compile the plugin for the host architecture.
        if (current_toolchain == host_toolchain) {
          ${cc_binary(tgt)}
        }
      % else:
        ${cc_binary(tgt)}
      % endif
    % endif
  % endfor
  <%def name="cc_library(lib)">
    <%
      sources = get_sources(lib)
      include_dirs = get_include_dirs(sources)
      sources = strip_sources(sources, lib.name)
      sources.sort()
    %>
    source_set("${lib.name}") {
      %if sources:
      sources = [
        % for src in sources:
          "${src}",
        % endfor
      ]
      %endif
      deps = [
        % for dep in get_deps(lib):
          "${dep}",
        % endfor
      ]
      <% extra_configs = get_extra_configs(lib) %>
      % if extra_configs:
        configs += [
          % for config in extra_configs:
            "${config}",
          % endfor
        ]
      % endif
      public_configs = [
        ":grpc_config",
      ]
      %if include_dirs:
      include_dirs = [
        %for d in include_dirs:
          "${d}",
        %endfor
      ]
      %endif
    }
  </%def>
  <%def name="cc_binary(tgt)">
    executable("${tgt.name}") {
      sources = [
        % for src in tgt.src:
          "${src}",
        % endfor
      ]
      deps = [
        % for dep in get_deps(tgt):
          "${dep}",
        % endfor
      ]
      <% extra_configs = get_extra_configs(tgt) %>
      % if extra_configs:
        configs += [
          % for config in extra_configs:
            "${config}",
          % endfor
        ]
      % endif
      public_configs = [ ":grpc_config" ]
    }
  </%def>
  ## vim: set ft=mako:ts=2:et:sw=2
