mirror of
https://github.com/1dot13/source.git
synced 2026-07-29 13:52:17 +02:00
A crash report is worth nothing sitting on the player's disk. On startup, drain the crash_report_*.txt files the handler left behind to the endpoint named by CRASH_TELEMETRY_URL in Ja2 Settings; an empty or absent key turns the feature off entirely. The first launch asks the player once and remembers the answer in telemetry.consent -- declined means the reports simply keep accumulating locally. This lands in its own translation unit rather than in more of debug_win_util.cpp. Everything in that file runs inside a faulting thread and may not allocate; everything here runs at startup with a healthy heap and is ordinary code. Two files keep the no-heap rule easy to see and easy to hold. The draining runs on a detached thread. The uploads are synchronous WinHttp calls with seconds-long timeouts, and this sits on the startup path, so on the main thread an unreachable endpoint is a stall the player watches before the splash screen. Nothing waits on the result: if the player quits first the process exits from under the thread, which costs nothing, since an interrupted upload leaves the file on disk and it goes out next launch. The consent prompt stays on the main thread on purpose -- it is a question, and a question has to be asked before anything is sent. Which reports get deleted is chosen so that a mistake cannot destroy them. A file goes away on 2xx, and on 400/413/415, i.e. content the server will never accept. Everything else keeps it: no connection, 5xx, and notably the 403/404 of a mistyped CRASH_TELEMETRY_URL, which would otherwise silently eat every player's crash history. Bounds all round: every WinHttp phase has a timeout, a report over 256 KB is not one of ours and never goes on the wire, at most 20 uploads per launch so a crash-looping build cannot turn startup into an upload session, and reports older than 30 days are dropped unsent. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
226 lines
8.2 KiB
CMake
226 lines
8.2 KiB
CMake
cmake_minimum_required(VERSION 3.20)
|
|
|
|
# /Z7 embedded debug info so objects are self-contained and sccache-able.
|
|
# CMP0141 is a 3.25 policy; our floor is 3.20, so opt in explicitly where known.
|
|
if(POLICY CMP0141)
|
|
cmake_policy(SET CMP0141 NEW)
|
|
endif()
|
|
|
|
project(ja2)
|
|
|
|
option(USE_SCCACHE "Cache compiled objects with sccache if installed" ON)
|
|
if(USE_SCCACHE)
|
|
find_program(SCCACHE_PROGRAM sccache)
|
|
if(SCCACHE_PROGRAM)
|
|
message(STATUS "Using sccache: ${SCCACHE_PROGRAM}")
|
|
set(CMAKE_C_COMPILER_LAUNCHER "${SCCACHE_PROGRAM}")
|
|
set(CMAKE_CXX_COMPILER_LAUNCHER "${SCCACHE_PROGRAM}")
|
|
endif()
|
|
endif()
|
|
|
|
include(cmake/CopyUserPresetTemplate.cmake)
|
|
CopyUserPresetTemplate()
|
|
|
|
set(CMAKE_CXX_STANDARD 17)
|
|
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
|
set(CMAKE_CXX_EXTENSIONS OFF)
|
|
|
|
option(LTO_OPTION "Enable link-time optimization if supported by compiler" OFF)
|
|
|
|
include(CheckIPOSupported)
|
|
check_ipo_supported(RESULT LinkTimeOptimization OUTPUT IpoError LANGUAGES C CXX)
|
|
if(LinkTimeOptimization AND LTO_OPTION)
|
|
message(STATUS "Configuring WITH link-time optimization")
|
|
set(CMAKE_INTERPROCEDURAL_OPTIMIZATION TRUE)
|
|
else()
|
|
message(STATUS "Configuring WITHOUT link-time optimization ${IpoError}")
|
|
endif()
|
|
|
|
option(ADDRESS_SANITIZER OFF)
|
|
if(ADDRESS_SANITIZER)
|
|
message(STATUS "AddressSanitizer ENABLED for non-Release builds")
|
|
add_compile_options($<IF:$<OR:$<CONFIG:Debug>,$<CONFIG:RelWithDebInfo>>,-fsanitize=address,>)
|
|
endif()
|
|
|
|
# whether we are using MSBuild as a generator
|
|
set(usingMsBuild $<STREQUAL:${CMAKE_VS_PLATFORM_NAME},Win32>)
|
|
|
|
# lua51.lib and lua51.vc9.lib have been built with /MTx, so we must as well
|
|
# TODO: build our own Lua 5.1.2 from source so we can use whichever
|
|
set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")
|
|
# make Debug builds /Z7 instead of /Zi so they can be sccache'd
|
|
set(CMAKE_MSVC_DEBUG_INFORMATION_FORMAT
|
|
"$<$<CONFIG:Debug,RelWithDebInfo>:Embedded>")
|
|
|
|
add_compile_definitions(CINTERFACE XML_STATIC VFS_STATIC VFS_WITH_SLF VFS_WITH_7ZIP _CRT_SECURE_NO_DEPRECATE)
|
|
include_directories(
|
|
"${CMAKE_SOURCE_DIR}/Ja2"
|
|
"${CMAKE_SOURCE_DIR}/ext/VFS/include"
|
|
"${CMAKE_SOURCE_DIR}/ext/libsmacker"
|
|
"${CMAKE_SOURCE_DIR}/Utils"
|
|
"${CMAKE_SOURCE_DIR}/TileEngine"
|
|
"${CMAKE_SOURCE_DIR}/TacticalAI"
|
|
"${CMAKE_SOURCE_DIR}/ModularizedTacticalAI/include"
|
|
"${CMAKE_SOURCE_DIR}/Tactical"
|
|
"${CMAKE_SOURCE_DIR}/Strategic"
|
|
"${CMAKE_SOURCE_DIR}/sgp"
|
|
"${CMAKE_SOURCE_DIR}/Ja2/Res"
|
|
"${CMAKE_SOURCE_DIR}/lua"
|
|
"${CMAKE_SOURCE_DIR}/Laptop"
|
|
"${CMAKE_SOURCE_DIR}/Multiplayer"
|
|
"${CMAKE_SOURCE_DIR}/Editor"
|
|
"${CMAKE_SOURCE_DIR}/i18n/include"
|
|
)
|
|
|
|
# external libraries
|
|
add_subdirectory("ext/libpng")
|
|
add_subdirectory("ext/libsmacker")
|
|
add_subdirectory("ext/zlib")
|
|
add_subdirectory("ext/VFS")
|
|
target_link_libraries(bfVFS PRIVATE 7z)
|
|
|
|
# from here on down our own code only: vendored code above keeps default flags
|
|
include(cmake/Warnings.cmake)
|
|
|
|
# ja2export utility
|
|
add_subdirectory("export/src")
|
|
|
|
# static libraries whose translation units don't rely on Application preprocessor definitions.
|
|
add_subdirectory(lua)
|
|
add_subdirectory(Multiplayer)
|
|
add_subdirectory(wine)
|
|
|
|
# Rebuild the Bink import library rather than link the one the game ships: that one
|
|
# is a 2002 long-format ordinal library, and only link.exe still binds it. lld-link
|
|
# takes it without complaint but emits an import descriptor with an empty thunk
|
|
# table, so every Bink call reaches a stale address and BinkInitialize faults the
|
|
# process during the intro. mingw/GNU ar cannot do this at all, see mingw.cmake
|
|
if(NOT binkw32_lib)
|
|
# Only the name shape differs by toolchain: lib.exe prepends the x86 leading
|
|
# underscore to every name in the .def, llvm-lib and llvm-dlltool take the name as
|
|
# written. The checked-in file carries the underscore for the llvm tools, so strip
|
|
# it back off for lib.exe -- get this backwards either way and the Bink symbols
|
|
# come out undefined at link time.
|
|
# The test is on the compiler because it is what CMAKE_AR follows: clang-cl reports
|
|
# COMPILER_ID Clang and brings llvm-lib, cl.exe reports MSVC and brings lib.exe. Do
|
|
# not reach for the MSVC variable or COMPILER_FRONTEND_VARIANT here -- both are set
|
|
# for clang-cl too, and either would strip the underscore for the wrong archiver.
|
|
set(binkw32Def "${CMAKE_SOURCE_DIR}/binkw32.def")
|
|
if(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
|
|
file(READ "${binkw32Def}" binkw32DefText)
|
|
string(REPLACE "\n_" "\n" binkw32DefText "${binkw32DefText}")
|
|
set(binkw32Def "${CMAKE_BINARY_DIR}/binkw32.msvc.def")
|
|
file(WRITE "${binkw32Def}" "${binkw32DefText}")
|
|
endif()
|
|
execute_process(
|
|
COMMAND "${CMAKE_AR}" /nologo /machine:X86
|
|
"/def:${binkw32Def}" "/out:${CMAKE_BINARY_DIR}/binkw32.lib"
|
|
RESULT_VARIABLE binkw32LibResult)
|
|
if(NOT binkw32LibResult EQUAL 0)
|
|
message(FATAL_ERROR "${CMAKE_AR} failed to build the binkw32 import library")
|
|
endif()
|
|
set(binkw32_lib "${CMAKE_BINARY_DIR}/binkw32.lib")
|
|
endif()
|
|
|
|
set(Ja2_Libraries
|
|
"${binkw32_lib}"
|
|
"${CMAKE_SOURCE_DIR}/libexpatMT.lib"
|
|
"${CMAKE_SOURCE_DIR}/lua51.lib"
|
|
"${CMAKE_SOURCE_DIR}/lua51.vc9.lib"
|
|
"dbghelp.lib"
|
|
"winmm.lib"
|
|
"ws2_32.lib"
|
|
"winhttp.lib"
|
|
bfVFS
|
|
Lua
|
|
Multiplayer
|
|
smacker
|
|
wine
|
|
)
|
|
|
|
# static libraries whose translation units rely on Application preprocessor definitions.
|
|
set(Ja2_Libs
|
|
Editor
|
|
Ja2
|
|
Laptop
|
|
ModularizedTacticalAI
|
|
sgp
|
|
Strategic
|
|
Tactical
|
|
TacticalAI
|
|
TileEngine
|
|
Utils
|
|
)
|
|
foreach(lib IN LISTS Ja2_Libs)
|
|
add_subdirectory(${lib})
|
|
endforeach()
|
|
|
|
# language library relies on Application preprocessor definition; compiled once per app
|
|
# with all 8 languages built in and selected at runtime (docs/plans/language-design.md).
|
|
add_subdirectory(i18n)
|
|
|
|
# simple function to validate the Application choice
|
|
include(cmake/ValidateOptions.cmake)
|
|
|
|
set(ValidApplications JA2 JA2MAPEDITOR JA2UB JA2UBMAPEDITOR)
|
|
ValidateOptions("${ValidApplications}" "Applications" "${Applications}" "ApplicationTargets")
|
|
|
|
|
|
# preprocessor definitions for Debug build, per the legacy MSBuild
|
|
set(debugFlags $<IF:$<CONFIG:Debug>,JA2BETAVERSION;JA2TESTVERSION;DEBUG_ATTACKBUSY,>)
|
|
|
|
foreach(app IN LISTS ApplicationTargets)
|
|
set(isEditor $<STREQUAL:${app},JA2MAPEDITOR>)
|
|
set(isUb $<STREQUAL:${app},JA2UB>)
|
|
set(isUbEditor $<STREQUAL:${app},JA2UBMAPEDITOR>)
|
|
set(compilationFlags
|
|
$<IF:${isEditor},JA2EDITOR;JA2BETAVERSION,>
|
|
$<IF:${isUb},JA2UB;JA2UBMAPS,>
|
|
$<IF:${isUbEditor},JA2UB;JA2UBMAPS;JA2EDITOR;JA2BETAVERSION,>
|
|
)
|
|
|
|
foreach(lib IN LISTS Ja2_Libs)
|
|
# library for an application, e.g. JA2UB_sgp
|
|
set(game_library ${app}_${lib})
|
|
add_library(${game_library})
|
|
target_sources(${game_library} PRIVATE ${${lib}Src})
|
|
target_compile_definitions(${game_library} PRIVATE ${compilationFlags} ${debugFlags})
|
|
endforeach()
|
|
|
|
# executable for the application, e.g. JA2.exe
|
|
set(exe ${app})
|
|
add_executable(${exe} WIN32
|
|
sgp/sgp.cpp
|
|
Ja2/Res/ja2.rc
|
|
)
|
|
# RakNetLibStatic.lib was built against an older CRT and still calls
|
|
# _vsnprintf, which the UCRT only exports through this compatibility library.
|
|
target_link_libraries(${exe} PRIVATE ${Ja2_Libraries} legacy_stdio_definitions.lib)
|
|
# The prebuilt lua51.lib and smackw32 import library carry no safe exception
|
|
# handler table, so the image cannot claim one whatever links it.
|
|
target_link_options(${exe} PRIVATE /SAFESEH:NO)
|
|
target_compile_definitions(${exe} PRIVATE ${compilationFlags} ${debugFlags})
|
|
|
|
# language library for the application, e.g. JA2MAPEDITOR_i18n — one per app, all 8
|
|
# languages compiled in, selected at runtime by BindLanguageStrings
|
|
set(language_library ${exe}_i18n)
|
|
add_library(${language_library})
|
|
target_sources(${language_library} PRIVATE ${i18nSrc})
|
|
target_compile_definitions(${language_library} PRIVATE ${compilationFlags} ${debugFlags})
|
|
target_compile_options(${language_library} PRIVATE /w14062)
|
|
target_link_libraries(${exe} PRIVATE ${language_library})
|
|
|
|
# go through all game libraries again and link them to the app executable
|
|
foreach(lib IN LISTS Ja2_Libs)
|
|
target_link_libraries(${exe} PRIVATE ${app}_${lib})
|
|
endforeach()
|
|
|
|
# for Utils only
|
|
target_link_libraries(${app}_Utils PRIVATE smacker)
|
|
|
|
# for SGP only
|
|
target_link_libraries(${app}_sgp PRIVATE "ddraw.lib" "${PROJECT_SOURCE_DIR}/fmodvc.lib")
|
|
target_link_libraries(${app}_sgp PRIVATE libpng)
|
|
target_compile_definitions(${app}_sgp PRIVATE ${compilationFlags} ${debugFlags} NO_ZLIB_COMPRESSION)
|
|
endforeach()
|