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

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

declare_args() {
  is_ggp = false

  # Extract native libs in ANGLE apk. Useful for flamegraph generation.
  angle_extract_native_libs = false
}

if (angle_has_build) {
  import("//build/config/dcheck_always_on.gni")
  import("//build/config/sanitizers/sanitizers.gni")
  import("//build/config/ui.gni")  # import the use_x11 variable
  import("//build_overrides/build.gni")
  import("//testing/test.gni")
  if (is_android) {
    import("//build/config/android/config.gni")
  }

  if (is_win) {
    import("//build/config/win/visual_studio_version.gni")
  }

  angle_use_x11 = use_x11 && !is_ggp
} else {
  declare_args() {
    is_ubsan = false
    is_tsan = false
    is_asan = false
    build_with_chromium = false
    dcheck_always_on = false
    angle_use_x11 = is_linux && !is_ggp
    use_ozone = false
    use_fuzzing_engine = false
  }
}

if (build_with_chromium) {
  import("//ui/ozone/ozone.gni")
} else {
  declare_args() {
    ozone_platform_gbm = false
  }
}

# Subdirectory to place data files (e.g. layer JSON files).
angle_data_dir = "angledata"

declare_args() {
  if (current_cpu == "arm64" || current_cpu == "x64" ||
      current_cpu == "mips64el" || current_cpu == "s390x" ||
      current_cpu == "ppc64") {
    angle_64bit_current_cpu = true
  } else if (current_cpu == "arm" || current_cpu == "x86" ||
             current_cpu == "mipsel" || current_cpu == "s390" ||
             current_cpu == "ppc") {
    angle_64bit_current_cpu = false
  } else {
    assert(false, "Unknown current CPU: $current_cpu")
  }
}

declare_args() {
  if (!is_android) {
    ndk_api_level_at_least_26 = false
  } else {
    ndk_api_level_at_least_26 =
        (!angle_64bit_current_cpu && android32_ndk_api_level >= 26) ||
        (angle_64bit_current_cpu && android64_ndk_api_level >= 26)
  }

  # Vulkan loader is statically linked on Mac. http://anglebug.com/4477
  angle_shared_libvulkan = !is_mac

  # There's no "is_winuwp" helper in BUILDCONFIG.gn, so we define one ourselves
  angle_is_winuwp = is_win && current_os == "winuwp"

  # Default to using "_angle" suffix on Android
  if (is_android) {
    angle_libs_suffix = "_angle"
  } else {
    angle_libs_suffix = ""
  }

  # Currently Windows on Arm doesn't support OpenGL or Vulkan.
  is_win_arm64 = is_win && target_cpu == "arm64"
}

declare_args() {
  # By default, ANGLE is using a thread pool for parallel compilation.
  # Activating the delegate worker results in posting the tasks using the
  # embedder API. In Chromium code base, it results in sending tasks to the
  # worker thread pool.
  angle_delegate_workers = build_with_chromium

  angle_enable_d3d9 = is_win && !angle_is_winuwp
  angle_enable_d3d11 = is_win
  angle_enable_gl =
      (ozone_platform_gbm || !is_linux || (angle_use_x11 && !is_chromeos)) &&
      !is_fuchsia && !angle_is_winuwp && !is_ggp && !is_win_arm64

  # ANGLE Vulkan backend on Android requires API level 26, i.e. Oreo, due to
  # Vulkan Validation Layers compatibility issues, see http://crrev/c/1405714.
  # Otherwise, API level 24 would have been enough.
  angle_enable_vulkan =
      angle_has_build && ((is_win && !angle_is_winuwp) ||
                          (is_linux && angle_use_x11 && !is_chromeos) ||
                          (is_android && ndk_api_level_at_least_26) ||
                          is_fuchsia || is_ggp || is_mac)
  angle_enable_null = true
  angle_enable_essl = true
  angle_enable_glsl = true

  # http://anglebug.com/2634
  angle_enable_metal = is_mac
}

declare_args() {
  # Currently SwiftShader's Vulkan front-end doesn't build on Android.
  # SwiftShader is not needed on Fuchsia because Vulkan is supported on all
  # devices that run Fuchsia.
  angle_enable_swiftshader =
      angle_enable_vulkan && !is_android && !is_fuchsia && !is_ggp

  angle_enable_gl_null = angle_enable_gl
  angle_enable_hlsl = angle_enable_d3d9 || angle_enable_d3d11
  angle_enable_trace = false

  # Disable the layers in ubsan builds because of really slow builds.
  # TODO(anglebug.com/4082) enable validation layers on mac for swiftshader
  angle_enable_vulkan_validation_layers =
      angle_enable_vulkan && !is_ubsan && !is_tsan && !is_asan &&
      (is_debug || dcheck_always_on) && !is_mac

  # Disable overlay by default
  angle_enable_overlay = false
}

if (!defined(angle_zlib_compression_utils_dir)) {
  angle_zlib_compression_utils_dir = "//third_party/zlib/google"
}

angle_common_configs = [
  angle_root + ":angle_release_asserts_config",
  angle_root + ":better_linux_stack_traces",
  angle_root + ":constructor_and_destructor_warnings",
  angle_root + ":extra_warnings",
  angle_root + ":internal_config",
]

angle_remove_configs = []

if (angle_has_build) {
  angle_remove_configs += [ "//build/config/compiler:default_include_dirs" ]
}
angle_better_stack_traces =
    (is_debug || dcheck_always_on) && is_linux && !is_asan && !is_cfi

if (angle_has_build && is_clang) {
  angle_remove_configs += [ "//build/config/clang:find_bad_constructs" ]

  # Disabled to enable better stack traces.
  if (angle_better_stack_traces) {
    # This line causes in-class-inline-functions in glslang to be weak symbols.  The KHR dEQP tests
    # link against glslang as well as libGLESv2.so, resulting in angle_deqp_khr_gles*_tests to link
    # those weak symbols.  Due to glslang's usage of a global variable in InitializeDll.cpp, a bug
    # is created where ANGLE sometimes calls into its own copy of glslang and sometimes the KHR
    # dEQP's version, with the two copies of the global variable being inconsistent.
    # Commented out until the underlying issue is resolved.  http://anglebug.com/4123
    # angle_remove_configs += [ "//build/config/gcc:symbol_visibility_hidden" ]
  }
}

set_defaults("angle_executable") {
  configs = angle_common_configs
  public_configs = []
  suppressed_configs = angle_remove_configs
}

set_defaults("angle_shared_library") {
  configs = angle_common_configs
  public_configs = []
  suppressed_configs = angle_remove_configs
}

set_defaults("angle_source_set") {
  configs = angle_common_configs
  public_configs = []
  suppressed_configs = angle_remove_configs
}

set_defaults("angle_static_library") {
  configs = angle_common_configs
  public_configs = []
  suppressed_configs = angle_remove_configs
}

set_defaults("angle_test") {
  configs = []

  # Gtest itself can't pass all the strict warning filters.
  public_configs = angle_common_configs - [
                     "$angle_root:constructor_and_destructor_warnings",
                     "$angle_root:extra_warnings",
                   ]

  public_deps = []
  sources = []
  data = []
  defines = []
  data_deps = []
  main = ""
  suppressed_configs = angle_remove_configs

  # By default use the Chromium harness in Chromium. Can be overriden in a target.
  standalone_harness = !build_with_chromium

  if (!standalone_harness) {
    suppressed_configs -= [ "//build/config/compiler:default_include_dirs" ]
  }
}

template("angle_executable") {
  executable(target_name) {
    forward_variables_from(invoker,
                           "*",
                           [
                             "configs",
                             "suppressed_configs",
                             "visibility",
                           ])

    # Needed because visibility is global.
    forward_variables_from(invoker, [ "visibility" ])

    configs += invoker.configs
    configs -= invoker.suppressed_configs
  }
}

template("angle_shared_library") {
  shared_library(target_name) {
    forward_variables_from(invoker,
                           "*",
                           [
                             "configs",
                             "suppressed_configs",
                             "visibility",
                           ])

    # Needed because visibility is global.
    forward_variables_from(invoker, [ "visibility" ])

    configs += invoker.configs
    configs -= invoker.suppressed_configs

    public_configs += [ angle_root + ":shared_library_public_config" ]

    if (is_android) {
      configs += [ angle_root + ":build_id_config" ]
      configs -= [ "//build/config/android:hide_all_but_jni_onload" ]
    }
  }
}

