From 7073aeccef685a6173eca7207a8284cff38c433c Mon Sep 17 00:00:00 2001 From: Segfault <5221072+Segfaultd@users.noreply.github.com> Date: Sat, 29 Aug 2026 08:25:58 +0200 Subject: [PATCH 1/2] Vendors: consume precompiled MafiaNet release archives Replace the FetchContent source build of MafiaNet with a download of the per-platform precompiled archive published by MafiaNet's release pipeline (static + shared libs, bundled opus/rnnoise, headers, CMake package). The archive is fetched at configure time into the build tree and consumed via find_package(MafiaNet CONFIG); consumers keep linking MafiaNet::MafiaNetStatic unchanged. The pin in cmake/MafiaNetPin.cmake (same path, so bump_version.sh keeps its wire-format signal) now names the release version plus the SHA-256 of each archive: tags are mutable refs, so the hashes are what actually pin content (file(DOWNLOAD EXPECTED_HASH) fails the configure on any mismatch). The archives carry a single Release configuration compiled with /MD on Windows -- the CRT FrameworkSetup forces even in Debug -- so Debug/ RelWithDebInfo/MinSizeRel are mapped onto it via MAP_IMPORTED_CONFIG_*, and the old _DEBUG/CRT reconciliation block for the source build is deleted. find_package imports are directory-scoped, unlike the old alias targets, so the imported targets are promoted IMPORTED_GLOBAL for the consumers under code/ (the GLOBAL keyword needs CMake 3.24; minimum here is 3.20). --- cmake/MafiaNetPin.cmake | 26 ++++--- vendors/CMakeLists.txt | 151 ++++++++++++++++++++++------------------ 2 files changed, 102 insertions(+), 75 deletions(-) diff --git a/cmake/MafiaNetPin.cmake b/cmake/MafiaNetPin.cmake index 428b5e75d..f1abc6507 100644 --- a/cmake/MafiaNetPin.cmake +++ b/cmake/MafiaNetPin.cmake @@ -16,12 +16,22 @@ # Note it must NOT live under vendors/: .gitignore carries `vendors/**/*.cmake`, # which would silently exclude it from the repository. -# Pinned by commit, not by tag. A tag is a mutable ref -- repointing it would -# change what every future build fetches while this file still reads the same -- -# whereas a commit is what it is. Keep the human-readable release beside it. +# The pin names a MafiaNet release whose precompiled per-platform archives are +# downloaded at configure time (see vendors/CMakeLists.txt). A tag is a mutable +# ref, so the version alone would not pin anything; the SHA-256 of each archive +# is what actually fixes the content -- file(DOWNLOAD EXPECTED_HASH) fails the +# configure if an archive is ever repointed or tampered with. When bumping, +# update the version and all five hashes together (they are printed by the +# MafiaNet release pipeline, or: shasum -a 256 MafiaNet--*). # -# Plain set(), not a CACHE entry: a cached value survives in an existing build -# tree, so bumping the pin here and rebuilding incrementally would silently keep -# fetching the old revision. This file is the single source of truth, and there is -# no reason to let -D override the wire format of the protocol. -set(MAFIANET_PIN "2221f074cc32bf305c181d145fe4ba1550bab1b7") # v0.15.0 -- session handshake (RAKNET_PROTOCOL_VERSION 7) +# Plain set(), not CACHE entries: a cached value survives in an existing build +# tree, so bumping the pin here and reconfiguring incrementally would silently +# keep the old release. This file is the single source of truth, and there is no +# reason to let -D override the wire format of the protocol. +set(MAFIANET_PIN_VERSION "0.15.0") # session handshake (RAKNET_PROTOCOL_VERSION 7) + +set(MAFIANET_PIN_SHA256_linux-x86_64 "860a230db94956847a02ca8022c0723bd73afb7db2b9be4c901d58d38c43b0d6") +set(MAFIANET_PIN_SHA256_macos-arm64 "7387fe0fa5801051f29e6b61b9eecb358cf8644d734ed30512513dce16680b64") +set(MAFIANET_PIN_SHA256_macos-x86_64 "db3500e51d3caa69c7beae43aea6c2a036e2fbe600dbd941c46127ab3bf2e774") +set(MAFIANET_PIN_SHA256_windows-x64 "fbef4cd7a5dd32f2ea6d0bc9b0ec41514c3750c696509ce431b9dbe5cfc75227") +set(MAFIANET_PIN_SHA256_windows-x86 "794bb615645524caa990cbbd1a864e97f2d38c3966d98c882b79e51bd4cdfa13") diff --git a/vendors/CMakeLists.txt b/vendors/CMakeLists.txt index cb0df59e4..6e665413f 100644 --- a/vendors/CMakeLists.txt +++ b/vendors/CMakeLists.txt @@ -51,80 +51,97 @@ set(HTTPLIB_REQUIRE_OPENSSL ON) set(HTTPLIB_COMPILE ON) add_subdirectory(httplib) -# MafiaNet (networking) - fetched, not vendored. +# MafiaNet (networking) - precompiled release archive, neither vendored nor +# built from source. # -# MafiaNet owns RakVoice, and therefore owns RakVoice's Opus and RNNoise -# dependencies, which its own build fetches. Vendoring MafiaNet here would mean -# hoisting those two a level up into this repository: ~85 MB of third-party -# source, a collision with this repo's `vendors/**/*.cmake` ignore rule, and a -# re-vendor split across three trees that have to stay in lockstep. Fetching the -# release instead keeps the dependency boundary where it belongs. +# MafiaNet's release pipeline publishes per-platform archives (linux-x86_64, +# windows-x86/x64, macos-x86_64/arm64) containing the static library, the +# bundled Opus/RNNoise static libs RakVoice needs, all public headers, and the +# MafiaNet CMake package. Downloading one archive replaces compiling ~85 MB of +# third-party source (plus MafiaNet's own Opus/RNNoise fetches) on every cold +# configure, and keeps the dependency boundary where it belongs. # -# This is the only FetchContent in the Framework build; everything else under -# vendors/ is genuinely vendored in-tree. Building therefore needs network access -# on a cold configure (the fetch is cached in the build tree afterwards). -include(FetchContent) - -# Framework links the static library only; samples and MafiaNet's own test suite -# are not our concern. -set(MAFIANET_BUILD_SHARED OFF CACHE BOOL "" FORCE) -set(MAFIANET_BUILD_STATIC ON CACHE BOOL "" FORCE) -set(MAFIANET_BUILD_SAMPLES OFF CACHE BOOL "" FORCE) -set(MAFIANET_BUILD_TESTS OFF CACHE BOOL "" FORCE) - -# Pinned to a release tag, never a branch: the message-id enum is positional, so -# an unpinned bump would silently change the wire format. The pin lives in -# cmake/MafiaNetPin.cmake so the release tooling can watch that one path. +# This is the only download in the Framework build; everything else under +# vendors/ is genuinely vendored in-tree. A cold configure therefore needs +# network access (the archive is cached in the build tree afterwards). +# +# The pin (version + per-archive SHA-256) lives in cmake/MafiaNetPin.cmake so +# the release tooling can watch that one path: the message-id enum is +# positional, so a bump can move the wire format. include(MafiaNetPin) -# No GIT_SHALLOW: it makes CMake clone the default branch at depth 1 and then check the -# pin out of it, which only resolves while the pinned commit is still that branch's tip. -# Any later MafiaNet commit leaves the pin unreachable and a cold configure dies with -# "unable to read tree". A full clone is the cost of pinning by commit at all. -FetchContent_Declare( - MafiaNet - GIT_REPOSITORY https://github.com/MafiaHub/MafiaNet.git - GIT_TAG ${MAFIANET_PIN} -) -FetchContent_MakeAvailable(MafiaNet) +if(WIN32) + if(CMAKE_SIZEOF_VOID_P EQUAL 4) + set(_mafianet_platform "windows-x86") + else() + set(_mafianet_platform "windows-x64") + endif() + set(_mafianet_ext "zip") +elseif(APPLE) + if(CMAKE_OSX_ARCHITECTURES STREQUAL "x86_64" + OR (NOT CMAKE_OSX_ARCHITECTURES AND CMAKE_SYSTEM_PROCESSOR STREQUAL "x86_64")) + set(_mafianet_platform "macos-x86_64") + elseif(CMAKE_OSX_ARCHITECTURES STREQUAL "arm64" + OR (NOT CMAKE_OSX_ARCHITECTURES AND CMAKE_SYSTEM_PROCESSOR STREQUAL "arm64")) + set(_mafianet_platform "macos-arm64") + else() + message(FATAL_ERROR "No precompiled MafiaNet archive for macOS architectures '${CMAKE_OSX_ARCHITECTURES}' (universal builds are not supported)") + endif() + set(_mafianet_ext "tar.gz") +elseif(CMAKE_SYSTEM_NAME STREQUAL "Linux" AND CMAKE_SYSTEM_PROCESSOR MATCHES "^(x86_64|amd64)$") + set(_mafianet_platform "linux-x86_64") + set(_mafianet_ext "tar.gz") +else() + message(FATAL_ERROR "No precompiled MafiaNet archive for ${CMAKE_SYSTEM_NAME}/${CMAKE_SYSTEM_PROCESSOR}") +endif() -# Reconcile the fetched dependencies with this build's CRT convention. -# -# Framework uses the RELEASE CRT even in Debug builds: FrameworkSetup forces -# CMAKE_MSVC_RUNTIME_LIBRARY to MultiThreadedDLL and replaces -# CMAKE_CXX_FLAGS_DEBUG outright, so no /MDd and no _DEBUG reach its objects. -# -# MafiaNet follows the ordinary convention instead -- Source/CMakeLists.txt does -# target_compile_definitions(... $<$:_DEBUG>). Defining _DEBUG makes -# MSVC select the debug CRT semantics in the object itself: _ITERATOR_DEBUG_LEVEL -# becomes 2 and the object records MDd_DynamicDebug. Linking that against -# Framework's MD_DynamicRelease objects fails with LNK2038, and no flag or -# MSVC_RUNTIME_LIBRARY property can override it, because the definition is what -# drives it. CI confirmed exactly that: the property was applied correctly and the -# objects still came out MDd. -# -# So drop the definition on the fetched targets rather than fighting the symptom. -# This is Framework adapting to its own unusual choice, not a defect upstream -- -# MafiaNet is right to define _DEBUG when it is built normally. -# -# Nothing analogous was needed while MafiaNet was vendored: that copy was a bare -# add_library() with no target_compile_definitions of its own. -if(MSVC) - foreach(_mafianet_target MafiaNetStatic MafiaNet opus rnnoise) - if(TARGET ${_mafianet_target}) - set_property(TARGET ${_mafianet_target} PROPERTY - MSVC_RUNTIME_LIBRARY "MultiThreadedDLL") - - get_target_property(_fw_defs ${_mafianet_target} COMPILE_DEFINITIONS) - if(_fw_defs) - list(REMOVE_ITEM _fw_defs "$<$:_DEBUG>" "_DEBUG") - set_property(TARGET ${_mafianet_target} PROPERTY - COMPILE_DEFINITIONS ${_fw_defs}) - endif() - endif() - endforeach() +set(_mafianet_name "MafiaNet-${MAFIANET_PIN_VERSION}-${_mafianet_platform}") +set(_mafianet_root "${CMAKE_BINARY_DIR}/mafianet/${_mafianet_name}") + +if(NOT EXISTS "${_mafianet_root}/lib/cmake/MafiaNet/MafiaNetConfig.cmake") + set(_mafianet_archive "${CMAKE_BINARY_DIR}/mafianet/${_mafianet_name}.${_mafianet_ext}") + message(STATUS "Downloading precompiled MafiaNet ${MAFIANET_PIN_VERSION} (${_mafianet_platform})") + # EXPECTED_HASH makes any failure fatal: a failed download, a repointed tag, + # or a tampered archive all stop the configure here. + file(DOWNLOAD + "https://github.com/MafiaHub/MafiaNet/releases/download/v${MAFIANET_PIN_VERSION}/${_mafianet_name}.${_mafianet_ext}" + "${_mafianet_archive}" + EXPECTED_HASH SHA256=${MAFIANET_PIN_SHA256_${_mafianet_platform}} + SHOW_PROGRESS + ) + file(ARCHIVE_EXTRACT INPUT "${_mafianet_archive}" DESTINATION "${CMAKE_BINARY_DIR}/mafianet") + file(REMOVE "${_mafianet_archive}") endif() +# The archives carry a single Release configuration, compiled with the /MD +# runtime on Windows -- exactly the CRT FrameworkSetup forces even in Debug +# builds -- so the old _DEBUG/CRT reconciliation the source build needed is gone +# with it. Map every consumer configuration onto that Release config; the +# variables seed MAP_IMPORTED_CONFIG_* on the imported targets find_package +# creates, and are cleared right after so no other target is affected. +set(CMAKE_MAP_IMPORTED_CONFIG_DEBUG Release) +set(CMAKE_MAP_IMPORTED_CONFIG_RELWITHDEBINFO Release) +set(CMAKE_MAP_IMPORTED_CONFIG_MINSIZEREL Release) +# Resolves OpenSSL through find_dependency: on Windows that is the vendored +# OpenSSL forced above, elsewhere the system one -- either way OpenSSL 3, which +# is what the archives were compiled against. +find_package(MafiaNet ${MAFIANET_PIN_VERSION} CONFIG REQUIRED + PATHS "${_mafianet_root}" + NO_DEFAULT_PATH +) +unset(CMAKE_MAP_IMPORTED_CONFIG_DEBUG) +unset(CMAKE_MAP_IMPORTED_CONFIG_RELWITHDEBINFO) +unset(CMAKE_MAP_IMPORTED_CONFIG_MINSIZEREL) + +# find_package imports are scoped to this directory; the consumers live under +# code/ (a sibling), which could see the old add_subdirectory alias targets but +# not these. Promote everything the package exports. +foreach(_mafianet_target MafiaNet::MafiaNetStatic MafiaNet::MafiaNet MafiaNet::opus MafiaNet::rnnoise) + if(TARGET ${_mafianet_target}) + set_target_properties(${_mafianet_target} PROPERTIES IMPORTED_GLOBAL TRUE) + endif() +endforeach() + # Build sentry set(CURL_STATICLIB ON) add_subdirectory(sentry) From 9b495065e7f64067491bc274bfb1e7e557f8f1f7 Mon Sep 17 00:00:00 2001 From: Segfault <5221072+Segfaultd@users.noreply.github.com> Date: Sat, 29 Aug 2026 08:40:08 +0200 Subject: [PATCH 2/2] Vendors: map configs on MafiaNet targets only, not via global variables CMAKE_MAP_IMPORTED_CONFIG_* was live during find_package(MafiaNet), so it also seeded the OpenSSL::SSL/Crypto imported targets that find_dependency(OpenSSL) creates inside that call. Those carry a single config-less IMPORTED_LOCATION, and a mapping they cannot satisfy fails Debug configures ('IMPORTED_LOCATION not set for ... configuration Debug') -- exactly what the Linux/macOS CI legs hit. Set MAP_IMPORTED_CONFIG_* directly on the MafiaNet targets instead, in the same loop that promotes them IMPORTED_GLOBAL. --- vendors/CMakeLists.txt | 36 ++++++++++++++++++++---------------- 1 file changed, 20 insertions(+), 16 deletions(-) diff --git a/vendors/CMakeLists.txt b/vendors/CMakeLists.txt index 6e665413f..a566662d9 100644 --- a/vendors/CMakeLists.txt +++ b/vendors/CMakeLists.txt @@ -113,15 +113,6 @@ if(NOT EXISTS "${_mafianet_root}/lib/cmake/MafiaNet/MafiaNetConfig.cmake") file(REMOVE "${_mafianet_archive}") endif() -# The archives carry a single Release configuration, compiled with the /MD -# runtime on Windows -- exactly the CRT FrameworkSetup forces even in Debug -# builds -- so the old _DEBUG/CRT reconciliation the source build needed is gone -# with it. Map every consumer configuration onto that Release config; the -# variables seed MAP_IMPORTED_CONFIG_* on the imported targets find_package -# creates, and are cleared right after so no other target is affected. -set(CMAKE_MAP_IMPORTED_CONFIG_DEBUG Release) -set(CMAKE_MAP_IMPORTED_CONFIG_RELWITHDEBINFO Release) -set(CMAKE_MAP_IMPORTED_CONFIG_MINSIZEREL Release) # Resolves OpenSSL through find_dependency: on Windows that is the vendored # OpenSSL forced above, elsewhere the system one -- either way OpenSSL 3, which # is what the archives were compiled against. @@ -129,16 +120,29 @@ find_package(MafiaNet ${MAFIANET_PIN_VERSION} CONFIG REQUIRED PATHS "${_mafianet_root}" NO_DEFAULT_PATH ) -unset(CMAKE_MAP_IMPORTED_CONFIG_DEBUG) -unset(CMAKE_MAP_IMPORTED_CONFIG_RELWITHDEBINFO) -unset(CMAKE_MAP_IMPORTED_CONFIG_MINSIZEREL) -# find_package imports are scoped to this directory; the consumers live under -# code/ (a sibling), which could see the old add_subdirectory alias targets but -# not these. Promote everything the package exports. +# Two per-target fixups, on the MafiaNet targets ONLY -- deliberately not via +# the CMAKE_MAP_IMPORTED_CONFIG_* variables, which would also seed the +# OpenSSL::SSL/Crypto targets that find_dependency creates inside the same +# find_package call; those carry a single config-less IMPORTED_LOCATION, and a +# mapping they cannot satisfy fails the configure ("IMPORTED_LOCATION not set +# for ... configuration Debug"). +# +# - MAP_IMPORTED_CONFIG_*: the archives carry a single Release configuration, +# compiled with the /MD runtime on Windows -- exactly the CRT FrameworkSetup +# forces even in Debug builds -- so every consumer configuration maps onto +# it (and the old _DEBUG/CRT reconciliation the source build needed is gone). +# - IMPORTED_GLOBAL: find_package imports are scoped to this directory; the +# consumers live under code/ (a sibling), which could see the old +# add_subdirectory alias targets but not these. foreach(_mafianet_target MafiaNet::MafiaNetStatic MafiaNet::MafiaNet MafiaNet::opus MafiaNet::rnnoise) if(TARGET ${_mafianet_target}) - set_target_properties(${_mafianet_target} PROPERTIES IMPORTED_GLOBAL TRUE) + set_target_properties(${_mafianet_target} PROPERTIES + IMPORTED_GLOBAL TRUE + MAP_IMPORTED_CONFIG_DEBUG Release + MAP_IMPORTED_CONFIG_RELWITHDEBINFO Release + MAP_IMPORTED_CONFIG_MINSIZEREL Release + ) endif() endforeach()