Skip to content

Auto-generate IlLink.Substitutions.xml to Remove F# Metadata Resources #18591

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
T-Gro opened this issue May 22, 2025 · 0 comments · May be fixed by #18592
Open

Auto-generate IlLink.Substitutions.xml to Remove F# Metadata Resources #18591

T-Gro opened this issue May 22, 2025 · 0 comments · May be fixed by #18592

Comments

@T-Gro
Copy link
Member

T-Gro commented May 22, 2025

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

  1. Study the existing embedded resource pattern: Look at how it generates embedded resources programmatically.

  2. 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).

  3. 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
  4. 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
  5. ** 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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Status: New
Development

Successfully merging a pull request may close this issue.

1 participant