From 635ae7060c0213a5d9bd031eb64fcc61470433e5 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Tue, 2 Dec 2025 07:52:06 +0000
Subject: [PATCH 01/10] Initial plan
From 1d230e9f28ed12f755a713441666126ea86daae3 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Tue, 2 Dec 2025 08:25:08 +0000
Subject: [PATCH 02/10] Fix ILLink Substitutions MSBuild Output ItemName and
add unit tests
Co-authored-by: T-Gro <46543583+T-Gro@users.noreply.github.com>
---
.../Microsoft.FSharp.NetSdk.targets | 2 +-
.../FSharp.Build.UnitTests.fsproj | 1 +
.../GenerateILLinkSubstitutionsTests.fs | 250 ++++++++++++++++++
3 files changed, 252 insertions(+), 1 deletion(-)
create mode 100644 tests/FSharp.Build.UnitTests/GenerateILLinkSubstitutionsTests.fs
diff --git a/src/FSharp.Build/Microsoft.FSharp.NetSdk.targets b/src/FSharp.Build/Microsoft.FSharp.NetSdk.targets
index 1fe773ad73b..708d435772c 100644
--- a/src/FSharp.Build/Microsoft.FSharp.NetSdk.targets
+++ b/src/FSharp.Build/Microsoft.FSharp.NetSdk.targets
@@ -176,7 +176,7 @@ WARNING: DO NOT MODIFY this file unless you are knowledgeable about MSBuild and
-
+
diff --git a/tests/FSharp.Build.UnitTests/FSharp.Build.UnitTests.fsproj b/tests/FSharp.Build.UnitTests/FSharp.Build.UnitTests.fsproj
index 07585566210..84e73f6d83a 100644
--- a/tests/FSharp.Build.UnitTests/FSharp.Build.UnitTests.fsproj
+++ b/tests/FSharp.Build.UnitTests/FSharp.Build.UnitTests.fsproj
@@ -16,6 +16,7 @@
+
diff --git a/tests/FSharp.Build.UnitTests/GenerateILLinkSubstitutionsTests.fs b/tests/FSharp.Build.UnitTests/GenerateILLinkSubstitutionsTests.fs
new file mode 100644
index 00000000000..5dfd19f6e7d
--- /dev/null
+++ b/tests/FSharp.Build.UnitTests/GenerateILLinkSubstitutionsTests.fs
@@ -0,0 +1,250 @@
+// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information.
+
+namespace FSharp.Build.UnitTests
+
+open System
+open System.IO
+open System.Xml.Linq
+open Microsoft.Build.Framework
+open FSharp.Build
+open Xunit
+
+type GenerateILLinkSubstitutionsTests() =
+
+ let newTask () =
+ GenerateILLinkSubstitutions(BuildEngine = MockEngine())
+
+ let createTempDirectory () =
+ let tempDir = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString())
+ Directory.CreateDirectory(tempDir) |> ignore
+ tempDir
+
+ let cleanupTempDirectory (tempDir: string) =
+ if Directory.Exists(tempDir) then
+ Directory.Delete(tempDir, true)
+
+ []
+ member _.``Task executes successfully with valid inputs``() =
+ let tempDir = createTempDirectory ()
+
+ try
+ let task = newTask ()
+ task.AssemblyName <- "TestAssembly"
+ task.IntermediateOutputPath <- tempDir
+
+ let result = task.Execute()
+
+ Assert.True(result, "Task should execute successfully")
+ finally
+ cleanupTempDirectory tempDir
+
+ []
+ member _.``Generated file is created in the correct path``() =
+ let tempDir = createTempDirectory ()
+
+ try
+ let task = newTask ()
+ task.AssemblyName <- "TestAssembly"
+ task.IntermediateOutputPath <- tempDir
+
+ let result = task.Execute()
+
+ Assert.True(result, "Task should execute successfully")
+
+ let expectedPath = Path.Combine(tempDir, "ILLink.Substitutions.xml")
+ Assert.True(File.Exists(expectedPath), $"File should exist at {expectedPath}")
+ finally
+ cleanupTempDirectory tempDir
+
+ []
+ member _.``Generated TaskItem has correct LogicalName metadata``() =
+ let tempDir = createTempDirectory ()
+
+ try
+ let task = newTask ()
+ task.AssemblyName <- "TestAssembly"
+ task.IntermediateOutputPath <- tempDir
+
+ let result = task.Execute()
+
+ Assert.True(result, "Task should execute successfully")
+ Assert.Equal(1, task.GeneratedItems.Length)
+
+ let item = task.GeneratedItems.[0]
+ let logicalName = item.GetMetadata("LogicalName")
+ Assert.Equal("ILLink.Substitutions.xml", logicalName)
+ finally
+ cleanupTempDirectory tempDir
+
+ []
+ member _.``Generated TaskItem has correct ItemSpec``() =
+ let tempDir = createTempDirectory ()
+
+ try
+ let task = newTask ()
+ task.AssemblyName <- "TestAssembly"
+ task.IntermediateOutputPath <- tempDir
+
+ let result = task.Execute()
+
+ Assert.True(result, "Task should execute successfully")
+ Assert.Equal(1, task.GeneratedItems.Length)
+
+ let item = task.GeneratedItems.[0]
+ let expectedPath = Path.Combine(tempDir, "ILLink.Substitutions.xml")
+ Assert.Equal(expectedPath, item.ItemSpec)
+ finally
+ cleanupTempDirectory tempDir
+
+ []
+ member _.``Generated file contains proper XML structure``() =
+ let tempDir = createTempDirectory ()
+
+ try
+ let task = newTask ()
+ task.AssemblyName <- "TestAssembly"
+ task.IntermediateOutputPath <- tempDir
+
+ let result = task.Execute()
+
+ Assert.True(result, "Task should execute successfully")
+
+ let filePath = Path.Combine(tempDir, "ILLink.Substitutions.xml")
+ let doc = XDocument.Load(filePath)
+
+ // Verify root element is
+ Assert.Equal("linker", doc.Root.Name.LocalName)
+
+ // Verify assembly element exists with correct fullname attribute
+ let assemblyElement = doc.Root.Element(XName.Get("assembly"))
+ Assert.NotNull(assemblyElement)
+ Assert.Equal("TestAssembly", assemblyElement.Attribute(XName.Get("fullname")).Value)
+ finally
+ cleanupTempDirectory tempDir
+
+ []
+ member _.``Generated XML contains all expected F# metadata resource prefixes``() =
+ let tempDir = createTempDirectory ()
+
+ try
+ let task = newTask ()
+ task.AssemblyName <- "TestAssembly"
+ task.IntermediateOutputPath <- tempDir
+
+ let result = task.Execute()
+
+ Assert.True(result, "Task should execute successfully")
+
+ let filePath = Path.Combine(tempDir, "ILLink.Substitutions.xml")
+ let doc = XDocument.Load(filePath)
+
+ // Expected resource prefixes
+ let expectedPrefixes =
+ [|
+ // Signature variants
+ "FSharpSignatureData"
+ "FSharpSignatureDataB"
+ "FSharpSignatureCompressedData"
+ "FSharpSignatureCompressedDataB"
+ // Optimization variants
+ "FSharpOptimizationData"
+ "FSharpOptimizationDataB"
+ "FSharpOptimizationCompressedData"
+ "FSharpOptimizationCompressedDataB"
+ // Info variants
+ "FSharpOptimizationInfo"
+ "FSharpSignatureInfo"
+ |]
+
+ let assemblyElement = doc.Root.Element(XName.Get("assembly"))
+ let resourceElements = assemblyElement.Elements(XName.Get("resource")) |> Seq.toArray
+
+ // Verify each expected prefix is present
+ for prefix in expectedPrefixes do
+ let expectedResourceName = $"{prefix}.TestAssembly"
+ let found =
+ resourceElements
+ |> Array.exists (fun elem -> elem.Attribute(XName.Get("name")).Value = expectedResourceName)
+
+ Assert.True(found, $"Expected resource prefix '{expectedResourceName}' not found in generated XML")
+
+ // Verify total count matches
+ Assert.Equal(expectedPrefixes.Length, resourceElements.Length)
+ finally
+ cleanupTempDirectory tempDir
+
+ []
+ member _.``Generated XML resource entries have remove action``() =
+ let tempDir = createTempDirectory ()
+
+ try
+ let task = newTask ()
+ task.AssemblyName <- "TestAssembly"
+ task.IntermediateOutputPath <- tempDir
+
+ let result = task.Execute()
+
+ Assert.True(result, "Task should execute successfully")
+
+ let filePath = Path.Combine(tempDir, "ILLink.Substitutions.xml")
+ let doc = XDocument.Load(filePath)
+
+ let assemblyElement = doc.Root.Element(XName.Get("assembly"))
+ let resourceElements = assemblyElement.Elements(XName.Get("resource")) |> Seq.toArray
+
+ // Verify all resource elements have action="remove"
+ for elem in resourceElements do
+ let action = elem.Attribute(XName.Get("action")).Value
+ Assert.Equal("remove", action)
+ finally
+ cleanupTempDirectory tempDir
+
+ []
+ member _.``Task creates intermediate output directory if it does not exist``() =
+ let rootTempDir = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString())
+ let tempDir = Path.Combine(rootTempDir, "nested", "path")
+
+ try
+ Assert.False(Directory.Exists(tempDir), "Temp directory should not exist initially")
+
+ let task = newTask ()
+ task.AssemblyName <- "TestAssembly"
+ task.IntermediateOutputPath <- tempDir
+
+ let result = task.Execute()
+
+ Assert.True(result, "Task should execute successfully")
+ Assert.True(Directory.Exists(tempDir), "Temp directory should be created")
+
+ let expectedPath = Path.Combine(tempDir, "ILLink.Substitutions.xml")
+ Assert.True(File.Exists(expectedPath), $"File should exist at {expectedPath}")
+ finally
+ cleanupTempDirectory rootTempDir
+
+ []
+ member _.``Task works with assembly names containing special characters``() =
+ let tempDir = createTempDirectory ()
+
+ try
+ let task = newTask ()
+ task.AssemblyName <- "My.Special.Assembly"
+ task.IntermediateOutputPath <- tempDir
+
+ let result = task.Execute()
+
+ Assert.True(result, "Task should execute successfully")
+
+ let filePath = Path.Combine(tempDir, "ILLink.Substitutions.xml")
+ let doc = XDocument.Load(filePath)
+
+ let assemblyElement = doc.Root.Element(XName.Get("assembly"))
+ Assert.Equal("My.Special.Assembly", assemblyElement.Attribute(XName.Get("fullname")).Value)
+
+ // Verify resource names contain the full assembly name
+ let resourceElements = assemblyElement.Elements(XName.Get("resource")) |> Seq.toArray
+
+ for elem in resourceElements do
+ let name = elem.Attribute(XName.Get("name")).Value
+ Assert.True(name.EndsWith(".My.Special.Assembly"), $"Resource name '{name}' should end with assembly name")
+ finally
+ cleanupTempDirectory tempDir
From b4e604e90b712626f419e492d9867e0566408e17 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Tue, 2 Dec 2025 08:35:21 +0000
Subject: [PATCH 03/10] Address code review: add null checks for XML attributes
in tests
Co-authored-by: T-Gro <46543583+T-Gro@users.noreply.github.com>
---
.../GenerateILLinkSubstitutionsTests.fs | 22 +++++++++++++------
1 file changed, 15 insertions(+), 7 deletions(-)
diff --git a/tests/FSharp.Build.UnitTests/GenerateILLinkSubstitutionsTests.fs b/tests/FSharp.Build.UnitTests/GenerateILLinkSubstitutionsTests.fs
index 5dfd19f6e7d..9d07c0d9bf7 100644
--- a/tests/FSharp.Build.UnitTests/GenerateILLinkSubstitutionsTests.fs
+++ b/tests/FSharp.Build.UnitTests/GenerateILLinkSubstitutionsTests.fs
@@ -118,7 +118,9 @@ type GenerateILLinkSubstitutionsTests() =
// Verify assembly element exists with correct fullname attribute
let assemblyElement = doc.Root.Element(XName.Get("assembly"))
Assert.NotNull(assemblyElement)
- Assert.Equal("TestAssembly", assemblyElement.Attribute(XName.Get("fullname")).Value)
+ let fullnameAttr = assemblyElement.Attribute(XName.Get("fullname"))
+ Assert.NotNull(fullnameAttr)
+ Assert.Equal("TestAssembly", fullnameAttr.Value)
finally
cleanupTempDirectory tempDir
@@ -164,7 +166,9 @@ type GenerateILLinkSubstitutionsTests() =
let expectedResourceName = $"{prefix}.TestAssembly"
let found =
resourceElements
- |> Array.exists (fun elem -> elem.Attribute(XName.Get("name")).Value = expectedResourceName)
+ |> Array.exists (fun elem ->
+ let nameAttr = elem.Attribute(XName.Get("name"))
+ nameAttr <> null && nameAttr.Value = expectedResourceName)
Assert.True(found, $"Expected resource prefix '{expectedResourceName}' not found in generated XML")
@@ -194,8 +198,9 @@ type GenerateILLinkSubstitutionsTests() =
// Verify all resource elements have action="remove"
for elem in resourceElements do
- let action = elem.Attribute(XName.Get("action")).Value
- Assert.Equal("remove", action)
+ let actionAttr = elem.Attribute(XName.Get("action"))
+ Assert.NotNull(actionAttr)
+ Assert.Equal("remove", actionAttr.Value)
finally
cleanupTempDirectory tempDir
@@ -238,13 +243,16 @@ type GenerateILLinkSubstitutionsTests() =
let doc = XDocument.Load(filePath)
let assemblyElement = doc.Root.Element(XName.Get("assembly"))
- Assert.Equal("My.Special.Assembly", assemblyElement.Attribute(XName.Get("fullname")).Value)
+ let fullnameAttr = assemblyElement.Attribute(XName.Get("fullname"))
+ Assert.NotNull(fullnameAttr)
+ Assert.Equal("My.Special.Assembly", fullnameAttr.Value)
// Verify resource names contain the full assembly name
let resourceElements = assemblyElement.Elements(XName.Get("resource")) |> Seq.toArray
for elem in resourceElements do
- let name = elem.Attribute(XName.Get("name")).Value
- Assert.True(name.EndsWith(".My.Special.Assembly"), $"Resource name '{name}' should end with assembly name")
+ let nameAttr = elem.Attribute(XName.Get("name"))
+ Assert.NotNull(nameAttr)
+ Assert.True(nameAttr.Value.EndsWith(".My.Special.Assembly"), $"Resource name '{nameAttr.Value}' should end with assembly name")
finally
cleanupTempDirectory tempDir
From be13f67682730db5397621bf00ca2847f2d78232 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Wed, 3 Dec 2025 11:08:33 +0000
Subject: [PATCH 04/10] Remove standalone unit tests, use real product targets
in integration test
Co-authored-by: T-Gro <46543583+T-Gro@users.noreply.github.com>
---
...SharpMetadataResource_Trimming_Test.fsproj | 11 +-
.../FSharp.Build.UnitTests.fsproj | 1 -
.../GenerateILLinkSubstitutionsTests.fs | 258 ------------------
3 files changed, 2 insertions(+), 268 deletions(-)
delete mode 100644 tests/FSharp.Build.UnitTests/GenerateILLinkSubstitutionsTests.fs
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 c02f7b56c2e..1531391ea41 100644
--- a/tests/AheadOfTime/Trimming/FSharpMetadataResource_Trimming_Test/FSharpMetadataResource_Trimming_Test.fsproj
+++ b/tests/AheadOfTime/Trimming/FSharpMetadataResource_Trimming_Test/FSharpMetadataResource_Trimming_Test.fsproj
@@ -24,15 +24,8 @@
True
-
-
-
-
-
-
-
+
+
diff --git a/tests/FSharp.Build.UnitTests/FSharp.Build.UnitTests.fsproj b/tests/FSharp.Build.UnitTests/FSharp.Build.UnitTests.fsproj
index 84e73f6d83a..07585566210 100644
--- a/tests/FSharp.Build.UnitTests/FSharp.Build.UnitTests.fsproj
+++ b/tests/FSharp.Build.UnitTests/FSharp.Build.UnitTests.fsproj
@@ -16,7 +16,6 @@
-
diff --git a/tests/FSharp.Build.UnitTests/GenerateILLinkSubstitutionsTests.fs b/tests/FSharp.Build.UnitTests/GenerateILLinkSubstitutionsTests.fs
deleted file mode 100644
index 9d07c0d9bf7..00000000000
--- a/tests/FSharp.Build.UnitTests/GenerateILLinkSubstitutionsTests.fs
+++ /dev/null
@@ -1,258 +0,0 @@
-// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information.
-
-namespace FSharp.Build.UnitTests
-
-open System
-open System.IO
-open System.Xml.Linq
-open Microsoft.Build.Framework
-open FSharp.Build
-open Xunit
-
-type GenerateILLinkSubstitutionsTests() =
-
- let newTask () =
- GenerateILLinkSubstitutions(BuildEngine = MockEngine())
-
- let createTempDirectory () =
- let tempDir = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString())
- Directory.CreateDirectory(tempDir) |> ignore
- tempDir
-
- let cleanupTempDirectory (tempDir: string) =
- if Directory.Exists(tempDir) then
- Directory.Delete(tempDir, true)
-
- []
- member _.``Task executes successfully with valid inputs``() =
- let tempDir = createTempDirectory ()
-
- try
- let task = newTask ()
- task.AssemblyName <- "TestAssembly"
- task.IntermediateOutputPath <- tempDir
-
- let result = task.Execute()
-
- Assert.True(result, "Task should execute successfully")
- finally
- cleanupTempDirectory tempDir
-
- []
- member _.``Generated file is created in the correct path``() =
- let tempDir = createTempDirectory ()
-
- try
- let task = newTask ()
- task.AssemblyName <- "TestAssembly"
- task.IntermediateOutputPath <- tempDir
-
- let result = task.Execute()
-
- Assert.True(result, "Task should execute successfully")
-
- let expectedPath = Path.Combine(tempDir, "ILLink.Substitutions.xml")
- Assert.True(File.Exists(expectedPath), $"File should exist at {expectedPath}")
- finally
- cleanupTempDirectory tempDir
-
- []
- member _.``Generated TaskItem has correct LogicalName metadata``() =
- let tempDir = createTempDirectory ()
-
- try
- let task = newTask ()
- task.AssemblyName <- "TestAssembly"
- task.IntermediateOutputPath <- tempDir
-
- let result = task.Execute()
-
- Assert.True(result, "Task should execute successfully")
- Assert.Equal(1, task.GeneratedItems.Length)
-
- let item = task.GeneratedItems.[0]
- let logicalName = item.GetMetadata("LogicalName")
- Assert.Equal("ILLink.Substitutions.xml", logicalName)
- finally
- cleanupTempDirectory tempDir
-
- []
- member _.``Generated TaskItem has correct ItemSpec``() =
- let tempDir = createTempDirectory ()
-
- try
- let task = newTask ()
- task.AssemblyName <- "TestAssembly"
- task.IntermediateOutputPath <- tempDir
-
- let result = task.Execute()
-
- Assert.True(result, "Task should execute successfully")
- Assert.Equal(1, task.GeneratedItems.Length)
-
- let item = task.GeneratedItems.[0]
- let expectedPath = Path.Combine(tempDir, "ILLink.Substitutions.xml")
- Assert.Equal(expectedPath, item.ItemSpec)
- finally
- cleanupTempDirectory tempDir
-
- []
- member _.``Generated file contains proper XML structure``() =
- let tempDir = createTempDirectory ()
-
- try
- let task = newTask ()
- task.AssemblyName <- "TestAssembly"
- task.IntermediateOutputPath <- tempDir
-
- let result = task.Execute()
-
- Assert.True(result, "Task should execute successfully")
-
- let filePath = Path.Combine(tempDir, "ILLink.Substitutions.xml")
- let doc = XDocument.Load(filePath)
-
- // Verify root element is
- Assert.Equal("linker", doc.Root.Name.LocalName)
-
- // Verify assembly element exists with correct fullname attribute
- let assemblyElement = doc.Root.Element(XName.Get("assembly"))
- Assert.NotNull(assemblyElement)
- let fullnameAttr = assemblyElement.Attribute(XName.Get("fullname"))
- Assert.NotNull(fullnameAttr)
- Assert.Equal("TestAssembly", fullnameAttr.Value)
- finally
- cleanupTempDirectory tempDir
-
- []
- member _.``Generated XML contains all expected F# metadata resource prefixes``() =
- let tempDir = createTempDirectory ()
-
- try
- let task = newTask ()
- task.AssemblyName <- "TestAssembly"
- task.IntermediateOutputPath <- tempDir
-
- let result = task.Execute()
-
- Assert.True(result, "Task should execute successfully")
-
- let filePath = Path.Combine(tempDir, "ILLink.Substitutions.xml")
- let doc = XDocument.Load(filePath)
-
- // Expected resource prefixes
- let expectedPrefixes =
- [|
- // Signature variants
- "FSharpSignatureData"
- "FSharpSignatureDataB"
- "FSharpSignatureCompressedData"
- "FSharpSignatureCompressedDataB"
- // Optimization variants
- "FSharpOptimizationData"
- "FSharpOptimizationDataB"
- "FSharpOptimizationCompressedData"
- "FSharpOptimizationCompressedDataB"
- // Info variants
- "FSharpOptimizationInfo"
- "FSharpSignatureInfo"
- |]
-
- let assemblyElement = doc.Root.Element(XName.Get("assembly"))
- let resourceElements = assemblyElement.Elements(XName.Get("resource")) |> Seq.toArray
-
- // Verify each expected prefix is present
- for prefix in expectedPrefixes do
- let expectedResourceName = $"{prefix}.TestAssembly"
- let found =
- resourceElements
- |> Array.exists (fun elem ->
- let nameAttr = elem.Attribute(XName.Get("name"))
- nameAttr <> null && nameAttr.Value = expectedResourceName)
-
- Assert.True(found, $"Expected resource prefix '{expectedResourceName}' not found in generated XML")
-
- // Verify total count matches
- Assert.Equal(expectedPrefixes.Length, resourceElements.Length)
- finally
- cleanupTempDirectory tempDir
-
- []
- member _.``Generated XML resource entries have remove action``() =
- let tempDir = createTempDirectory ()
-
- try
- let task = newTask ()
- task.AssemblyName <- "TestAssembly"
- task.IntermediateOutputPath <- tempDir
-
- let result = task.Execute()
-
- Assert.True(result, "Task should execute successfully")
-
- let filePath = Path.Combine(tempDir, "ILLink.Substitutions.xml")
- let doc = XDocument.Load(filePath)
-
- let assemblyElement = doc.Root.Element(XName.Get("assembly"))
- let resourceElements = assemblyElement.Elements(XName.Get("resource")) |> Seq.toArray
-
- // Verify all resource elements have action="remove"
- for elem in resourceElements do
- let actionAttr = elem.Attribute(XName.Get("action"))
- Assert.NotNull(actionAttr)
- Assert.Equal("remove", actionAttr.Value)
- finally
- cleanupTempDirectory tempDir
-
- []
- member _.``Task creates intermediate output directory if it does not exist``() =
- let rootTempDir = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString())
- let tempDir = Path.Combine(rootTempDir, "nested", "path")
-
- try
- Assert.False(Directory.Exists(tempDir), "Temp directory should not exist initially")
-
- let task = newTask ()
- task.AssemblyName <- "TestAssembly"
- task.IntermediateOutputPath <- tempDir
-
- let result = task.Execute()
-
- Assert.True(result, "Task should execute successfully")
- Assert.True(Directory.Exists(tempDir), "Temp directory should be created")
-
- let expectedPath = Path.Combine(tempDir, "ILLink.Substitutions.xml")
- Assert.True(File.Exists(expectedPath), $"File should exist at {expectedPath}")
- finally
- cleanupTempDirectory rootTempDir
-
- []
- member _.``Task works with assembly names containing special characters``() =
- let tempDir = createTempDirectory ()
-
- try
- let task = newTask ()
- task.AssemblyName <- "My.Special.Assembly"
- task.IntermediateOutputPath <- tempDir
-
- let result = task.Execute()
-
- Assert.True(result, "Task should execute successfully")
-
- let filePath = Path.Combine(tempDir, "ILLink.Substitutions.xml")
- let doc = XDocument.Load(filePath)
-
- let assemblyElement = doc.Root.Element(XName.Get("assembly"))
- let fullnameAttr = assemblyElement.Attribute(XName.Get("fullname"))
- Assert.NotNull(fullnameAttr)
- Assert.Equal("My.Special.Assembly", fullnameAttr.Value)
-
- // Verify resource names contain the full assembly name
- let resourceElements = assemblyElement.Elements(XName.Get("resource")) |> Seq.toArray
-
- for elem in resourceElements do
- let nameAttr = elem.Attribute(XName.Get("name"))
- Assert.NotNull(nameAttr)
- Assert.True(nameAttr.Value.EndsWith(".My.Special.Assembly"), $"Resource name '{nameAttr.Value}' should end with assembly name")
- finally
- cleanupTempDirectory tempDir
From 6a5af336e97d7b07e4cb1513a659985ce7375c88 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Wed, 3 Dec 2025 11:38:21 +0000
Subject: [PATCH 05/10] Update test to match product targets and add comments
documenting the test-product relationship
Co-authored-by: T-Gro <46543583+T-Gro@users.noreply.github.com>
---
...SharpMetadataResource_Trimming_Test.fsproj | 19 +++++++++++++++++--
1 file changed, 17 insertions(+), 2 deletions(-)
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 1531391ea41..6ec1b8ea9dd 100644
--- a/tests/AheadOfTime/Trimming/FSharpMetadataResource_Trimming_Test/FSharpMetadataResource_Trimming_Test.fsproj
+++ b/tests/AheadOfTime/Trimming/FSharpMetadataResource_Trimming_Test/FSharpMetadataResource_Trimming_Test.fsproj
@@ -24,8 +24,23 @@
True
-
-
+
+
+
+
+
+
+
+
+
+
From 7eaf4ebc0987165b63ef06b14cce17e29e7bdf45 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Wed, 3 Dec 2025 11:40:13 +0000
Subject: [PATCH 06/10] Add missing FSharp.Core condition to match product
targets exactly
Co-authored-by: T-Gro <46543583+T-Gro@users.noreply.github.com>
---
.../FSharpMetadataResource_Trimming_Test.fsproj | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
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 6ec1b8ea9dd..ed5a8a4159b 100644
--- a/tests/AheadOfTime/Trimming/FSharpMetadataResource_Trimming_Test/FSharpMetadataResource_Trimming_Test.fsproj
+++ b/tests/AheadOfTime/Trimming/FSharpMetadataResource_Trimming_Test/FSharpMetadataResource_Trimming_Test.fsproj
@@ -33,7 +33,7 @@
Currently this should be:
If the product targets are wrong, this test will fail.
-->
-
+
From 9d6756b4c50bdb601bb21ab391045218fd5a2f17 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Wed, 3 Dec 2025 14:05:17 +0000
Subject: [PATCH 07/10] Use FSharpTargetsShim instead of duplicating target
logic
Co-authored-by: T-Gro <46543583+T-Gro@users.noreply.github.com>
---
...SharpMetadataResource_Trimming_Test.fsproj | 24 +++++--------------
1 file changed, 6 insertions(+), 18 deletions(-)
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 ed5a8a4159b..8332103487b 100644
--- a/tests/AheadOfTime/Trimming/FSharpMetadataResource_Trimming_Test/FSharpMetadataResource_Trimming_Test.fsproj
+++ b/tests/AheadOfTime/Trimming/FSharpMetadataResource_Trimming_Test/FSharpMetadataResource_Trimming_Test.fsproj
@@ -22,25 +22,13 @@
$(LocalFSharpBuildBinPath)/fsc.dll
False
True
+
+ $(LocalFSharpBuildBinPath)/Microsoft.FSharp.NetSdk.targets
-
-
-
-
-
-
-
-
-
-
-
From dab957fa1f457b94e0c9d34d91082fe871860ddd Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Wed, 3 Dec 2025 14:06:53 +0000
Subject: [PATCH 08/10] Fix comment format to use full URL reference
Co-authored-by: T-Gro <46543583+T-Gro@users.noreply.github.com>
---
.../FSharpMetadataResource_Trimming_Test.fsproj | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
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 8332103487b..42809b78f0d 100644
--- a/tests/AheadOfTime/Trimming/FSharpMetadataResource_Trimming_Test/FSharpMetadataResource_Trimming_Test.fsproj
+++ b/tests/AheadOfTime/Trimming/FSharpMetadataResource_Trimming_Test/FSharpMetadataResource_Trimming_Test.fsproj
@@ -25,7 +25,7 @@
$(LocalFSharpBuildBinPath)/Microsoft.FSharp.NetSdk.targets
From f4bd37d64175faa8427a118d1991f12ebd69786f Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Wed, 3 Dec 2025 14:21:06 +0000
Subject: [PATCH 09/10] Add GenerateILLinkSubstitutions task to
UseLocalCompiler.Directory.Build.props
Co-authored-by: T-Gro <46543583+T-Gro@users.noreply.github.com>
---
UseLocalCompiler.Directory.Build.props | 1 +
1 file changed, 1 insertion(+)
diff --git a/UseLocalCompiler.Directory.Build.props b/UseLocalCompiler.Directory.Build.props
index 35148efc0b5..99729830b30 100644
--- a/UseLocalCompiler.Directory.Build.props
+++ b/UseLocalCompiler.Directory.Build.props
@@ -29,6 +29,7 @@
+
From 157fe7fb3e3eea1bd045aa1bf58530f920b75556 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Wed, 3 Dec 2025 14:37:58 +0000
Subject: [PATCH 10/10] Simplify UseLocalCompiler.Directory.Build.props by
relying on FSharpTargetsShim
Co-authored-by: T-Gro <46543583+T-Gro@users.noreply.github.com>
---
UseLocalCompiler.Directory.Build.props | 10 ++++++----
1 file changed, 6 insertions(+), 4 deletions(-)
diff --git a/UseLocalCompiler.Directory.Build.props b/UseLocalCompiler.Directory.Build.props
index 99729830b30..532d0b566f8 100644
--- a/UseLocalCompiler.Directory.Build.props
+++ b/UseLocalCompiler.Directory.Build.props
@@ -18,6 +18,12 @@
True
+
$(LocalFSharpCompilerPath)/artifacts/bin/fsc/$(LocalFSharpCompilerConfiguration)/net10.0
$(LocalFSharpBuildBinPath)/FSharp.Build.dll
@@ -27,10 +33,6 @@
$(LocalFSharpBuildBinPath)/Microsoft.FSharp.Overrides.NetSdk.targets
-
-
-
-