Skip to content

a huge failure in the compilation process of plugin-sdk specifically (MSVC 14.50.35717) #320

Description

@Zorono

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

  1. Set up a minimal plugin_sa ASI project against this commit, targeting MSVC 14.50.35717 / VS2026 Build Tools, 32-bit (-A Win32).
  2. 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.hplugin.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.)
  3. Include any header that pulls in game_sa/CAnimBlendAssociation.h (e.g. via game_sa/CPed.hgame_sa/CVehicle.h → ... or directly).
  4. 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;
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions