# Copyright 2014 The Chromium 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/config/android/config.gni")
import("//build/config/sanitizers/sanitizers.gni")
import("//build_overrides/build.gni")
import("//testing/libfuzzer/fuzzer_test.gni")
import("BUILD.generated.gni")
import("BUILD.generated_tests.gni")

# Config for us and everybody else depending on BoringSSL.
config("external_config") {
  include_dirs = [ "src/include" ]
  if (is_component_build) {
    defines = [ "BORINGSSL_SHARED_LIBRARY" ]
  }
}

# Config internal to this build file, shared by boringssl and boringssl_fuzzer.
config("internal_config") {
  visibility = [ ":*" ]  # Only targets in this file can depend on this.
  defines = [
    "BORINGSSL_IMPLEMENTATION",
    "BORINGSSL_NO_STATIC_INITIALIZER",
    "OPENSSL_SMALL",
  ]
  configs = [
    # TODO(davidben): Fix size_t truncations in BoringSSL.
    # https://crbug.com/429039
    "//build/config/compiler:no_size_t_to_int_warning",
  ]
  if (is_posix) {
    cflags_c = [ "-std=c99" ]
    defines += [ "_XOPEN_SOURCE=700" ]
  }
}

config("no_asm_config") {
  visibility = [ ":*" ]  # Only targets in this file can depend on this.
  defines = [ "OPENSSL_NO_ASM" ]
}

all_sources = crypto_sources + ssl_sources

# Windows' assembly is built with Yasm. The other platforms use the platform
# assembler.
if (is_win && !is_msan) {
  import("//third_party/yasm/yasm_assemble.gni")
  yasm_assemble("boringssl_asm") {
    if (current_cpu == "x64") {
      sources = crypto_sources_win_x86_64
    } else if (current_cpu == "x86") {
      sources = crypto_sources_win_x86
    }
  }
} else {
  # This has no sources on some platforms so must be a source_set.
  source_set("boringssl_asm") {
    visibility = [ ":*" ]  # Only targets in this file can depend on this.

    defines = [ "BORINGSSL_CLANG_SUPPORTS_DOT_ARCH" ]
    sources = []
    asmflags = []
    include_dirs = [ "src/include" ]

    if ((current_cpu == "arm" || current_cpu == "arm64") && is_clang) {
      if (current_cpu == "arm") {
        # TODO(hans) Enable integrated-as (crbug.com/124610).
        asmflags += [ "-fno-integrated-as" ]
      }
      if (is_android) {
        rebased_android_toolchain_root =
            rebase_path(android_toolchain_root, root_build_dir)

        # Else /usr/bin/as gets picked up.
        asmflags += [ "-B${rebased_android_toolchain_root}/bin" ]
      }
    }

    if (is_msan) {
      public_configs = [ ":no_asm_config" ]
    } else if (current_cpu == "x64") {
      if (is_mac) {
        sources += crypto_sources_mac_x86_64
      } else if (is_linux || is_android) {
        sources += crypto_sources_linux_x86_64
      } else {
        public_configs = [ ":no_asm_config" ]
      }
    } else if (current_cpu == "x86") {
      if (is_mac) {
        sources += crypto_sources_mac_x86
      } else if (is_linux || is_android) {
        sources += crypto_sources_linux_x86
      } else {
        public_configs = [ ":no_asm_config" ]
      }
    } else if (current_cpu == "arm" && (is_linux || is_android)) {
      sources += crypto_sources_linux_arm
    } else if (current_cpu == "arm64" && (is_linux || is_android)) {
      sources += crypto_sources_linux_aarch64
    } else {
      public_configs = [ ":no_asm_config" ]
    }
  }
}

component("boringssl") {
  sources = all_sources
  deps = [
    ":boringssl_asm",
  ]

  public_configs = [ ":external_config" ]
  configs += [ ":internal_config" ]

  configs -= [ "//build/config/compiler:chromium_code" ]
  configs += [ "//build/config/compiler:no_chromium_code" ]

  if (is_nacl) {
    deps += [ "//native_client_sdk/src/libraries/nacl_io" ]
  }
}

if (build_with_chromium) {
  create_tests("boringssl_tests") {
    configs_exclude = [ "//build/config/compiler:chromium_code" ]
    configs = [
      ":internal_config",
      "//build/config/compiler:no_chromium_code",
    ]
    deps = [
      ":boringssl",
      "//build/win:default_exe_manifest",
    ]
  }

  if (!is_ios) {
    test("boringssl_unittests") {
      deps = [
        ":boringssl_tests",
        "//base",
        "//base/test:run_all_unittests",
        "//base/test:test_support",
        "//testing/gtest",
      ]
      sources = [
        "boringssl_unittest.cc",
      ]
    }
  }

  config("fuzzer_config") {
    visibility = [ ":*" ]  # Only targets in this file can depend on this.
    defines = [
      "BORINGSSL_UNSAFE_FUZZER_MODE",
      "BORINGSSL_UNSAFE_DETERMINISTIC_MODE",
    ]
  }

  # The same as boringssl, but builds with BORINGSSL_UNSAFE_FUZZER_MODE.
  component("boringssl_fuzzer") {
    visibility = [ ":*" ]  # Only targets in this file can depend on this.

    sources = all_sources
    deps = [
      ":boringssl_asm",
    ]

    public_configs = [
      ":external_config",
      ":fuzzer_config",
    ]
    configs += [ ":internal_config" ]

    configs -= [ "//build/config/compiler:chromium_code" ]
    configs += [ "//build/config/compiler:no_chromium_code" ]

    if (is_nacl) {
      deps += [ "//native_client_sdk/src/libraries/nacl_io" ]
    }
  }

  foreach(fuzzer, fuzzers) {
    fuzzer_test("boringssl_${fuzzer}_fuzzer") {
      sources = [
        "src/fuzz/${fuzzer}.cc",
      ]
      deps = [
        ":boringssl_fuzzer",
      ]
      seed_corpus = "src/fuzz/${fuzzer}_corpus"

      if ("cert" == fuzzer) {
        libfuzzer_options = [ "max_len=3072" ]
      } else if ("client" == fuzzer) {
        libfuzzer_options = [ "max_len=20000" ]
      } else if ("pkcs8" == fuzzer) {
        libfuzzer_options = [ "max_len=2048" ]
      } else if ("privkey" == fuzzer) {
        libfuzzer_options = [ "max_len=2048" ]
      } else if ("read_pem" == fuzzer) {
        libfuzzer_options = [ "max_len=512" ]
      } else if ("server" == fuzzer) {
        libfuzzer_options = [ "max_len=4096" ]
      } else if ("spki" == fuzzer) {
        libfuzzer_options = [ "max_len=1024" ]
      } else if ("ssl_ctx_api" == fuzzer) {
        libfuzzer_options = [ "max_len=256" ]
      }
    }
  }

  config("fuzzer_no_fuzzer_mode_config") {
    visibility = [ ":*" ]  # Only targets in this file can depend on this.
    defines = [ "BORINGSSL_UNSAFE_DETERMINISTIC_MODE" ]
  }

  # The same as boringssl, but builds with BORINGSSL_UNSAFE_DETERMINISTIC_MODE.
  component("boringssl_fuzzer_no_fuzzer_mode") {
    visibility = [ ":*" ]  # Only targets in this file can depend on this.

    sources = all_sources
    deps = [
      ":boringssl_asm",
    ]

    public_configs = [
      ":external_config",
      ":fuzzer_no_fuzzer_mode_config",
    ]
    configs += [ ":internal_config" ]

    configs -= [ "//build/config/compiler:chromium_code" ]
    configs += [ "//build/config/compiler:no_chromium_code" ]

    if (is_nacl) {
      deps += [ "//native_client_sdk/src/libraries/nacl_io" ]
    }
  }

  fuzzer_test("boringssl_client_no_fuzzer_mode_fuzzer") {
    sources = [
      "src/fuzz/client.cc",
    ]
    deps = [
      ":boringssl_fuzzer_no_fuzzer_mode",
    ]
    seed_corpus = "src/fuzz/client_corpus_no_fuzzer_mode"
  }

  fuzzer_test("boringssl_server_no_fuzzer_mode_fuzzer") {
    sources = [
      "src/fuzz/server.cc",
    ]
    deps = [
      ":boringssl_fuzzer_no_fuzzer_mode",
    ]
    seed_corpus = "src/fuzz/server_corpus_no_fuzzer_mode"
  }
}
