Build failure on MSVC 14.50.35717 (Visual Studio 2026 Build Tools): m_link/offsetof-based static_asserts cause cascading parse errors in CAnimBlendAssociation.h / AnimAssociationData.h
Environment
- plugin-sdk commit:
5da18b6f1956bb20bdfa39dcb07c44863ce26c81
- Target:
plugin_sa (GTA:SA)
- Toolset: MSVC
14.50.35717 (Visual Studio 2026 Build Tools)
- Generator:
cmake -B build -A Win32 (32-bit)
- Required compile flags for this toolset:
/std:c++latest /Zc:offsetof- (see below — both are necessary just to get past unrelated errors first)
Summary
Compiling any translation unit that transitively includes plugin_sa/game_sa/AnimAssociationData.h or plugin_sa/game_sa/CAnimBlendAssociation.h fails with a cascading sequence of parser errors, starting from an offsetof-based VALIDATE_OFFSET/static_assert failure on the m_link member (a CLink<T> instance), which then desyncs the parser for the remainder of the header and everything that follows it in the translation unit (CMatrix.h, CMatrixLink.h, C2dEffect.h, etc. all then fail too).
Steps to reproduce
- Set up a minimal
plugin_sa ASI project against this commit, targeting MSVC 14.50.35717 / VS2026 Build Tools, 32-bit (-A Win32).
- Compile with:
target_compile_features(${PROJECT_NAME} PUBLIC cxx_std_23)
target_compile_options(${PROJECT_NAME} PRIVATE /std:c++latest /Zc:offsetof-)
(/std:c++latest is required because safetyhook.hpp, pulled in transitively via plugin_sa.h → plugin.h, uses std::expected, which this MSVC version only exposes under /std:c++latest, not plain /std:c++23. /Zc:offsetof- is required because plugin-sdk's VALIDATE_OFFSET/VALIDATE_SIZE macros use offsetof() on non-standard-layout types, which the conforming offsetof() rejects with C2618: illegal member designator in offsetof.)
- Include any header that pulls in
game_sa/CAnimBlendAssociation.h (e.g. via game_sa/CPed.h → game_sa/CVehicle.h → ... or directly).
- Build.
Observed error (abbreviated)
plugin_sa\game_sa\AnimAssociationData.h(17,14): error C3646: 'm_link': unknown override specifier
plugin_sa\game_sa\AnimAssociationData.h(17,5): error C4430: missing type specifier - int assumed
plugin_sa\game_sa\AnimAssociationData.h(30,1): error C2039: 'm_link': is not a member of 'AnimAssociationData'
plugin_sa\game_sa\AnimAssociationData.h(30,1): error C2618: illegal member designator in offsetof
plugin_sa\game_sa\AnimAssociationData.h(31,1): error C2338: static assertion failed: 'The offset of m_nNumBlendNodes in AnimAssociationData is not 0x8...'
... (continues through every member of AnimAssociationData, then identically through CAnimBlendAssociation.h, then meta/meta.CAnimBlendAssociation.h with RpClump/RwMatrix undeclared-identifier errors, then CMatrix.h, CMatrixLink.h, C2dEffect.h, until error count exceeds 100 and compilation stops)
the rest of the errors
The same cascade occurs identically in every .cpp translation unit that reaches these headers, at the same line numbers, regardless of include order in the consuming .cpp/.hpp files — which rules out include-order issues on the consumer side.
What I've ruled out
- Not consumer-side include order (verified — cascade is identical and order-independent across multiple translation units with different include sequences).
- Not project include-path misconfiguration (verified with a minimal
shared + plugin_sa + plugin_sa/game_sa include set).
- Not
/Zc:offsetof-/C++23 standard selection on their own (both are individually required for this toolset just to get past safetyhook.hpp's std::expected usage and the VALIDATE_OFFSET macros elsewhere in the SDK — removing either produces different, earlier failures).
CMakeLists.txt:
# cmake -B build -A Win32
# cmake --build build --config Release
cmake_minimum_required(VERSION 3.20)
project("brownturbo-chandling" LANGUAGES C CXX VERSION 0.0.1)
set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>DLL" CACHE STRING "" FORCE)
set(POLYHOOK_STATIC_RUNTIME OFF CACHE BOOL "" FORCE)
set(FORCE_STATIC_CRT OFF CACHE BOOL "" FORCE)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}/bin)
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}/bin)
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
add_compile_definitions(__BITSTREAM_NATIVE_END)
add_library(${PROJECT_NAME} SHARED)
target_compile_definitions(${PROJECT_NAME} PRIVATE
_NDEBUG
_CRT_SECURE_NO_WARNINGS
_CRT_NON_CONFORMING_SWPRINTFS
GTASA
GTAGAME_NAME="San Andreas"
GTAGAME_ABBR="SA"
GTAGAME_ABBRLOW="sa"
GTAGAME_PROTAGONISTNAME="CJ"
GTAGAME_CITYNAME="San Andreas"
_LA_SUPPORT
PLUGIN_SGV_10US
)
target_sources(${PROJECT_NAME} PRIVATE
Plugin.cpp
handling_manager.cpp
)
set_target_properties(${PROJECT_NAME}
PROPERTIES
OUTPUT_NAME ${PROJECT_NAME}
SUFFIX ".asi"
)
target_compile_features(${PROJECT_NAME} PUBLIC cxx_std_20)
target_compile_options(${PROJECT_NAME} PRIVATE /std:c++latest /Zc:offsetof-)
target_compile_definitions(${PROJECT_NAME} PRIVATE _SILENCE_CXX20_ISSUES)
set(PLUGIN_SDK_DIR "${CMAKE_CURRENT_SOURCE_DIR}/deps/plugin-sdk")
set(SAMPAPI_DIR "${CMAKE_CURRENT_SOURCE_DIR}/deps/samp-api")
set(RAKHOOK_DIR "${CMAKE_CURRENT_SOURCE_DIR}/deps/rakhook")
add_subdirectory(${RAKHOOK_DIR}/lib/minhook)
add_subdirectory(${RAKHOOK_DIR})
add_subdirectory(${SAMPAPI_DIR})
target_include_directories(${PROJECT_NAME} PRIVATE ${SAMPAPI_DIR}/include/sampapi)
target_include_directories(${PROJECT_NAME} PRIVATE ${RAKHOOK_DIR}/lib/minhook/include)
target_include_directories(${PROJECT_NAME} PRIVATE ${RAKHOOK_DIR}/include)
target_include_directories(${PROJECT_NAME} PRIVATE
${PLUGIN_SDK_DIR}/shared
${PLUGIN_SDK_DIR}/plugin_sa
${PLUGIN_SDK_DIR}/plugin_sa/game_sa
${PLUGIN_SDK_DIR}/plugin_sa/game_sa/enums
)
target_link_libraries(${PROJECT_NAME} PRIVATE
$<$<CONFIG:Debug>:plugin_d>
$<$<CONFIG:Release>:plugin>
minhook
sampapi
rakhook
)
function(force_dynamic_runtime_on_all_targets dir)
get_property(subdirs DIRECTORY ${dir} PROPERTY SUBDIRECTORIES)
foreach(subdir ${subdirs})
force_dynamic_runtime_on_all_targets(${subdir})
endforeach()
get_property(current_targets DIRECTORY ${dir} PROPERTY BUILDSYSTEM_TARGETS)
foreach(target ${current_targets})
get_target_property(target_type ${target} TYPE)
if(NOT target_type STREQUAL "INTERFACE_LIBRARY")
set_property(TARGET ${target} PROPERTY
MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>DLL"
)
endif()
endforeach()
endfunction()
force_dynamic_runtime_on_all_targets(${CMAKE_CURRENT_SOURCE_DIR})
Plugin.cpp:
#include <windows.h>
#include <iostream>
// SDK's own vector definitions
#include <game/CVector.h>
#include <game/CVector2D.h>
// RenderWare
#include <RenderWare.h>
// plugin-sdk
#include <plugin_sa.h>
// game_sa headers
#include <game_sa/CPed.h>
#include <sampapi/sampapi.h>
#include <sampapi/CChat.h>
#include <sampapi/CNetGame.h>
#include <RakNet/PacketEnumerations.h>
#include <RakNet/StringCompressor.h>
#include <RakNet/BitStream.h>
#include <RakHook/samp.hpp>
#include <map>
#include <memory>
#include <thread>
#include <chrono>
#include <cstring>
#include "handling_manager.hpp"
using namespace plugin;
void InitializeHooks() {
static bool initialized = false;
if (initialized) return;
initialized = true;
// Initialize RakHook once SAMP is fully initialized
std::thread([]() {
sampapi::CChat::AddMessageToPlayer(-1, "{00FF00}[HandlingPlugin]{FFFFFF} Loaded successfully!");
// Initialize RakHook hooks
rakhook::initialize();
// ....
}).detach();
}
BOOL APIENTRY DllMain(HMODULE hModule, DWORD dwReason, LPVOID lpReserved)
{
switch (dwReason) {
case DLL_PROCESS_ATTACH: {
DisableThreadLibraryCalls(hModule);
// ...
break;
}
case DLL_PROCESS_DETACH: {
rakhook::on_receive_rpc.clear();
rakhook::on_send_rpc.clear();
rakhook::on_receive_packet.clear();
rakhook::on_send_packet.clear();
if (GetModuleHandleA("samp.dll") != nullptr) {
rakhook::destroy();
}
break;
}
}
return true;
}
Build failure on MSVC 14.50.35717 (Visual Studio 2026 Build Tools):
m_link/offsetof-based static_asserts cause cascading parse errors inCAnimBlendAssociation.h/AnimAssociationData.hEnvironment
5da18b6f1956bb20bdfa39dcb07c44863ce26c81plugin_sa(GTA:SA)14.50.35717(Visual Studio 2026 Build Tools)cmake -B build -A Win32(32-bit)/std:c++latest /Zc:offsetof-(see below — both are necessary just to get past unrelated errors first)Summary
Compiling any translation unit that transitively includes
plugin_sa/game_sa/AnimAssociationData.horplugin_sa/game_sa/CAnimBlendAssociation.hfails with a cascading sequence of parser errors, starting from anoffsetof-basedVALIDATE_OFFSET/static_assertfailure on them_linkmember (aCLink<T>instance), which then desyncs the parser for the remainder of the header and everything that follows it in the translation unit (CMatrix.h,CMatrixLink.h,C2dEffect.h, etc. all then fail too).Steps to reproduce
plugin_saASI project against this commit, targeting MSVC 14.50.35717 / VS2026 Build Tools, 32-bit (-A Win32)./std:c++latestis required becausesafetyhook.hpp, pulled in transitively viaplugin_sa.h→plugin.h, usesstd::expected, which this MSVC version only exposes under/std:c++latest, not plain/std:c++23./Zc:offsetof-is required because plugin-sdk'sVALIDATE_OFFSET/VALIDATE_SIZEmacros useoffsetof()on non-standard-layout types, which the conformingoffsetof()rejects withC2618: illegal member designator in offsetof.)game_sa/CAnimBlendAssociation.h(e.g. viagame_sa/CPed.h→game_sa/CVehicle.h→ ... or directly).Observed error (abbreviated)
the rest of the errors
The same cascade occurs identically in every
.cpptranslation unit that reaches these headers, at the same line numbers, regardless of include order in the consuming.cpp/.hppfiles — which rules out include-order issues on the consumer side.What I've ruled out
shared+plugin_sa+plugin_sa/game_sainclude set)./Zc:offsetof-/C++23 standard selection on their own (both are individually required for this toolset just to get pastsafetyhook.hpp'sstd::expectedusage and theVALIDATE_OFFSETmacros elsewhere in the SDK — removing either produces different, earlier failures).CMakeLists.txt:
Plugin.cpp: