Overview
Cosmos.Patcher.Build wires the Cosmos.Patcher tool into the MSBuild pipeline. Cosmos.Patcher rewrites IL in candidate assemblies by applying CosmosOS-style plugs so that the .NET Core framework can run on NativeAOT targets. Static analysis is provided by Cosmos.Patcher.Analyzer, which reports plug errors during C# compilation before any IL is rewritten.
.NET Assembly Structure
A .NET assembly (.dll or .exe) is a portable executable containing metadata and IL code. The patcher manipulates these structures using Mono.Cecil.
┌─────────────────────────────────────────────────────────────────────┐
│ AssemblyDefinition │
│ ┌───────────────────────────────────────────────────────────────┐ │
│ │ Name: "MyAssembly" │ │
│ │ Version: 1.0.0.0 │ │
│ │ CustomAttributes: [AssemblyInfo, ...] │ │
│ └───────────────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌───────────────────────────────────────────────────────────────┐ │
│ │ ModuleDefinition[0] │ │
│ │ ┌─────────────────────────────────────────────────────────┐ │ │
│ │ │ Name: "MyAssembly.dll" │ │ │
│ │ │ AssemblyReferences: [mscorlib, System.Runtime, ...] │ │ │
│ │ │ TypeReferences: [external type tokens] │ │ │
│ │ └─────────────────────────────────────────────────────────┘ │ │
│ │ │ │ │
│ │ ▼ │ │
│ │ ┌─────────────────────────────────────────────────────────┐ │ │
│ │ │ TypeDefinition[0] │ │ │
│ │ │ ┌───────────────────────────────────────────────────┐ │ │ │
│ │ │ │ FullName: "MyNamespace.MyClass" │ │ │ │
│ │ │ │ BaseType: System.Object │ │ │ │
│ │ │ │ Interfaces: [IDisposable, ...] │ │ │ │
│ │ │ │ CustomAttributes: [Plug, Serializable, ...] │ │ │ │
│ │ │ │ │ │ │ │
│ │ │ │ ┌─────────────────────────────────────────────┐ │ │ │ │
│ │ │ │ │ FieldDefinition[0] │ │ │ │ │
│ │ │ │ │ Name, FieldType, Attributes, Constant │ │ │ │ │
│ │ │ │ ├─────────────────────────────────────────────┤ │ │ │ │
│ │ │ │ │ FieldDefinition[n] │ │ │ │ │
│ │ │ │ └─────────────────────────────────────────────┘ │ │ │ │
│ │ │ │ │ │ │ │
│ │ │ │ ┌─────────────────────────────────────────────┐ │ │ │ │
│ │ │ │ │ PropertyDefinition[0] │ │ │ │ │
│ │ │ │ │ Name, PropertyType, GetMethod, SetMethod │ │ │ │ │
│ │ │ │ ├─────────────────────────────────────────────┤ │ │ │ │
│ │ │ │ │ PropertyDefinition[n] │ │ │ │ │
│ │ │ │ └─────────────────────────────────────────────┘ │ │ │ │
│ │ │ │ │ │ │ │
│ │ │ │ ┌─────────────────────────────────────────────┐ │ │ │ │
│ │ │ │ │ MethodDefinition[0] │ │ │ │ │
│ │ │ │ │ Name, ReturnType, Parameters, Attributes │ │ │ │ │
│ │ │ │ │ │ │ │ │ │
│ │ │ │ │ ┌───────────────────────────────────────┐ │ │ │ │ │
│ │ │ │ │ │ MethodBody │ │ │ │ │ │
│ │ │ │ │ │ Variables: [local0, local1, ...] │ │ │ │ │ │
│ │ │ │ │ │ MaxStackSize: 8 │ │ │ │ │ │
│ │ │ │ │ │ InitLocals: true │ │ │ │ │ │
│ │ │ │ │ │ │ │ │ │ │ │
│ │ │ │ │ │ Instructions: │ │ │ │ │ │
│ │ │ │ │ │ IL_0000: ldarg.0 │ │ │ │ │ │
│ │ │ │ │ │ IL_0001: call .ctor │ │ │ │ │ │
│ │ │ │ │ │ IL_0006: ldstr "Hello" │ │ │ │ │ │
│ │ │ │ │ │ IL_000B: call Console.WriteLine │ │ │ │ │ │
│ │ │ │ │ │ IL_0010: ret │ │ │ │ │ │
│ │ │ │ │ │ │ │ │ │ │ │
│ │ │ │ │ │ ExceptionHandlers: │ │ │ │ │ │
│ │ │ │ │ │ [try/catch/finally blocks] │ │ │ │ │ │
│ │ │ │ │ └───────────────────────────────────────┘ │ │ │ │ │
│ │ │ │ ├─────────────────────────────────────────────┤ │ │ │ │
│ │ │ │ │ MethodDefinition[n] │ │ │ │ │
│ │ │ │ └─────────────────────────────────────────────┘ │ │ │ │
│ │ │ └───────────────────────────────────────────────────┘ │ │ │
│ │ ├─────────────────────────────────────────────────────────┤ │ │
│ │ │ TypeDefinition[n] │ │ │
│ │ └─────────────────────────────────────────────────────────┘ │ │
│ └───────────────────────────────────────────────────────────────┘ │
│ ┌───────────────────────────────────────────────────────────────┐ │
│ │ ModuleDefinition[n] │ │
│ └───────────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────────┘
Flow chart
flowchart TD
A[SetupPatcher] --> B[FindPluggedAssembliesTask]
B --> C{AssembliesToPatch}
C -->|for each| D[PatcherTask]
D --> E[Program patch]
E --> F[PatchCommand.Execute]
F --> G[PlugScanner.LoadPlugs]
G --> H[PlugPatcher.PatchAssembly]
H --> I[ProcessPlugMembers]
I --> J[MethodResolver.ResolveMethod]
J --> K[MethodPatcher.PatchMethod]
K --> L[ILCloner.CloneInstructions]
L --> M[TypeImporter.SafeImport*]
I --> N[PropertyPatcher.PatchProperty]
I --> O[FieldPatcher.PatchField]
K --> P[Patched assemblies]
N --> P
O --> P
A --> X[CleanPatcher]
Parameters
| Name | Description | Default |
|---|---|---|
EnablePatching |
Enables or disables patching. | true |
CosmosPatcherExe |
Path to the Cosmos.Patcher executable. |
%USERPROFILE%\.dotnet\tools\cosmos.patcher.exe on Windows, cosmos.patcher on Unix |
PatcherOutputPath |
Directory where patched assemblies are written. | $(IntermediateOutputPath)/cosmos/ref/ |
PlugReference |
Names of plug assemblies to include. | none |
Tasks
| Task | Description | Depends On |
|---|---|---|
SetupPatcher |
Collects candidate assemblies, resolves plug references, and prepares output directories. | Build, ResolveIlcPath |
RunPatcher |
Executes Cosmos.Patcher for each entry in AssembliesToPatch. |
SetupPatcher |
CleanPatcher |
Removes files generated by the patcher. | Clean |
FindPluggedAssembliesTask |
Filters candidate assemblies to only those containing target types. | SetupPatcher |
PatcherTask |
MSBuild wrapper around Cosmos.Patcher for custom scenarios. |
none |
Detailed workflow
SetupPatcher gathers output and reference assemblies, resolves plug references, and stores them in
$(IntermediateOutputPath)/cosmos.FindPluggedAssembliesTask uses
PlugScanner.FindPluggedAssembliesto cross-reference plug targets against the candidate assemblies and producesAssembliesToPatch.RunPatcher iterates over
AssembliesToPatchand, for each assembly, thePatcherTasklaunches theCosmos.PatcherCLI (Program→PatchCommand.Execute). InsideExecute:- The target assembly is loaded with
AssemblyDefinition.ReadAssemblyand plug assemblies are gathered. PlugScanner.LoadPlugsdiscovers plug types in those assemblies.PlugPatcher.PatchAssemblygroups plugs by their[Plug]target and patches each target type using:MethodResolvermatches plug signatures (including constructors andaThisparameters) by name and parameter types.MethodPatcherswaps or clones IL and strips P/Invoke metadata.ILClonerclones instructions, remaps parameters, and fixes branch targets.TypeImportersafely imports type/method/field references, fixing self-references that would cause invalid IL metadata.PropertyPatcherwires getters and setters to plug implementations.FieldPatchercopies constant values and redirects field accesses.
- The patched assembly is written to
PatcherOutputPath.
- The target assembly is loaded with
CleanPatcher deletes the patched output when the project is cleaned.
Cosmos.Patcher.Analyzervalidates plug rules during compilation to catch errors before patching.
Outputs
- Patched app assembly:
$(IntermediateOutputPath)/cosmos/$(AssemblyName)_patched.dll— main project output after plug application. - Reference assemblies for ILC:
$(IntermediateOutputPath)/cosmos/ref/*.dll— patched where plugs apply; otherwise copied unmodified for resolution. - Intermediate directories are created on demand under
$(IntermediateOutputPath)/cosmos/.
Notes:
RunPatcheronly runs whenEnablePatchingistrueand afterSetupPatchercomputes@(AssembliesToPatch)and destinations.