diff --git a/.ci/Debian12/Dockerfile b/.ci/Debian12/Dockerfile index 4da910dc0..14c6f018c 100644 --- a/.ci/Debian12/Dockerfile +++ b/.ci/Debian12/Dockerfile @@ -3,13 +3,11 @@ FROM debian:12 RUN apt-get update && \ DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \ build-essential \ - ca-certificates \ ccache \ cmake \ file \ g++ \ git \ - libcurl4-openssl-dev \ libgl-dev \ liblzma-dev \ libmariadb-dev-compat \ diff --git a/.ci/Debian13/Dockerfile b/.ci/Debian13/Dockerfile index 94f711398..b597307c5 100644 --- a/.ci/Debian13/Dockerfile +++ b/.ci/Debian13/Dockerfile @@ -9,7 +9,6 @@ RUN apt-get update && \ file \ g++ \ git \ - libcurl4-openssl-dev \ libgl-dev \ liblzma-dev \ libmariadb-dev-compat \ diff --git a/.ci/Fedora43/Dockerfile b/.ci/Fedora43/Dockerfile index 8aa345651..463da5a51 100644 --- a/.ci/Fedora43/Dockerfile +++ b/.ci/Fedora43/Dockerfile @@ -1,12 +1,10 @@ FROM fedora:43 RUN dnf install -y \ - ca-certificates \ ccache \ cmake \ gcc-c++ \ git \ - libcurl-devel \ mariadb-devel \ ninja-build \ openssl-devel \ diff --git a/.ci/Fedora44/Dockerfile b/.ci/Fedora44/Dockerfile index 15204fa1a..62238e760 100644 --- a/.ci/Fedora44/Dockerfile +++ b/.ci/Fedora44/Dockerfile @@ -1,12 +1,10 @@ FROM fedora:44 RUN dnf install -y \ - ca-certificates \ ccache \ cmake \ gcc-c++ \ git \ - libcurl-devel \ mariadb-devel \ ninja-build \ openssl-devel \ diff --git a/.ci/Ubuntu24.04/Dockerfile b/.ci/Ubuntu24.04/Dockerfile index 43497dd3b..b9fb2b701 100644 --- a/.ci/Ubuntu24.04/Dockerfile +++ b/.ci/Ubuntu24.04/Dockerfile @@ -3,13 +3,11 @@ FROM ubuntu:24.04 RUN apt-get update && \ DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \ build-essential \ - ca-certificates \ ccache \ cmake \ file \ g++ \ git \ - libcurl4-openssl-dev \ libgl-dev \ liblzma-dev \ libmariadb-dev-compat \ diff --git a/.ci/Ubuntu26.04/Dockerfile b/.ci/Ubuntu26.04/Dockerfile index 4dc861ae9..cc6528858 100644 --- a/.ci/Ubuntu26.04/Dockerfile +++ b/.ci/Ubuntu26.04/Dockerfile @@ -10,7 +10,6 @@ RUN apt-get update && \ g++ \ gcovr \ git \ - libcurl4-openssl-dev \ libgl-dev \ liblzma-dev \ libmariadb-dev-compat \ diff --git a/.ci/compile.sh b/.ci/compile.sh index 63c027473..6789b9817 100755 --- a/.ci/compile.sh +++ b/.ci/compile.sh @@ -200,20 +200,6 @@ if [[ $USE_VCPKG ]]; then flags+=("-DUSE_VCPKG=1") flags+=("-DVCPKG_INSTALL_OPTIONS=--x-abi-tools-use-exact-versions") fi -if [[ ${WITH_CRASH_REPORTING:-} == "ON" ]]; then - # Release CI opts into the sentry-native SDK (default is OFF so from-source, distro and - # offline package builds never fetch it). Debug builds stay SDK-free so crashes from - # developer builds never reach Sentry. - flags+=("-DWITH_CRASH_REPORTING=ON") -fi -if [[ ${BUILDTYPE:-Release} == "Release" && -n ${COCKATRICE_SENTRY_DSN:-} ]]; then - # Release-only: Debug builds stay DSN-free so crashes from developer builds - # never reach Sentry. Empty (local builds, forks without the secret, and non-tag - # CI builds, which never receive the secret) keeps today's mock fallback via the - # compiled-in default. CI passes the value from the SENTRY_DSN secret on tag - # Release builds only, so pre-release test artifacts never report to Sentry. - flags+=("-DCOCKATRICE_SENTRY_DSN=$COCKATRICE_SENTRY_DSN") -fi # Add cmake --build flags buildflags=(--config "$BUILDTYPE") diff --git a/.ci/docker.sh b/.ci/docker.sh index 64ea6baa7..412ad6a1d 100644 --- a/.ci/docker.sh +++ b/.ci/docker.sh @@ -175,12 +175,6 @@ function RUN () args+=(--mount "type=bind,source=$GITHUB_OUTPUT,target=/gh_output") args+=(--env "GITHUB_OUTPUT=/gh_output") fi - # The container does not inherit host env vars: without this, WITH_CRASH_REPORTING=ON set in - # the workflow never reaches compile.sh inside the container, so the Linux packages silently - # build with crash reporting OFF while the libcurl packages in the Dockerfiles go unused. - if [[ ${WITH_CRASH_REPORTING:-} ]]; then - args+=(--env "WITH_CRASH_REPORTING=${WITH_CRASH_REPORTING}") - fi # shellcheck disable=2086 docker run "${args[@]}" $RUN_ARGS "$IMAGE_NAME" bash "$BUILD_SCRIPT" $RUN_OPTS "$@" return $? diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 75494dc3e..75fbc59f1 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -60,10 +60,8 @@ jobs: run: | sudo apt-get update sudo apt-get install -y --no-install-recommends \ - ca-certificates \ cmake \ g++ \ - libcurl4-openssl-dev \ libgl-dev \ liblzma-dev \ libmariadb-dev-compat \ diff --git a/.github/workflows/desktop-build.yml b/.github/workflows/desktop-build.yml index c97b48342..0b9502fe3 100644 --- a/.github/workflows/desktop-build.yml +++ b/.github/workflows/desktop-build.yml @@ -46,11 +46,6 @@ jobs: outputs: tag: ${{ steps.configure.outputs.tag }} sha: ${{ steps.configure.outputs.sha }} - # MAJ.MIN.PATCH[-beta[.N]] of a tag build; empty otherwise. Mirrors what - # cmake/getversion.cmake derives as PROJECT_VERSION, which the client bakes as its - # Sentry release (cmake/CrashReporting.cmake) — symbol uploads must use the same - # string so stack traces de-symbolicate against this build's binaries. - sentry_release: ${{ steps.configure.outputs.sentry_release }} steps: - name: "Configure" @@ -61,9 +56,6 @@ jobs: run: | if [[ "$GITHUB_REF_TYPE" == 'tag' ]]; then # release echo "tag=$GITHUB_REF_NAME" >> "$GITHUB_OUTPUT" - # Tag format is YYYY-MM-DD-{Release|Development}-MAJ.MIN.PATCH[-beta[.N]]; - # PROJECT_VERSION is the tail after the type (see cmake/getversion.cmake). - echo "sentry_release=$(sed -E 's/^[0-9]{4}-[0-9]{2}-[0-9]{2}-(Release|Development)-//' <<< "$GITHUB_REF_NAME")" >> "$GITHUB_OUTPUT" fi echo "sha=$RESOLVED_SHA" >> "$GITHUB_OUTPUT" @@ -247,12 +239,6 @@ jobs: SUFFIX: '-${{ matrix.distro }}${{ matrix.version }}' package: '${{ matrix.package }}' server_only: '${{ matrix.server_only }}' - WITH_CRASH_REPORTING: 'ON' - # Tag builds only: artifacts from master pushes and PR branches must not report to - # Sentry. Forks get no secrets on pull_request, so they keep the mock fallback either way. - # configure.outputs.tag is set for ANY tag, so beta (Development) tags get the DSN - # and the symbol upload below just like full releases. - COCKATRICE_SENTRY_DSN: ${{ needs.configure.outputs.tag != null && secrets.SENTRY_DSN || '' }} run: | source .ci/docker.sh args=() @@ -261,58 +247,9 @@ jobs: args+=(--ccache "$CCACHE_SIZE") args+=(--cmake-generator "$CMAKE_GENERATOR") args+=(--suffix "$SUFFIX") - # The container inherits no environment, so the DSN rides in explicitly. -e without - # =value passes it through (possibly empty); compile.sh only consumes it for Release - # configures, and empty keeps the mock fallback. - export RUN_ARGS="${RUN_ARGS:-} -e COCKATRICE_SENTRY_DSN" RUN --server --release --package "$package" "${args[@]}" - - name: "Install sentry-cli" - if: matrix.package != 'skip' && needs.configure.outputs.tag != null - # Downloads from Sentry's release registry: a Sentry outage or a broken install under - # Git Bash must not take down the release assets below. - continue-on-error: true - shell: bash - env: - SENTRY_CLI_VERSION: '3.8.0' - run: | - export INSTALL_DIR="$GITHUB_WORKSPACE/.sentry-cli" - curl -sL https://sentry.io/get-cli/ | bash - echo "$GITHUB_WORKSPACE/.sentry-cli" >> "$GITHUB_PATH" - - - name: "Upload debug symbols to Sentry" - # Like the DSN above, this runs for every tag — beta (Development) tags included. - if: matrix.package != 'skip' && needs.configure.outputs.tag != null - # A Sentry outage or rotated token must not take down the release assets below. - continue-on-error: true - shell: bash - env: - SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }} - run: | - paths=() - # The binaries only, not the directories: a directory makes sentry-cli walk the - # whole build tree, where it finds (and uploads) object files and other fragments - # that can never match a stack frame. The packaged copy is split and stripped by - # cpack, but keeps this binary's GNU build-id, which is how Sentry matches it. - for app in cockatrice oracle servatrice; do - binary="build/$app/$app" - [[ -f $binary ]] && paths+=("$binary") - done - if [[ ${#paths[@]} == 0 ]]; then - # Fail loudly instead of skipping: see the Windows/macOS leg below — this step - # is the only way symbols reach Sentry and `continue-on-error` keeps the job - # green either way, so a silent skip looks exactly like a successful upload. - echo "::error::No debug symbol files found; nothing would be uploaded" - exit 1 - fi - # Project slug on Sentry; must match the project the baked DSN points at. - # No --release here: `debug-files upload` has no such option (sentry-cli errors on - # the unknown flag and uploads nothing), and debug information files are matched to - # events by debug ID via the event's debug_meta, not by release. The release grouping - # comes from the client event itself (COCKATRICE_SENTRY_RELEASE). - sentry-cli debug-files upload --org cockatrice --project cockatrice-desktop "${paths[@]}" - # Delete used cache to emulate a ccache update. See https://github.com/actions/cache/issues/342 - name: "Delete remote compiler cache (ccache)" if: github.ref == 'refs/heads/master' && steps.restore_ccache.outputs.cache-hit @@ -598,11 +535,6 @@ jobs: BUILDTYPE: '${{ matrix.type }}' CCACHE_EVICTION_AGE: ${{ matrix.ccache_eviction_age }} CMAKE_GENERATOR: ${{ matrix.cmake_generator }} - # Tag builds only: artifacts from master pushes and PR branches must not report to - # Sentry. Forks get no secrets on pull_request, so they keep the mock fallback either way. - # configure.outputs.tag is set for ANY tag, so beta (Development) tags get the DSN - # and the symbol upload below just like full releases. - COCKATRICE_SENTRY_DSN: ${{ needs.configure.outputs.tag != null && secrets.SENTRY_DSN || '' }} DEVELOPER_DIR: '/Applications/Xcode_${{ matrix.xcode }}.app/Contents/Developer' GITHUB_TOKEN: ${{ github.token }} # needed for vcpkg dependency graph updates, see VCPKG_FEATURE_FLAGS MACOS_CERTIFICATE: ${{ secrets.PROD_MACOS_CERTIFICATE }} @@ -626,125 +558,8 @@ jobs: VCPKG_DISABLE_METRICS: 1 VCPKG_FEATURE_FLAGS: dependencygraph VCPKG_TARGET_MACOS_VERSION: ${{ matrix.vcpkg_deployment_target }} - # Release legs compile the sentry-native SDK; Debug legs stay SDK-free. - WITH_CRASH_REPORTING: ${{ matrix.type == 'Release' && 'ON' || '' }} run: .ci/compile.sh --server --test --vcpkg - - name: "Install sentry-cli" - if: needs.configure.outputs.tag != null && matrix.make_package == '1' - # Same as the Linux leg above: the install downloads from Sentry's registry, so a - # failure here must not block the release upload below. - continue-on-error: true - shell: bash - env: - SENTRY_CLI_VERSION: '3.8.0' - run: | - export INSTALL_DIR="$GITHUB_WORKSPACE/.sentry-cli" - curl -sL https://sentry.io/get-cli/ | bash - echo "$GITHUB_WORKSPACE/.sentry-cli" >> "$GITHUB_PATH" - - - name: "Upload debug symbols to Sentry" - # Like the DSN above, this runs for every tag — beta (Development) tags included. - if: needs.configure.outputs.tag != null && matrix.make_package == '1' - # A Sentry outage or rotated token must not take down the release assets below. - continue-on-error: true - shell: bash - env: - SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }} - run: | - paths=() - if [[ '${{ matrix.os }}' == 'Windows' ]]; then - # Top-level CMakeLists.txt links /DEBUG even in release, so the linker PDBs - # land next to the binaries. Ninja is single-config, so that is - # build// and NOT build//Release/ — the same globs the symbol - # artifact step below uses. - # - # The executables are uploaded as well, in the same invocation. On 64-bit - # Windows the Call Frame Information (.pdata/.xdata) lives in the PE and is - # not copied into the PDB, so a PDB on its own leaves Sentry reporting - # "Stack Unwinding: Missing" for the image. sentry-cli also needs to see the - # PE and its PDB together: only then does it associate the PE's code - # identifier with the PDB's debug identifier. - shopt -s nullglob - for target in cockatrice oracle servatrice; do - paths+=("build/$target"/*.exe "build/$target"/*.pdb) - done - shopt -u nullglob - - # Qt's own runtime DLLs, taken from required-runtime.txt — the manifest - # .ci/compile.sh asserts the installer against — so the set uploaded is - # the set an install actually carries. The PE is the only carrier of - # unwind information for a 64-bit image, and sending it in the same - # invocation as a PDB is what lets sentry-cli associate the PE's code - # identifier with the PDB's debug identifier. Qt ships no PDBs with the - # SDK, so Qt frames resolve through the export table: names, no lines. - qt_dir= - qt_core_dir= - # Existence guards matter: the step runs under `bash -eo pipefail`, so a - # redirection-less sed over a missing file would abort the step outright - # and continue-on-error would hide it. - if [[ -f build/CMakeCache.txt ]]; then - qt_core_dir=$(sed -n 's/^Qt6Core_DIR:PATH=//p' build/CMakeCache.txt | head -1) - fi - if [[ -n $qt_core_dir ]]; then - qt_dir=$(dirname "$(dirname "$(dirname "$qt_core_dir")")") - fi - if [[ -z $qt_dir || ! -d $qt_dir ]]; then - # Warnings, not failures: the upload of our own binaries is what this - # step is for, and continue-on-error already means an upload failure - # cannot be told apart from a successful one. - echo "::warning::Qt runtime directory not resolved from build/CMakeCache.txt; Qt images get no unwind information" - elif [[ ! -f build/required-runtime.txt ]]; then - echo "::warning::build/required-runtime.txt is missing; cannot tell which Qt DLLs ship" - else - while IFS= read -r runtime; do - name=${runtime##*/} - if [[ $runtime == */* ]]; then - # A Qt plugin: the install root keeps it as plugins//. - # `|| true`: an unmatched glob makes ls exit non-zero, and pipefail - # turns that into a step abort. - runtime_path=$(ls "$qt_dir/plugins"/*/"$name" 2>/dev/null | head -1) || true - else - runtime_path="$qt_dir/bin/$name" - fi - if [[ -f ${runtime_path:-} ]]; then - paths+=("$runtime_path") - else - echo "::warning::shipped Qt runtime $runtime not found under $qt_dir" - fi - done < <(grep -E '^(Qt6[^/]*\.dll|Plugins/)' build/required-runtime.txt) - fi - else - # Release builds carry DWARF (-g, kept by CrashReporting.cmake); macOS keeps its - # debug info in dSYM bundles, so materialize them before uploading. - for app in cockatrice oracle servatrice; do - binary="build/$app/$app.app/Contents/MacOS/$app" - if [[ -f $binary ]]; then - if [[ '${{ matrix.os }}' == 'macOS' ]]; then - dsymutil "$binary" -o "$binary.dSYM" - paths+=("$binary.dSYM") - # The dSYM holds the debug information, but the unwind information - # Sentry needs to walk a minidump stack lives in the Mach-O itself. - paths+=("$binary") - else - paths+=("$binary") - fi - fi - done - fi - if [[ ${#paths[@]} == 0 ]]; then - # Fail loudly instead of skipping: this step is the only way symbols reach - # Sentry, and `continue-on-error` keeps the job green either way, so a - # silent skip is indistinguishable from a successful upload. It also hid a - # wrong Windows path (build//Release, which Ninja never creates). - echo "::error::No debug symbol files found; nothing would be uploaded" - exit 1 - fi - # Project slug on Sentry; must match the project the baked DSN points at. - # No --release: see the Linux leg above — the flag does not exist on - # `debug-files upload` and DIFs are matched by debug ID, not release. - sentry-cli debug-files upload --org cockatrice --project cockatrice-desktop "${paths[@]}" - # CPack reports a failed makensis run as "Problem running NSIS command" # plus a path to NSISOutput.log, and that log lives only on the runner, so # the actual compile error is otherwise nowhere in the workflow output. @@ -888,6 +703,19 @@ jobs: if-no-files-found: error path: ${{ steps.build.outputs.path }} + # Ninja is single-config: binaries and their PDBs land directly in the + # target directories instead of a Release subdirectory. + - name: "[Windows] Upload PDBs (Program Databases)" + if: matrix.os == 'Windows' && github.ref_type != 'tag' + uses: actions/upload-artifact@v7 + with: + if-no-files-found: error + name: ${{ steps.build.outputs.name }}-PDBs + path: | + build/cockatrice/*.pdb + build/oracle/*.pdb + build/servatrice/*.pdb + - name: "Upload to release" if: needs.configure.outputs.tag != null && matrix.make_package == '1' id: upload_release @@ -899,33 +727,6 @@ jobs: tag_name: ${{ needs.configure.outputs.tag }} run: gh release upload "$tag_name" "$asset_path#$asset_name" - # Ninja is single-config: binaries and their PDBs land directly in the - # target directories instead of a Release subdirectory. - # - # Archived for tag builds only, and ordered after the release upload so - # a missing PDB can never block a release from being published. On a tag - # build this artifact is the only durable copy of the symbols: the Sentry - # upload is continue-on-error, so without it a failed upload would lose - # the ability to symbolicate that release permanently. Other builds upload - # no symbols at all, so archiving them there would only cost storage. - # - # The executables travel with their PDBs: re-uploading the pair together is - # what lets sentry-cli associate the PE's code identifier with the PDB's - # debug identifier, and the PE is what carries the unwind information. - - name: "[Windows] Upload debug symbols (exe + pdb)" - if: matrix.os == 'Windows' && needs.configure.outputs.tag != null - uses: actions/upload-artifact@v7 - with: - if-no-files-found: error - name: ${{ steps.build.outputs.name }}-Symbols - path: | - build/cockatrice/*.exe - build/cockatrice/*.pdb - build/oracle/*.exe - build/oracle/*.pdb - build/servatrice/*.exe - build/servatrice/*.pdb - - name: "Attest binary provenance" if: steps.upload_release.outcome == 'success' id: attestation diff --git a/CMakeLists.txt b/CMakeLists.txt index 97b87a1d8..87f1c746a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -220,7 +220,6 @@ endif() # when ENABLE_SANITIZERS or ENABLE_COVERAGE is on. include(Sanitizers) include(Coverage) -include(CrashReporting) # GNU systems need to define the Mersenne exponent for the RNG to compile w/o warning if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang") @@ -337,15 +336,6 @@ elseif(WIN32) # Configure file with custom definitions for NSIS. configure_file("${COCKATRICE_CMAKE_PATH}/NSIS.definitions.nsh.in" "${PROJECT_BINARY_DIR}/NSIS.definitions.nsh") - # Installer-log sender for the AbortInstall Sentry hook (values parsed out of COCKATRICE_SENTRY_DSN in - # cmake/CrashReporting.cmake). Generated only when a DSN was parsed: cmake/NSIS.template.in embeds it under - # the same CPACK_SENTRY_ENABLED check, so a build without reporting never references or carries the helper. - if(CPACK_SENTRY_ENABLED) - configure_file( - "${COCKATRICE_CMAKE_PATH}/SendInstallerLog.ps1.in" "${PROJECT_BINARY_DIR}/SendInstallerLog.ps1" @ONLY - ) - endif() - # Every runtime DLL a Windows install has to contain, as paths relative to the # install root. .ci/compile.sh reads this and fails the build when the packaged # installer is missing one of them, or carries a runtime it does not know about. diff --git a/cmake/CrashReporting.cmake b/cmake/CrashReporting.cmake deleted file mode 100644 index 6f9cf4849..000000000 --- a/cmake/CrashReporting.cmake +++ /dev/null @@ -1,212 +0,0 @@ -# Crash reporting via sentry-native (Sentry protocol, MIT). -# Included once from the root CMakeLists.txt, right after the sanitizer/coverage helpers. -# -# Inputs: -# WITH_CRASH_REPORTING -- build the client with the sentry-native SDK (default OFF, our release -# CI passes ON; packagers and from-source builds stay SDK-free until this -# ships something real, so offline package builds never fetch the SDK) -# COCKATRICE_SENTRY_DSN -- Sentry DSN baked into the build (default empty = SDK init skipped at runtime) -# COCKATRICE_SENTRY_TAG -- sentry-native release tag to vendor via FetchContent -# ENABLE_SANITIZERS -- forces the sentry backend to "none" (crashpad vs ASan conflict) -# Defines: cockatrice_target_enable_crash_reporting() - -option(WITH_CRASH_REPORTING "Build with crash reporting via sentry-native" OFF) -set(COCKATRICE_SENTRY_DSN - "" - CACHE STRING "Sentry DSN baked into the client; empty disables crash-report upload at runtime" -) -# Pinned stable release; tag verified at https://github.com/getsentry/sentry-native/tags. -set(COCKATRICE_SENTRY_TAG - "0.17.3" - CACHE STRING "sentry-native release tag to vendor via FetchContent" -) - -# Wire the SDK (or the no-op fallback) into a client target. Always callable: with the -# option OFF the compile definitions below make crash_reporter.cpp compile to no-ops. -function(cockatrice_target_enable_crash_reporting _target) - if(WITH_CRASH_REPORTING AND TARGET sentry::sentry) - target_link_libraries(${_target} PRIVATE sentry::sentry) - target_compile_definitions(${_target} PRIVATE COCKATRICE_WITH_CRASH_REPORTING=1) - else() - target_compile_definitions(${_target} PRIVATE COCKATRICE_WITH_CRASH_REPORTING=0) - endif() - # Always baked in (possibly empty): main() prefers the COCKATRICE_SENTRY_DSN env var at runtime. - target_compile_definitions(${_target} PRIVATE "COCKATRICE_SENTRY_DSN=\"${COCKATRICE_SENTRY_DSN}\"") - # Sentry release for events from this target: PROJECT_VERSION (getversion.cmake ran before this - # file was included). Deliberately not PROJECT_VERSION_FRIENDLY / VERSION_STRING — that carries - # a build date, so every build of the same version would land in a different Sentry release. - # PROJECT_VERSION matches what the installer reports in its own log and what CPack derives the - # package version from, so client and installer events group under one release. - target_compile_definitions(${_target} PRIVATE "COCKATRICE_SENTRY_RELEASE=\"${PROJECT_VERSION}\"") -endfunction() - -if(WITH_CRASH_REPORTING AND WITH_CLIENT) - include(FetchContent) - - if(ENABLE_SANITIZERS) - # The crash handler cannot run under ASan/UBSan, so there is no backend to capture with. - set(_sentry_backend "none") - else() - # Breakpad on every OS (increment 3 probe, 2026-10-14): the crashpad sources - # do vendor friction-free (FetchContent inits all submodules recursively by - # default, verified populated in a local build tree), but the crashpad backend - # would need its out-of-process crashpad_handler binary installed next to the - # exe, into the macOS bundle, and through NSIS, plus handler-path wiring and - # notarization care. Breakpad is in-process, needs no extra binary and no - # packaging on any OS sentry-native builds, so simplicity wins. - set(_sentry_backend "breakpad") - endif() - # FORCE so toggling ENABLE_SANITIZERS on a reused build dir cannot leave a stale backend behind. - set(SENTRY_BACKEND - "${_sentry_backend}" - CACHE STRING "Crash handler backend for sentry-native" FORCE - ) - unset(_sentry_backend) - - if(NOT MSVC) - # Symbol upload needs debug info in Release binaries: the top-level flags build GCC - # Release as -s -O2 (stripped, no DWARF) and Clang/Apple Release as plain -O2 (no DWARF), - # both of which upload nothing useful. Keep -g and drop the strip flag while the SDK is - # on; the OFF default leaves local, distro and Debug builds untouched. MSVC already - # links /DEBUG with PDBs in release (see top-level CMakeLists.txt), so it needs nothing. - string(REGEX REPLACE "(^| )-s( |$)" "\\1\\2" CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE}") - if(NOT CMAKE_CXX_FLAGS_RELEASE MATCHES "(^| )-g( |$)") - set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -g") - endif() - endif() - - # No Qt integration: it runs find_package(Qt6) inside the vendored build, which - # cannot see our thin/aqt Qt layouts (macOS CI) under foreign toolchains, and its - # breadcrumbs could carry unredacted log lines into native crash events that bypass - # before_send. Our attached redacted log preview already carries the log context. - set(SENTRY_INTEGRATION_QT - OFF - CACHE BOOL "Qt log-message breadcrumbs for sentry-native (off: discovery + secret surface)" FORCE - ) - # The transport stays at the SDK default (curl on Apple/Linux, winhttp on Windows). - set(SENTRY_BUILD_TESTS - OFF - CACHE BOOL "Build sentry-native tests" FORCE - ) - set(SENTRY_BUILD_EXAMPLES - OFF - CACHE BOOL "Build sentry-native examples" FORCE - ) - - fetchcontent_declare( - sentry - GIT_REPOSITORY https://github.com/getsentry/sentry-native.git - GIT_TAG ${COCKATRICE_SENTRY_TAG} - GIT_SHALLOW TRUE - ) - fetchcontent_makeavailable(sentry) - - # Vendored sentry-native (and its breakpad/crashpad trees) warn under our -Wall -Wextra - # (e.g. breakpad's -Wmissing-field-initializers), and WARNING_AS_ERROR would fail the build - # on code we cannot fix. Those findings are not actionable for us, so opt the whole vendored - # tree out of warnings-as-errors while keeping the warnings themselves visible; our own - # targets keep -Werror. Interface libraries compile nothing, so they are skipped outright: - # an INTERFACE -Wno-error would propagate to our consumers and weaken their build. - function(_cockatrice_sentry_opt_out_of_werror _dir) - get_property( - _sentry_targets - DIRECTORY "${_dir}" - PROPERTY BUILDSYSTEM_TARGETS - ) - foreach(_sentry_target IN LISTS _sentry_targets) - get_target_property(_sentry_type ${_sentry_target} TYPE) - if(_sentry_type STREQUAL "INTERFACE_LIBRARY") - continue() - elseif(_sentry_type MATCHES "LIBRARY|EXECUTABLE") - get_target_property(_sentry_imported ${_sentry_target} IMPORTED) - if(NOT _sentry_imported) - target_compile_options(${_sentry_target} PRIVATE -Wno-error) - endif() - endif() - endforeach() - get_property( - _sentry_subdirs - DIRECTORY "${_dir}" - PROPERTY SUBDIRECTORIES - ) - foreach(_sentry_subdir IN LISTS _sentry_subdirs) - _cockatrice_sentry_opt_out_of_werror("${_sentry_subdir}") - endforeach() - endfunction() - if(NOT MSVC) - _cockatrice_sentry_opt_out_of_werror("${sentry_SOURCE_DIR}") - endif() - - message(STATUS "Crash reporting: sentry-native ${COCKATRICE_SENTRY_TAG} (backend: ${SENTRY_BACKEND})") -else() - message(STATUS "Crash reporting: SDK not vendored " - "(WITH_CRASH_REPORTING=${WITH_CRASH_REPORTING}, WITH_CLIENT=${WITH_CLIENT})" - ) -endif() - -# Packaged release binaries must not ship the DWARF that the symbol upload needs: it is -# 80-90% of an unstripped binary and nobody downloads a 500 MB installer to get it. The -# build tree keeps -g (CI uploads symbols from there); the *packaged copy* is split at -# install time by a CPack install script, which extracts the debug info next to the staging -# dir and strips the binary. Only ELF (Linux/BSD) needs this: Windows links /DEBUG with -# separate PDBs, and macOS keeps its dSYM extracted from the bundle. -option(COCKATRICE_SPLIT_DEBUG_SYMBOLS "Strip DWARF out of packaged release binaries" ON) -set(COCKATRICE_DEBUG_SYMBOL_DIR - "${CMAKE_BINARY_DIR}/debug-symbols" - CACHE PATH "Where the packaged binaries' split debug information is written (kept out of the package)" -) -if(WITH_CRASH_REPORTING - AND WITH_CLIENT - AND COCKATRICE_SPLIT_DEBUG_SYMBOLS - AND CMAKE_BUILD_TYPE STREQUAL "Release" - AND UNIX - AND NOT APPLE -) - find_program(COCKATRICE_OBJCOPY NAMES objcopy) - find_program(COCKATRICE_STRIP_TOOL NAMES strip) - if(COCKATRICE_OBJCOPY AND COCKATRICE_STRIP_TOOL) - configure_file( - "${CMAKE_CURRENT_LIST_DIR}/SplitDebugSymbols.cmake.in" "${CMAKE_BINARY_DIR}/cmake/SplitDebugSymbols.cmake" @ONLY - ) - # PRE_BUILD runs after CPack stages the install tree and before the package is produced. - # CPACK_INSTALL_SCRIPTS would run too early (staging is still empty); the script walks - # CPACK_TEMPORARY_DIRECTORY, never CMAKE_INSTALL_PREFIX, and refuses to run otherwise. - list(APPEND CPACK_PRE_BUILD_SCRIPTS "${CMAKE_BINARY_DIR}/cmake/SplitDebugSymbols.cmake") - message(STATUS "Crash reporting: packaged binaries stripped, debug info split to ${COCKATRICE_DEBUG_SYMBOL_DIR}") - else() - message(WARNING "COCKATRICE_SPLIT_DEBUG_SYMBOLS is ON but objcopy/strip were not found; " - "packaged release binaries will keep their debug information" - ) - endif() -endif() - -# Installer failure reporting (increment 4): parse COCKATRICE_SENTRY_DSN into the parts the Windows installer -# needs. These are CPACK_* so CPack snapshots them at include(CPack) time and substitutes them into -# cmake/NSIS.template.in at package time; on non-Windows they are inert (only the NSIS template consumes them). -# Set from COCKATRICE_SENTRY_DSN on every configure, so a changed or removed DSN can never leave a stale value -# behind. Plain variables, not CACHE: they only need to be in scope when include(CPack) later snapshots every -# CPACK_* variable into CPackConfig.cmake. -set(CPACK_SENTRY_ENABLED "0") -set(CPACK_SENTRY_KEY "") -set(CPACK_SENTRY_ENVELOPE_URL "") -set(CPACK_SENTRY_DSN_FULL "") -# Deliberately PROJECT_VERSION: that is what the client bakes as its Sentry release and what CI passes to -# `sentry-cli debug-files upload`, so installer and client events group under one release. It is not the -# CPACK_PACKAGE_VERSION the installer logs in its own log line — on Development tags PROJECT_VERSION carries a -# "-