Fix MSVC build breaks on origin/main (stdarg.h va_list, mnmaps.c #-in-macro-arg)#131
Merged
Fix MSVC build breaks on origin/main (stdarg.h va_list, mnmaps.c #-in-macro-arg)#131
Conversation
Bump decomp submodule to JRickey/ssb-decomp-re#agent/msvc-build-fixes (commit 62ba3fd23) which contains two pre-existing MSVC build breaks that have been blocking Windows RelWithDebInfo builds since the src/ → decomp/ submodule migration (#129) landed: (1) decomp/include/stdarg.h re-`#define`s `va_list __builtin_va_list` on MSVC, where that intrinsic doesn't exist (C2061). Fixed by guarding the GCC-builtin branch with `#ifndef _MSC_VER`; MSVC falls through the existing `#ifdef _MSC_VER` block at top via <vadefs.h> + __crt_va_*. (2) decomp/src/mn/mnmaps/mnmaps.c (line 1073) puts `#ifdef PORT` directives inside the `lbRelocGetFileData(...)` macro argument list. C standard says `#` in function-like macro args is undefined behavior; clang/gcc accept leniently, MSVC rejects with C2059. Fixed by hoisting the conditional values out into local variables before the macro call. A tree-wide scan turned up 30 candidate sites in 11 files but 29 of them sit inside regular function calls (accepted), so this was the only one that needed restructuring. Verified: clean RelWithDebInfo Windows build (MSVC 19.44.35225) succeeds end-to-end and produces BattleShip.exe. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
JRickey
added a commit
that referenced
this pull request
May 4, 2026
NamedTemporaryFile on Windows holds an exclusive file lock until the context exits, which would block clang from writing to the path even after `with` exits cleanly (Windows file-mapping semantics differ from POSIX). mkstemp returns a file descriptor we close immediately, giving clang an unlocked path on every platform. The C++ port code uses std::getenv with the same C++17 init-statement if pattern as five existing port/*.cpp files (port.cpp:739, port_save.cpp, renderdoc_trigger.cpp, lbreloc_byteswap.cpp, etc.) that are known to compile cleanly under MSVC, so port/port.cpp's SSB64_RELOC_FROMSOURCE block is MSVC-compatible without further changes. The MSVC fixes in PR #131 (decomp submodule bump 7a0da1e → 62ba3fd for the stdarg.h va_list guard + mnmaps.c #-in-macro-arg restructure) are pre-existing breaks unrelated to this branch — but the rebase onto post-#131 main means we're now on the MSVC-clean submodule state.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Two pre-existing MSVC build breaks have been blocking Windows RelWithDebInfo builds since the
src/→decomp/submodule migration (#129) landed. Reproduce on a clean checkout oforigin/mainwith no other patches applied.What was broken
(1)
decomp/include/stdarg.h—va_list __builtin_va_listredefinition on MSVCThe
#ifndef __sgiblock re-#definesva_list __builtin_va_list. MSVC has no__builtin_va_listintrinsic, so this fires C2061 (syntax error: identifier '__gnuc_va_list') cascading from the__GNUC_VA_LISTtypedef.MSVC fully sets up
va_*via<vadefs.h>+__crt_va_*in the existing#ifdef _MSC_VERblock at the top of the file, so it just needs to skip the GCC-builtin branch AND the IDO#elsebranch (the IDO branch would re-typedef char* va_listaftervadefs.halready typedef'd it).Fix: wrap both the GCC-builtin and IDO branches in
#ifndef _MSC_VER.(2)
decomp/src/mn/mnmaps/mnmaps.c:1073—#ifdef PORTinside macro arg list#ifdef PORTdirectives sit inside thelbRelocGetFileData(...)argument list.lbRelocGetFileDatais a function-like macro defined insrc/lb/library.h:The C standard says
#directives inside function-like macro args are undefined behavior. Clang/gcc accept leniently, MSVC rejects with C2059 (syntax error: '#') regardless of/Zc:preprocessor(the conforming preprocessor turns it into a C5101 warning AND a C2059 error).Fix: hoist the PORT/non-PORT conditional values into local variables before the macro call so the macro args themselves are directive-free. Same end semantics, no behavior change — it's purely a textual/structural fix to satisfy the C-standard rule on macro-arg preprocessor directives.
Scope
A tree-wide scan for
#ifdef PORTat non-zero paren depth turned up 30 candidate sites in 11 files, but 29 of them sit inside regular function calls (which MSVC's preprocessor accepts because the rule only applies to function-like macro args, not function args). Only the two#ifdef PORTs inmnmaps.cneeded restructuring. No other files affected.Test plan
error C2061: syntax error: identifier '__gnuc_va_list'anderror C2059: syntax error: '#'. Build succeeds after, producesBattleShip.exe.#ifndef _MSC_VERguard makes the GCC-builtin branch fire identically as before, and the mnmaps.c hoist is just a refactor. Cross-platform CI would confirm.BattleShip.exe, verify VS match boots and a Training-mode wallpaper renders (the only path the mnmaps.c hoist touches).Submodule pointer bump
Decomp pushed to
JRickey/ssb-decomp-re#agent/msvc-build-fixesat commit62ba3fd23. Outer commit69b912bbumps the submodule pointer.🤖 Generated with Claude Code