template("angle_source_set") {
  source_set(target_name) {
    forward_variables_from(invoker,
                           "*",
                           [
                             "configs",
                             "suppressed_configs",
                             "visibility",
                           ])

    # Needed because visibility is global.
    forward_variables_from(invoker, [ "visibility" ])

    configs += invoker.configs
    configs -= invoker.suppressed_configs
  }
}

template("angle_static_library") {
  static_library(target_name) {
    forward_variables_from(invoker,
                           "*",
                           [
                             "configs",
                             "suppressed_configs",
                             "visibility",
                           ])

    # Needed because visibility is global.
    forward_variables_from(invoker, [ "visibility" ])

    configs += invoker.configs
    configs -= invoker.suppressed_configs
  }
}

template("angle_test") {
  _lib = target_name + "_lib"
  angle_source_set(_lib) {
    testonly = true
    forward_variables_from(invoker,
                           "*",
                           [
                             "deps",
                             "manifest",
                             "use_xvfb",
                           ])

    if (is_android) {
      public_configs += [ "$angle_root:build_id_config" ]
    }

    public_deps += invoker.deps + [
                     "$angle_root:angle_common",
                     "$angle_root:includes",
                     "$angle_root/third_party/rapidjson:rapidjson",
                     "$angle_root/util:angle_test_utils",
                     "//testing/gmock",
                     "//testing/gtest",
                     "//third_party/googletest:gmock",
                     "//third_party/googletest:gtest",
                   ]

    sources += [
      "$angle_root/src/tests/test_utils/runner/TestSuite.cpp",
      "$angle_root/src/tests/test_utils/runner/TestSuite.h",
    ]
  }

  # To use the Chromium test infrastructure we must currently use the
  # //base test launcher. Eventually we could switch to using standalone
  # testing. See http://crbug.com/837741.
  # TODO(jmadill): Clean up duplication as part of http://anglebug.com/3152

  _standalone_harness_test_name = target_name

  if (build_with_chromium) {
    _standalone_harness_test_name = "standalone_" + target_name
    test(target_name) {
      if ((is_linux && !is_chromeos) ||
          (build_with_chromium && chromeos_is_browser_only)) {
        use_xvfb = true
      }

      public_deps = [ ":${_lib}" ]
      if (invoker.main != "") {
        sources = [ "//gpu/${invoker.main}.cc" ]
      }
      deps = [ "//base/test:test_support" ]
      if (is_android) {
        configs -= [ "//build/config/android:hide_all_but_jni" ]
      }

      if (is_linux && !is_component_build) {
        # Set rpath to find shared libs in a non-component build.
        configs += [ "//build/config/gcc:rpath_for_built_shared_libraries" ]
      }

      if (defined(invoker.manifest)) {
        manifest = invoker.manifest
      }

      if (is_android) {
        use_native_activity = true
      }
    }
  }

  test(_standalone_harness_test_name) {
    if ((is_linux && !is_chromeos) ||
        (build_with_chromium && chromeos_is_browser_only)) {
      use_xvfb = true
    }

    public_deps = [ ":${_lib}" ]
    if (invoker.main != "") {
      sources = [ "${invoker.main}.cpp" ]
    }
    data = invoker.data + [
             "$angle_root/scripts/run_gtest_angle_test.py",
             "//testing/scripts/common.py",
             "//testing/xvfb.py",
           ]

    if (is_linux && !is_component_build) {
      # Set rpath to find shared libs in a non-component build.
      configs += [ "//build/config/gcc:rpath_for_built_shared_libraries" ]
    }

    if (defined(invoker.manifest)) {
      manifest = invoker.manifest
    }

    if (is_android) {
      if (build_with_chromium) {
        use_native_activity = true
        configs -= [ "//build/config/android:hide_all_but_jni" ]
      } else {
        use_raw_android_executable = true
      }
    }
  }
}
