What happened
Building any app target (OloEditor, OloRuntime, OloServer) in Dist config fails to link on a clean origin/master checkout (reproduced at cafd1734, no local modifications):
OloEngine.lib : fatal error LNK1248: image size (10007B6EE) exceeds maximum allowable size (FFFFFFFF)
0x10007B6EE = 4,295,472,878 bytes — the archive is ~494 KB over the classic COFF archive format's hard 4 GiB member-offset limit.
Root cause
cmake/SetupConfigurations.cmake copies Release's compiler/linker flags to Dist verbatim, and both configs get LTO/whole-program-optimization (/GL + /LTCG) — confirmed at configure time:
-- Enabled Link-Time Optimization (LTO) for OloEngine (Release/Dist only)
/GL defers native codegen to the final link step, so each .obj stores compiler IL/AST bitcode instead of machine code. For template- and binding-heavy translation units this bitcode is enormous — inspecting the partial Dist build's intermediates:
| Object file |
Size |
LuaScriptGlue.obj |
360 MB |
Scene.obj |
91 MB |
ScriptGlue.obj |
87 MB |
SceneSerializer.obj |
66 MB |
SaveGameSerializer.obj |
61 MB |
Prefab.obj |
43 MB |
(LuaScriptGlue.cpp is 5175 lines of Sol2 usertype registration — hundreds of heavily-templated bindings, consistent with the theory.) Normal (non-/GL) .obj files for the same TUs are a few MB at most. Multiplied across the ~900 translation units in OloEngine, the archived total crosses the 4 GiB ceiling.
Why CI has never seen this
Every CI workflow that builds the engine (Windows.yml, asan.yml, cross-vendor.yml, flaky-repro-281.yml, video-ffmpeg.yml, SonarCloud.yml) builds Release or Debug, never Dist:
Windows.yml:24: BUILD_TYPE: Release
Release links fine (confirmed: Windows CI green through the latest master commit, cafd1734). So this has presumably been silently broken in Dist for a while — Dist is the shipping/distribution config and, as far as I can tell, has no CI coverage at all.
Reproduction
cmake --preset msvc
cmake --build build --target OloServer --config Dist --parallel 6
```//fails partway through linking OloEngine.vcxproj
## Suggested directions (not investigated further — scoping this as a spike)
- Split `OloEngine` into multiple static libs (would also help the "OloEngine.lib is monolithic" issue class generally), so no single archive approaches the limit.
- Investigate whether `/GL` object bloat can be reduced for the worst offenders (e.g. does splitting `LuaScriptGlue.cpp`'s registration across multiple TUs help, given each TU's IL is presumably compiled/stored independently?).
- Add a Dist build to CI (even just a link-only smoke build) so this class of regression is caught going forward — right now Dist is completely unverified.
- Confirm whether this is a recent regression (codebase growth) or has been broken for a long time; a bisect wasn't attempted here since Dist has no CI signal to bisect against.
## Context
Found while investigating C++Now 2026 audit item 2 (a `/Gw` linker-flag A/B on Dist binary size, from Vito Gamberini's *Leveraging the Linker* talk) — the `/Gw` measurement itself is blocked by this: there's no linkable Dist baseline to compare against. See `HANDOVER.md` on `feature/cppnow26-audits` for the full context; this issue was filed instead of attempting a workaround so the underlying breakage doesn't stay silent.
What happened
Building any app target (
OloEditor,OloRuntime,OloServer) in Dist config fails to link on a cleanorigin/mastercheckout (reproduced atcafd1734, no local modifications):0x10007B6EE= 4,295,472,878 bytes — the archive is ~494 KB over the classic COFF archive format's hard 4 GiB member-offset limit.Root cause
cmake/SetupConfigurations.cmakecopies Release's compiler/linker flags to Dist verbatim, and both configs get LTO/whole-program-optimization (/GL+/LTCG) — confirmed at configure time:/GLdefers native codegen to the final link step, so each.objstores compiler IL/AST bitcode instead of machine code. For template- and binding-heavy translation units this bitcode is enormous — inspecting the partial Dist build's intermediates:LuaScriptGlue.objScene.objScriptGlue.objSceneSerializer.objSaveGameSerializer.objPrefab.obj(
LuaScriptGlue.cppis 5175 lines of Sol2usertyperegistration — hundreds of heavily-templated bindings, consistent with the theory.) Normal (non-/GL).objfiles for the same TUs are a few MB at most. Multiplied across the ~900 translation units inOloEngine, the archived total crosses the 4 GiB ceiling.Why CI has never seen this
Every CI workflow that builds the engine (
Windows.yml,asan.yml,cross-vendor.yml,flaky-repro-281.yml,video-ffmpeg.yml,SonarCloud.yml) builds Release or Debug, never Dist:Release links fine (confirmed: Windows CI green through the latest master commit,
cafd1734). So this has presumably been silently broken in Dist for a while — Dist is the shipping/distribution config and, as far as I can tell, has no CI coverage at all.Reproduction