# Copyright (C) 2017 The Android Open Source Project
#
# 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_overrides/build.gni")
import("wasm_vars.gni")

# Summary of our typical build configurations:

# 1. Standalone builds
#    build_with_chromium = false
#    is_perfetto_build_generator = false
#    perfetto_build_standalone = true
#    perfetto_build_with_android = false
#    perfetto_build_with_embedder = false

# 2. Android tree builds
#    build_with_chromium = false
#    is_perfetto_build_generator = true
#    perfetto_build_standalone = false
#    perfetto_build_with_android = true
#    perfetto_build_with_embedder = false

# 3. Chromium tree builds
#    build_with_chromium = true
#    is_perfetto_build_generator = false
#    perfetto_build_standalone = false
#    perfetto_build_with_android = false
#    perfetto_build_with_embedder = true

# 4. Builds in other embedder trees (e.g. V8 standalone)
#    build_with_chromium = false
#    is_perfetto_build_generator = false
#    perfetto_build_standalone = false
#    perfetto_build_with_android = false
#    perfetto_build_with_embedder = true

# 5. Amalgamated sources (Client library)
#    build_with_chromium = false
#    is_perfetto_build_generator = true
#    perfetto_build_standalone = false
#    perfetto_build_with_android = false
#    perfetto_build_with_embedder = true

# +----------------------------------------------------------------------------+
# | Toolchain / environment related configuration                              |
# +----------------------------------------------------------------------------+
# This section contains a bunch of variables that are related with the toolchain
# and the build environment. Only tools/gen_xxx should customize them.

# Note that |build_with_chromium| is a global convention used by several
# projects, set outside of our control.

# Chromium sets this to true in its //build_overrides/build.gni.
if (!defined(build_with_chromium)) {
  build_with_chromium = false
}

if (!defined(is_nacl)) {
  is_nacl = false
}

if (!defined(is_gcc)) {
  is_gcc = !is_clang && !is_win
}

if (!defined(is_qnx)) {
  is_qnx = false
}

if (!defined(is_freebsd)) {
  is_freebsd = false
}

declare_args() {
  # The Android blueprint file generator set this to true (as well as
  # is_perfetto_build_generator). This is just about being built in the
  # Android tree (AOSP and internal) and is NOT related with the target OS.
  # In standalone Android builds and Chromium Android builds, this is false.
  perfetto_build_with_android = false

  # All the tools/gen_* scripts set this to true. This is mainly used to locate
  # .gni files from //gn rather than //build.
  is_perfetto_build_generator = false

  # This is for override via `gn args` (e.g. for tools/gen_xxx). Embedders
  # based on GN (e.g. v8) should NOT set this and instead directly sets
  # perfetto_build_with_embedder=true in their GN files.
  is_perfetto_embedder = false

  # Comma-separated list of additional CORS origins to allow in trace_processor
  # and websocket_bridge.
  perfetto_http_additional_cors_origins = ""
}

# This can be overridden by embedders (e.g. v8) in their .gn(i) files. This must
# be different from the GN args flag (is_perfetto_embedder) because of the way
# GN works.
if (!defined(perfetto_build_with_embedder)) {
  perfetto_build_with_embedder = build_with_chromium || is_perfetto_embedder
}

# Controls whether the `libperfetto` target bundles the JSON export code in its
# dependencies. Can be overriden by embedders to reduce dependency bloat.
if (!defined(perfetto_libperfetto_includes_json)) {
  perfetto_libperfetto_includes_json = build_with_chromium && !is_nacl
}

perfetto_build_standalone =
    !perfetto_build_with_android && !build_with_chromium &&
    !perfetto_build_with_embedder

# Only relevant for GN builds. Sets the path where perfetto lives. This is //
# for standalone builds and //third_party/perfetto/ in embedders. The embedder
# can override it in its GN files.
if (perfetto_build_standalone || is_perfetto_build_generator) {
  perfetto_root_path = "//"
  import("//gn/standalone/android.gni")  # For android_api_level
  import("//gn/standalone/libc++/libc++.gni")  # For use_custom_libcxx
  import("//gn/standalone/sanitizers/vars.gni")  # For is_fuzzer
  import("//gn/standalone/toolchain/llvm.gni")
} else if (!defined(perfetto_root_path)) {
  perfetto_root_path = "//third_party/perfetto/"
  import("//build/config/android/config.gni")  # For android_api_level
}

# Whether the ftrace producer and the service should be started
# by the integration test or assumed to be running.
# If we're building in the Android tree, we expect that the testing infra
# will start the binaries in the system image before the tests are run.
# In all other cases (i.e. when true), a temporary in-process instance will be
# brought up by our own integrationtest harness.
start_daemons_for_testing = !perfetto_build_with_android

# +----------------------------------------------------------------------------+
# | Tunable build variables for embedders                                      |
# +----------------------------------------------------------------------------+
# The variables in this section allow embedders to enable/disable features
# at the build-system level. This allows to opt-in into the various services
# and tools.

perfetto_force_dlog_default = ""
if (build_with_chromium) {
  perfetto_force_dlog_default = "off"
}

declare_args() {
  # Enables build of platform-wide tracing services (traced, traced_probes)
  # and executables (perfetto_cmd, trigger_perfetto).
  # When disabled, only the client library and other auxiliary tools can be
  # built (for Chromium and other GN embedders).
  # Note that traced_probes is further conditioned by the GN variable
  # enable_perfetto_traced_probes, in the declare_args() section below.
  enable_perfetto_platform_services =
      perfetto_build_standalone || perfetto_build_with_android

  # Allow the embedder to use the IPC layer. In turn this allows to use the
  # system backend in the client library.
  # This includes building things that rely on POSIX sockets, this places
  # limitations on the supported operating systems.
  # For now the IPC layer is conservatively not enabled on Chromium+Windows
  # builds.
  enable_perfetto_ipc =
      !is_nacl && (perfetto_build_standalone || perfetto_build_with_android ||
                   (build_with_chromium && !is_win) || is_fuchsia)

  # Makes the heap profiling daemon target reachable. It works only on Android,
  # but is built on Linux as well for test/compiler coverage.
  # On Android, it requires API level 26 due to libunwindstack.
  enable_perfetto_heapprofd =
      perfetto_build_with_android ||
      (perfetto_build_standalone && is_clang &&
       (is_linux || (is_android && android_api_level >= 26)))

  # Build the perf event profiler (traced_perf).
  # TODO(rsavitski): figure out how to make the android-core dependencies build
  # under gcc (_Atomic and other issues).
  enable_perfetto_traced_perf =
      perfetto_build_with_android ||
      (perfetto_build_standalone && is_clang &&
       (is_linux || (is_android && android_api_level >= 29)))

  # The Trace Processor: offline analytical engine to process traces and compute
  # metrics using a SQL engine.
  if (!defined(enable_perfetto_trace_processor)) {
    enable_perfetto_trace_processor =
        perfetto_build_standalone || build_with_chromium ||
        is_perfetto_build_generator
  }

  # Enables base::Watchdog. Is supported only on Linux-based platforms in
  # standalone GN builds (NOT in bazel/blaze).
  # gn/BUILD.gn further restricts this to OS_LINUX || OS_ANDROID when generating
  # the perfetto_build_flags.h header.
  enable_perfetto_watchdog =
      perfetto_build_with_android ||
      (perfetto_build_standalone && !is_perfetto_build_generator)

  # Misc host executable under tools/.
  enable_perfetto_tools =
      perfetto_build_standalone || perfetto_build_with_android

  enable_perfetto_unittests = perfetto_build_standalone ||
                              build_with_chromium || perfetto_build_with_android

  enable_perfetto_integration_tests =
      perfetto_build_standalone || perfetto_build_with_android

  enable_perfetto_android_java_sdk =
      perfetto_build_with_android || (is_android && perfetto_build_standalone)

  enable_perfetto_benchmarks = perfetto_build_standalone && !is_win && !is_qnx

  enable_perfetto_fuzzers =
      perfetto_build_standalone && defined(is_fuzzer) && is_fuzzer

  # Enables the write_version_header.py tool that generates a .h that contains a
  # macro with the current git revision and latest release version from
  # CHANGELOG. If false base/version.h will return "unknown".
  enable_perfetto_version_gen =
      perfetto_build_standalone || is_perfetto_build_generator ||
      perfetto_build_with_android

  # Only for local development. When true the binaries (perfetto, traced, ...)
  # are monolithic and don't use a common shared library. This is mainly to
  # avoid LD_LIBRARY_PATH dances when testing locally.
  # On Windows we default to monolithic executables, because pairing
  # dllexport/import adds extra complexity for little benefit. Te only reason
  # for monolithic_binaries=false is saving binary size, which matters mainly on
  # Android. See also comments on PERFETTO_EXPORT_ENTRYPOINT in compiler.h.
  monolithic_binaries =
      !perfetto_build_with_android && (is_win || is_mac || is_freebsd)

  # Whether DLOG should be enabled on debug builds (""), all builds ("on"), or
  # none ("off"). We disable it by default for embedders to avoid spamming their
  # console.
  perfetto_force_dlog = perfetto_force_dlog_default

  # Whether DCHECKs should be enabled or not. Values: "on" | "off" | "".
  # By default ("") DCHECKs are enabled only:
  # - If DCHECK_ALWAYS_ON is defined (which is mainly a Chromium-ism).
  # - On debug builds (i.e. if NDEBUG is NOT defined) but only in Chromium,
  #   Android and standalone builds.
  # - On all other builds (e.g., SDK) it's off regardless of NDEBUG (unless
  #   DCHECK_ALWAYS_ON is defined).
  # See base/logging.h for the implementation of all this.
  perfetto_force_dcheck = ""

  # Installs a signal handler for the most common crash signals which unwinds
  # the stack and prints the stack trace on stderr. Requires a dependency on
  # libbacktrace when enabled.
  enable_perfetto_stderr_crash_dump =
      is_debug && perfetto_build_standalone && !is_wasm && !is_win && !is_qnx

  # Enables more aggressive compiler flags that assume recent Intel CPUs.
  # Runtime checks during initialization will print an error message and exit
  # if the CPU doesn't support those flags.
  # Don't enable by default for MacOS. Old Intel Macs as used in CIs
  # etc don't have the fancy CPU instructions (i.e. AVX2) this implies.
  enable_perfetto_x64_cpu_opt =
      current_cpu == "x64" && is_linux && !is_wasm &&
      perfetto_build_standalone && !is_perfetto_build_generator

  # Enables complie-time thread safety analysis.
  perfetto_thread_safety_annotations =
      perfetto_build_standalone && !is_perfetto_build_generator &&
      defined(use_custom_libcxx) && use_custom_libcxx

  # Enables the use of priority-inheritance mutexes via PTHREAD_PRIO_INHERIT
  # or wrapper around PI Futexes (dependant on OS).
  # Note that on Android platform (non-standalone) builds this flag is ignored.
  # "use_rt_mutex", "use_rt_futex" are used instead (see perfetto_flags.aconfig)
  # This is disabled in chromium, because the BPF-sandbox allows PI-futex only
  # when a field-trial is enabled, which is incompatible with a build time flag.
  enable_perfetto_rt_mutex =
      !is_wasm && (perfetto_build_standalone || is_perfetto_build_generator) &&
      !build_with_chromium

  # This flag enables the use of inotify on AF_UNIX sockets to re-connect when
  # the server disconnects. Disabled in chromium as inotify is not allowed by
  # Chrome's seccomp sandbox (b/470556120).
  # On Android platform (non-standalone) builds this flag is ignored. The flag
  # "use_unix_socket_inotify" is used instead (see perfetto_flags.aconfig).
  enable_perfetto_sock_inotify =
      !is_wasm && (perfetto_build_standalone || is_perfetto_build_generator) &&
      !build_with_chromium

  # This flag is used for the migration of UnixTaskRunner -> LockFreeTaskRunner.
  # It determines whether MaybeLockFreeTaskRunner is backed by UnixTaskRunner
  # or the newer LockFreeTaskRunner.
  # UnixTaskRunner is the battle-tested original TaskRunner implementaiton used
  # from 2017 -> 2025. LockFreeTaskRunner is the new improved TaskRunner which
  # is planning to sunset UnixTaskRunner.
  # Note that on Android platform (non-standalone) builds this flag is ignored
  # and the Android flag "use_lockfree_taskrunner" is used instead (see
  # perfetto_flags.aconfig)
  enable_perfetto_lockfree_taskrunner = true
}

declare_args() {
  # When false, it disables system backend consumer support in the Perfetto SDK.
  # Saves ~300KB binary size.
  if (!defined(enable_perfetto_system_consumer)) {
    enable_perfetto_system_consumer = enable_perfetto_ipc
  }
}

declare_args() {
  perfetto_enable_git_rev_version_header =
      enable_perfetto_version_gen && perfetto_build_standalone &&
      !is_perfetto_build_generator

  # The traced_probes daemon is very Linux-specific, as it depends on ftrace and
  # various /proc interfaces. There is no point making its code platform-neutral
  # as it won't do anything useful on Windows or QNX.
  # The only reason why we still build it on Mac OS is to be able to run the
  # unittests there and making dev on mac less cumbersome. The traced_probes
  # code happens to build cleanly and for now the mainteinance cost on Mac is
  # extremely low.
  enable_perfetto_traced_probes =
      enable_perfetto_platform_services && !is_win && !is_qnx

  # The relay service is enabled when platform services are enabled.
  # TODO(chinglinyu) check if we can enable on Windows.
  enable_perfetto_traced_relay = enable_perfetto_platform_services && !is_win

  # Whether info-level logging is enabled.
  perfetto_verbose_logs_enabled =
      !build_with_chromium || perfetto_force_dlog == "on"

  # Enables the SQL query layer of trace processor.
  enable_perfetto_trace_processor_sqlite =
      enable_perfetto_trace_processor &&
      (build_with_chromium || !perfetto_build_with_embedder)

  # Enables the optional SQLite percentile module.
  enable_perfetto_trace_processor_percentile =
      enable_perfetto_trace_processor &&
      (perfetto_build_standalone || perfetto_build_with_android)

  # Enables the REPL interactive prompt in the trace processor.
  enable_perfetto_trace_processor_linenoise =
      perfetto_build_standalone && enable_perfetto_trace_processor &&
      (is_linux || is_android || is_mac)

  # Enables JSON support in the trace processor. Required for JSON trace import
  # and export.
  enable_perfetto_trace_processor_json =
      enable_perfetto_trace_processor && !perfetto_build_with_android

  # Enables the support for importing profiles from the MacOS Instruments app.
  # Requires a dependency on libexpat for XML parsing.
  # Disabled in chromium due to some fuzzer related build failure (b/363347029).
  enable_perfetto_trace_processor_mac_instruments =
      enable_perfetto_trace_processor &&
      (perfetto_build_standalone || perfetto_build_with_android) &&
      !is_perfetto_build_generator

  # Enables httpd RPC support in the trace processor.
  # Further per-OS conditionals are applied in gn/BUILD.gn.
  # Chromium+Win: httpd support depends on enable_perfetto_ipc, which is not
  # enabled on Chromium+Win for now (see a comment there).
  enable_perfetto_trace_processor_httpd =
      enable_perfetto_trace_processor &&
      (perfetto_build_standalone || perfetto_build_with_android ||
       (build_with_chromium && !is_win))

  # Enables Zlib support. This is used to compress traces (by the tracing
  # service and by the "perfetto" cmdline client) and to decompress traces (by
  # trace_processor).
  enable_perfetto_zlib =
      enable_perfetto_trace_processor || enable_perfetto_platform_services

  # Enables function name demangling using sources from llvm. Otherwise
  # trace_processor falls back onto using the c++ runtime demangler, which
  # typically handles only itanium mangling.
  # llvm-demangle is incompatible with GCC and can be used only when building
  # with clang.
  enable_perfetto_llvm_demangle =
      is_clang && enable_perfetto_trace_processor && perfetto_build_standalone

  # Enables gRPC in the Perfetto codebase. gRPC significantly increases build
  # times and the general footprint of Perfetto. As it only required for
  # BigTrace and even then only to build the final ready-to-ship binary, don't
  # enable this by default.
  enable_perfetto_grpc = false

  # Enables the ETM importer in trace_processor. This feature is experimental at
  # this point and it requires extra libraries so we only enable it in selected
  # builds.
  enable_perfetto_etm_importer =
      is_linux && enable_perfetto_trace_processor &&
      perfetto_build_standalone && !is_perfetto_build_generator

  # Enables the use of the LLVM symbolizer in trace_processor.
  enable_perfetto_llvm_symbolizer = false

  # Enables Winscope features in trace_processor. These are used by the
  # standalone Winscope tool, Android prebuilts, and trace extractor metrics.
  enable_perfetto_winscope =
      enable_perfetto_trace_processor &&
      (perfetto_build_standalone || is_perfetto_build_generator)
}

declare_args() {
  # Enables the traceconv tool.
  enable_perfetto_traceconv =
      enable_perfetto_tools && enable_perfetto_trace_processor_sqlite

  # Allows to build the UI (TypeScript/ HTML / WASM)
  enable_perfetto_ui =
      perfetto_build_standalone && enable_perfetto_trace_processor_sqlite &&
      host_os != "win"

  # Allows to build the perfetto.dev website.
  # WARNING: if this flag is enabled, the build performs globbing at generation
  # time. Incremental builds that add/remove files will not be supported without
  # rerunning gn.
  enable_perfetto_site = false

  # Check that the merged perfetto_trace.proto can be translated to a C++ lite
  # proto and compiled. This is disabled by default because it's expensive (it
  # can take a couple of minutes).
  enable_perfetto_merged_protos_check = false

  # Skip buildtools dependency checks (needed for ChromeOS).
  skip_buildtools_check = false

  # Used by CrOS builds. Uses pkg-config to determine the appropriate flags
  # for including and linking system libraries.
  #   set `host_pkg_config` to the `BUILD_PKG_CONFIG` and
  #   set `pkg_config` to the target `PKG_CONFIG`.
  # Note: that if this is enabled `perfetto_use_system_protobuf` should be also.
  perfetto_use_pkgconfig = false

  # Used by CrOS system builds. Uses the system version of protobuf
  # from /usr/include instead of the hermetic one.
  perfetto_use_system_protobuf = false

  # Used by CrOS system builds. Uses the system version of sqlite
  # from /usr/include instead of the hermetic one.
  perfetto_use_system_sqlite = false

  perfetto_use_system_zlib = false
}

if (is_win) {
  # clang-cl
  perfetto_isystem_cflag = "/I"
} else {
  perfetto_isystem_cflag = "-isystem"
}

# +---------------------------------------------------------------------------+
# | Cross-checks                                                              |
# +---------------------------------------------------------------------------+

# Exactly one between build_with_android, build_standalone and
# build_with_embedder must be true.
assert(perfetto_build_standalone || perfetto_build_with_android ||
       perfetto_build_with_embedder)
assert(!(perfetto_build_with_android && perfetto_build_standalone))
assert(!(perfetto_build_with_embedder && perfetto_build_standalone))
assert(!(perfetto_build_with_android && perfetto_build_with_embedder))

# If |build_with_chromium| is true then also |perfetto_build_with_embedder|
# must be true
assert(!build_with_chromium || perfetto_build_with_embedder)

# If |perfetto_build_with_android| is true then also
# |is_perfetto_build_generator| must be true.
assert(!perfetto_build_with_android || is_perfetto_build_generator)

# We should never end up in a state where is_perfetto_embedder=true but
# perfetto_build_with_embedder=false.
assert(!is_perfetto_embedder || perfetto_build_with_embedder)

# The monolithic binaries is not supported when building in the Android tree.
assert(!monolithic_binaries || !perfetto_build_with_android)

# Watchdog must be on in Android builds.
assert(enable_perfetto_watchdog || !perfetto_build_with_android)

assert(perfetto_force_dlog == "" || perfetto_force_dlog == "on" ||
       perfetto_force_dlog == "off")

# If enable_perfetto_traced_probes is set, enable_perfetto_platform_services
# must be set as well. Doesn't make sense to build traced_probes without the
# rest. traced_probes integration tests depend on traced.
assert(!enable_perfetto_traced_probes || enable_perfetto_platform_services)

# |perfetto_use_pkgconfig| changes the behavior of
# |perfetto_use_system_protobuf|, so if perfetto_use_pkgconfig is set,
# |perfetto_use_system_protobuf| must be set.
assert(!perfetto_use_pkgconfig || perfetto_use_system_protobuf,
       "perfetto_use_pkgconfig requires perfetto_use_system_protobuf")

# enable_perfetto_llvm_symbolizer is not compatible with use_custom_libcxx
# because the former dynamically links to system llvm which is compiled using
# libstdc++ which makes it incompatible with building using libcxx.
assert(
    !enable_perfetto_llvm_symbolizer || !use_custom_libcxx,
    "enable_perfetto_llvm_symbolizer and use_custom_libcxx are mutually exclusive. If you are seeing this error then you have set enable_perfetto_llvm_symbolizer=true and must set use_custom_libcxx=false to use llvm_symbolizer.")
