# Copyright 2018 The ANGLE Project Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

# BUILD settings for Vulkan Loader
# Loader repo is at
# https://github.com/KhronosGroup/Vulkan-Loader

import("../../gni/angle.gni")

import("$angle_root/third_party/vulkan-headers/vulkan_headers_script_deps.gni")

# Fuchsia has non-upstream changes to the vulkan loader, so we don't want
# to build it from upstream sources.
assert(!is_fuchsia)

if (!is_android) {
  vulkan_undefine_configs = []
}
if (is_win) {
  vulkan_undefine_configs += [
    "//build/config/win:nominmax",
    "//build/config/win:unicode",
  ]
}

vulkan_gen_dir = "$target_gen_dir/angle/vulkan"
raw_vulkan_gen_dir = rebase_path(vulkan_gen_dir, root_build_dir)

# Vulkan helper scripts
# ---------------------

helper_script_and_deps = [
  [
    "vulkan_gen_dispatch_table_helper_h",
    "vk_dispatch_table_helper.h",
    "dispatch_table_helper_generator.py",
  ],
  [
    "vulkan_gen_enum_string_helper",
    "vk_enum_string_helper.h",
    "helper_file_generator.py",
  ],
  [
    "vulkan_gen_extension_helper",
    "vk_extension_helper.h",
    "helper_file_generator.py",
  ],
  [
    "vulkan_gen_layer_dispatch_table_h",
    "vk_layer_dispatch_table.h",
    "loader_extension_generator.py",
  ],
  [
    "vulkan_gen_loader_extensions_c",
    "vk_loader_extensions.c",
    "loader_extension_generator.py",
  ],
  [
    "vulkan_gen_loader_extensions_h",
    "vk_loader_extensions.h",
    "loader_extension_generator.py",
  ],
  [
    "vulkan_gen_object_types_h",
    "vk_object_types.h",
    "helper_file_generator.py",
  ],
  [
    "vulkan_gen_safe_struct_cpp",
    "vk_safe_struct.cpp",
    "helper_file_generator.py",
  ],
  [
    "vulkan_gen_safe_struct_h",
    "vk_safe_struct.h",
    "helper_file_generator.py",
  ],
  [
    "vulkan_gen_typemap_helper",
    "vk_typemap_helper.h",
    "helper_file_generator.py",
  ],
]

# Python scripts needed for codegen, copy them to a temp dir
# so that all dependencies are together. The reg.py script from
# the headers repo is required input to loader_genvk.py.
copy("python_gen_deps") {
  sources = vulkan_registry_script_files + [
              "src/scripts/common_codegen.py",
              "src/scripts/dispatch_table_helper_generator.py",
              "src/scripts/helper_file_generator.py",
              "src/scripts/loader_extension_generator.py",
              "src/scripts/loader_genvk.py",
            ]
  outputs = [
    "$vulkan_gen_dir/{{source_file_part}}",
  ]
}

foreach(script_and_dep, helper_script_and_deps) {
  target_name = script_and_dep[0]
  file = script_and_dep[1]
  dep = script_and_dep[2]
  target("action", target_name) {
    public_deps = [
      ":python_gen_deps",
    ]
    script = "$vulkan_gen_dir/loader_genvk.py"
    inputs = [
      "$vulkan_gen_dir/$dep",
      "$vulkan_gen_dir/common_codegen.py",
    ]
    outputs = [
      "$vulkan_gen_dir/$file",
    ]
    args = [
      "-o",
      raw_vulkan_gen_dir,
      "-registry",
      "$raw_vulkan_gen_dir/vk.xml",
      "-scripts",
      raw_vulkan_gen_dir,
      "$file",
      "-quiet",
    ]
  }
}

config("vulkan_generated_files_config") {
  include_dirs = [ vulkan_gen_dir ]
}

group("vulkan_generate_helper_files") {
  public_deps = [
    "$angle_root/third_party/vulkan-headers:vulkan_headers",
  ]
  public_configs = [ ":vulkan_generated_files_config" ]
  foreach(script_and_dep, helper_script_and_deps) {
    target_name = script_and_dep[0]
    public_deps += [ ":$target_name" ]
  }
}

config("vulkan_internal_config") {
  defines = [ "VULKAN_NON_CMAKE_BUILD" ]
  if (is_clang || !is_win) {
    cflags = [ "-Wno-unused-function" ]
  }
  if (is_linux) {
    defines += [
      "SYSCONFDIR=\"/etc\"",
      "FALLBACK_CONFIG_DIRS=\"/etc/xdg\"",
      "FALLBACK_DATA_DIRS=\"/usr/local/share:/usr/share\"",
    ]
  }
}

# Vulkan loader
# -------------

config("vulkan_loader_config") {
  include_dirs = [
    vulkan_gen_dir,
    "$angle_root/third_party/vulkan-headers/src/include",
    "src/loader",
  ]
  defines = [ "API_NAME=\"Vulkan\"" ]

  if (is_win) {
    cflags = [ "/wd4201" ]
  }
  if (is_linux) {
    # assume secure_getenv() is available
    defines += [ "HAVE_SECURE_GETENV" ]
  }
}

if (!is_android) {
  if (angle_shared_libvulkan) {
    library_type = "shared_library"
  } else {
    library_type = "static_library"
  }

  target(library_type, "libvulkan") {
    sources = [
      "src/loader/asm_offset.c",
      "src/loader/cJSON.c",
      "src/loader/cJSON.h",
      "src/loader/debug_utils.c",
      "src/loader/debug_utils.h",
      "src/loader/dev_ext_trampoline.c",
      "src/loader/extension_manual.c",
      "src/loader/extension_manual.h",
      "src/loader/gpa_helper.h",
      "src/loader/loader.c",
      "src/loader/loader.h",
      "src/loader/murmurhash.c",
      "src/loader/murmurhash.h",
      "src/loader/phys_dev_ext.c",
      "src/loader/trampoline.c",

      # TODO(jmadill): Use assembler where available.
      "src/loader/unknown_ext_chain.c",
      "src/loader/vk_loader_platform.h",
      "src/loader/wsi.c",
      "src/loader/wsi.h",
    ]
    if (is_win) {
      sources += [
        "src/loader/dirent_on_windows.c",
        "src/loader/dirent_on_windows.h",
      ]
      if (!is_clang) {
        cflags = [
          "/wd4054",  # Type cast from function pointer
          "/wd4055",  # Type cast from data pointer
          "/wd4100",  # Unreferenced formal parameter
          "/wd4152",  # Nonstandard extension used (pointer conversion)
          "/wd4201",  # Nonstandard extension used: nameless struct/union
          "/wd4214",  # Nonstandard extension used: bit field types other than int
          "/wd4232",  # Nonstandard extension used: address of dllimport is not static
          "/wd4305",  # Type cast truncation
          "/wd4706",  # Assignment within conditional expression
          "/wd4996",  # Unsafe stdlib function
        ]
      }
    }
    deps = [
      ":vulkan_generate_helper_files",
    ]
    public_deps = [
      "$angle_root/third_party/vulkan-headers:vulkan_headers",
    ]
    configs -= [ "//build/config/compiler:chromium_code" ]
    configs += [ "//build/config/compiler:no_chromium_code" ]
    configs += [ ":vulkan_internal_config" ]
    public_configs = [
      "$angle_root:vulkan_config",
      ":vulkan_loader_config",
    ]
    configs -= vulkan_undefine_configs
  }
}
