Skip to content

Make JasperFx.RuntimeCompiler a development-only dependency (decouple Roslyn from core WolverineFx) #2876

Description

@jeremydmiller

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-130UseWolverine() 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

  1. 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.
  2. 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.
  3. 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.
  4. 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).
  5. 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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions