##
##  Workarounds for bugs and temporary things
##

try-import .bazelrc.local
startup --host_jvm_args=-Xmx3072m # we need at least 3G to reliably build, the default is to use 1/4 of memory, which makes flaky on 8G boxes

# enable https://github.com/google/googletest/pull/1653
common:build --define absl=1
common:test --test_env=GTEST_INSTALL_FAILURE_SIGNAL_HANDLER=1

# With rules_cc 0.2.14 and Abseil 20240722.0, Abseil fails to build
# if module_maps are enabled:
# $ ./bazel build @@com_google_absl//absl/types:bad_variant_access --config=dbg
# ERROR <..> undeclared inclusion(s) in rule <..>
#  'bazel-out/k8-dbg/bin/external/com_google_absl/absl/base/core_headers.cppmap'
#  <other cppmap files>
build --host_features=-module_maps --features=-module_maps

# Port over all dependencies to use Bzlmod. Until then, disable it,
# as enabling it pulls in the module version of dependencies such
# as @@zlib~. By default, @@zlib~ doesn't build; we need to pass in
# in flags to disable warnings to make the code build.
common --enable_bzlmod=false

##
##  Common build options across all build configurations
##

# Enable strict_action_env flag to. For more information on this feature see
# https://groups.google.com/forum/#!topic/bazel-discuss/_VmRfMyyHBk.
# This will be the new default behavior at some point (and the flag was flipped
# shortly in 0.21.0 - https://github.com/bazelbuild/bazel/issues/7026). Remove
# this flag here once flipped in Bazel again.
build --incompatible_strict_action_env

# C / C++ Options
# Don't depend on system compiler
build --cxxopt=-std=c++20 --host_cxxopt=-std=c++20

build --copt=-fno-omit-frame-pointer

build --copt=-fstack-protector

build --copt=-Werror --copt=-Wimplicit-fallthrough --copt=-Wmissing-field-initializers

build --copt=-D_LIBCPP_ENABLE_NODISCARD

build --host_copt=-O1
build --host_copt=-DFORCE_DEBUG
build --host_cxxopt=-Wno-unused-variable --host_cxxopt=-Wno-overloaded-virtual --host_cxxopt=-Wno-unused-const-variable # ragel violates those and we want a silent build
build --host_cxxopt=-Wno-pass-failed # host build doesn't have enough optimizations enabled for clang to vectorize this loop reliably

# The MacOS CROSSTOOL in bazel defines _FORTIFY_SOURCE both on
# <command line>:1:9: and <built-in>:355:9: so sadly we turn them all off
build --copt=-Wno-macro-redefined

build --host_cxxopt=-Wno-deprecated-anon-enum-enum-conversion
build --host_cxxopt=-Wno-deprecated-enum-enum-conversion
build --cxxopt=-Wno-deprecated-anon-enum-enum-conversion
build --cxxopt=-Wno-deprecated-enum-enum-conversion
build --cxxopt=-Wno-ambiguous-reversed-operator

# TODO(jez) Something between Clang 12 and Clang 15 seems to have introduced a
# warning saying _never_ use unqualified `std` calls...
build --cxxopt=-Wno-unqualified-std-cast-call --host_cxxopt=-Wno-unqualified-std-cast-call

##
## debug configuration
##
build:dbg --copt=-O0
build:dbg --compilation_mode=dbg
build:dbg --config=debugsymbols
# As of Bazel 7, cached files are not put into the `bazel-bin/` folder unless they're toplevel targets.
# We want to force files to be downloaded because otherwise clangd won't find them (and possibly lldb, though I haven't checked)
# TODO(jez) Do newer compile commands generators suffer from this problem? The one we use is archived
build:dbg --remote_download_outputs=all

build:rubydbg --copt=-DRUBY_DEBUG --copt=-DVM_CHECK_MODE=1 --copt=-DTRANSIENT_HEAP_CHECK_MODE --copt=-DRGENGC_CHECK_MODE --copt=-DENC_DEBUG

build:coverage --config=forcedebug
build:coverage --cxxopt=-Wno-pass-failed # coverage build fails vectorization
test:coverage --spawn_strategy=local

build --define=versioned=false
build:versioned --workspace_status_command=tools/buildstamp/get_workspace_status --stamp --define=versioned=true

build:dbg-darwin --config=dbg --platforms=@//tools/platforms:darwin_x86_64
build:dbg-linux --config=dbg --platforms=@//tools/platforms:linux_x86_64

##
## Configurations used for releases
##
# release version: optimized, with debug symbols and version information
build:release-common --define release=true
build:release-common --compilation_mode=opt
build:release-common --config=backtracesymbols
build:release-common --config=versioned

build:release-debug-common --config=forcedebug
build:release-debug-common --config=debugsymbols
build:release-debug-common --config=skipslowenforce

# This mode has been added to allow tracking the symbols
# which are to blame for usages of untyped code in a codebase.
# This allows identifying what symbols would be the highest impact
# to type.
#
# Earlier, we allowed for such statistic collection only in DEBUG mode
# However, that was far too slow for our purposes. Thus, this mode allows
# you to build in release mode and track these statistics.
build:untyped-blame --copt=-DTRACK_UNTYPED_BLAME_MODE

# harden: mark relocation sections read-only
build:release-linux --linkopt=-Wl,-z,relro,-z,now
build:release-linux --config=lto-linux --config=release-common
build:release-linux --config=static-libs
# Separate config for aarch64, so x86_64 can be differently optimized
build:release-linux-aarch64 --linkopt=-Wl,-z,relro,-z,now
build:release-linux-aarch64 --config=lto-linux --config=release-common
build:release-linux-aarch64 --config=static-libs

# It would be nice to move this back to release-common, but there is a build
# failure when using clang 15 on macOS to build GNU make via rules_foreign_cc:
# <https://github.com/bazelbuild/rules_foreign_cc/issues/1186>
# We only use rules_foreign_cc for mimalloc and we only use mimalloc in release
# builds, so I'm moving this here until we can figure out a better workaround,
# or a fix lands upstream.
build:release-linux --define mimalloc=true
build:release-linux-aarch64 --define mimalloc=true

# This is to turn on vector instructions where available.
# We used to do this unconditionally, but Rosetta 2 doesn't translate all vector instructions well.
#
# If we ever start making universal x86-64 + aarch64 binaries for macOS, we
# could think about re-enabling the vector instructions for x86-64.
#
# At Stripe: developer laptops run skylake, devboxes run skylake-avx512
# however some AWS instances in our fleet still run Sandy Bridge (Skylake predecessor), as of 2018.
build:release-linux                   --copt=-march=sandybridge
build:release-linux-aarch64           --copt=-march=armv8.1a
build:release-sanitized-linux         --copt=-march=sandybridge
build:release-sanitized-linux-aarch64 --copt=-march=armv8.1a

build:release-mac --config=release-common --config=shared-libs

build:cross-to-darwin-x86_64 --platforms=@//tools/platforms:darwin_x86_64
build:cross-to-darwin-x86_64 --extra_toolchains=@llvm_toolchain_15_0_7//:cc-toolchain-x86_64-darwin
build:cross-to-darwin-x86_64 --copt=-stdlib=libc++ --linkopt=-lc++

build:cross-to-darwin-arm64 --platforms=@//tools/platforms:darwin_arm64
build:cross-to-darwin-arm64 --extra_toolchains=@llvm_toolchain_15_0_7//:cc-toolchain-aarch64-darwin
build:cross-to-darwin-arm64 --copt=-stdlib=libc++ --linkopt=-lc++

build:release-debug-linux --config=release-linux
build:release-debug-linux --config=release-debug-common

build:release-debug-linux-aarch64 --config=release-linux-aarch64
build:release-debug-linux-aarch64 --config=release-debug-common

build:release-debug-mac --config=release-mac
build:release-debug-mac --config=release-debug-common

build:release-sanitized-linux --copt=-O2
build:release-sanitized-linux --config=sanitize-linux
build:release-sanitized-linux --define jemalloc=false
build:release-sanitized-linux --config=release-debug-common

build:release-sanitized-linux-aarch64 --copt=-O2
build:release-sanitized-linux-aarch64 --config=sanitize-linux-aarch64
build:release-sanitized-linux-aarch64 --define jemalloc=false
build:release-sanitized-linux-aarch64 --config=release-debug-common

build:release-sanitized-mac --copt=-O2
build:release-sanitized-mac --config=sanitize-mac
build:release-sanitized-mac --define jemalloc=false

##
## Configuration used to to as much testing as possible in CI
##
build:test-sanitized-linux --config=release-sanitized-linux --config=dbg --nostamp --define release=false
common:test-sanitized-linux --test_env="UBSAN_OPTIONS=print_stacktrace=1"
common:test-sanitized-linux --test_env="ASAN_OPTIONS=detect_leaks=0"

build:test-sanitized-linux-aarch64 --config=release-sanitized-linux-aarch64 --config=dbg --nostamp --define release=false
common:test-sanitized-linux-aarch64 --test_env="UBSAN_OPTIONS=print_stacktrace=1"
common:test-sanitized-linux-aarch64 --test_env="ASAN_OPTIONS=detect_leaks=0"

build:test-sanitized-mac --config=release-sanitized-mac --config=dbg --nostamp --define release=false
common:test-sanitized-mac --test_env="UBSAN_OPTIONS=print_stacktrace=1"

build:reduce-intermediate-file-size-base --copt=-g0 --linkopt=-g0 # used by buildfarm to have less debug information on disk
build:reduce-intermediate-file-size-base --strip=always
build:reduce-intermediate-file-size-base --copt=-fno-standalone-debug --linkopt=-fno-standalone-debug # used by buildfarm to have less debug information on disk

# extend reduce-intermediate-file-size with -Os
build:buildfarm --copt=-Os --linkopt=-Os --config=reduce-intermediate-file-size-base
test:buildfarm --test_output=errors

build:buildfarm-sanitized-linux --config=test-sanitized-linux --config=buildfarm
build:buildfarm-sanitized-linux-aarch64 --config=test-sanitized-linux-aarch64 --config=buildfarm
build:buildfarm-sanitized-mac --config=test-sanitized-mac --config=buildfarm --config=shared-libs

##
## Shared fragments of configuration
##

# DEBUG_MODE is set by default for all builds except --config=release.
# Use this flag to set DEBUG_MODE even for --config=release.
build:forcedebug --copt=-DFORCE_DEBUG

# DEBUG_MODE controls whether ENFORCEs are enabled.  Some ENFORCEs are super
# slow and/or don't pass on Stripe's codebase.  Long term we should definitely
# make these checks pass and maybe even make them fast, but for now we provide
# a way to skip slow debug checks (for example, when compiling debug release
# builds)
build:skipslowenforce --copt=-DSKIP_SLOW_ENFORCE

# LTO build. Much longer compilation time. Smaller size and better perf.
build:lto --copt=-flto=thin
build:lto --linkopt=-flto=thin
build:lto --config=static-libs

## flags that substantially increase Clang&LLVMs ability to devirtualize calls
build:lto-linux --linkopt=-Wl,--icf=all

# Improves linking time on arm64 hosts
build:lto-linux --linkopt=-Wl,--thinlto-jobs=all
build:lto-linux --config=lto

# By default, we make static builds, but we can also use dynamic linking if asked to.
# Note that dynamic linking is not fully supported by some of our toolchains and thus it may not always work.
build --define=linkshared=false

build:shared-libs --define=linkshared=true --copt=-fPIC --linkopt=-fPIC

build:static-libs --define=linkshared=false --copt=-fno-PIC --linkopt=-fno-PIC
build:static-libs --linkopt=-fno-pie --copt=-fno-pie

# It's useful to be able to write `config_setting` rules for "this is
# an unsanitized build", but we can't express "copt does not contain
# -fsanitize". So we set this `--define` and unset it if we're using a
# sanitizer.
build --define unsanitized=true
# sanitize build: run with ASAN and UBSAN. Catches most memory and
# undefined-behavior errors, substantially larger and slower binary.
build:sanitize --config=asan --config=ubsan

build:asan --copt=-fsanitize=address --copt=-fsanitize-address-use-after-scope
build:asan --linkopt=-fsanitize=address --linkopt=-fsanitize-address-use-after-scope
build:asan --copt=-DADDRESS_SANITIZER # used by abseil
build:asan --copt=-DHAS_SANITIZER
build:asan --define unsanitized=false

build:ubsan --copt=-fsanitize=undefined --copt=-fno-sanitize-recover=undefined
build:ubsan --linkopt=-fsanitize=undefined --copt=-fno-sanitize-recover=undefined
build:ubsan --define unsanitized=false
build:ubsan --copt=-DHAS_SANITIZER

# TODO(jez) It's not clear whether we still need these tricks to get sanitizers to work,
# because we're using the toolchain's lld linker now.
# We could consider replacing this with something more typical.
# Original motivation: Bazel links C++ files with $CC, not $CXX, this breaks UBSan
build:sanitize-linux --linkopt=../../external/llvm_toolchain_15_0_7_llvm/lib/clang/15.0.7/lib/x86_64-unknown-linux-gnu/libclang_rt.asan_cxx.a
build:sanitize-linux --linkopt=../../external/llvm_toolchain_15_0_7_llvm/lib/clang/15.0.7/lib/x86_64-unknown-linux-gnu/libclang_rt.ubsan_standalone_cxx.a
build:sanitize-linux --linkopt=../../external/llvm_toolchain_15_0_7_llvm/lib/clang/15.0.7/lib/x86_64-unknown-linux-gnu/libclang_rt.ubsan_standalone.a
build:sanitize-linux --config=sanitize

build:sanitize-linux-aarch64 --linkopt=../../external/llvm_toolchain_15_0_7_llvm/lib/clang/15.0.7/lib/aarch64-unknown-linux-gnu/libclang_rt.asan_cxx.a
build:sanitize-linux-aarch64 --linkopt=../../external/llvm_toolchain_15_0_7_llvm/lib/clang/15.0.7/lib/aarch64-unknown-linux-gnu/libclang_rt.ubsan_standalone_cxx.a
build:sanitize-linux-aarch64 --linkopt=../../external/llvm_toolchain_15_0_7_llvm/lib/clang/15.0.7/lib/aarch64-unknown-linux-gnu/libclang_rt.ubsan_standalone.a
build:sanitize-linux-aarch64 --config=sanitize

build:sanitize-mac --config=sanitize

build:tsan --copt=-fsanitize=thread
build:tsan --linkopt=-fsanitize=thread

# Build optimized for executable size. Can be faster if size of executable code is a bottleneck.
build:size --linkopt=-Os --config=lto
build:size --copt=-Os --config=lto

### Debug symbols on OS X. ###
# From https://github.com/RobotLocomotion/drake/blob/master/tools/cc_toolchain/bazel.rc
# See https://github.com/bazelbuild/bazel/issues/2537
build:debugsymbols --copt=-g3 --copt=-fstandalone-debug --copt=-DDEBUG_SYMBOLS --copt=-glldb
build:debugsymbols --linkopt=-g3 --linkopt=-fstandalone-debug --linkopt=-DDEBUG_SYMBOLS --linkopt=-glldb
build:debugsymbols --spawn_strategy=local
build:debugsymbols --genrule_strategy=local

# simpler & smaller debug symbols. Good enough for backtraces, but not for debugging.
build:backtracesymbols --copt=-DDEBUG_SYMBOLS --copt=-gline-tables-only
build:backtracesymbols --linkopt=-DDEBUG_SYMBOLS --linkopt=-gline-tables-only
build:backtracesymbols --spawn_strategy=local
build:backtracesymbols --genrule_strategy=local

build --strip=never

##
## Fuzzing
##
build:fuzz --copt=-fsanitize=fuzzer --linkopt=-fsanitize=fuzzer --config=asan
build:fuzz --config=forcedebug --config=debugsymbols
build:fuzz --copt=-DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION

##
## Webasm config. Please use either of those depending on your platform
##
build:webasm --copt=-DMDB_USE_ROBUST=0
build:webasm --define release=true
build:webasm --compilation_mode=opt
# https://emscripten.org/docs/porting/exceptions.html#webassembly-exception-handling-based-support
build:webasm --features=exceptions --cxxopt=-fwasm-exceptions --linkopt=-fwasm-exceptions
# Blocked on https://github.com/emscripten-core/emscripten/issues/9780
build:webasm --copt=-fno-stack-protector
# We put the stack first, so that an argument stack overflow doesn't clobber
# global data, and traps instead.
build:webasm --linkopt=--stack-first

##
## Stripe's ci passes --config=ci, we need it to exist
##
common:stripeci --config=ci
common:ci --color yes


# enables a lot of features in mac instruments profiler
build:instruments --linkopt=-framework --linkopt=CoreFoundation

# clang-tidy via bazel_clang_tidy aspect
build:clang-tidy --aspects @bazel_clang_tidy//clang_tidy:clang_tidy.bzl%clang_tidy_aspect
build:clang-tidy --output_groups=report
build:clang-tidy --@bazel_clang_tidy//:clang_tidy_config=//:clang_tidy_config
build:clang-tidy --@bazel_clang_tidy//:clang_tidy_executable=//tools/clang_tidy
