Description
Background
F# assemblies contain embedded resources for signature and optimization data that can significantly increase assembly size. These resource names are templates that get combined with the actual assembly name. To reduce the size of trimmed F# assemblies, we need to automatically remove these metadata resources during IL linking:
(the asterisk is not there, this is where the project name goes)
The full set of F#-compiler-generated prefixes currently is:
FSharpSignatureData.*
FSharpSignatureDataB.*
FSharpSignatureCompressedData.*
FSharpSignatureCompressedDataB.*
FSharpOptimizationData.*
FSharpOptimizationDataB.*
FSharpOptimizationCompressedData.*
FSharpOptimizationCompressedDataB.*
FSharpOptimizationInfo.*
FSharpSignatureInfo.*
Files to Modify
1. Create new MSBuild task: src/FSharp.Build/GenerateILLinkSubstitutions.fs
Create a new task that follows the pattern of existing embedded resource generators. Study how it creates TaskItem
objects for embedded resources.
The task should:
- Inherit from
Microsoft.Build.Utilities.Task
- Take the assembly name as input
- Generate XML content with actual resource names (not patterns with asterisks)
- Create the content in memory and add it as an
EmbeddedResource
item
Example of what the generated XML should contain (using actual assembly name):
<linker>
<assembly fullname="MyProject">
<resource name="FSharpOptimizationData.MyProject" action="remove" />
<resource name="FSharpSignatureData.MyProject" action="remove" />
<resource name="FSharpOptimizationCompressedData.MyProject" action="remove" />
<resource name="FSharpSignatureCompressedData.MyProject" action="remove" />
<resource name="FSharpOptimizationDataB.MyProject" action="remove" />
<resource name="FSharpSignatureDataB.MyProject" action="remove" />
<resource name="FSharpOptimizationCompressedDataB.MyProject" action="remove" />
<resource name="FSharpSignatureCompressedDataB.MyProject" action="remove" />
<resource name="FSharpOptimizationInfo.MyProject" action="remove" />
<resource name="FSharpSignatureInfo.MyProject" action="remove" />
</assembly>
</linker>
2. Update src/FSharp.Build/FSharp.Build.fsproj
Add the new task file to the compilation list: 3
<Compile Include="GenerateILLinkSubstitutions.fs" />
3. Add target to src/FSharp.Build/Microsoft.FSharp.NetSdk.targets
Create a new target that runs during every compilation. Looking at the existing props file structure, add:
<UsingTask TaskName="GenerateILLinkSubstitutions" AssemblyFile="$(FSharpBuildTasksAssembly)" />
<Target Name="GenerateFSharpILLinkSubstitutions" BeforeTargets="CoreCompile">
<GenerateILLinkSubstitutions
AssemblyName="$(AssemblyName)"
IntermediateOutputPath="$(IntermediateOutputPath)" />
</Target>
Implementation Steps
-
Study the existing embedded resource pattern: Look at how it generates embedded resources programmatically.
-
Understand resource name construction: The patterns are templates. You need to append the actual assembly name to create the full resource names (e.g.,
"FSharpOptimizationData." + assemblyName
). -
Create the MSBuild task:
- Follow the structure of existing tasks in
src/FSharp.Build/
- Generate XML content in memory
- Create
TaskItem
with the XML content as an embedded resource - Set appropriate metadata like
LogicalName="ILLink.Substitutions.xml"
- Use
action="remove"
for all resource entries
- Follow the structure of existing tasks in
-
Wire into the build system:
- Add the target to run during normal compilation
- Use
BeforeTargets="CoreCompile"
to ensure it runs at the right time - Pass the assembly name from MSBuild properties
-
** Create tests for the behavior.
Look at the folder https://github.com/dotnet/fsharp/tree/main/tests/AheadOfTime/Trimming to see existing trimming tests.
You will need to adjust the test setup to make it use freshly built FSharp.Build.dll as well as the adjusted props and targets.
Notes
This approach generates the substitution file as an embedded resource during compilation, ensuring F# metadata resources are removed during IL linking to reduce the size of trimmed F# assemblies.
Metadata
Metadata
Assignees
Type
Projects
Status