Toolchain: VS2022 (v143) is the build of record -- /FORCE:UNRESOLVED retired

The v143 linker refuses to emit an image with unresolved externals even
under /FORCE, so the dead offline-tool ladders in mech3.cpp
(Mech::CreateSubsystemStream / SubsystemDefaultData -- never called at
runtime, resources ship prebuilt in BTL4.RES) are compiled out behind
BT412_OFFLINE_TOOLS (default off). The exe links /FORCE:MULTIPLE only:
a genuinely unresolved symbol is now a hard link error instead of a
hidden runtime AV. No other source changes needed for v143.

Verified: clean build; solo DEV.EGG runs; two-instance loopback MP via
btconsole.py -- mesh forms, mission runs both sides, master + replicant
tick in each world. (Phase 1 of docs/BT412-ROADMAP.md)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Cyd
2026-07-14 07:36:19 -05:00
co-authored by Claude Fable 5
parent d8dd512843
commit 55e4295dc3
5 changed files with 84 additions and 29 deletions
+23 -3
View File
@@ -96,9 +96,11 @@
// Those ~21 classes live in sibling modules not visible here (and PPC /
// GaussRifle / SubsystemMessageManager have no reconstructed class at all),
// so the uniform factory surface is declared here as minimal stubs. The
// bodies/data are resolved at link against the real subsystem modules; these
// declarations only let the dispatch compile. Kept LOCAL so they never
// collide with the real sibling classes.
// bodies/data were NEVER reconstructed anywhere -- under v142 the link
// left them unresolved and /FORCE tolerated it (the path is dead at
// runtime); the v143 linker does not, so the dispatch ladders below are
// compiled out unless BT412_OFFLINE_TOOLS is defined. Kept LOCAL so they
// never collide with the real sibling classes if ever reconstructed.
//===========================================================================//
typedef Mech::SharedData SharedData; // namespace-scope alias (== Entity__SharedData)
@@ -711,6 +713,20 @@ void
NotationFile *subsystem_file, // param_8
const ResourceDirectories *directories) // param_9
{
#if !BT412_OFFLINE_TOOLS
//-----------------------------------------------------------------------
// BT412 NEUTRALIZED (offline authoring path -- never called at runtime;
// resources ship prebuilt in BTL4.RES). The ~21 per-subsystem
// CreateStreamedSubsystem statics were never reconstructed, and the
// VS2022 (v143) linker fails the image on unresolved externals even
// under /FORCE (the v142 linker tolerated them). The authentic
// dispatch ladder is preserved under BT412_OFFLINE_TOOLS for the day
// the offline tool path is reconstructed.
//-----------------------------------------------------------------------
DEBUG_STREAM << "[offline] Mech::CreateSubsystemStream(" << type_name
<< ") reached with BT412_OFFLINE_TOOLS off\n" << std::flush;
return -1;
#else
int result;
if (Streq(type_name, "HeatSinkClassID"))
@@ -765,6 +781,7 @@ void
}
return (result == 0) ? -1 : 1;
#endif // BT412_OFFLINE_TOOLS
}
@@ -909,6 +926,8 @@ fail:
Mech::SubsystemDefaultData(const char *type_name)
{
if (Streq(type_name, "")) return &Mech::DefaultData; // 0050bde4 (DAT_0050dc1f == "")
#if BT412_OFFLINE_TOOLS // BT412 NEUTRALIZED with the factory above -- the per-subsystem
// DefaultData statics were never reconstructed (no callers at runtime).
if (Streq(type_name, "ControlsMapper")) return &MechControlsMapper::DefaultData; // 0050ee00
if (Streq(type_name, "AmmoBinClassID")) return &AmmoBin::DefaultData; // 005125bc
if (Streq(type_name, "HeatSinkClassID")) return &HeatSink::DefaultData; // 0050e580
@@ -930,6 +949,7 @@ fail:
if (Streq(type_name, "GaussRifleClassID")) return &GaussRifle::DefaultData; // 00512478 (shares MissileLauncher table)
if (Streq(type_name, "ControlsMapper")) return &MechControlsMapper::DefaultData; // 0050ee00 (2nd alias)
if (Streq(type_name, "MechTech")) return &MechTech::DefaultData; // 0050e270
#endif // BT412_OFFLINE_TOOLS
return 0;
}