Tracking the final step of the cold-start / AOT-readiness work (#1577, #2715 master, #2746 AOT pillar): stop shipping JasperFx.RuntimeCompiler (Roslyn, ~6 MB) as a transitive runtime dependency of core WolverineFx, so TypeLoadMode.Static / AOT apps ship without Roslyn and cold start faster.
Current state (verified on main / 6.0.0-rc.1)
src/Wolverine/Wolverine.csproj:58 — <PackageReference Include="JasperFx.RuntimeCompiler" />, no PrivateAssets, so Roslyn flows to every consumer.
src/Wolverine/HostBuilderExtensions.cs:128-130 — UseWolverine() registers the Roslyn AssemblyGenerator by default (with an [UnconditionalSuppressMessage] IL2026 suppression).
- The opt-in package
WolverineFx.RuntimeCompilation already exists: UseRuntimeCompilation() does Services.TryAddSingleton<IAssemblyGenerator, AssemblyGenerator>() (idempotent), plus AddWolverineRuntimeCompilation(IServiceCollection).
IAssemblyGenerator is defined in JasperFx.CodeGeneration (already a core dependency). Only the concrete AssemblyGenerator lives in JasperFx.RuntimeCompiler. Core's entire dependency on the RuntimeCompiler package is the one registration line + the using JasperFx.RuntimeCompiler; at HostBuilderExtensions.cs:21.
Goal
Core WolverineFx depends only on the IAssemblyGenerator abstraction (JasperFx.CodeGeneration). The Roslyn implementation ships only in WolverineFx.RuntimeCompilation. Static-mode apps carry no Roslyn; Dynamic/Auto-mode apps add the package.
Plan
- Drop the core dependency. Remove the
JasperFx.RuntimeCompiler PackageReference from src/Wolverine/Wolverine.csproj and the using JasperFx.RuntimeCompiler; + default RegisterAssemblyGenerator(...) block from HostBuilderExtensions.cs.
- Fail fast with guidance. When
TypeLoadMode is Dynamic/Auto (or Static falls back) and no IAssemblyGenerator is registered, throw at bootstrap with an actionable message: "install WolverineFx.RuntimeCompilation and call opts.UseRuntimeCompilation(), or pre-generate with TypeLoadMode.Static." No silent NullRef / missing-service.
- Decide how the package activates — the key design call:
- (a) Explicit
opts.UseRuntimeCompilation() (what exists today), or
- (b) Auto-on-reference: referencing
WolverineFx.RuntimeCompilation is sufficient — register via a module initializer / assembly-scanned IWolverineExtension so neither users nor the test suite need an explicit call.
- Recommendation: (b) to minimize the breaking blast radius — installing the package "just works" in Dynamic mode, while Static/AOT apps that omit the package ship Roslyn-free.
- Test-suite migration (the bulk of the work). ~101 of 102
CoreTests bootstrap Dynamic mode on the default registration (only 1 calls UseRuntimeCompilation); the same is true across Http/Marten/transport suites. Either auto-on-reference (#3b) so a single package reference per test project suffices, or a shared test bootstrap helper. Verify the aot/Wolverine.AotSmoke guard still passes (it must NOT reference the compiler).
- Docs + skill. Flip
docs/guide/aot.md, docs/guide/codegen.md, and docs/guide/migration.md from "planned for v6" to "required"; update the wolverine-migration-v5-to-v6 AI skill (tracked separately in JasperFx/ai-skills).
Migration impact (BREAKING for Dynamic-mode apps)
Apps on the Dynamic/Auto default must dotnet add package WolverineFx.RuntimeCompilation (and, under option 3a, call opts.UseRuntimeCompilation()). Apps already on TypeLoadMode.Static with fully pre-generated code are unaffected and get a smaller, Roslyn-free deployment.
Open decisions
- Activation model (3a explicit vs 3b auto-on-reference) — drives the whole migration ergonomics.
- Timing — land in a 6.0 rc, or hold for 6.0 GA / a 6.x minor given it's a breaking default flip? (The in-code comment at
HostBuilderExtensions.cs:111-119 says "expected to be removed in v6".)
Refs: #1577 (cold-start roadmap), #2715 (6.0 master), #2745 (release punchlist), #2746 (AOT pillar). Companion docs/skill update: JasperFx/ai-skills.
Tracking the final step of the cold-start / AOT-readiness work (#1577, #2715 master, #2746 AOT pillar): stop shipping
JasperFx.RuntimeCompiler(Roslyn, ~6 MB) as a transitive runtime dependency of coreWolverineFx, soTypeLoadMode.Static/ AOT apps ship without Roslyn and cold start faster.Current state (verified on
main/ 6.0.0-rc.1)src/Wolverine/Wolverine.csproj:58—<PackageReference Include="JasperFx.RuntimeCompiler" />, noPrivateAssets, so Roslyn flows to every consumer.src/Wolverine/HostBuilderExtensions.cs:128-130—UseWolverine()registers the RoslynAssemblyGeneratorby default (with an[UnconditionalSuppressMessage]IL2026 suppression).WolverineFx.RuntimeCompilationalready exists:UseRuntimeCompilation()doesServices.TryAddSingleton<IAssemblyGenerator, AssemblyGenerator>()(idempotent), plusAddWolverineRuntimeCompilation(IServiceCollection).IAssemblyGeneratoris defined inJasperFx.CodeGeneration(already a core dependency). Only the concreteAssemblyGeneratorlives inJasperFx.RuntimeCompiler. Core's entire dependency on the RuntimeCompiler package is the one registration line + theusing JasperFx.RuntimeCompiler;atHostBuilderExtensions.cs:21.Goal
Core
WolverineFxdepends only on theIAssemblyGeneratorabstraction (JasperFx.CodeGeneration). The Roslyn implementation ships only inWolverineFx.RuntimeCompilation. Static-mode apps carry no Roslyn; Dynamic/Auto-mode apps add the package.Plan
JasperFx.RuntimeCompilerPackageReferencefromsrc/Wolverine/Wolverine.csprojand theusing JasperFx.RuntimeCompiler;+ defaultRegisterAssemblyGenerator(...)block fromHostBuilderExtensions.cs.TypeLoadModeisDynamic/Auto(orStaticfalls back) and noIAssemblyGeneratoris registered, throw at bootstrap with an actionable message: "installWolverineFx.RuntimeCompilationand callopts.UseRuntimeCompilation(), or pre-generate withTypeLoadMode.Static." No silent NullRef / missing-service.opts.UseRuntimeCompilation()(what exists today), orWolverineFx.RuntimeCompilationis sufficient — register via a module initializer / assembly-scannedIWolverineExtensionso neither users nor the test suite need an explicit call.CoreTestsbootstrap Dynamic mode on the default registration (only 1 callsUseRuntimeCompilation); the same is true across Http/Marten/transport suites. Either auto-on-reference (#3b) so a single package reference per test project suffices, or a shared test bootstrap helper. Verify theaot/Wolverine.AotSmokeguard still passes (it must NOT reference the compiler).docs/guide/aot.md,docs/guide/codegen.md, anddocs/guide/migration.mdfrom "planned for v6" to "required"; update thewolverine-migration-v5-to-v6AI skill (tracked separately in JasperFx/ai-skills).Migration impact (BREAKING for Dynamic-mode apps)
Apps on the
Dynamic/Autodefault mustdotnet add package WolverineFx.RuntimeCompilation(and, under option 3a, callopts.UseRuntimeCompilation()). Apps already onTypeLoadMode.Staticwith fully pre-generated code are unaffected and get a smaller, Roslyn-free deployment.Open decisions
HostBuilderExtensions.cs:111-119says "expected to be removed in v6".)Refs: #1577 (cold-start roadmap), #2715 (6.0 master), #2745 (release punchlist), #2746 (AOT pillar). Companion docs/skill update: JasperFx/ai-skills.