From 0cd324beae7606a5c65655573dce73718027423e Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 22 May 2025 12:20:06 +0000 Subject: [PATCH 1/9] Initial plan for issue From 3aff8dbeef1f84a5c646dcf6a02443e17dda6c41 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 23 May 2025 08:54:05 +0000 Subject: [PATCH 2/9] Implement GenerateILLinkSubstitutions task for F# metadata trimming Co-authored-by: T-Gro <46543583+T-Gro@users.noreply.github.com> --- src/FSharp.Build/FSharp.Build.fsproj | 1 + .../GenerateILLinkSubstitutions.fs | 94 +++++++++++++++++++ .../Microsoft.FSharp.NetSdk.targets | 12 +++ 3 files changed, 107 insertions(+) create mode 100644 src/FSharp.Build/GenerateILLinkSubstitutions.fs diff --git a/src/FSharp.Build/FSharp.Build.fsproj b/src/FSharp.Build/FSharp.Build.fsproj index 8f2fd4f5951..080c53399b1 100644 --- a/src/FSharp.Build/FSharp.Build.fsproj +++ b/src/FSharp.Build/FSharp.Build.fsproj @@ -46,6 +46,7 @@ + diff --git a/src/FSharp.Build/GenerateILLinkSubstitutions.fs b/src/FSharp.Build/GenerateILLinkSubstitutions.fs new file mode 100644 index 00000000000..77ab08a5d69 --- /dev/null +++ b/src/FSharp.Build/GenerateILLinkSubstitutions.fs @@ -0,0 +1,94 @@ +// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information. + +namespace FSharp.Build + +open System +open System.IO +open System.Text +open Microsoft.Build.Framework +open Microsoft.Build.Utilities + +/// +/// MSBuild task that generates ILLink.Substitutions.xml file to remove F# metadata resources during IL linking. +/// +type GenerateILLinkSubstitutions() = + inherit Task() + + let mutable _assemblyName = "" + let mutable _intermediateOutputPath = "" + let mutable _generatedItems: ITaskItem[] = [||] + + /// + /// Assembly name to use when generating resource names to be removed. + /// + [] + member _.AssemblyName + with get () = _assemblyName + and set value = _assemblyName <- value + + /// + /// Intermediate output path for storing the generated file. + /// + [] + member _.IntermediateOutputPath + with get () = _intermediateOutputPath + and set value = _intermediateOutputPath <- value + + /// + /// Generated embedded resource items. + /// + [] + member _.GeneratedItems + with get () = _generatedItems + and set value = _generatedItems <- value + + override this.Execute() = + try + // Define the resource prefixes that need to be removed + let resourcePrefixes = [| + "FSharpSignatureData" + "FSharpSignatureDataB" + "FSharpSignatureCompressedData" + "FSharpSignatureCompressedDataB" + "FSharpOptimizationData" + "FSharpOptimizationDataB" + "FSharpOptimizationCompressedData" + "FSharpOptimizationCompressedDataB" + "FSharpOptimizationInfo" + "FSharpSignatureInfo" + |] + + // Generate the XML content + let sb = StringBuilder() + sb.AppendLine("") |> ignore + sb.AppendLine("") |> ignore + sb.AppendLine($" ") |> ignore + + // Add each resource entry + for prefix in resourcePrefixes do + sb.AppendLine($" ") |> ignore + + // Close all resource tags + for _ in resourcePrefixes do + sb.Append("") |> ignore + + // Close assembly and linker tags + sb.AppendLine("") |> ignore + sb.AppendLine("") |> ignore + + let xmlContent = sb.ToString() + + // Create a file in the intermediate output path + let outputFileName = Path.Combine(_intermediateOutputPath, "ILLink.Substitutions.xml") + Directory.CreateDirectory(_intermediateOutputPath) |> ignore + File.WriteAllText(outputFileName, xmlContent) + + // Create a TaskItem for the generated file + let item = TaskItem(outputFileName) :> ITaskItem + item.SetMetadata("LogicalName", "ILLink.Substitutions.xml") + + _generatedItems <- [| item |] + true + with ex -> + this.Log.LogErrorFromException(ex, true) + false \ No newline at end of file diff --git a/src/FSharp.Build/Microsoft.FSharp.NetSdk.targets b/src/FSharp.Build/Microsoft.FSharp.NetSdk.targets index 2b121a778b2..6e3dbe14f2c 100644 --- a/src/FSharp.Build/Microsoft.FSharp.NetSdk.targets +++ b/src/FSharp.Build/Microsoft.FSharp.NetSdk.targets @@ -154,6 +154,18 @@ WARNING: DO NOT MODIFY this file unless you are knowledgeable about MSBuild and true + + + + + + + + + + + + From 4b8ac746dde97df7d6643a8ba73713e4c3ef258c Mon Sep 17 00:00:00 2001 From: Tomas Grosup Date: Thu, 29 May 2025 12:34:13 +0200 Subject: [PATCH 5/9] Update src/FSharp.Build/GenerateILLinkSubstitutions.fs --- src/FSharp.Build/GenerateILLinkSubstitutions.fs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/FSharp.Build/GenerateILLinkSubstitutions.fs b/src/FSharp.Build/GenerateILLinkSubstitutions.fs index 3bf461ce928..457ba39bbe6 100644 --- a/src/FSharp.Build/GenerateILLinkSubstitutions.fs +++ b/src/FSharp.Build/GenerateILLinkSubstitutions.fs @@ -29,7 +29,7 @@ type GenerateILLinkSubstitutions() = /// /// Generated embedded resource items. /// - [] + [] member val GeneratedItems = [| |] : ITaskItem[] with get, set override this.Execute() = From 28d99ca46801e217d5fafa51897aa81e84163263 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 3 Jun 2025 08:54:20 +0000 Subject: [PATCH 6/9] Update check.ps1 to report actual file sizes when expected length is placeholder -1 Co-authored-by: T-Gro <46543583+T-Gro@users.noreply.github.com> --- tests/AheadOfTime/Trimming/check.ps1 | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/tests/AheadOfTime/Trimming/check.ps1 b/tests/AheadOfTime/Trimming/check.ps1 index 349bfc9eca3..bda575bddcd 100644 --- a/tests/AheadOfTime/Trimming/check.ps1 +++ b/tests/AheadOfTime/Trimming/check.ps1 @@ -33,7 +33,11 @@ function CheckTrim($root, $tfm, $outputfile, $expected_len) { # Checking that the trimmed outputfile binary is of expected size (needs adjustments if test is updated). $file = Get-Item (Join-Path $PSScriptRoot "${root}\bin\release\${tfm}\win-x64\publish\${outputfile}") $file_len = $file.Length - if (-not ($expected_len -eq -1 -or $file_len -eq $expected_len)) + if ($expected_len -eq -1) + { + Write-Host "Actual ${tfm} - trimmed ${outputfile} length: ${file_len} Bytes (expected length is placeholder -1, update test with this actual value)" + } + elseif ($file_len -ne $expected_len) { Write-Error "Test failed with unexpected ${tfm} - trimmed ${outputfile} length:`nExpected:`n`t${expected_len} Bytes`nActual:`n`t${file_len} Bytes`nEither codegen or trimming logic have changed. Please investigate and update expected dll size or report an issue." -ErrorAction Stop } From 18cb57d74c66295616ca1f1e5531d28a3d2a4f65 Mon Sep 17 00:00:00 2001 From: Tomas Grosup Date: Fri, 11 Jul 2025 18:08:22 +0200 Subject: [PATCH 7/9] Registering task that produces ILLink.substitutions.xml --- .../Microsoft.FSharp.NetSdk.targets | 2 +- ...SharpMetadataResource_Trimming_Test.fsproj | 21 ++++++++++++------- tests/AheadOfTime/Trimming/check.ps1 | 9 ++++++-- 3 files changed, 22 insertions(+), 10 deletions(-) diff --git a/src/FSharp.Build/Microsoft.FSharp.NetSdk.targets b/src/FSharp.Build/Microsoft.FSharp.NetSdk.targets index 6e3dbe14f2c..6b38487d22c 100644 --- a/src/FSharp.Build/Microsoft.FSharp.NetSdk.targets +++ b/src/FSharp.Build/Microsoft.FSharp.NetSdk.targets @@ -158,7 +158,7 @@ WARNING: DO NOT MODIFY this file unless you are knowledgeable about MSBuild and - + diff --git a/tests/AheadOfTime/Trimming/FSharpMetadataResource_Trimming_Test/FSharpMetadataResource_Trimming_Test.fsproj b/tests/AheadOfTime/Trimming/FSharpMetadataResource_Trimming_Test/FSharpMetadataResource_Trimming_Test.fsproj index 8673b85506e..5b56160b3d1 100644 --- a/tests/AheadOfTime/Trimming/FSharpMetadataResource_Trimming_Test/FSharpMetadataResource_Trimming_Test.fsproj +++ b/tests/AheadOfTime/Trimming/FSharpMetadataResource_Trimming_Test/FSharpMetadataResource_Trimming_Test.fsproj @@ -16,16 +16,23 @@ - $(MSBuildThisFileDirectory)../../../../artifacts/bin/fsc/Release/net9.0/fsc.dll - $(MSBuildThisFileDirectory)../../../../artifacts/bin/fsc/Release/net9.0/fsc.dll - $(MSBuildThisFileDirectory)../../../../artifacts/bin/FSharp.Build/Release/net9.0/FSharp.Build.dll + $(MSBuildThisFileDirectory)../../../../artifacts/bin/fsc/Release/net9.0 + $(LocalFSharpBuildBinPath)/FSharp.Build.dll + $(LocalFSharpBuildBinPath)/fsc.dll + $(LocalFSharpBuildBinPath)/fsc.dll False True - - - + + + + + + + @@ -37,4 +44,4 @@ - \ No newline at end of file + diff --git a/tests/AheadOfTime/Trimming/check.ps1 b/tests/AheadOfTime/Trimming/check.ps1 index bda575bddcd..0a28df7529b 100644 --- a/tests/AheadOfTime/Trimming/check.ps1 +++ b/tests/AheadOfTime/Trimming/check.ps1 @@ -1,6 +1,6 @@ function CheckTrim($root, $tfm, $outputfile, $expected_len) { Write-Host "Publish and Execute: ${tfm} - ${root}" - Write-Host "Expecting ${expected_len}" + Write-Host "Expecting ${expected_len} for ${outputfile}" $cwd = Get-Location Set-Location (Join-Path $PSScriptRoot "${root}") @@ -41,6 +41,11 @@ function CheckTrim($root, $tfm, $outputfile, $expected_len) { { Write-Error "Test failed with unexpected ${tfm} - trimmed ${outputfile} length:`nExpected:`n`t${expected_len} Bytes`nActual:`n`t${file_len} Bytes`nEither codegen or trimming logic have changed. Please investigate and update expected dll size or report an issue." -ErrorAction Stop } + + $fileBeforePublish = Get-Item (Join-Path $PSScriptRoot "${root}\bin\release\${tfm}\win-x64\${outputfile}") + $sizeBeforePublish = $fileBeforePublish.Length + $sizeDiff = $sizeBeforePublish - $file_len + Write-Host "Size of ${tfm} - ${outputfile} before publish: ${sizeBeforePublish} Bytes, which means the diff is ${sizeDiff} Bytes" } # NOTE: Trimming now errors out on desktop TFMs, as shown below: @@ -53,5 +58,5 @@ CheckTrim -root "SelfContained_Trimming_Test" -tfm "net9.0" -outputfile "FSharp. CheckTrim -root "StaticLinkedFSharpCore_Trimming_Test" -tfm "net9.0" -outputfile "StaticLinkedFSharpCore_Trimming_Test.dll" -expected_len 9154048 # Check net9.0 trimmed assemblies with F# metadata resources removed -CheckTrim -root "FSharpMetadataResource_Trimming_Test" -tfm "net9.0" -outputfile "FSharpMetadataResource_Trimming_Test.dll" -expected_len -1 +CheckTrim -root "FSharpMetadataResource_Trimming_Test" -tfm "net9.0" -outputfile "FSharpMetadataResource_Trimming_Test.dll" -expected_len 7601152 From b0a078154d1412d7ac39684cca1b866ae8a55267 Mon Sep 17 00:00:00 2001 From: GH Actions Date: Fri, 11 Jul 2025 16:15:45 +0000 Subject: [PATCH 8/9] Apply patch from /run fantomas --- .../GenerateILLinkSubstitutions.fs | 49 +++++++++++-------- 1 file changed, 29 insertions(+), 20 deletions(-) diff --git a/src/FSharp.Build/GenerateILLinkSubstitutions.fs b/src/FSharp.Build/GenerateILLinkSubstitutions.fs index 457ba39bbe6..0478d36201d 100644 --- a/src/FSharp.Build/GenerateILLinkSubstitutions.fs +++ b/src/FSharp.Build/GenerateILLinkSubstitutions.fs @@ -30,23 +30,29 @@ type GenerateILLinkSubstitutions() = /// Generated embedded resource items. /// [] - member val GeneratedItems = [| |] : ITaskItem[] with get, set + member val GeneratedItems = [||]: ITaskItem[] with get, set override this.Execute() = try // Define the resource prefixes that need to be removed - let resourcePrefixes = - [| + let resourcePrefixes = + [| // Signature variants - yield! [| for dataType in [| "Data"; "DataB" |] do - for compression in [| ""; "Compressed" |] do - yield $"FSharpSignature{compression}{dataType}" |] - + yield! + [| + for dataType in [| "Data"; "DataB" |] do + for compression in [| ""; "Compressed" |] do + yield $"FSharpSignature{compression}{dataType}" + |] + // Optimization variants - yield! [| for dataType in [| "Data"; "DataB" |] do - for compression in [| ""; "Compressed" |] do - yield $"FSharpOptimization{compression}{dataType}" |] - + yield! + [| + for dataType in [| "Data"; "DataB" |] do + for compression in [| ""; "Compressed" |] do + yield $"FSharpOptimization{compression}{dataType}" + |] + // Info variants yield "FSharpOptimizationInfo" yield "FSharpSignatureInfo" @@ -57,28 +63,31 @@ type GenerateILLinkSubstitutions() = sb.AppendLine("") |> ignore sb.AppendLine("") |> ignore sb.AppendLine($" ") |> ignore - + // Add each resource entry with proper closing tag on the same line for prefix in resourcePrefixes do - sb.AppendLine($" ") |> ignore - + sb.AppendLine($" ") + |> ignore + // Close assembly and linker tags sb.AppendLine(" ") |> ignore sb.AppendLine("") |> ignore - + let xmlContent = sb.ToString() - + // Create a file in the intermediate output path - let outputFileName = Path.Combine(this.IntermediateOutputPath, "ILLink.Substitutions.xml") + let outputFileName = + Path.Combine(this.IntermediateOutputPath, "ILLink.Substitutions.xml") + Directory.CreateDirectory(this.IntermediateOutputPath) |> ignore File.WriteAllText(outputFileName, xmlContent) - + // Create a TaskItem for the generated file let item = TaskItem(outputFileName) :> ITaskItem item.SetMetadata("LogicalName", "ILLink.Substitutions.xml") - + this.GeneratedItems <- [| item |] true with ex -> this.Log.LogErrorFromException(ex, true) - false \ No newline at end of file + false From 96859b64e01f420433336f34820e0f35eaa1abc5 Mon Sep 17 00:00:00 2001 From: Tomas Grosup Date: Mon, 28 Jul 2025 17:48:15 +0200 Subject: [PATCH 9/9] special case Fsharp.Core which already has its subst xml file --- global.json | 4 ++-- src/FSharp.Build/Microsoft.FSharp.NetSdk.targets | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/global.json b/global.json index ca151b6f12f..822df2620e9 100644 --- a/global.json +++ b/global.json @@ -1,6 +1,6 @@ { "sdk": { - "version": "10.0.100-preview.7.25322.101", + "version": "10.0.100-preview.5.25277.114", "allowPrerelease": true, "paths": [ ".dotnet", @@ -9,7 +9,7 @@ "errorMessage": "The .NET SDK could not be found, please run ./eng/common/dotnet.sh." }, "tools": { - "dotnet": "10.0.100-preview.7.25322.101", + "dotnet": "10.0.100-preview.5.25277.114", "vs": { "version": "17.8", "components": [ diff --git a/src/FSharp.Build/Microsoft.FSharp.NetSdk.targets b/src/FSharp.Build/Microsoft.FSharp.NetSdk.targets index 6b38487d22c..5f5c4e56cea 100644 --- a/src/FSharp.Build/Microsoft.FSharp.NetSdk.targets +++ b/src/FSharp.Build/Microsoft.FSharp.NetSdk.targets @@ -157,12 +157,12 @@ WARNING: DO NOT MODIFY this file unless you are knowledgeable about MSBuild and - - + + - +