# Copyright 2015 The Crashpad 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.

import("../build/crashpad_buildconfig.gni")

static_library("handler") {
  sources = [
    "handler_main.cc",
    "handler_main.h",
    "prune_crash_reports_thread.cc",
    "prune_crash_reports_thread.h",
  ]

  if (crashpad_is_mac) {
    sources += [
      "mac/crash_report_exception_handler.cc",
      "mac/crash_report_exception_handler.h",
      "mac/exception_handler_server.cc",
      "mac/exception_handler_server.h",
    ]
  }

  if (crashpad_is_linux || crashpad_is_android) {
    sources += [
      "linux/capture_snapshot.cc",
      "linux/capture_snapshot.h",
      "linux/crash_report_exception_handler.cc",
      "linux/crash_report_exception_handler.h",
      "linux/exception_handler_server.cc",
      "linux/exception_handler_server.h",
    ]
  }

  if (crashpad_is_linux) {
    sources += [
      "linux/cros_crash_report_exception_handler.cc",
      "linux/cros_crash_report_exception_handler.h",
    ]

    # TODO(https://crbug.com/1420445): Remove this config when M115 branches.
    configs += [ "../build:crashpad_is_in_chromium" ]
  }

  if (crashpad_is_win) {
    sources += [
      "win/crash_report_exception_handler.cc",
      "win/crash_report_exception_handler.h",
    ]
  }

  public_configs = [ "..:crashpad_config" ]

  public_deps = [
    ":common",
    "../client",
    "../third_party/mini_chromium:base",
    "../util",
  ]

  deps = [
    ":common",
    "../minidump",
    "../snapshot",
    "../tools:tool_support",
  ]

  if (crashpad_is_win) {
    cflags = [ "/wd4201" ]  # nonstandard extension used : nameless struct/union
  }
}

if (crashpad_is_android) {
  # CrashpadHandlerMain is defined in a separate target so that it can be
  # overriden by implementers
  source_set("crashpad_handler_main") {
    sources = [ "crashpad_handler_main.cc" ]

    deps = [ ":handler" ]
  }
}

static_library("common") {
  sources = [
    "crash_report_upload_rate_limit.cc",
    "crash_report_upload_rate_limit.h",
    "crash_report_upload_thread.cc",
    "crash_report_upload_thread.h",
    "minidump_to_upload_parameters.cc",
    "minidump_to_upload_parameters.h",
    "user_stream_data_source.cc",
    "user_stream_data_source.h",
  ]
  if (crashpad_is_apple) {
    sources += [
      "mac/file_limit_annotation.cc",
      "mac/file_limit_annotation.h",
    ]
  }
  public_configs = [ "..:crashpad_config" ]
  public_deps = [
    "../third_party/mini_chromium:base",
    "../util",
  ]
  deps = [
    "../client:common",
    "../minidump",
    "../snapshot",
    "../util",
    "../util:net",
  ]
  if (crashpad_is_win) {
    cflags = [ "/wd4201" ]  # nonstandard extension used : nameless struct/union
  }
}

source_set("handler_test") {
  testonly = true

  sources = [
    "crash_report_upload_rate_limit_test.cc",
    "minidump_to_upload_parameters_test.cc",
  ]

  if (crashpad_is_linux || crashpad_is_android) {
    sources += [ "linux/exception_handler_server_test.cc" ]
  }

  if (crashpad_is_win) {
    sources += [ "crashpad_handler_test.cc" ]
  }

  deps = [
    ":handler",
    "../client",
    "../compat",
    "../snapshot",
    "../snapshot:test_support",
    "../test",
    "../third_party/googletest",
    "../third_party/mini_chromium:base",
    "../util",
  ]

  if (crashpad_is_win) {
    deps += [
      "../minidump:test_support",
      "win/wer:crashpad_wer_test",
    ]

    data_deps = [
      ":crashpad_handler_test_extended_handler",
      ":fake_handler_that_crashes_at_startup",
    ]
  }
}

if (!crashpad_is_ios) {
  crashpad_executable("crashpad_handler") {
    sources = [ "main.cc" ]

    deps = [
      ":handler",
      "../build:default_exe_manifest_win",
      "../compat",
      "../third_party/mini_chromium:base",
      "../tools:tool_support",
    ]

    if (crashpad_is_win) {
      if (crashpad_is_in_chromium || crashpad_is_in_dart) {
        remove_configs = [ "//build/config/win:console" ]
        configs = [ "//build/config/win:windowed" ]
      } else if (crashpad_is_external) {
        remove_configs =
            [ "//../../mini_chromium/mini_chromium/build/config:win_console" ]
        configs =
            [ "//../../mini_chromium/mini_chromium/build/config:win_windowed" ]
      } else {
        remove_configs = [
          "//third_party/mini_chromium/mini_chromium/build/config:win_console",
        ]
        configs = [
          "//third_party/mini_chromium/mini_chromium/build/config:win_windowed",
        ]
      }
    }

    if (crashpad_is_linux) {
      deps += [ "../client:pthread_create" ]
    }
  }
}

# There is not any normal way to package native executables in an Android APK.
# It is normal to package native code as a loadable module but Android's APK
# installer will ignore files not named like a shared object, so give the
# handler executable an acceptable name.
if (crashpad_is_android) {
  copy("crashpad_handler_named_as_so") {
    deps = [ ":crashpad_handler" ]

    sources = [ "$root_out_dir/crashpad_handler" ]

    outputs = [ "$root_out_dir/libcrashpad_handler.so" ]
  }

  crashpad_executable("crashpad_handler_trampoline") {
    output_name = "libcrashpad_handler_trampoline.so"

    sources = [ "linux/handler_trampoline.cc" ]

    deps = [ "../util:no_cfi_icall" ]

    libs = [ "log" ]

    if (crashpad_is_in_chromium) {
      # Chromium's sanitizer runtime libraries do not include an unwinder,
      # so add Chromium's standard dependencies to link against the in-tree
      # libunwind. The coverage wrapper similarly requires an unwinder, as
      # well as a few other bits from libc++abi. There are some issues with pgo
      # as well.
      import("//build/config/compiler/pgo/pgo.gni")
      import("//build/config/coverage/coverage.gni")
      import("//build/config/sanitizers/sanitizers.gni")
      no_default_deps =
          !use_clang_coverage && !using_sanitizer && chrome_pgo_phase != 1
      remove_configs =
          [ "//build/config/android:default_orderfile_instrumentation" ]
    }
  }
}

if (!crashpad_is_ios) {
  crashpad_executable("crashpad_handler_test_extended_handler") {
    testonly = true

    sources = [ "crashpad_handler_test_extended_handler.cc" ]

    deps = [
      ":handler",
      "../build:default_exe_manifest_win",
      "../compat",
      "../minidump:test_support",
      "../third_party/mini_chromium:base",
      "../tools:tool_support",
    ]
  }
}

if (crashpad_is_win) {
  crashpad_executable("crashpad_handler_com") {
    sources = [ "main.cc" ]

    # Avoid .exp, .ilk, and .lib file collisions with crashpad_handler.exe by
    # having this target produce crashpad_handler_com.com. Don’t use this target
    # directly. Instead, use crashpad_handler_console.
    output_extension = "com"

    deps = [
      ":handler",
      "../build:default_exe_manifest_win",
      "../compat",
      "../third_party/mini_chromium:base",
      "../tools:tool_support",
    ]
  }

  copy("crashpad_handler_console") {
    deps = [ ":crashpad_handler_com" ]
    sources = [ "$root_out_dir/crashpad_handler_com.com" ]
    outputs = [ "$root_out_dir/crashpad_handler.com" ]
  }

  crashpad_executable("crash_other_program") {
    testonly = true

    sources = [ "win/crash_other_program.cc" ]

    deps = [
      "../client",
      "../test",
      "../third_party/googletest",
      "../third_party/mini_chromium:base",
    ]
  }

  crashpad_executable("crashy_program") {
    testonly = true

    sources = [ "win/crashy_test_program.cc" ]

    deps = [
      "../client",
      "../third_party/mini_chromium:base",
    ]
  }

  crashpad_executable("crashy_signal") {
    testonly = true

    sources = [ "win/crashy_signal.cc" ]

    cflags = [ "/wd4702" ]  # Unreachable code.

    deps = [
      "../client",
      "../third_party/mini_chromium:base",
    ]
  }

  crashpad_executable("fake_handler_that_crashes_at_startup") {
    testonly = true

    sources = [ "win/fake_handler_that_crashes_at_startup.cc" ]
  }

  crashpad_executable("hanging_program") {
    testonly = true

    sources = [ "win/hanging_program.cc" ]

    deps = [
      "../client",
      "../third_party/mini_chromium:base",
    ]
  }

  crashpad_loadable_module("loader_lock_dll") {
    testonly = true

    sources = [ "win/loader_lock_dll.cc" ]
  }

  crashpad_executable("self_destroying_program") {
    testonly = true

    sources = [ "win/self_destroying_test_program.cc" ]

    deps = [
      "../client",
      "../compat",
      "../snapshot",
      "../third_party/mini_chromium:base",
    ]
  }

  crashpad_executable("heap_corrupting_program") {
    testonly = true

    sources = [ "win/heap_corrupting_program.cc" ]

    deps = [
      "../client",
      "../compat",
      "../snapshot",
      "../third_party/mini_chromium:base",
    ]
  }

  if (current_cpu == "x86") {
    # Cannot create an x64 DLL with embedded debug info.
    crashpad_executable("crashy_z7_loader") {
      testonly = true

      sources = [ "win/crashy_test_z7_loader.cc" ]

      deps = [
        "../client",
        "../test",
        "../third_party/mini_chromium:base",
      ]
    }
  }

  config("enable_cfg") {
    cflags = [ "/guard:cf" ]
    ldflags = [ "/guard:cf" ]
  }
  crashpad_executable("fastfail_program") {
    testonly = true

    sources = [ "win/fastfail_test_program.cc" ]
    configs = [ ":enable_cfg" ]

    deps = [
      "../client",
      "../third_party/mini_chromium:base",
    ]
  }
}
