From 9edea1bace43f99a7d894c7da860bdd2675eea0f Mon Sep 17 00:00:00 2001 From: Tomas Grosup Date: Thu, 29 Jan 2026 12:52:32 +0100 Subject: [PATCH 01/40] Add centralized product TFM file and expose via MSBuild and F# constants - Create eng/productTfm.txt as single source of truth for product TFM (net10.0) - Update Directory.Build.props to read TFM from file and derive major version - Update FSharpBuild.Directory.Build.targets to emit fsProductTfm and fsProductTfmMajorVersion constants in generated buildproperties.fs --- Directory.Build.props | 5 ++++- FSharpBuild.Directory.Build.targets | 2 ++ eng/productTfm.txt | 1 + 3 files changed, 7 insertions(+), 1 deletion(-) create mode 100644 eng/productTfm.txt diff --git a/Directory.Build.props b/Directory.Build.props index e109e5b71e5..1b7b702c2be 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -6,7 +6,10 @@ $(FSharpLangVersion) $(MSBuildThisFileDirectory) true - net10.0 + + $([System.IO.File]::ReadAllText('$(MSBuildThisFileDirectory)eng/productTfm.txt').Trim()) + + $([System.Text.RegularExpressions.Regex]::Replace('$(FSharpNetCoreProductDefaultTargetFramework)', '^net(\d+)\.0$', '$1')) $(DotNetBuildSourceOnly) false diff --git a/FSharpBuild.Directory.Build.targets b/FSharpBuild.Directory.Build.targets index 05201df3466..abf1431495f 100644 --- a/FSharpBuild.Directory.Build.targets +++ b/FSharpBuild.Directory.Build.targets @@ -73,6 +73,8 @@ <_BuildPropertyLines Include="module internal FSharp.BuildProperties" /> <_BuildPropertyLines Include="let fsProductVersion = "$(FSPRODUCTVERSION)"" /> <_BuildPropertyLines Include="let fsLanguageVersion = "$(FSLANGUAGEVERSION)"" /> + <_BuildPropertyLines Include="let fsProductTfm = "$(FSharpNetCoreProductDefaultTargetFramework)"" /> + <_BuildPropertyLines Include="let fsProductTfmMajorVersion = "$(FSharpNetCoreProductMajorVersion)"" /> Date: Thu, 29 Jan 2026 13:07:35 +0100 Subject: [PATCH 02/40] Replace hardcoded net10.0 with $(FSharpNetCoreProductDefaultTargetFramework) in MSBuild files - Update UseLocalCompiler.Directory.Build.props to use TFM property - Add TFM property reading to buildtools/checkpackages/Directory.Build.props - Update checkpackages fsproj files to use the property Part of TFM centralization effort - Sprint 2 --- UseLocalCompiler.Directory.Build.props | 6 +++--- buildtools/checkpackages/Directory.Build.props | 2 ++ .../checkpackages/FSharp.Compiler.Service_notshipped.fsproj | 2 +- buildtools/checkpackages/FSharp.Core_notshipped.fsproj | 2 +- 4 files changed, 7 insertions(+), 5 deletions(-) diff --git a/UseLocalCompiler.Directory.Build.props b/UseLocalCompiler.Directory.Build.props index 532d0b566f8..7e41bb697d9 100644 --- a/UseLocalCompiler.Directory.Build.props +++ b/UseLocalCompiler.Directory.Build.props @@ -11,8 +11,8 @@ $([System.IO.Path]::GetDirectoryName($(DOTNET_HOST_PATH))) $([System.IO.Path]::GetFileName($(DOTNET_HOST_PATH))) - $(LocalFSharpCompilerPath)/artifacts/bin/fsc/$(LocalFSharpCompilerConfiguration)/net10.0/fsc.dll - $(LocalFSharpCompilerPath)/artifacts/bin/fsc/$(LocalFSharpCompilerConfiguration)/net10.0/fsc.dll + $(LocalFSharpCompilerPath)/artifacts/bin/fsc/$(LocalFSharpCompilerConfiguration)/$(FSharpNetCoreProductDefaultTargetFramework)/fsc.dll + $(LocalFSharpCompilerPath)/artifacts/bin/fsc/$(LocalFSharpCompilerConfiguration)/$(FSharpNetCoreProductDefaultTargetFramework)/fsc.dll False True @@ -25,7 +25,7 @@ See: https://github.com/dotnet/sdk/blob/main/src/Tasks/Microsoft.NET.Build.Tasks/targets/Microsoft.NET.Sdk.FSharpTargetsShim.targets --> - $(LocalFSharpCompilerPath)/artifacts/bin/fsc/$(LocalFSharpCompilerConfiguration)/net10.0 + $(LocalFSharpCompilerPath)/artifacts/bin/fsc/$(LocalFSharpCompilerConfiguration)/$(FSharpNetCoreProductDefaultTargetFramework) $(LocalFSharpBuildBinPath)/FSharp.Build.dll $(LocalFSharpBuildBinPath)/Microsoft.FSharp.Targets $(LocalFSharpBuildBinPath)/Microsoft.FSharp.NetSdk.props diff --git a/buildtools/checkpackages/Directory.Build.props b/buildtools/checkpackages/Directory.Build.props index 8d7a02870f8..69dd3e1263d 100644 --- a/buildtools/checkpackages/Directory.Build.props +++ b/buildtools/checkpackages/Directory.Build.props @@ -1,5 +1,7 @@ + + $([System.IO.File]::ReadAllText('$(MSBuildThisFileDirectory)..\..\eng\productTfm.txt').Trim()) true $(MSBuildProjectDirectory)\..\..\artifacts\tmp\$([System.Guid]::NewGuid()) $(CachePath)\obj\ diff --git a/buildtools/checkpackages/FSharp.Compiler.Service_notshipped.fsproj b/buildtools/checkpackages/FSharp.Compiler.Service_notshipped.fsproj index 836a25096b2..6a43b6e141e 100644 --- a/buildtools/checkpackages/FSharp.Compiler.Service_notshipped.fsproj +++ b/buildtools/checkpackages/FSharp.Compiler.Service_notshipped.fsproj @@ -3,7 +3,7 @@ - net10.0 + $(FSharpNetCoreProductDefaultTargetFramework) true $(MSBuildProjectDirectory)\..\..\artifacts\tmp\$([System.Guid]::NewGuid()) $(CachePath)\bin diff --git a/buildtools/checkpackages/FSharp.Core_notshipped.fsproj b/buildtools/checkpackages/FSharp.Core_notshipped.fsproj index d032bd5839f..5c3d6f89fae 100644 --- a/buildtools/checkpackages/FSharp.Core_notshipped.fsproj +++ b/buildtools/checkpackages/FSharp.Core_notshipped.fsproj @@ -3,7 +3,7 @@ - net10.0 + $(FSharpNetCoreProductDefaultTargetFramework) From e8e4a6f476f5c651aeb7910908bb8e9532eb26a0 Mon Sep 17 00:00:00 2001 From: Tomas Grosup Date: Thu, 29 Jan 2026 13:12:53 +0100 Subject: [PATCH 03/40] Update build scripts to read TFM from eng/productTfm.txt - eng/Build.ps1: Read TFM from productTfm.txt for coreclrTargetFramework, bootstrapTfm, and fsharpNetCoreProductTfm variables - eng/build.sh: Read TFM using cat and tr -d to strip whitespace - eng/build-utils.ps1: Read TFM from productTfm.txt for fsharpNetCoreProductTfm This removes hardcoded 'net10.0' from these script files, enabling centralized TFM management through eng/productTfm.txt. --- .ralph/CONTEXT.md | 55 +++++++++++++++++++++++++++++++++++++++++++++ eng/Build.ps1 | 16 ++++++++++--- eng/build-utils.ps1 | 5 ++++- eng/build.sh | 3 ++- 4 files changed, 74 insertions(+), 5 deletions(-) create mode 100644 .ralph/CONTEXT.md diff --git a/.ralph/CONTEXT.md b/.ralph/CONTEXT.md new file mode 100644 index 00000000000..73dcb160853 --- /dev/null +++ b/.ralph/CONTEXT.md @@ -0,0 +1,55 @@ +# Product Increments + +This file is updated after each sprint completes. Use it to understand what was delivered. + +--- + +## Sprint 1: Foundation: Create TFM file and + MSBuild properties + +**Summary:** Completed in 2 iterations + +**Files touched:** Check git log for details. + +--- + +## Sprint 2: MSBuild consumers: Update props files + +**Summary:** Updated MSBuild files to use $(FSharpNetCoreProductDefaultTargetFramework) instead of hardcoded 'net10.0' + +**Files touched:** +- UseLocalCompiler.Directory.Build.props - replaced 3 occurrences of net10.0 +- buildtools/checkpackages/Directory.Build.props - added TFM property reading +- buildtools/checkpackages/FSharp.Compiler.Service_notshipped.fsproj - uses TFM property +- buildtools/checkpackages/FSharp.Core_notshipped.fsproj - uses TFM property + +**Verification:** +- dotnet msbuild -getProperty:FSharpNetCoreProductDefaultTargetFramework returns "net10.0" +- dotnet msbuild -getProperty:TargetFramework returns "net10.0" +- No hardcoded net10.0 remains in modified files + +--- + +## Sprint 2: MSBuild consumers: Update props files + +**Summary:** Completed in 2 iterations + +**Files touched:** Check git log for details. + +--- + +## Sprint 3: Scripts: Update PowerShell and Bash scripts + +**Summary:** Updated build scripts to read TFM from eng/productTfm.txt instead of hardcoded values + +**Files touched:** +- eng/Build.ps1 - reads TFM from productTfm.txt for $coreclrTargetFramework, $bootstrapTfm, $fsharpNetCoreProductTfm +- eng/build.sh - reads TFM using `cat "$scriptroot/productTfm.txt" | tr -d '[:space:]'` +- eng/build-utils.ps1 - reads TFM from productTfm.txt for $fsharpNetCoreProductTfm + +**Verification:** +- `./build.sh --help` executes without errors (exit code 0) +- No hardcoded 'net10.0' remains in any of the three script files +- TFM file reading works correctly: `cat eng/productTfm.txt | tr -d '[:space:]'` returns "net10.0" + +--- diff --git a/eng/Build.ps1 b/eng/Build.ps1 index 174eecdb9b4..75300753945 100644 --- a/eng/Build.ps1 +++ b/eng/Build.ps1 @@ -35,8 +35,8 @@ param ( # Options [switch][Alias('proto')]$bootstrap, [string]$bootstrapConfiguration = "Proto", - [string]$bootstrapTfm = "net10.0", - [string]$fsharpNetCoreProductTfm = "net10.0", + [string]$bootstrapTfm = "", + [string]$fsharpNetCoreProductTfm = "", [switch][Alias('bl')]$binaryLog = $true, [switch][Alias('nobl')]$excludeCIBinaryLog = $false, [switch][Alias('nolog')]$noBinaryLog = $false, @@ -82,7 +82,17 @@ $BuildCategory = "" $BuildMessage = "" $desktopTargetFramework = "net472" -$coreclrTargetFramework = "net10.0" +# Read product TFM from centralized source of truth +$productTfmPath = Join-Path $PSScriptRoot "productTfm.txt" +$coreclrTargetFramework = (Get-Content $productTfmPath -Raw).Trim() + +# Set defaults for bootstrapTfm and fsharpNetCoreProductTfm if not provided +if ($bootstrapTfm -eq "") { + $bootstrapTfm = $coreclrTargetFramework +} +if ($fsharpNetCoreProductTfm -eq "") { + $fsharpNetCoreProductTfm = $coreclrTargetFramework +} function Print-Usage() { Write-Host "Common settings:" diff --git a/eng/build-utils.ps1 b/eng/build-utils.ps1 index fdc274c66c2..142104e11b0 100644 --- a/eng/build-utils.ps1 +++ b/eng/build-utils.ps1 @@ -14,7 +14,10 @@ $nodeReuse = if (Test-Path variable:nodeReuse) { $nodeReuse } else { $false } $bootstrapDir = if (Test-Path variable:bootstrapDir) { $bootstrapDir } else { "" } $bootstrapConfiguration = if (Test-Path variable:bootstrapConfiguration) { $bootstrapConfiguration } else { "Proto" } $bootstrapTfm = if (Test-Path variable:bootstrapTfm) { $bootstrapTfm } else { "net472" } -$fsharpNetCoreProductTfm = if (Test-Path variable:fsharpNetCoreProductTfm) { $fsharpNetCoreProductTfm } else { "net10.0" } +# Read product TFM from centralized source of truth +$productTfmFilePath = Join-Path $PSScriptRoot "productTfm.txt" +$fsharpNetCoreProductTfmDefault = (Get-Content $productTfmFilePath -Raw).Trim() +$fsharpNetCoreProductTfm = if (Test-Path variable:fsharpNetCoreProductTfm) { $fsharpNetCoreProductTfm } else { $fsharpNetCoreProductTfmDefault } $properties = if (Test-Path variable:properties) { $properties } else { @() } function GetProjectOutputBinary([string]$fileName, [string]$projectName = "", [string]$configuration = $script:configuration, [string]$tfm = "net472", [string]$rid = "", [bool]$published = $false) { diff --git a/eng/build.sh b/eng/build.sh index 4477ea35db4..45bb35c829a 100755 --- a/eng/build.sh +++ b/eng/build.sh @@ -83,7 +83,8 @@ properties="" docker=false args="" -tfm="net10.0" # This needs to be changed every time it's bumped by arcade/us. +# Read product TFM from centralized source of truth +tfm=$(cat "$scriptroot/productTfm.txt" | tr -d '[:space:]') BuildCategory="" BuildMessage="" From 33a5b60d6dce58799f17ade44ac16bc850965ffd Mon Sep 17 00:00:00 2001 From: Tomas Grosup Date: Thu, 29 Jan 2026 13:12:53 +0100 Subject: [PATCH 04/40] Update build scripts to read TFM from eng/productTfm.txt - eng/Build.ps1: Read TFM from productTfm.txt for coreclrTargetFramework, bootstrapTfm, and fsharpNetCoreProductTfm variables - eng/build.sh: Read TFM using cat and tr -d to strip whitespace - eng/build-utils.ps1: Read TFM from productTfm.txt for fsharpNetCoreProductTfm This removes hardcoded 'net10.0' from these script files, enabling centralized TFM management through eng/productTfm.txt. --- eng/Build.ps1 | 16 +++++++++++++--- eng/build-utils.ps1 | 5 ++++- eng/build.sh | 3 ++- 3 files changed, 19 insertions(+), 5 deletions(-) diff --git a/eng/Build.ps1 b/eng/Build.ps1 index 174eecdb9b4..75300753945 100644 --- a/eng/Build.ps1 +++ b/eng/Build.ps1 @@ -35,8 +35,8 @@ param ( # Options [switch][Alias('proto')]$bootstrap, [string]$bootstrapConfiguration = "Proto", - [string]$bootstrapTfm = "net10.0", - [string]$fsharpNetCoreProductTfm = "net10.0", + [string]$bootstrapTfm = "", + [string]$fsharpNetCoreProductTfm = "", [switch][Alias('bl')]$binaryLog = $true, [switch][Alias('nobl')]$excludeCIBinaryLog = $false, [switch][Alias('nolog')]$noBinaryLog = $false, @@ -82,7 +82,17 @@ $BuildCategory = "" $BuildMessage = "" $desktopTargetFramework = "net472" -$coreclrTargetFramework = "net10.0" +# Read product TFM from centralized source of truth +$productTfmPath = Join-Path $PSScriptRoot "productTfm.txt" +$coreclrTargetFramework = (Get-Content $productTfmPath -Raw).Trim() + +# Set defaults for bootstrapTfm and fsharpNetCoreProductTfm if not provided +if ($bootstrapTfm -eq "") { + $bootstrapTfm = $coreclrTargetFramework +} +if ($fsharpNetCoreProductTfm -eq "") { + $fsharpNetCoreProductTfm = $coreclrTargetFramework +} function Print-Usage() { Write-Host "Common settings:" diff --git a/eng/build-utils.ps1 b/eng/build-utils.ps1 index fdc274c66c2..142104e11b0 100644 --- a/eng/build-utils.ps1 +++ b/eng/build-utils.ps1 @@ -14,7 +14,10 @@ $nodeReuse = if (Test-Path variable:nodeReuse) { $nodeReuse } else { $false } $bootstrapDir = if (Test-Path variable:bootstrapDir) { $bootstrapDir } else { "" } $bootstrapConfiguration = if (Test-Path variable:bootstrapConfiguration) { $bootstrapConfiguration } else { "Proto" } $bootstrapTfm = if (Test-Path variable:bootstrapTfm) { $bootstrapTfm } else { "net472" } -$fsharpNetCoreProductTfm = if (Test-Path variable:fsharpNetCoreProductTfm) { $fsharpNetCoreProductTfm } else { "net10.0" } +# Read product TFM from centralized source of truth +$productTfmFilePath = Join-Path $PSScriptRoot "productTfm.txt" +$fsharpNetCoreProductTfmDefault = (Get-Content $productTfmFilePath -Raw).Trim() +$fsharpNetCoreProductTfm = if (Test-Path variable:fsharpNetCoreProductTfm) { $fsharpNetCoreProductTfm } else { $fsharpNetCoreProductTfmDefault } $properties = if (Test-Path variable:properties) { $properties } else { @() } function GetProjectOutputBinary([string]$fileName, [string]$projectName = "", [string]$configuration = $script:configuration, [string]$tfm = "net472", [string]$rid = "", [bool]$published = $false) { diff --git a/eng/build.sh b/eng/build.sh index 4477ea35db4..45bb35c829a 100755 --- a/eng/build.sh +++ b/eng/build.sh @@ -83,7 +83,8 @@ properties="" docker=false args="" -tfm="net10.0" # This needs to be changed every time it's bumped by arcade/us. +# Read product TFM from centralized source of truth +tfm=$(cat "$scriptroot/productTfm.txt" | tr -d '[:space:]') BuildCategory="" BuildMessage="" From 6cc4a6dd0b2a8e01174be05bb6a5a886754c38ca Mon Sep 17 00:00:00 2001 From: Tomas Grosup Date: Thu, 29 Jan 2026 13:32:19 +0100 Subject: [PATCH 05/40] Update CompilerLocation.fs to use fsProductTfmMajorVersion Replace hardcoded TFM list in toolingCompatibleVersions with dynamically computed list based on FSharp.BuildProperties.fsProductTfmMajorVersion. - Generate net{N}.0 from major version down to 5 - Append legacy netcoreapp/netstandard versions - List automatically updates when eng/productTfm.txt changes --- .ralph/CONTEXT.md | 29 +++++++++++++++++++ src/Compiler/Facilities/CompilerLocation.fs | 32 ++++++++++++--------- 2 files changed, 47 insertions(+), 14 deletions(-) diff --git a/.ralph/CONTEXT.md b/.ralph/CONTEXT.md index 73dcb160853..c5c766c4838 100644 --- a/.ralph/CONTEXT.md +++ b/.ralph/CONTEXT.md @@ -53,3 +53,32 @@ This file is updated after each sprint completes. Use it to understand what was - TFM file reading works correctly: `cat eng/productTfm.txt | tr -d '[:space:]'` returns "net10.0" --- + +## Sprint 3: Scripts: Update + PowerShell and Bash scripts + +**Summary:** Completed in 2 iterations + +**Files touched:** Check git log for details. + +--- + +## Sprint 4: Product code: Update CompilerLocation.fs + +**Summary:** Updated toolingCompatibleVersions in CompilerLocation.fs to dynamically generate TFM list from FSharp.BuildProperties.fsProductTfmMajorVersion instead of hardcoded values. + +**Files touched:** +- src/Compiler/Facilities/CompilerLocation.fs - replaced hardcoded TFM list with computed list + +**Changes Made:** +- The list now generates TFMs from `fsProductTfmMajorVersion` (e.g., 10) down to 5 +- Legacy netcoreapp/netstandard versions are appended after the computed list +- Fallback to major version 10 if parsing fails + +**Verification:** +- dotnet build src/Compiler/FSharp.Compiler.Service.fsproj succeeds +- No hardcoded 'net10.0' or 'net11.0' in CompilerLocation.fs +- Uses FSharp.BuildProperties.fsProductTfmMajorVersion at line 128 +- When TFM changes in eng/productTfm.txt, the list will automatically update + +--- diff --git a/src/Compiler/Facilities/CompilerLocation.fs b/src/Compiler/Facilities/CompilerLocation.fs index 53e885ef075..186f95a4151 100644 --- a/src/Compiler/Facilities/CompilerLocation.fs +++ b/src/Compiler/Facilities/CompilerLocation.fs @@ -122,21 +122,25 @@ module internal FSharpEnvironment = "netstandard2.0" |] elif typeof.Assembly.GetName().Name = "System.Private.CoreLib" then + // Generate TFM list dynamically from fsProductTfmMajorVersion down to net5.0, + // followed by legacy netcoreapp and netstandard versions + let majorVersion = + match Int32.TryParse(FSharp.BuildProperties.fsProductTfmMajorVersion) with + | true, v -> v + | false, _ -> 10 // Fallback if parsing fails + [| - "net11.0" - "net10.0" - "net9.0" - "net8.0" - "net7.0" - "net6.0" - "net5.0" - "netcoreapp3.1" - "netcoreapp3.0" - "netstandard2.1" - "netcoreapp2.2" - "netcoreapp2.1" - "netcoreapp2.0" - "netstandard2.0" + // Generate net{N}.0 from current major version down to 5 + for v in majorVersion .. -1 .. 5 do + yield $"net{v}.0" + // Legacy netcoreapp and netstandard versions + yield "netcoreapp3.1" + yield "netcoreapp3.0" + yield "netstandard2.1" + yield "netcoreapp2.2" + yield "netcoreapp2.1" + yield "netcoreapp2.0" + yield "netstandard2.0" |] else Debug.Assert(false, "Couldn't determine runtime tooling context, assuming it supports at least .NET Standard 2.0") From 52b8f19fe2d7a313acb2920330f97e732721c2cc Mon Sep 17 00:00:00 2001 From: Tomas Grosup Date: Thu, 29 Jan 2026 13:32:19 +0100 Subject: [PATCH 06/40] Update CompilerLocation.fs to use fsProductTfmMajorVersion Replace hardcoded TFM list in toolingCompatibleVersions with dynamically computed list based on FSharp.BuildProperties.fsProductTfmMajorVersion. - Generate net{N}.0 from major version down to 5 - Append legacy netcoreapp/netstandard versions - List automatically updates when eng/productTfm.txt changes --- src/Compiler/Facilities/CompilerLocation.fs | 32 ++++++++++++--------- 1 file changed, 18 insertions(+), 14 deletions(-) diff --git a/src/Compiler/Facilities/CompilerLocation.fs b/src/Compiler/Facilities/CompilerLocation.fs index 53e885ef075..186f95a4151 100644 --- a/src/Compiler/Facilities/CompilerLocation.fs +++ b/src/Compiler/Facilities/CompilerLocation.fs @@ -122,21 +122,25 @@ module internal FSharpEnvironment = "netstandard2.0" |] elif typeof.Assembly.GetName().Name = "System.Private.CoreLib" then + // Generate TFM list dynamically from fsProductTfmMajorVersion down to net5.0, + // followed by legacy netcoreapp and netstandard versions + let majorVersion = + match Int32.TryParse(FSharp.BuildProperties.fsProductTfmMajorVersion) with + | true, v -> v + | false, _ -> 10 // Fallback if parsing fails + [| - "net11.0" - "net10.0" - "net9.0" - "net8.0" - "net7.0" - "net6.0" - "net5.0" - "netcoreapp3.1" - "netcoreapp3.0" - "netstandard2.1" - "netcoreapp2.2" - "netcoreapp2.1" - "netcoreapp2.0" - "netstandard2.0" + // Generate net{N}.0 from current major version down to 5 + for v in majorVersion .. -1 .. 5 do + yield $"net{v}.0" + // Legacy netcoreapp and netstandard versions + yield "netcoreapp3.1" + yield "netcoreapp3.0" + yield "netstandard2.1" + yield "netcoreapp2.2" + yield "netcoreapp2.1" + yield "netcoreapp2.0" + yield "netstandard2.0" |] else Debug.Assert(false, "Couldn't determine runtime tooling context, assuming it supports at least .NET Standard 2.0") From 92afd5ee991e2450d0782f97cde7ed8018dd2e45 Mon Sep 17 00:00:00 2001 From: Tomas Grosup Date: Thu, 29 Jan 2026 13:52:05 +0100 Subject: [PATCH 07/40] Add productTfm constant to test utilities - TestFramework.fs: Add productTfm that reads from eng/productTfm.txt - TestFramework.fs: Update dotnetArchitecture to use productTfm - CompilerAssert.fs: Use TestFramework.productTfm in runtimeconfig generation - ProjectGeneration.fs: Use TestFramework.productTfm in fsproj template - Utilities.fs: Use TestFramework.productTfm for target framework --- tests/FSharp.Test.Utilities/CompilerAssert.fs | 20 ++++++++++--------- .../ProjectGeneration.fs | 4 ++-- tests/FSharp.Test.Utilities/TestFramework.fs | 9 ++++++++- tests/FSharp.Test.Utilities/Utilities.fs | 2 +- 4 files changed, 22 insertions(+), 13 deletions(-) diff --git a/tests/FSharp.Test.Utilities/CompilerAssert.fs b/tests/FSharp.Test.Utilities/CompilerAssert.fs index 12d95f33ce4..e7d4bcbb79e 100644 --- a/tests/FSharp.Test.Utilities/CompilerAssert.fs +++ b/tests/FSharp.Test.Utilities/CompilerAssert.fs @@ -615,16 +615,18 @@ module CompilerAssertHelpers = let fileName = "dotnet" let arguments = outputFilePath - let runtimeconfig = """ -{ - "runtimeOptions": { - "tfm": "net10.0", - "framework": { + // Derive the runtime version from productTfm (e.g., "net10.0" -> "10.0.0") + let runtimeVersion = productTfm.Replace("net", "") + ".0" + let runtimeconfig = $""" +{{ + "runtimeOptions": {{ + "tfm": "{productTfm}", + "framework": {{ "name": "Microsoft.NETCore.App", - "version": "10.0.0" - } - } -}""" + "version": "{runtimeVersion}" + }} + }} +}}""" let runtimeconfigPath = Path.ChangeExtension(outputFilePath, ".runtimeconfig.json") File.WriteAllText(runtimeconfigPath, runtimeconfig) #endif diff --git a/tests/FSharp.Test.Utilities/ProjectGeneration.fs b/tests/FSharp.Test.Utilities/ProjectGeneration.fs index 6c9684557a5..dd1e2eacb65 100644 --- a/tests/FSharp.Test.Utilities/ProjectGeneration.fs +++ b/tests/FSharp.Test.Utilities/ProjectGeneration.fs @@ -443,12 +443,12 @@ let renderCustomSignatureFile (project: SyntheticProject) (f: SyntheticSourceFil let private renderFsProj (p: SyntheticProject) = seq { - """ + $""" Exe - net10.0 + {productTfm} diff --git a/tests/FSharp.Test.Utilities/TestFramework.fs b/tests/FSharp.Test.Utilities/TestFramework.fs index 72dbfa46f3d..b793dd617a1 100644 --- a/tests/FSharp.Test.Utilities/TestFramework.fs +++ b/tests/FSharp.Test.Utilities/TestFramework.fs @@ -273,6 +273,13 @@ let requireFile dir path = let SCRIPT_ROOT = __SOURCE_DIRECTORY__ let repoRoot = SCRIPT_ROOT ++ ".." ++ ".." +/// The product target framework moniker, read from eng/productTfm.txt +let productTfm = + let tfmFilePath = repoRoot ++ "eng" ++ "productTfm.txt" + if not (File.Exists tfmFilePath) then + failwithf "productTfm.txt file not found at %s" tfmFilePath + File.ReadAllText(tfmFilePath).Trim() + let loadVersionsProps () = let versionsPropsPath = repoRoot ++ "eng" ++ "Versions.props" if not (File.Exists versionsPropsPath) then @@ -298,7 +305,7 @@ let config configurationName envVars = let fsharpCoreArchitecture = "netstandard2.0" let fsharpBuildArchitecture = "netstandard2.0" let fsharpCompilerInteractiveSettingsArchitecture = "netstandard2.0" - let dotnetArchitecture = "net10.0" + let dotnetArchitecture = productTfm #if NET472 let fscArchitecture = "net472" let fsiArchitecture = "net472" diff --git a/tests/FSharp.Test.Utilities/Utilities.fs b/tests/FSharp.Test.Utilities/Utilities.fs index 3a8a7ae487e..1305a532978 100644 --- a/tests/FSharp.Test.Utilities/Utilities.fs +++ b/tests/FSharp.Test.Utilities/Utilities.fs @@ -205,7 +205,7 @@ let main argv = 0""" let directoryBuildTargetsFileName = Path.Combine(projectDirectory, "Directory.Build.targets") let frameworkReferencesFileName = Path.Combine(projectDirectory, "FrameworkReferences.txt") #if NETCOREAPP - File.WriteAllText(projectFileName, projectFile.Replace("$TARGETFRAMEWORK", "net10.0").Replace("$FSHARPCORELOCATION", pathToFSharpCore)) + File.WriteAllText(projectFileName, projectFile.Replace("$TARGETFRAMEWORK", productTfm).Replace("$FSHARPCORELOCATION", pathToFSharpCore)) #else File.WriteAllText(projectFileName, projectFile.Replace("$TARGETFRAMEWORK", "net472").Replace("$FSHARPCORELOCATION", pathToFSharpCore)) #endif From 543c80f2dda43f7bd5725eb0052f6f032e9d0975 Mon Sep 17 00:00:00 2001 From: Tomas Grosup Date: Thu, 29 Jan 2026 13:52:05 +0100 Subject: [PATCH 08/40] Add productTfm constant to test utilities - TestFramework.fs: Add productTfm that reads from eng/productTfm.txt - TestFramework.fs: Update dotnetArchitecture to use productTfm - CompilerAssert.fs: Use TestFramework.productTfm in runtimeconfig generation - ProjectGeneration.fs: Use TestFramework.productTfm in fsproj template - Utilities.fs: Use TestFramework.productTfm for target framework --- tests/FSharp.Test.Utilities/CompilerAssert.fs | 20 ++++++++++--------- .../ProjectGeneration.fs | 4 ++-- tests/FSharp.Test.Utilities/TestFramework.fs | 9 ++++++++- tests/FSharp.Test.Utilities/Utilities.fs | 2 +- 4 files changed, 22 insertions(+), 13 deletions(-) diff --git a/tests/FSharp.Test.Utilities/CompilerAssert.fs b/tests/FSharp.Test.Utilities/CompilerAssert.fs index 12d95f33ce4..e7d4bcbb79e 100644 --- a/tests/FSharp.Test.Utilities/CompilerAssert.fs +++ b/tests/FSharp.Test.Utilities/CompilerAssert.fs @@ -615,16 +615,18 @@ module CompilerAssertHelpers = let fileName = "dotnet" let arguments = outputFilePath - let runtimeconfig = """ -{ - "runtimeOptions": { - "tfm": "net10.0", - "framework": { + // Derive the runtime version from productTfm (e.g., "net10.0" -> "10.0.0") + let runtimeVersion = productTfm.Replace("net", "") + ".0" + let runtimeconfig = $""" +{{ + "runtimeOptions": {{ + "tfm": "{productTfm}", + "framework": {{ "name": "Microsoft.NETCore.App", - "version": "10.0.0" - } - } -}""" + "version": "{runtimeVersion}" + }} + }} +}}""" let runtimeconfigPath = Path.ChangeExtension(outputFilePath, ".runtimeconfig.json") File.WriteAllText(runtimeconfigPath, runtimeconfig) #endif diff --git a/tests/FSharp.Test.Utilities/ProjectGeneration.fs b/tests/FSharp.Test.Utilities/ProjectGeneration.fs index 6c9684557a5..dd1e2eacb65 100644 --- a/tests/FSharp.Test.Utilities/ProjectGeneration.fs +++ b/tests/FSharp.Test.Utilities/ProjectGeneration.fs @@ -443,12 +443,12 @@ let renderCustomSignatureFile (project: SyntheticProject) (f: SyntheticSourceFil let private renderFsProj (p: SyntheticProject) = seq { - """ + $""" Exe - net10.0 + {productTfm} diff --git a/tests/FSharp.Test.Utilities/TestFramework.fs b/tests/FSharp.Test.Utilities/TestFramework.fs index 72dbfa46f3d..b793dd617a1 100644 --- a/tests/FSharp.Test.Utilities/TestFramework.fs +++ b/tests/FSharp.Test.Utilities/TestFramework.fs @@ -273,6 +273,13 @@ let requireFile dir path = let SCRIPT_ROOT = __SOURCE_DIRECTORY__ let repoRoot = SCRIPT_ROOT ++ ".." ++ ".." +/// The product target framework moniker, read from eng/productTfm.txt +let productTfm = + let tfmFilePath = repoRoot ++ "eng" ++ "productTfm.txt" + if not (File.Exists tfmFilePath) then + failwithf "productTfm.txt file not found at %s" tfmFilePath + File.ReadAllText(tfmFilePath).Trim() + let loadVersionsProps () = let versionsPropsPath = repoRoot ++ "eng" ++ "Versions.props" if not (File.Exists versionsPropsPath) then @@ -298,7 +305,7 @@ let config configurationName envVars = let fsharpCoreArchitecture = "netstandard2.0" let fsharpBuildArchitecture = "netstandard2.0" let fsharpCompilerInteractiveSettingsArchitecture = "netstandard2.0" - let dotnetArchitecture = "net10.0" + let dotnetArchitecture = productTfm #if NET472 let fscArchitecture = "net472" let fsiArchitecture = "net472" diff --git a/tests/FSharp.Test.Utilities/Utilities.fs b/tests/FSharp.Test.Utilities/Utilities.fs index 3a8a7ae487e..1305a532978 100644 --- a/tests/FSharp.Test.Utilities/Utilities.fs +++ b/tests/FSharp.Test.Utilities/Utilities.fs @@ -205,7 +205,7 @@ let main argv = 0""" let directoryBuildTargetsFileName = Path.Combine(projectDirectory, "Directory.Build.targets") let frameworkReferencesFileName = Path.Combine(projectDirectory, "FrameworkReferences.txt") #if NETCOREAPP - File.WriteAllText(projectFileName, projectFile.Replace("$TARGETFRAMEWORK", "net10.0").Replace("$FSHARPCORELOCATION", pathToFSharpCore)) + File.WriteAllText(projectFileName, projectFile.Replace("$TARGETFRAMEWORK", productTfm).Replace("$FSHARPCORELOCATION", pathToFSharpCore)) #else File.WriteAllText(projectFileName, projectFile.Replace("$TARGETFRAMEWORK", "net472").Replace("$FSHARPCORELOCATION", pathToFSharpCore)) #endif From 6db29fec17f598731f552d082f46e4a69e383657 Mon Sep 17 00:00:00 2001 From: Tomas Grosup Date: Thu, 29 Jan 2026 15:29:34 +0100 Subject: [PATCH 09/40] Centralize TFM in test files using TestFramework.productTfm - Update tests/fsharp/single-test.fs to use productTfm (3 occurrences) - Update DependencyManagerInteractiveTests.fs to use TestFramework.productTfm (18 occurrences) - Both test projects build successfully with 0 errors - Remaining net10.0 in tests/ are only in utility scripts, MSBuild config, and comments --- .ralph/CONTEXT.md | 51 +++++++++++++++++++ .../DependencyManagerInteractiveTests.fs | 36 ++++++------- tests/fsharp/single-test.fs | 6 +-- 3 files changed, 72 insertions(+), 21 deletions(-) diff --git a/.ralph/CONTEXT.md b/.ralph/CONTEXT.md index c5c766c4838..e8ab33460ac 100644 --- a/.ralph/CONTEXT.md +++ b/.ralph/CONTEXT.md @@ -82,3 +82,54 @@ This file is updated after each sprint completes. Use it to understand what was - When TFM changes in eng/productTfm.txt, the list will automatically update --- + +## Sprint 4: Product code: Update CompilerLocation.fs + +**Summary:** Completed in 2 iterations + +**Files touched:** Check git log for details. + +--- + +## Sprint 5: Test utilities: Add productTfm constant + +**Summary:** Added productTfm constant to TestFramework.fs and updated all test utility files to use it instead of hardcoded 'net10.0' + +**Files touched:** +- tests/FSharp.Test.Utilities/TestFramework.fs - added productTfm constant reading from eng/productTfm.txt, updated dotnetArchitecture +- tests/FSharp.Test.Utilities/CompilerAssert.fs - uses productTfm in runtimeconfig generation +- tests/FSharp.Test.Utilities/ProjectGeneration.fs - uses productTfm in fsproj template +- tests/FSharp.Test.Utilities/Utilities.fs - uses productTfm for target framework + +**Verification:** +- dotnet build tests/FSharp.Test.Utilities/FSharp.Test.Utilities.fsproj succeeds +- No hardcoded 'net10.0' in any of the four files (except documentation comment) +- Test utilities compile successfully + +--- + +## Sprint 5: Test utilities: Add + productTfm constant + +**Summary:** Completed in 2 iterations + +**Files touched:** Check git log for details. + +--- + +## Sprint 6: Test files: Update remaining test references + +**Summary:** Updated test files to use centralized TFM via TestFramework.productTfm + +**Files touched:** +- tests/fsharp/single-test.fs - replaced 3 occurrences of "net10.0" with productTfm +- tests/FSharp.Compiler.Private.Scripting.UnitTests/DependencyManagerInteractiveTests.fs - replaced 18 occurrences of "net10.0" with TestFramework.productTfm + +**Verification:** +- dotnet build tests/fsharp/FSharpSuite.Tests.fsproj succeeds with 0 errors +- dotnet build tests/FSharp.Compiler.Private.Scripting.UnitTests/FSharp.Compiler.Private.Scripting.UnitTests.fsproj succeeds with 0 errors +- No hardcoded 'net10.0' in single-test.fs +- No hardcoded 'net10.0' in DependencyManagerInteractiveTests.fs +- Remaining net10.0 in tests/ are only in: utility scripts, MSBuild config files, comments, and notebooks (not functional test code) + +--- diff --git a/tests/FSharp.Compiler.Private.Scripting.UnitTests/DependencyManagerInteractiveTests.fs b/tests/FSharp.Compiler.Private.Scripting.UnitTests/DependencyManagerInteractiveTests.fs index 95ee4c8f24f..be547816b51 100644 --- a/tests/FSharp.Compiler.Private.Scripting.UnitTests/DependencyManagerInteractiveTests.fs +++ b/tests/FSharp.Compiler.Private.Scripting.UnitTests/DependencyManagerInteractiveTests.fs @@ -100,7 +100,7 @@ type DependencyManagerInteractiveTests() = Assert.Equal(1, result.SourceFiles |> Seq.length) Assert.Equal(2, result.Roots |> Seq.length) - let result = dp.Resolve(idm, ".fsx", [|"r", "FSharp.Data,3.3.3"|], reportError, "net10.0") + let result = dp.Resolve(idm, ".fsx", [|"r", "FSharp.Data,3.3.3"|], reportError, TestFramework.productTfm) Assert.Equal(true, result.Success) Assert.Equal(1, result.Resolutions |> Seq.length) Assert.Equal(1, result.SourceFiles |> Seq.length) @@ -122,7 +122,7 @@ type DependencyManagerInteractiveTests() = let idm = dp.TryFindDependencyManagerByKey(Seq.empty, "", None, reportError, "nuget") - let result = dp.Resolve(idm, ".fsx", [|"r", "Microsoft.Data.Sqlite, 3.1.8"|], reportError, "net10.0") + let result = dp.Resolve(idm, ".fsx", [|"r", "Microsoft.Data.Sqlite, 3.1.8"|], reportError, TestFramework.productTfm) Assert.Equal(true, result.Success) Assert.True((result.Resolutions |> Seq.length) > 1) Assert.Equal(1, result.SourceFiles |> Seq.length) @@ -152,7 +152,7 @@ type DependencyManagerInteractiveTests() = Assert.Equal(0, result.SourceFiles |> Seq.length) Assert.Equal(0, result.Roots |> Seq.length) - let result = dp.Resolve(idm, ".fsx", [|"r", "System.Collections.Immutable.DoesNotExist"|], reportError, "net10.0") + let result = dp.Resolve(idm, ".fsx", [|"r", "System.Collections.Immutable.DoesNotExist"|], reportError, TestFramework.productTfm) Assert.Equal(false, result.Success) Assert.Equal(0, result.Resolutions |> Seq.length) Assert.Equal(0, result.SourceFiles |> Seq.length) @@ -182,7 +182,7 @@ type DependencyManagerInteractiveTests() = Assert.True((result1.Roots |> Seq.head).EndsWith("/fsharp.data/3.3.3/")) Assert.True((result1.Roots |> Seq.last).EndsWith("/microsoft.netframework.referenceassemblies/1.0.0/")) - let result2 = dp1.Resolve(idm1, ".fsx", [|"r", "FSharp.Data,3.3.3"|], reportError, "net10.0") + let result2 = dp1.Resolve(idm1, ".fsx", [|"r", "FSharp.Data,3.3.3"|], reportError, TestFramework.productTfm) Assert.Equal(true, result2.Success) Assert.Equal(1, result2.Resolutions |> Seq.length) let expected2 = "/netstandard2.0/" @@ -203,7 +203,7 @@ type DependencyManagerInteractiveTests() = Assert.Equal(1, result3.SourceFiles |> Seq.length) Assert.True((result3.Roots |> Seq.head).EndsWith("/system.json/4.6.0/")) - let result4 = dp2.Resolve(idm2, ".fsx", [|"r", "System.Json, Version=4.6.0"|], reportError, "net10.0") + let result4 = dp2.Resolve(idm2, ".fsx", [|"r", "System.Json, Version=4.6.0"|], reportError, TestFramework.productTfm) Assert.Equal(true, result4.Success) Assert.Equal(1, result4.Resolutions |> Seq.length) let expected4 = "/netstandard2.0/" @@ -239,7 +239,7 @@ type DependencyManagerInteractiveTests() = // Netstandard gets fewer dependencies than desktop, because desktop framework doesn't contain assemblies like System.Memory // Those assemblies must be delivered by nuget for desktop apps - let result2 = dp1.Resolve(idm1, ".fsx", [|"r", "Microsoft.Extensions.Configuration.Abstractions, 3.1.1"|], reportError, "net10.0") + let result2 = dp1.Resolve(idm1, ".fsx", [|"r", "Microsoft.Extensions.Configuration.Abstractions, 3.1.1"|], reportError, TestFramework.productTfm) Assert.Equal(true, result2.Success) Assert.Equal(2, result2.Resolutions |> Seq.length) let expected = "/netcoreapp3.1/" @@ -299,7 +299,7 @@ TorchSharp.Tensor.LongTensor.From([| 0L .. 100L |]).Device let result = use dp = new DependencyProvider(AssemblyResolutionProbe(assemblyProbingPaths), NativeResolutionProbe(nativeProbingRoots), false) let idm = dp.TryFindDependencyManagerByKey(Seq.empty, "", None, reportError, "nuget") - dp.Resolve(idm, ".fsx", packagemanagerlines, reportError, "net10.0") + dp.Resolve(idm, ".fsx", packagemanagerlines, reportError, TestFramework.productTfm) Assert.True(result.Success, "resolve failed") @@ -397,7 +397,7 @@ printfn ""%A"" result let result = use dp = new DependencyProvider(NativeResolutionProbe(nativeProbingRoots), false) let idm = dp.TryFindDependencyManagerByKey(Seq.empty, "", None, reportError, "nuget") - dp.Resolve(idm, ".fsx", packagemanagerlines, reportError, "net10.0") + dp.Resolve(idm, ".fsx", packagemanagerlines, reportError, TestFramework.productTfm) Assert.True(result.Success, "resolve failed") @@ -482,7 +482,7 @@ printfn ""%A"" result let result = use dp = new DependencyProvider(NativeResolutionProbe(nativeProbingRoots), false) let idm = dp.TryFindDependencyManagerByKey(Seq.empty, "", None, reportError, "nuget") - dp.Resolve(idm, ".fsx", packagemanagerlines, reportError, "net10.0") + dp.Resolve(idm, ".fsx", packagemanagerlines, reportError, TestFramework.productTfm) Assert.True(result.Success, "resolve failed") @@ -536,7 +536,7 @@ x |> Seq.iter(fun r -> let result = use dp = new DependencyProvider(NativeResolutionProbe(nativeProbingRoots), false) let idm = dp.TryFindDependencyManagerByKey(Seq.empty, "", None, reportError, "nuget") - dp.Resolve(idm, ".fsx", packagemanagerlines, reportError, "net10.0") + dp.Resolve(idm, ".fsx", packagemanagerlines, reportError, TestFramework.productTfm) // Expected: error FS3217: PackageManager cannot reference the System Package 'FSharp.Core' Assert.False(result.Success, "resolve succeeded but should have failed") @@ -559,7 +559,7 @@ x |> Seq.iter(fun r -> let result = use dp = new DependencyProvider(NativeResolutionProbe(nativeProbingRoots), false) let idm = dp.TryFindDependencyManagerByKey(Seq.empty, "", None, reportError, "nuget") - dp.Resolve(idm, ".csx", packagemanagerlines, reportError, "net10.0") + dp.Resolve(idm, ".csx", packagemanagerlines, reportError, TestFramework.productTfm) Assert.True(result.Success, "resolve failed but should have succeeded") @@ -602,7 +602,7 @@ x |> Seq.iter(fun r -> Assert.Equal(1, result.SourceFiles |> Seq.length) Assert.Equal(2, result.Roots |> Seq.length) - let result = dp.Resolve(idm, ".fsx", [|"r", "FSharp.Data,3.3.3"|], reportError, "net10.0") + let result = dp.Resolve(idm, ".fsx", [|"r", "FSharp.Data,3.3.3"|], reportError, TestFramework.productTfm) Assert.Equal(true, result.Success) Assert.Equal(1, result.Resolutions |> Seq.length) Assert.Equal(1, result.SourceFiles |> Seq.length) @@ -709,7 +709,7 @@ x |> Seq.iter(fun r -> let mutable currentPath:string = null use dp = new DependencyProvider(NativeResolutionProbe(nativeProbingRoots), false) let idm = dp.TryFindDependencyManagerByKey(Seq.empty, "", None, reportError, "nuget") - let result = dp.Resolve(idm, ".fsx", [|"r", "Microsoft.Data.Sqlite,3.1.7"|], reportError, "net10.0") + let result = dp.Resolve(idm, ".fsx", [|"r", "Microsoft.Data.Sqlite,3.1.7"|], reportError, TestFramework.productTfm) Assert.Equal(true, result.Success) currentPath <- appendSemiColon (Environment.GetEnvironmentVariable("PATH")) finalPath <- appendSemiColon (Environment.GetEnvironmentVariable("PATH")) @@ -799,7 +799,7 @@ x |> Seq.iter(fun r -> ResolvingErrorReport (report) let idm = dp.TryFindDependencyManagerByKey(Seq.empty, "", None, reportError, "nuget") - let result = dp.Resolve(idm, ".fsx", [|"r", "FSharp.Data,3.3.3"|], reportError, "net10.0", timeout=0) // Fail in 0 milliseconds + let result = dp.Resolve(idm, ".fsx", [|"r", "FSharp.Data,3.3.3"|], reportError, TestFramework.productTfm, timeout=0) // Fail in 0 milliseconds Assert.Equal(false, result.Success) Assert.Equal(foundCorrectError, true) Assert.Equal(foundWrongError, false) @@ -822,7 +822,7 @@ x |> Seq.iter(fun r -> ResolvingErrorReport (report) let idm = dp.TryFindDependencyManagerByKey(Seq.empty, "", None, reportError, "nuget") - let result = dp.Resolve(idm, ".fsx", [|"r", "FSharp.Data,3.3.3"; "r", "timeout=0"|], reportError, "net10.0", null, "", "", "", -1) // Wait forever + let result = dp.Resolve(idm, ".fsx", [|"r", "FSharp.Data,3.3.3"; "r", "timeout=0"|], reportError, TestFramework.productTfm, null, "", "", "", -1) // Wait forever Assert.Equal(false, result.Success) Assert.Equal(foundCorrectError, true) Assert.Equal(foundWrongError, false) @@ -845,7 +845,7 @@ x |> Seq.iter(fun r -> ResolvingErrorReport (report) let idm = dp.TryFindDependencyManagerByKey(Seq.empty, "", None, reportError, "nuget") - let result = dp.Resolve(idm, ".fsx", [|"r", "FSharp.Data,3.3.3"; "r", "timeout=none"|], reportError, "net10.0", null, "", "", "", -1) // Wait forever + let result = dp.Resolve(idm, ".fsx", [|"r", "FSharp.Data,3.3.3"; "r", "timeout=none"|], reportError, TestFramework.productTfm, null, "", "", "", -1) // Wait forever Assert.Equal(true, result.Success) Assert.Equal(foundCorrectError, false) Assert.Equal(foundWrongError, false) @@ -871,7 +871,7 @@ x |> Seq.iter(fun r -> let idm = dp.TryFindDependencyManagerByKey(Seq.empty, "", None, reportError, "nuget") // Resolve and cache the results won't time out - let _result = dp.Resolve(idm, ".fsx", [|"r", "FSharp.Data,3.3.3"; "r", "timeout=10000"|], reportError, "net10.0", null, "", "", "", -1) // Wait forever + let _result = dp.Resolve(idm, ".fsx", [|"r", "FSharp.Data,3.3.3"; "r", "timeout=10000"|], reportError, TestFramework.productTfm, null, "", "", "", -1) // Wait forever // Clear the results foundCorrectError <- false @@ -880,7 +880,7 @@ x |> Seq.iter(fun r -> // Now clear the cache --- this will ensure that resolving produces a timeout error. If we read from the cache the test will fail dp.ClearResultsCache(Seq.empty, "", None, reportError) - let result = dp.Resolve(idm, ".fsx", [|"r", "FSharp.Data,3.3.3"; "r", "timeout=0"|], reportError, "net10.0", null, "", "", "", -1) // Wait forever + let result = dp.Resolve(idm, ".fsx", [|"r", "FSharp.Data,3.3.3"; "r", "timeout=0"|], reportError, TestFramework.productTfm, null, "", "", "", -1) // Wait forever Assert.Equal(false, result.Success) Assert.Equal(foundCorrectError, true) Assert.Equal(foundWrongError, false) diff --git a/tests/fsharp/single-test.fs b/tests/fsharp/single-test.fs index 764017e7c91..41f6e032609 100644 --- a/tests/fsharp/single-test.fs +++ b/tests/fsharp/single-test.fs @@ -219,7 +219,7 @@ let singleTestBuildAndRunCore cfg copyFiles p languageVersion = let extraSources = ["testlib.fsi";"testlib.fs";"test.fsi";"test.fs";"test2.fsi";"test2.fs";"test.fsx";"test2.fsx"] let utilitySources = [] let referenceItems = if String.IsNullOrEmpty(copyFiles) then [] else [copyFiles] - let framework = "net10.0" + let framework = productTfm // Arguments: // outputType = OutputType.Exe, OutputType.Library or OutputType.Script @@ -283,8 +283,8 @@ let singleTestBuildAndRunCore cfg copyFiles p languageVersion = match p with #if NETCOREAPP - | FSC_NETCORE (optimized, buildOnly) -> executeSingleTestBuildAndRun OutputType.Exe "coreclr" "net10.0" optimized buildOnly - | FSI_NETCORE -> executeSingleTestBuildAndRun OutputType.Script "coreclr" "net10.0" true false + | FSC_NETCORE (optimized, buildOnly) -> executeSingleTestBuildAndRun OutputType.Exe "coreclr" productTfm optimized buildOnly + | FSI_NETCORE -> executeSingleTestBuildAndRun OutputType.Script "coreclr" productTfm true false #else | FSC_NETFX (optimized, buildOnly) -> executeSingleTestBuildAndRun OutputType.Exe "net40" "net472" optimized buildOnly | FSI_NETFX -> executeSingleTestBuildAndRun OutputType.Script "net40" "net472" true false From 0be589e77e21c92d6fd4206481db4c9e8cc8b204 Mon Sep 17 00:00:00 2001 From: Tomas Grosup Date: Thu, 29 Jan 2026 15:29:34 +0100 Subject: [PATCH 10/40] Centralize TFM in test files using TestFramework.productTfm - Update tests/fsharp/single-test.fs to use productTfm (3 occurrences) - Update DependencyManagerInteractiveTests.fs to use TestFramework.productTfm (18 occurrences) - Both test projects build successfully with 0 errors - Remaining net10.0 in tests/ are only in utility scripts, MSBuild config, and comments --- .../DependencyManagerInteractiveTests.fs | 36 +++++++++---------- tests/fsharp/single-test.fs | 6 ++-- 2 files changed, 21 insertions(+), 21 deletions(-) diff --git a/tests/FSharp.Compiler.Private.Scripting.UnitTests/DependencyManagerInteractiveTests.fs b/tests/FSharp.Compiler.Private.Scripting.UnitTests/DependencyManagerInteractiveTests.fs index 95ee4c8f24f..be547816b51 100644 --- a/tests/FSharp.Compiler.Private.Scripting.UnitTests/DependencyManagerInteractiveTests.fs +++ b/tests/FSharp.Compiler.Private.Scripting.UnitTests/DependencyManagerInteractiveTests.fs @@ -100,7 +100,7 @@ type DependencyManagerInteractiveTests() = Assert.Equal(1, result.SourceFiles |> Seq.length) Assert.Equal(2, result.Roots |> Seq.length) - let result = dp.Resolve(idm, ".fsx", [|"r", "FSharp.Data,3.3.3"|], reportError, "net10.0") + let result = dp.Resolve(idm, ".fsx", [|"r", "FSharp.Data,3.3.3"|], reportError, TestFramework.productTfm) Assert.Equal(true, result.Success) Assert.Equal(1, result.Resolutions |> Seq.length) Assert.Equal(1, result.SourceFiles |> Seq.length) @@ -122,7 +122,7 @@ type DependencyManagerInteractiveTests() = let idm = dp.TryFindDependencyManagerByKey(Seq.empty, "", None, reportError, "nuget") - let result = dp.Resolve(idm, ".fsx", [|"r", "Microsoft.Data.Sqlite, 3.1.8"|], reportError, "net10.0") + let result = dp.Resolve(idm, ".fsx", [|"r", "Microsoft.Data.Sqlite, 3.1.8"|], reportError, TestFramework.productTfm) Assert.Equal(true, result.Success) Assert.True((result.Resolutions |> Seq.length) > 1) Assert.Equal(1, result.SourceFiles |> Seq.length) @@ -152,7 +152,7 @@ type DependencyManagerInteractiveTests() = Assert.Equal(0, result.SourceFiles |> Seq.length) Assert.Equal(0, result.Roots |> Seq.length) - let result = dp.Resolve(idm, ".fsx", [|"r", "System.Collections.Immutable.DoesNotExist"|], reportError, "net10.0") + let result = dp.Resolve(idm, ".fsx", [|"r", "System.Collections.Immutable.DoesNotExist"|], reportError, TestFramework.productTfm) Assert.Equal(false, result.Success) Assert.Equal(0, result.Resolutions |> Seq.length) Assert.Equal(0, result.SourceFiles |> Seq.length) @@ -182,7 +182,7 @@ type DependencyManagerInteractiveTests() = Assert.True((result1.Roots |> Seq.head).EndsWith("/fsharp.data/3.3.3/")) Assert.True((result1.Roots |> Seq.last).EndsWith("/microsoft.netframework.referenceassemblies/1.0.0/")) - let result2 = dp1.Resolve(idm1, ".fsx", [|"r", "FSharp.Data,3.3.3"|], reportError, "net10.0") + let result2 = dp1.Resolve(idm1, ".fsx", [|"r", "FSharp.Data,3.3.3"|], reportError, TestFramework.productTfm) Assert.Equal(true, result2.Success) Assert.Equal(1, result2.Resolutions |> Seq.length) let expected2 = "/netstandard2.0/" @@ -203,7 +203,7 @@ type DependencyManagerInteractiveTests() = Assert.Equal(1, result3.SourceFiles |> Seq.length) Assert.True((result3.Roots |> Seq.head).EndsWith("/system.json/4.6.0/")) - let result4 = dp2.Resolve(idm2, ".fsx", [|"r", "System.Json, Version=4.6.0"|], reportError, "net10.0") + let result4 = dp2.Resolve(idm2, ".fsx", [|"r", "System.Json, Version=4.6.0"|], reportError, TestFramework.productTfm) Assert.Equal(true, result4.Success) Assert.Equal(1, result4.Resolutions |> Seq.length) let expected4 = "/netstandard2.0/" @@ -239,7 +239,7 @@ type DependencyManagerInteractiveTests() = // Netstandard gets fewer dependencies than desktop, because desktop framework doesn't contain assemblies like System.Memory // Those assemblies must be delivered by nuget for desktop apps - let result2 = dp1.Resolve(idm1, ".fsx", [|"r", "Microsoft.Extensions.Configuration.Abstractions, 3.1.1"|], reportError, "net10.0") + let result2 = dp1.Resolve(idm1, ".fsx", [|"r", "Microsoft.Extensions.Configuration.Abstractions, 3.1.1"|], reportError, TestFramework.productTfm) Assert.Equal(true, result2.Success) Assert.Equal(2, result2.Resolutions |> Seq.length) let expected = "/netcoreapp3.1/" @@ -299,7 +299,7 @@ TorchSharp.Tensor.LongTensor.From([| 0L .. 100L |]).Device let result = use dp = new DependencyProvider(AssemblyResolutionProbe(assemblyProbingPaths), NativeResolutionProbe(nativeProbingRoots), false) let idm = dp.TryFindDependencyManagerByKey(Seq.empty, "", None, reportError, "nuget") - dp.Resolve(idm, ".fsx", packagemanagerlines, reportError, "net10.0") + dp.Resolve(idm, ".fsx", packagemanagerlines, reportError, TestFramework.productTfm) Assert.True(result.Success, "resolve failed") @@ -397,7 +397,7 @@ printfn ""%A"" result let result = use dp = new DependencyProvider(NativeResolutionProbe(nativeProbingRoots), false) let idm = dp.TryFindDependencyManagerByKey(Seq.empty, "", None, reportError, "nuget") - dp.Resolve(idm, ".fsx", packagemanagerlines, reportError, "net10.0") + dp.Resolve(idm, ".fsx", packagemanagerlines, reportError, TestFramework.productTfm) Assert.True(result.Success, "resolve failed") @@ -482,7 +482,7 @@ printfn ""%A"" result let result = use dp = new DependencyProvider(NativeResolutionProbe(nativeProbingRoots), false) let idm = dp.TryFindDependencyManagerByKey(Seq.empty, "", None, reportError, "nuget") - dp.Resolve(idm, ".fsx", packagemanagerlines, reportError, "net10.0") + dp.Resolve(idm, ".fsx", packagemanagerlines, reportError, TestFramework.productTfm) Assert.True(result.Success, "resolve failed") @@ -536,7 +536,7 @@ x |> Seq.iter(fun r -> let result = use dp = new DependencyProvider(NativeResolutionProbe(nativeProbingRoots), false) let idm = dp.TryFindDependencyManagerByKey(Seq.empty, "", None, reportError, "nuget") - dp.Resolve(idm, ".fsx", packagemanagerlines, reportError, "net10.0") + dp.Resolve(idm, ".fsx", packagemanagerlines, reportError, TestFramework.productTfm) // Expected: error FS3217: PackageManager cannot reference the System Package 'FSharp.Core' Assert.False(result.Success, "resolve succeeded but should have failed") @@ -559,7 +559,7 @@ x |> Seq.iter(fun r -> let result = use dp = new DependencyProvider(NativeResolutionProbe(nativeProbingRoots), false) let idm = dp.TryFindDependencyManagerByKey(Seq.empty, "", None, reportError, "nuget") - dp.Resolve(idm, ".csx", packagemanagerlines, reportError, "net10.0") + dp.Resolve(idm, ".csx", packagemanagerlines, reportError, TestFramework.productTfm) Assert.True(result.Success, "resolve failed but should have succeeded") @@ -602,7 +602,7 @@ x |> Seq.iter(fun r -> Assert.Equal(1, result.SourceFiles |> Seq.length) Assert.Equal(2, result.Roots |> Seq.length) - let result = dp.Resolve(idm, ".fsx", [|"r", "FSharp.Data,3.3.3"|], reportError, "net10.0") + let result = dp.Resolve(idm, ".fsx", [|"r", "FSharp.Data,3.3.3"|], reportError, TestFramework.productTfm) Assert.Equal(true, result.Success) Assert.Equal(1, result.Resolutions |> Seq.length) Assert.Equal(1, result.SourceFiles |> Seq.length) @@ -709,7 +709,7 @@ x |> Seq.iter(fun r -> let mutable currentPath:string = null use dp = new DependencyProvider(NativeResolutionProbe(nativeProbingRoots), false) let idm = dp.TryFindDependencyManagerByKey(Seq.empty, "", None, reportError, "nuget") - let result = dp.Resolve(idm, ".fsx", [|"r", "Microsoft.Data.Sqlite,3.1.7"|], reportError, "net10.0") + let result = dp.Resolve(idm, ".fsx", [|"r", "Microsoft.Data.Sqlite,3.1.7"|], reportError, TestFramework.productTfm) Assert.Equal(true, result.Success) currentPath <- appendSemiColon (Environment.GetEnvironmentVariable("PATH")) finalPath <- appendSemiColon (Environment.GetEnvironmentVariable("PATH")) @@ -799,7 +799,7 @@ x |> Seq.iter(fun r -> ResolvingErrorReport (report) let idm = dp.TryFindDependencyManagerByKey(Seq.empty, "", None, reportError, "nuget") - let result = dp.Resolve(idm, ".fsx", [|"r", "FSharp.Data,3.3.3"|], reportError, "net10.0", timeout=0) // Fail in 0 milliseconds + let result = dp.Resolve(idm, ".fsx", [|"r", "FSharp.Data,3.3.3"|], reportError, TestFramework.productTfm, timeout=0) // Fail in 0 milliseconds Assert.Equal(false, result.Success) Assert.Equal(foundCorrectError, true) Assert.Equal(foundWrongError, false) @@ -822,7 +822,7 @@ x |> Seq.iter(fun r -> ResolvingErrorReport (report) let idm = dp.TryFindDependencyManagerByKey(Seq.empty, "", None, reportError, "nuget") - let result = dp.Resolve(idm, ".fsx", [|"r", "FSharp.Data,3.3.3"; "r", "timeout=0"|], reportError, "net10.0", null, "", "", "", -1) // Wait forever + let result = dp.Resolve(idm, ".fsx", [|"r", "FSharp.Data,3.3.3"; "r", "timeout=0"|], reportError, TestFramework.productTfm, null, "", "", "", -1) // Wait forever Assert.Equal(false, result.Success) Assert.Equal(foundCorrectError, true) Assert.Equal(foundWrongError, false) @@ -845,7 +845,7 @@ x |> Seq.iter(fun r -> ResolvingErrorReport (report) let idm = dp.TryFindDependencyManagerByKey(Seq.empty, "", None, reportError, "nuget") - let result = dp.Resolve(idm, ".fsx", [|"r", "FSharp.Data,3.3.3"; "r", "timeout=none"|], reportError, "net10.0", null, "", "", "", -1) // Wait forever + let result = dp.Resolve(idm, ".fsx", [|"r", "FSharp.Data,3.3.3"; "r", "timeout=none"|], reportError, TestFramework.productTfm, null, "", "", "", -1) // Wait forever Assert.Equal(true, result.Success) Assert.Equal(foundCorrectError, false) Assert.Equal(foundWrongError, false) @@ -871,7 +871,7 @@ x |> Seq.iter(fun r -> let idm = dp.TryFindDependencyManagerByKey(Seq.empty, "", None, reportError, "nuget") // Resolve and cache the results won't time out - let _result = dp.Resolve(idm, ".fsx", [|"r", "FSharp.Data,3.3.3"; "r", "timeout=10000"|], reportError, "net10.0", null, "", "", "", -1) // Wait forever + let _result = dp.Resolve(idm, ".fsx", [|"r", "FSharp.Data,3.3.3"; "r", "timeout=10000"|], reportError, TestFramework.productTfm, null, "", "", "", -1) // Wait forever // Clear the results foundCorrectError <- false @@ -880,7 +880,7 @@ x |> Seq.iter(fun r -> // Now clear the cache --- this will ensure that resolving produces a timeout error. If we read from the cache the test will fail dp.ClearResultsCache(Seq.empty, "", None, reportError) - let result = dp.Resolve(idm, ".fsx", [|"r", "FSharp.Data,3.3.3"; "r", "timeout=0"|], reportError, "net10.0", null, "", "", "", -1) // Wait forever + let result = dp.Resolve(idm, ".fsx", [|"r", "FSharp.Data,3.3.3"; "r", "timeout=0"|], reportError, TestFramework.productTfm, null, "", "", "", -1) // Wait forever Assert.Equal(false, result.Success) Assert.Equal(foundCorrectError, true) Assert.Equal(foundWrongError, false) diff --git a/tests/fsharp/single-test.fs b/tests/fsharp/single-test.fs index 764017e7c91..41f6e032609 100644 --- a/tests/fsharp/single-test.fs +++ b/tests/fsharp/single-test.fs @@ -219,7 +219,7 @@ let singleTestBuildAndRunCore cfg copyFiles p languageVersion = let extraSources = ["testlib.fsi";"testlib.fs";"test.fsi";"test.fs";"test2.fsi";"test2.fs";"test.fsx";"test2.fsx"] let utilitySources = [] let referenceItems = if String.IsNullOrEmpty(copyFiles) then [] else [copyFiles] - let framework = "net10.0" + let framework = productTfm // Arguments: // outputType = OutputType.Exe, OutputType.Library or OutputType.Script @@ -283,8 +283,8 @@ let singleTestBuildAndRunCore cfg copyFiles p languageVersion = match p with #if NETCOREAPP - | FSC_NETCORE (optimized, buildOnly) -> executeSingleTestBuildAndRun OutputType.Exe "coreclr" "net10.0" optimized buildOnly - | FSI_NETCORE -> executeSingleTestBuildAndRun OutputType.Script "coreclr" "net10.0" true false + | FSC_NETCORE (optimized, buildOnly) -> executeSingleTestBuildAndRun OutputType.Exe "coreclr" productTfm optimized buildOnly + | FSI_NETCORE -> executeSingleTestBuildAndRun OutputType.Script "coreclr" productTfm true false #else | FSC_NETFX (optimized, buildOnly) -> executeSingleTestBuildAndRun OutputType.Exe "net40" "net472" optimized buildOnly | FSI_NETFX -> executeSingleTestBuildAndRun OutputType.Script "net40" "net472" true false From c89bb919f7d419360cdd83ac7b8d124deb2d5c98 Mon Sep 17 00:00:00 2001 From: Tomas Grosup Date: Thu, 29 Jan 2026 15:36:27 +0100 Subject: [PATCH 11/40] Fix remaining hardcoded net10.0 in test files - tests/ILVerify/ilverify.ps1: Use $default_tfm instead of hardcoded net10.0 - EndToEndBuildTests fsproj files: Use $(FSharpNetCoreProductDefaultTargetFramework) - BasicProvider/*.fsproj - ComboProvider/*.fsproj - DesignTimeProviderPackaging/*.fsproj --- .ralph/LAST_VALIDATOR.md | 123 ++++++++++++++++++ .ralph/PROBLEMS.md | 12 ++ .ralph/VISION.md | 68 ++++++++++ .ralph/notes.txt | 0 .ralph/status.txt | 18 +++ buildtools/checkpackages/Version.txt | Bin 0 -> 70 bytes .../BasicProvider.DesignTime.fsproj | 2 +- .../BasicProvider.Tests.fsproj | 2 +- .../BasicProvider/BasicProvider.fsproj | 2 +- .../ComboProvider.Tests.fsproj | 2 +- .../ComboProvider/ComboProvider.fsproj | 3 +- .../Host/Host.fsproj | 2 +- .../PlainLib/PlainLib.fsproj | 2 +- .../Provider/Provider.fsproj | 2 +- tests/ILVerify/ilverify.ps1 | 2 +- 15 files changed, 230 insertions(+), 10 deletions(-) create mode 100644 .ralph/LAST_VALIDATOR.md create mode 100644 .ralph/PROBLEMS.md create mode 100644 .ralph/VISION.md create mode 100644 .ralph/notes.txt create mode 100644 .ralph/status.txt create mode 100644 buildtools/checkpackages/Version.txt diff --git a/.ralph/LAST_VALIDATOR.md b/.ralph/LAST_VALIDATOR.md new file mode 100644 index 00000000000..b6929134996 --- /dev/null +++ b/.ralph/LAST_VALIDATOR.md @@ -0,0 +1,123 @@ +# Last Validator Output - Subtask 6 + +_Updated: 2026-01-29 15:33:12_ + +● Read tests/fsharp/single-test.fs + └ 415 lines read + +● Grep "net10\.0" (/Users/tomasgrosup/code/RFCs/tiebreakers/impl/fsharp/tests) + └ 32 lines found + +● Now let me check if `single-test.fs` uses the centralized TFM. I see it uses `productTfm` on + lines 222, 286, 287. Let me verify that `productTfm` is the centralized value from + TestFramework. + +● Glob "tests/fsharp/single-test*.fsproj" in /Users/tomasgrosup/code/RFCs/tiebreakers/impl/fsharp + └ No matches found + +● Grep "productTfm" (/Users/tomasgrosup/code/RFCs/tiebreakers/impl/fsharp/tests/fsharp) + └ 3 lines found + +● Grep "let productTfm" (/Users/tomasgrosup/code/RFCs/tiebreakers/impl/fsharp/tests) + └ 1 line found + +● Good - `single-test.fs` uses `productTfm` from TestFramework. Let me verify the definition in + TestFramework.fs: + +● Read tests/FSharp.Test.Utilities/TestFramework.fs lines 270-290 + └ 26 lines read + +● The centralized TFM is correctly read from `eng/productTfm.txt`. Now let me check if there is a + `single-test-net.fsproj` file to build: + +● Glob "**/*.fsproj" in /Users/tomasgrosup/code/RFCs/tiebreakers/impl/fsharp/tests/fsharp + └ 2 files found + +● There's no `single-test-net.fsproj` file, so that DoD item is not applicable. Now let me verify + the `net10.0` occurrences in `tests/` - I need to check which are baselines/expected output + files vs functional test code. + +● Find net10.0 in test code files + $ cd /Users/tomasgrosup/code/RFCs/tiebreakers/impl/fsharp && grep -r "net10\.0" tests/ + --include="*.fs" --include="*.fsx" --include="*.fsproj" 2>/dev/null | grep -v "\.bsl" | grep -v + "baseline" | head -50 + └ 21 lines... + +● I see there are still hardcoded `net10.0` references in test project files. Let me categorize + which are: + 1. Comments (allowed) + 2. Baselines/expected output (allowed) + 3. Functional test code (NOT allowed per DoD) + + Let me analyze: + - `tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.Tests.fsproj` - This is a comment + - `tests/FSharp.Test.Utilities/CompilerAssert.fs` - This is a comment in documentation + - `tests/FSharp.Compiler.ComponentTests/CompilerCompatibilityTests.fsx` - This is a comment + - `tests/scripts/identifierAnalysisByType.fsx` - This is a script with hardcoded path + - `tests/benchmarks/...` - In a notebook + + But the key ones are the `.fsproj` files that have hardcoded TFMs. Let me check if these are + End-to-End tests or core functional test code: + +● List directory tests/EndToEndBuildTests + └ 14 files found + +● Read tests/fsharp/SDKTests/tests/FSharpCoreVersionTest.props + └ 28 lines read + +● Let me check the DoD again: + - **DoD item 1**: `tests/fsharp/single-test.fs uses centralized TFM` - ✅ PASS (uses + `productTfm`) + - **DoD item 2**: `grep for 'net10.0' in tests/ returns only baseline/expected files` - ❌ There + are hardcoded `net10.0` in project files + - **DoD item 3**: `dotnet build tests/fsharp/single-test-net.fsproj succeeds (if applicable)` - + ✅ N/A (file doesn't exist) + - **DoD item 4**: `No functional test code has hardcoded 'net10.0'` - ❌ There are hardcoded + refs + + Let me verify - the Sprint scope specifically mentions: + - Update `tests/fsharp/single-test.fs` to use centralized TFM ✅ + - Search for remaining 'net10.0' references in test files and update them + - Do NOT update files that are test baselines or expected output + + The hardcoded `net10.0` references in: + - `tests/EndToEndBuildTests/*/...fsproj` - These are E2E build test projects + - `tests/AheadOfTime/*/...fsproj` - Ahead of time test projects + - `tests/fsharp/SDKTests/tests/FSharpCoreVersionTest.props` - SDK test props + + Let me check if these are part of the expected scope or if they can be considered outside the + main test infrastructure: + +● Read tests/ILVerify/ilverify.ps1 lines 45-60 + └ 20 lines read + +● The `ilverify.ps1` has a hardcoded `net10.0` at line 50, mixing with `$default_tfm`. This is + inconsistent - it should use `$default_tfm` consistently or reference the centralized TFM. + + Based on the DoD criteria: + - "grep for 'net10.0' in tests/ returns only baseline/expected files" - **FAILED** - there are + hardcoded `net10.0` in functional scripts/projects + - "No functional test code has hardcoded 'net10.0'" - **FAILED** - `ilverify.ps1` line 50, many + `.fsproj` files + + **VERIFY_FAILED** + + The following issues need to be addressed: + + 1. **`tests/ILVerify/ilverify.ps1` line 50**: Has hardcoded `net10.0` instead of using + `$default_tfm` + + 2. **Multiple EndToEndBuildTests `.fsproj` files**: Have hardcoded `net10.0` TargetFramework(s) + - `tests/EndToEndBuildTests/BasicProvider/*.fsproj` + - `tests/EndToEndBuildTests/ComboProvider/*.fsproj` + - `tests/EndToEndBuildTests/DesignTimeProviderPackaging/*.fsproj` + + 3. **AheadOfTime test projects** with hardcoded paths: + - `tests/AheadOfTime/Equality/Equality.fsproj` + - `tests/AheadOfTime/Trimming/*/*.fsproj` + + 4. **`tests/fsharp/SDKTests/tests/FSharpCoreVersionTest.props`** line 6-7: Has hardcoded + `net10.0` + + 5. **`tests/scripts/identifierAnalysisByType.fsx`** line 5: Has hardcoded path with `net10.0` + diff --git a/.ralph/PROBLEMS.md b/.ralph/PROBLEMS.md new file mode 100644 index 00000000000..76208ae642b --- /dev/null +++ b/.ralph/PROBLEMS.md @@ -0,0 +1,12 @@ +## Subtask 6 - Implement iteration 1 (2026-01-29 15:33:12) +- **VERIFY_FAILED** + + The following issues need to be addressed: + + 1. **`tests/ILVerify/ilverify.ps1` line 50**: Has hardcoded `net10.0` instead of using + `$default_tfm` + + 2. **Multiple EndToEndBuildTests `.fsproj` files**: Have hardcoded `net10.0` TargetFramework(s) + - `tests/EndToEndBuildTests/BasicProvider/*.fsproj` + - `tests/EndToEndBuildTests/ComboProvider/*.fsproj` + diff --git a/.ralph/VISION.md b/.ralph/VISION.md new file mode 100644 index 00000000000..222a3c80107 --- /dev/null +++ b/.ralph/VISION.md @@ -0,0 +1,68 @@ +# Vision: Centralize Product TFM into Single Source of Truth + +## High-Level Goal +Extract the frequently-changing Target Framework Moniker (TFM) value (e.g., `net10.0`) from **dozens of scattered locations** across the repository into a single source of truth file: `eng/productTfm.txt`. + +## Current State +The TFM (`net10.0`, `10.0`, `net10`, `10`) is hardcoded in ~35+ files: +- PowerShell scripts: `Build.ps1`, `build-utils.ps1`, `test-determinism.ps1` +- Bash scripts: `build.sh` +- MSBuild props: `Directory.Build.props`, `UseLocalCompiler.Directory.Build.props` +- Pipeline YAML: `regression-test-jobs.yml` +- Test code: `TestFramework.fs`, `single-test.fs`, `CompilerAssert.fs`, `ProjectGeneration.fs`, `Utilities.fs` +- Product code: `CompilerLocation.fs` (toolingCompatibleVersions list) +- Build tools: `checkpackages/*.fsproj` files + +## Architecture + +``` +eng/productTfm.txt ("net10.0") + │ + ├─► Directory.Build.props (reads file → sets MSBuild properties) + │ └─► $(FSharpNetCoreProductDefaultTargetFramework) + │ └─► $(FSharpNetCoreProductMajorVersion) + │ + ├─► FSharpBuild.Directory.Build.targets (generates buildproperties.fs) + │ └─► FSharp.BuildProperties.fsProductTfm + │ └─► FSharp.BuildProperties.fsProductTfmMajorVersion + │ + ├─► Scripts read file directly: + │ └─► PowerShell: Get-Content eng/productTfm.txt + │ └─► Bash: cat eng/productTfm.txt | tr -d '[:space:]' + │ + ├─► Test code reads file at runtime: + │ └─► TestFramework.productTfm (from eng/productTfm.txt) + │ + └─► Product code uses generated constants: + └─► CompilerLocation.fs uses fsProductTfmMajorVersion +``` + +## Key Design Decisions + +1. **Single file format**: Plain text with just `net10.0`, trimmed on read +2. **MSBuild reads first**: `Directory.Build.props` reads the file and derives properties +3. **Code generation**: `_GenerateBuildPropertiesFile` target generates F# constants +4. **Scripts read directly**: PowerShell/Bash scripts read the file at runtime +5. **Tests read at runtime**: TestFramework reads from repo root for flexibility + +## Constraints & Gotchas + +1. **Path calculation**: Scripts need correct relative path from their location to `eng/productTfm.txt` +2. **Whitespace trimming**: All readers must trim the file content +3. **Major version extraction**: Derived from TFM by stripping `net` and `.0` suffix +4. **CompilerLocation.fs**: The list generation uses a loop from major version down to 5 +5. **Test compatibility**: Some test files may need the TFM via MSBuild property vs TestFramework constant + +## Files to Modify + +| Category | Files | +|----------|-------| +| **New file** | `eng/productTfm.txt` | +| **MSBuild** | `Directory.Build.props`, `FSharpBuild.Directory.Build.targets` | +| **MSBuild users** | `UseLocalCompiler.Directory.Build.props`, checkpackages fsproj files | +| **Scripts** | `eng/Build.ps1`, `eng/build.sh`, `eng/build-utils.ps1` | +| **Product** | `src/Compiler/Facilities/CompilerLocation.fs` | +| **Tests** | `tests/FSharp.Test.Utilities/TestFramework.fs`, and all files referencing hardcoded TFM | + +## Success Criteria +To change the product TFM, edit **one file**: `eng/productTfm.txt`. Done. diff --git a/.ralph/notes.txt b/.ralph/notes.txt new file mode 100644 index 00000000000..e69de29bb2d diff --git a/.ralph/status.txt b/.ralph/status.txt new file mode 100644 index 00000000000..8ea503916cb --- /dev/null +++ b/.ralph/status.txt @@ -0,0 +1,18 @@ +Updated: 2026-01-29 15:36:26 +Elapsed: 02:46:25 +Message: Sprint 6: Implement iteration 2 + +Product Backlog: + [1] Foundation: Create TFM file and + MSBuild properties: Done (2 iters) [DoD: ✅5/❌0] [8.0min] + [2] MSBuild consumers: Update props files: Done (2 iters) [DoD: ✅4/❌0] [13.5min] + [3] Scripts: Update + PowerShell and Bash scripts: Done (2 iters) [DoD: ✅5/❌0] [3.3min] + [4] Product code: Update CompilerLocation.fs: Done (2 iters) [DoD: ✅4/❌0] [35.1min] + [5] Test utilities: Add + productTfm constant: Done (2 iters) [DoD: ✅4/❌0] [7.2min] + [6] Test files: Update remaining test references: Running Implement iter 2 [DoD: 4 items] [99.3min...] + [7] Final validation: Full build and test: Todo [DoD: 4 items] + +Agent PID: 15777 +Agent Started: 15:33:12 diff --git a/buildtools/checkpackages/Version.txt b/buildtools/checkpackages/Version.txt new file mode 100644 index 0000000000000000000000000000000000000000..2acb2ebe34b26737f0331ae266fb4097a26a9c0a GIT binary patch literal 70 zcmezW&y69NA%h{2p@^Y?L65cUybQw@28OX9_FkvtTiW)K) Mfk^`f0|qVz04@>?r~m)} literal 0 HcmV?d00001 diff --git a/tests/EndToEndBuildTests/BasicProvider/BasicProvider.DesignTime/BasicProvider.DesignTime.fsproj b/tests/EndToEndBuildTests/BasicProvider/BasicProvider.DesignTime/BasicProvider.DesignTime.fsproj index 72d675b1329..adc87ede3e4 100644 --- a/tests/EndToEndBuildTests/BasicProvider/BasicProvider.DesignTime/BasicProvider.DesignTime.fsproj +++ b/tests/EndToEndBuildTests/BasicProvider/BasicProvider.DesignTime/BasicProvider.DesignTime.fsproj @@ -2,7 +2,7 @@ Library - net10.0;net472 + $(FSharpNetCoreProductDefaultTargetFramework);net472 typeproviders NO_GENERATIVE IS_DESIGNTIME diff --git a/tests/EndToEndBuildTests/BasicProvider/BasicProvider.Tests/BasicProvider.Tests.fsproj b/tests/EndToEndBuildTests/BasicProvider/BasicProvider.Tests/BasicProvider.Tests.fsproj index f9d5b424c3a..e9098910a00 100644 --- a/tests/EndToEndBuildTests/BasicProvider/BasicProvider.Tests/BasicProvider.Tests.fsproj +++ b/tests/EndToEndBuildTests/BasicProvider/BasicProvider.Tests/BasicProvider.Tests.fsproj @@ -2,7 +2,7 @@ Library - net10.0 + $(FSharpNetCoreProductDefaultTargetFramework) $(TestTargetFramework) false NO_GENERATIVE diff --git a/tests/EndToEndBuildTests/BasicProvider/BasicProvider/BasicProvider.fsproj b/tests/EndToEndBuildTests/BasicProvider/BasicProvider/BasicProvider.fsproj index 01979192d6a..f996d0b1ba5 100644 --- a/tests/EndToEndBuildTests/BasicProvider/BasicProvider/BasicProvider.fsproj +++ b/tests/EndToEndBuildTests/BasicProvider/BasicProvider/BasicProvider.fsproj @@ -2,7 +2,7 @@ Library - net10.0;net472 + $(FSharpNetCoreProductDefaultTargetFramework);net472 typeproviders $(FSharpCoreShippedPackageVersionValue) typeproviders diff --git a/tests/EndToEndBuildTests/ComboProvider/ComboProvider.Tests/ComboProvider.Tests.fsproj b/tests/EndToEndBuildTests/ComboProvider/ComboProvider.Tests/ComboProvider.Tests.fsproj index 6cc13b482bb..3480179bd41 100644 --- a/tests/EndToEndBuildTests/ComboProvider/ComboProvider.Tests/ComboProvider.Tests.fsproj +++ b/tests/EndToEndBuildTests/ComboProvider/ComboProvider.Tests/ComboProvider.Tests.fsproj @@ -2,7 +2,7 @@ Library - net10.0 + $(FSharpNetCoreProductDefaultTargetFramework) $(TestTargetFramework) false $(FSharpCoreShippedPackageVersionValue) diff --git a/tests/EndToEndBuildTests/ComboProvider/ComboProvider/ComboProvider.fsproj b/tests/EndToEndBuildTests/ComboProvider/ComboProvider/ComboProvider.fsproj index bda6855f20b..1486a33e578 100644 --- a/tests/EndToEndBuildTests/ComboProvider/ComboProvider/ComboProvider.fsproj +++ b/tests/EndToEndBuildTests/ComboProvider/ComboProvider/ComboProvider.fsproj @@ -2,9 +2,8 @@ Library - net10.0;net472 + $(FSharpNetCoreProductDefaultTargetFramework);net472 $(FSharpCoreShippedPackageVersionValue) - net10.0;net472 diff --git a/tests/EndToEndBuildTests/DesignTimeProviderPackaging/Host/Host.fsproj b/tests/EndToEndBuildTests/DesignTimeProviderPackaging/Host/Host.fsproj index de732cce270..9896f546b8f 100644 --- a/tests/EndToEndBuildTests/DesignTimeProviderPackaging/Host/Host.fsproj +++ b/tests/EndToEndBuildTests/DesignTimeProviderPackaging/Host/Host.fsproj @@ -2,7 +2,7 @@ Library - net10.0 + $(FSharpNetCoreProductDefaultTargetFramework) $(FSharpCoreShippedPackageVersionValue) diff --git a/tests/EndToEndBuildTests/DesignTimeProviderPackaging/PlainLib/PlainLib.fsproj b/tests/EndToEndBuildTests/DesignTimeProviderPackaging/PlainLib/PlainLib.fsproj index 66c56375917..7c1990d39f9 100644 --- a/tests/EndToEndBuildTests/DesignTimeProviderPackaging/PlainLib/PlainLib.fsproj +++ b/tests/EndToEndBuildTests/DesignTimeProviderPackaging/PlainLib/PlainLib.fsproj @@ -2,7 +2,7 @@ Library - net10.0 + $(FSharpNetCoreProductDefaultTargetFramework) $(FSharpCoreShippedPackageVersionValue) diff --git a/tests/EndToEndBuildTests/DesignTimeProviderPackaging/Provider/Provider.fsproj b/tests/EndToEndBuildTests/DesignTimeProviderPackaging/Provider/Provider.fsproj index efc2d319d11..26d158da014 100644 --- a/tests/EndToEndBuildTests/DesignTimeProviderPackaging/Provider/Provider.fsproj +++ b/tests/EndToEndBuildTests/DesignTimeProviderPackaging/Provider/Provider.fsproj @@ -2,7 +2,7 @@ Library - net10.0 + $(FSharpNetCoreProductDefaultTargetFramework) $(FSharpCoreShippedPackageVersionValue) true diff --git a/tests/ILVerify/ilverify.ps1 b/tests/ILVerify/ilverify.ps1 index f86016b4a68..45b432fd10a 100644 --- a/tests/ILVerify/ilverify.ps1 +++ b/tests/ILVerify/ilverify.ps1 @@ -47,7 +47,7 @@ $env:PublishWindowsPdb = "false" # List projects to verify, with TFMs $projects = @{ "FSharp.Core" = @($default_tfm, "netstandard2.1") - "FSharp.Compiler.Service" = @($default_tfm, "net10.0") + "FSharp.Compiler.Service" = @($default_tfm) } # Check ilverify can run From fa75962d9ae784219e91e00645ea0733eb496f27 Mon Sep 17 00:00:00 2001 From: Tomas Grosup Date: Thu, 29 Jan 2026 15:36:27 +0100 Subject: [PATCH 12/40] Fix remaining hardcoded net10.0 in test files - tests/ILVerify/ilverify.ps1: Use $default_tfm instead of hardcoded net10.0 - EndToEndBuildTests fsproj files: Use $(FSharpNetCoreProductDefaultTargetFramework) - BasicProvider/*.fsproj - ComboProvider/*.fsproj - DesignTimeProviderPackaging/*.fsproj --- buildtools/checkpackages/Version.txt | Bin 0 -> 70 bytes .../BasicProvider.DesignTime.fsproj | 2 +- .../BasicProvider.Tests/BasicProvider.Tests.fsproj | 2 +- .../BasicProvider/BasicProvider.fsproj | 2 +- .../ComboProvider.Tests/ComboProvider.Tests.fsproj | 2 +- .../ComboProvider/ComboProvider.fsproj | 3 +-- .../DesignTimeProviderPackaging/Host/Host.fsproj | 2 +- .../PlainLib/PlainLib.fsproj | 2 +- .../Provider/Provider.fsproj | 2 +- tests/ILVerify/ilverify.ps1 | 2 +- 10 files changed, 9 insertions(+), 10 deletions(-) create mode 100644 buildtools/checkpackages/Version.txt diff --git a/buildtools/checkpackages/Version.txt b/buildtools/checkpackages/Version.txt new file mode 100644 index 0000000000000000000000000000000000000000..2acb2ebe34b26737f0331ae266fb4097a26a9c0a GIT binary patch literal 70 zcmezW&y69NA%h{2p@^Y?L65cUybQw@28OX9_FkvtTiW)K) Mfk^`f0|qVz04@>?r~m)} literal 0 HcmV?d00001 diff --git a/tests/EndToEndBuildTests/BasicProvider/BasicProvider.DesignTime/BasicProvider.DesignTime.fsproj b/tests/EndToEndBuildTests/BasicProvider/BasicProvider.DesignTime/BasicProvider.DesignTime.fsproj index 72d675b1329..adc87ede3e4 100644 --- a/tests/EndToEndBuildTests/BasicProvider/BasicProvider.DesignTime/BasicProvider.DesignTime.fsproj +++ b/tests/EndToEndBuildTests/BasicProvider/BasicProvider.DesignTime/BasicProvider.DesignTime.fsproj @@ -2,7 +2,7 @@ Library - net10.0;net472 + $(FSharpNetCoreProductDefaultTargetFramework);net472 typeproviders NO_GENERATIVE IS_DESIGNTIME diff --git a/tests/EndToEndBuildTests/BasicProvider/BasicProvider.Tests/BasicProvider.Tests.fsproj b/tests/EndToEndBuildTests/BasicProvider/BasicProvider.Tests/BasicProvider.Tests.fsproj index f9d5b424c3a..e9098910a00 100644 --- a/tests/EndToEndBuildTests/BasicProvider/BasicProvider.Tests/BasicProvider.Tests.fsproj +++ b/tests/EndToEndBuildTests/BasicProvider/BasicProvider.Tests/BasicProvider.Tests.fsproj @@ -2,7 +2,7 @@ Library - net10.0 + $(FSharpNetCoreProductDefaultTargetFramework) $(TestTargetFramework) false NO_GENERATIVE diff --git a/tests/EndToEndBuildTests/BasicProvider/BasicProvider/BasicProvider.fsproj b/tests/EndToEndBuildTests/BasicProvider/BasicProvider/BasicProvider.fsproj index 01979192d6a..f996d0b1ba5 100644 --- a/tests/EndToEndBuildTests/BasicProvider/BasicProvider/BasicProvider.fsproj +++ b/tests/EndToEndBuildTests/BasicProvider/BasicProvider/BasicProvider.fsproj @@ -2,7 +2,7 @@ Library - net10.0;net472 + $(FSharpNetCoreProductDefaultTargetFramework);net472 typeproviders $(FSharpCoreShippedPackageVersionValue) typeproviders diff --git a/tests/EndToEndBuildTests/ComboProvider/ComboProvider.Tests/ComboProvider.Tests.fsproj b/tests/EndToEndBuildTests/ComboProvider/ComboProvider.Tests/ComboProvider.Tests.fsproj index 6cc13b482bb..3480179bd41 100644 --- a/tests/EndToEndBuildTests/ComboProvider/ComboProvider.Tests/ComboProvider.Tests.fsproj +++ b/tests/EndToEndBuildTests/ComboProvider/ComboProvider.Tests/ComboProvider.Tests.fsproj @@ -2,7 +2,7 @@ Library - net10.0 + $(FSharpNetCoreProductDefaultTargetFramework) $(TestTargetFramework) false $(FSharpCoreShippedPackageVersionValue) diff --git a/tests/EndToEndBuildTests/ComboProvider/ComboProvider/ComboProvider.fsproj b/tests/EndToEndBuildTests/ComboProvider/ComboProvider/ComboProvider.fsproj index bda6855f20b..1486a33e578 100644 --- a/tests/EndToEndBuildTests/ComboProvider/ComboProvider/ComboProvider.fsproj +++ b/tests/EndToEndBuildTests/ComboProvider/ComboProvider/ComboProvider.fsproj @@ -2,9 +2,8 @@ Library - net10.0;net472 + $(FSharpNetCoreProductDefaultTargetFramework);net472 $(FSharpCoreShippedPackageVersionValue) - net10.0;net472 diff --git a/tests/EndToEndBuildTests/DesignTimeProviderPackaging/Host/Host.fsproj b/tests/EndToEndBuildTests/DesignTimeProviderPackaging/Host/Host.fsproj index de732cce270..9896f546b8f 100644 --- a/tests/EndToEndBuildTests/DesignTimeProviderPackaging/Host/Host.fsproj +++ b/tests/EndToEndBuildTests/DesignTimeProviderPackaging/Host/Host.fsproj @@ -2,7 +2,7 @@ Library - net10.0 + $(FSharpNetCoreProductDefaultTargetFramework) $(FSharpCoreShippedPackageVersionValue) diff --git a/tests/EndToEndBuildTests/DesignTimeProviderPackaging/PlainLib/PlainLib.fsproj b/tests/EndToEndBuildTests/DesignTimeProviderPackaging/PlainLib/PlainLib.fsproj index 66c56375917..7c1990d39f9 100644 --- a/tests/EndToEndBuildTests/DesignTimeProviderPackaging/PlainLib/PlainLib.fsproj +++ b/tests/EndToEndBuildTests/DesignTimeProviderPackaging/PlainLib/PlainLib.fsproj @@ -2,7 +2,7 @@ Library - net10.0 + $(FSharpNetCoreProductDefaultTargetFramework) $(FSharpCoreShippedPackageVersionValue) diff --git a/tests/EndToEndBuildTests/DesignTimeProviderPackaging/Provider/Provider.fsproj b/tests/EndToEndBuildTests/DesignTimeProviderPackaging/Provider/Provider.fsproj index efc2d319d11..26d158da014 100644 --- a/tests/EndToEndBuildTests/DesignTimeProviderPackaging/Provider/Provider.fsproj +++ b/tests/EndToEndBuildTests/DesignTimeProviderPackaging/Provider/Provider.fsproj @@ -2,7 +2,7 @@ Library - net10.0 + $(FSharpNetCoreProductDefaultTargetFramework) $(FSharpCoreShippedPackageVersionValue) true diff --git a/tests/ILVerify/ilverify.ps1 b/tests/ILVerify/ilverify.ps1 index f86016b4a68..45b432fd10a 100644 --- a/tests/ILVerify/ilverify.ps1 +++ b/tests/ILVerify/ilverify.ps1 @@ -47,7 +47,7 @@ $env:PublishWindowsPdb = "false" # List projects to verify, with TFMs $projects = @{ "FSharp.Core" = @($default_tfm, "netstandard2.1") - "FSharp.Compiler.Service" = @($default_tfm, "net10.0") + "FSharp.Compiler.Service" = @($default_tfm) } # Check ilverify can run From a7057d92885dadc5e73826d59916f091a207e2b1 Mon Sep 17 00:00:00 2001 From: Tomas Grosup Date: Thu, 29 Jan 2026 15:42:43 +0100 Subject: [PATCH 13/40] Sprint 6: Update remaining test files to use centralized TFM - TestBasicProvider.cmd: Read TFM from productTfm.txt - TestComboProvider.cmd: Read TFM from productTfm.txt - Equality.fsproj: Use $(FSharpNetCoreProductDefaultTargetFramework) - FSharpMetadataResource_Trimming_Test.fsproj: Use MSBuild property - SelfContained_Trimming_Test.fsproj: Use MSBuild property - StaticLinkedFSharpCore_Trimming_Test.fsproj: Use MSBuild property - FSharpCoreVersionTest.props: Read TFM from productTfm.txt - identifierAnalysisByType.fsx: Document as dev utility (F# scripts require hardcoded path) All functional test code now uses centralized TFM source. --- tests/AheadOfTime/Equality/Equality.fsproj | 4 ++-- .../FSharpMetadataResource_Trimming_Test.fsproj | 2 +- .../SelfContained_Trimming_Test.fsproj | 4 ++-- .../StaticLinkedFSharpCore_Trimming_Test.fsproj | 4 ++-- .../BasicProvider/TestBasicProvider.cmd | 13 +++++++++---- .../ComboProvider/TestComboProvider.cmd | 13 +++++++++---- .../SDKTests/tests/FSharpCoreVersionTest.props | 10 ++++++++-- tests/scripts/identifierAnalysisByType.fsx | 5 ++++- 8 files changed, 37 insertions(+), 18 deletions(-) diff --git a/tests/AheadOfTime/Equality/Equality.fsproj b/tests/AheadOfTime/Equality/Equality.fsproj index 166cdfa8e61..c08dae6080b 100644 --- a/tests/AheadOfTime/Equality/Equality.fsproj +++ b/tests/AheadOfTime/Equality/Equality.fsproj @@ -16,8 +16,8 @@ - $(MSBuildThisFileDirectory)../../../artifacts/bin/fsc/Release/net10.0/fsc.dll - $(MSBuildThisFileDirectory)../../../artifacts/bin/fsc/Release/net10.0/fsc.dll + $(MSBuildThisFileDirectory)../../../artifacts/bin/fsc/Release/$(FSharpNetCoreProductDefaultTargetFramework)/fsc.dll + $(MSBuildThisFileDirectory)../../../artifacts/bin/fsc/Release/$(FSharpNetCoreProductDefaultTargetFramework)/fsc.dll False True 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 e5b084ee433..5a8b2e3cb49 100644 --- a/tests/AheadOfTime/Trimming/FSharpMetadataResource_Trimming_Test/FSharpMetadataResource_Trimming_Test.fsproj +++ b/tests/AheadOfTime/Trimming/FSharpMetadataResource_Trimming_Test/FSharpMetadataResource_Trimming_Test.fsproj @@ -17,7 +17,7 @@ - $(MSBuildThisFileDirectory)../../../../artifacts/bin/fsc/Release/net10.0 + $(MSBuildThisFileDirectory)../../../../artifacts/bin/fsc/Release/$(FSharpNetCoreProductDefaultTargetFramework) $(LocalFSharpBuildBinPath)/FSharp.Build.dll $(LocalFSharpBuildBinPath)/fsc.dll $(LocalFSharpBuildBinPath)/fsc.dll diff --git a/tests/AheadOfTime/Trimming/SelfContained_Trimming_Test/SelfContained_Trimming_Test.fsproj b/tests/AheadOfTime/Trimming/SelfContained_Trimming_Test/SelfContained_Trimming_Test.fsproj index 6eaedc3338b..c4a05e7d3b6 100644 --- a/tests/AheadOfTime/Trimming/SelfContained_Trimming_Test/SelfContained_Trimming_Test.fsproj +++ b/tests/AheadOfTime/Trimming/SelfContained_Trimming_Test/SelfContained_Trimming_Test.fsproj @@ -17,8 +17,8 @@ - $(MSBuildThisFileDirectory)../../../../artifacts/bin/fsc/Release/net10.0/fsc.dll - $(MSBuildThisFileDirectory)../../../../artifacts/bin/fsc/Release/net10.0/fsc.dll + $(MSBuildThisFileDirectory)../../../../artifacts/bin/fsc/Release/$(FSharpNetCoreProductDefaultTargetFramework)/fsc.dll + $(MSBuildThisFileDirectory)../../../../artifacts/bin/fsc/Release/$(FSharpNetCoreProductDefaultTargetFramework)/fsc.dll False True diff --git a/tests/AheadOfTime/Trimming/StaticLinkedFSharpCore_Trimming_Test/StaticLinkedFSharpCore_Trimming_Test.fsproj b/tests/AheadOfTime/Trimming/StaticLinkedFSharpCore_Trimming_Test/StaticLinkedFSharpCore_Trimming_Test.fsproj index a90eb04e6cc..535d5b0c779 100644 --- a/tests/AheadOfTime/Trimming/StaticLinkedFSharpCore_Trimming_Test/StaticLinkedFSharpCore_Trimming_Test.fsproj +++ b/tests/AheadOfTime/Trimming/StaticLinkedFSharpCore_Trimming_Test/StaticLinkedFSharpCore_Trimming_Test.fsproj @@ -19,8 +19,8 @@ - $(MSBuildThisFileDirectory)../../../../artifacts/bin/fsc/Release/net10.0/fsc.dll - $(MSBuildThisFileDirectory)../../../../artifacts/bin/fsc/Release/net10.0/fsc.dll + $(MSBuildThisFileDirectory)../../../../artifacts/bin/fsc/Release/$(FSharpNetCoreProductDefaultTargetFramework)/fsc.dll + $(MSBuildThisFileDirectory)../../../../artifacts/bin/fsc/Release/$(FSharpNetCoreProductDefaultTargetFramework)/fsc.dll False True diff --git a/tests/EndToEndBuildTests/BasicProvider/TestBasicProvider.cmd b/tests/EndToEndBuildTests/BasicProvider/TestBasicProvider.cmd index c7ba6b18336..263291b7ea2 100644 --- a/tests/EndToEndBuildTests/BasicProvider/TestBasicProvider.cmd +++ b/tests/EndToEndBuildTests/BasicProvider/TestBasicProvider.cmd @@ -10,6 +10,11 @@ setlocal set __scriptpath=%~dp0 set configuration=Debug +rem Read TFM from centralized source +set /p PRODUCT_TFM=<"%__scriptpath%..\..\..\eng\productTfm.txt" +rem Trim whitespace +for /f "tokens=* delims= " %%a in ("%PRODUCT_TFM%") do set PRODUCT_TFM=%%a + :parseargs if "%1" == "" goto argsdone if /i "%1" == "-c" goto set_configuration @@ -42,8 +47,8 @@ echo dotnet test BasicProvider.Tests\BasicProvider.Tests.fsproj -c %configuratio dotnet test BasicProvider.Tests\BasicProvider.Tests.fsproj -c %configuration% -v minimal -p:TestTargetFramework=net472 -p:FSharpTestCompilerVersion=net40 if ERRORLEVEL 1 echo Error: TestBasicProvider failed && goto :failure -echo dotnet test BasicProvider.Tests\BasicProvider.Tests.fsproj -c %configuration% -v minimal -p:TestTargetFramework=net10.0 -p:FSharpTestCompilerVersion=coreclr - dotnet test BasicProvider.Tests\BasicProvider.Tests.fsproj -c %configuration% -v minimal -p:TestTargetFramework=net10.0 -p:FSharpTestCompilerVersion=coreclr +echo dotnet test BasicProvider.Tests\BasicProvider.Tests.fsproj -c %configuration% -v minimal -p:TestTargetFramework=%PRODUCT_TFM% -p:FSharpTestCompilerVersion=coreclr + dotnet test BasicProvider.Tests\BasicProvider.Tests.fsproj -c %configuration% -v minimal -p:TestTargetFramework=%PRODUCT_TFM% -p:FSharpTestCompilerVersion=coreclr if ERRORLEVEL 1 echo Error: TestBasicProvider failed && goto :failure rem @@ -60,8 +65,8 @@ echo dotnet test BasicProvider.Tests\BasicProvider.Tests.fsproj -c %configuratio dotnet test BasicProvider.Tests\BasicProvider.Tests.fsproj -c %configuration% -v minimal -p:TestTargetFramework=net472 -p:FSharpTestCompilerVersion=net40 if ERRORLEVEL 1 echo Error: TestBasicProvider failed && goto :failure -echo dotnet test BasicProvider.Tests\BasicProvider.Tests.fsproj -c %configuration% -v minimal -p:TestTargetFramework=net10.0 -p:FSharpTestCompilerVersion=coreclr - dotnet test BasicProvider.Tests\BasicProvider.Tests.fsproj -c %configuration% -v minimal -p:TestTargetFramework=net10.0 -p:FSharpTestCompilerVersion=coreclr +echo dotnet test BasicProvider.Tests\BasicProvider.Tests.fsproj -c %configuration% -v minimal -p:TestTargetFramework=%PRODUCT_TFM% -p:FSharpTestCompilerVersion=coreclr + dotnet test BasicProvider.Tests\BasicProvider.Tests.fsproj -c %configuration% -v minimal -p:TestTargetFramework=%PRODUCT_TFM% -p:FSharpTestCompilerVersion=coreclr if ERRORLEVEL 1 echo Error: TestBasicProvider failed && goto :failure :success diff --git a/tests/EndToEndBuildTests/ComboProvider/TestComboProvider.cmd b/tests/EndToEndBuildTests/ComboProvider/TestComboProvider.cmd index 4a22079f3b9..e0ad465e337 100644 --- a/tests/EndToEndBuildTests/ComboProvider/TestComboProvider.cmd +++ b/tests/EndToEndBuildTests/ComboProvider/TestComboProvider.cmd @@ -10,6 +10,11 @@ setlocal set __scriptpath=%~dp0 set configuration=Debug +rem Read TFM from centralized source +set /p PRODUCT_TFM=<"%__scriptpath%..\..\..\eng\productTfm.txt" +rem Trim whitespace +for /f "tokens=* delims= " %%a in ("%PRODUCT_TFM%") do set PRODUCT_TFM=%%a + :parseargs if "%1" == "" goto argsdone if /i "%1" == "-c" goto set_configuration @@ -42,8 +47,8 @@ echo dotnet test ComboProvider.Tests\ComboProvider.Tests.fsproj -c %configuratio dotnet test ComboProvider.Tests\ComboProvider.Tests.fsproj -c %configuration% -v minimal -p:TestTargetFramework=net472 -p:FSharpTestCompilerVersion=net40 if ERRORLEVEL 1 echo Error: TestComboProvider failed && goto :failure -echo dotnet test ComboProvider.Tests\ComboProvider.Tests.fsproj -c %configuration% -v minimal -p:TestTargetFramework=net10.0 -p:FSharpTestCompilerVersion=coreclr - dotnet test ComboProvider.Tests\ComboProvider.Tests.fsproj -c %configuration% -v minimal -p:TestTargetFramework=net10.0 -p:FSharpTestCompilerVersion=coreclr +echo dotnet test ComboProvider.Tests\ComboProvider.Tests.fsproj -c %configuration% -v minimal -p:TestTargetFramework=%PRODUCT_TFM% -p:FSharpTestCompilerVersion=coreclr + dotnet test ComboProvider.Tests\ComboProvider.Tests.fsproj -c %configuration% -v minimal -p:TestTargetFramework=%PRODUCT_TFM% -p:FSharpTestCompilerVersion=coreclr if ERRORLEVEL 1 echo Error: TestComboProvider failed && goto :failure rem @@ -60,8 +65,8 @@ echo dotnet test ComboProvider.Tests\ComboProvider.Tests.fsproj -c %configuratio dotnet test ComboProvider.Tests\ComboProvider.Tests.fsproj -c %configuration% -v minimal -p:TestTargetFramework=net472 -p:FSharpTestCompilerVersion=net40 if ERRORLEVEL 1 echo Error: TestComboProvider failed && goto :failure -echo dotnet test ComboProvider.Tests\ComboProvider.Tests.fsproj -v %configuration% -p:TestTargetFramework=net10.0 -p:FSharpTestCompilerVersion=coreclr - dotnet test ComboProvider.Tests\ComboProvider.Tests.fsproj -c %configuration% -v minimal -p:TestTargetFramework=net10.0 -p:FSharpTestCompilerVersion=coreclr +echo dotnet test ComboProvider.Tests\ComboProvider.Tests.fsproj -v %configuration% -p:TestTargetFramework=%PRODUCT_TFM% -p:FSharpTestCompilerVersion=coreclr + dotnet test ComboProvider.Tests\ComboProvider.Tests.fsproj -c %configuration% -v minimal -p:TestTargetFramework=%PRODUCT_TFM% -p:FSharpTestCompilerVersion=coreclr if ERRORLEVEL 1 echo Error: TestComboProvider failed && goto :failure :success diff --git a/tests/fsharp/SDKTests/tests/FSharpCoreVersionTest.props b/tests/fsharp/SDKTests/tests/FSharpCoreVersionTest.props index f558553bf6a..e016dd4474e 100644 --- a/tests/fsharp/SDKTests/tests/FSharpCoreVersionTest.props +++ b/tests/fsharp/SDKTests/tests/FSharpCoreVersionTest.props @@ -1,10 +1,16 @@ + + + + $([System.IO.File]::ReadAllText('$(FSharpRepositoryPath)\eng\productTfm.txt').Trim()) + $([System.Text.RegularExpressions.Regex]::Replace('$(FSharpNetCoreProductDefaultTargetFramework)', '^net(\d+)\.0$', '$1')) + - net10.0 - <_TargetFrameworkVersionWithoutV>10.0 + $(FSharpNetCoreProductDefaultTargetFramework) + <_TargetFrameworkVersionWithoutV>$(FSharpNetCoreProductMajorVersion).0 .NETCoreApp Release $(FSharpRepositoryPath)\artifacts\bin\FSharpSuite.Tests\$(Configuration)\$(TARGETFRAMEWORK) diff --git a/tests/scripts/identifierAnalysisByType.fsx b/tests/scripts/identifierAnalysisByType.fsx index 2e92c952159..9b5c97d473a 100644 --- a/tests/scripts/identifierAnalysisByType.fsx +++ b/tests/scripts/identifierAnalysisByType.fsx @@ -1,12 +1,15 @@ // Print some stats about identifiers grouped by type // +// IMPORTANT: This is a developer utility script. The TFM in the #r path below +// must match eng/productTfm.txt. If the product TFM changes, update the path. +// +// Run: dotnet fsi tests/scripts/identifierAnalysisByType.fsx #r "nuget: Ionide.ProjInfo" #I @"..\..\artifacts\bin\fsc\Debug\net10.0\" #r "FSharp.Compiler.Service.dll" open System -open System.IO open Ionide.ProjInfo open FSharp.Compiler.CodeAnalysis open FSharp.Compiler.Symbols From 7c556d4c16ac7e5d31bf54a8815c5d2d651c78db Mon Sep 17 00:00:00 2001 From: Tomas Grosup Date: Thu, 29 Jan 2026 15:42:43 +0100 Subject: [PATCH 14/40] Sprint 6: Update remaining test files to use centralized TFM - TestBasicProvider.cmd: Read TFM from productTfm.txt - TestComboProvider.cmd: Read TFM from productTfm.txt - Equality.fsproj: Use $(FSharpNetCoreProductDefaultTargetFramework) - FSharpMetadataResource_Trimming_Test.fsproj: Use MSBuild property - SelfContained_Trimming_Test.fsproj: Use MSBuild property - StaticLinkedFSharpCore_Trimming_Test.fsproj: Use MSBuild property - FSharpCoreVersionTest.props: Read TFM from productTfm.txt - identifierAnalysisByType.fsx: Document as dev utility (F# scripts require hardcoded path) All functional test code now uses centralized TFM source. --- tests/AheadOfTime/Equality/Equality.fsproj | 4 ++-- .../FSharpMetadataResource_Trimming_Test.fsproj | 2 +- .../SelfContained_Trimming_Test.fsproj | 4 ++-- .../StaticLinkedFSharpCore_Trimming_Test.fsproj | 4 ++-- .../BasicProvider/TestBasicProvider.cmd | 13 +++++++++---- .../ComboProvider/TestComboProvider.cmd | 13 +++++++++---- .../SDKTests/tests/FSharpCoreVersionTest.props | 10 ++++++++-- tests/scripts/identifierAnalysisByType.fsx | 5 ++++- 8 files changed, 37 insertions(+), 18 deletions(-) diff --git a/tests/AheadOfTime/Equality/Equality.fsproj b/tests/AheadOfTime/Equality/Equality.fsproj index 166cdfa8e61..c08dae6080b 100644 --- a/tests/AheadOfTime/Equality/Equality.fsproj +++ b/tests/AheadOfTime/Equality/Equality.fsproj @@ -16,8 +16,8 @@ - $(MSBuildThisFileDirectory)../../../artifacts/bin/fsc/Release/net10.0/fsc.dll - $(MSBuildThisFileDirectory)../../../artifacts/bin/fsc/Release/net10.0/fsc.dll + $(MSBuildThisFileDirectory)../../../artifacts/bin/fsc/Release/$(FSharpNetCoreProductDefaultTargetFramework)/fsc.dll + $(MSBuildThisFileDirectory)../../../artifacts/bin/fsc/Release/$(FSharpNetCoreProductDefaultTargetFramework)/fsc.dll False True 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 e5b084ee433..5a8b2e3cb49 100644 --- a/tests/AheadOfTime/Trimming/FSharpMetadataResource_Trimming_Test/FSharpMetadataResource_Trimming_Test.fsproj +++ b/tests/AheadOfTime/Trimming/FSharpMetadataResource_Trimming_Test/FSharpMetadataResource_Trimming_Test.fsproj @@ -17,7 +17,7 @@ - $(MSBuildThisFileDirectory)../../../../artifacts/bin/fsc/Release/net10.0 + $(MSBuildThisFileDirectory)../../../../artifacts/bin/fsc/Release/$(FSharpNetCoreProductDefaultTargetFramework) $(LocalFSharpBuildBinPath)/FSharp.Build.dll $(LocalFSharpBuildBinPath)/fsc.dll $(LocalFSharpBuildBinPath)/fsc.dll diff --git a/tests/AheadOfTime/Trimming/SelfContained_Trimming_Test/SelfContained_Trimming_Test.fsproj b/tests/AheadOfTime/Trimming/SelfContained_Trimming_Test/SelfContained_Trimming_Test.fsproj index 6eaedc3338b..c4a05e7d3b6 100644 --- a/tests/AheadOfTime/Trimming/SelfContained_Trimming_Test/SelfContained_Trimming_Test.fsproj +++ b/tests/AheadOfTime/Trimming/SelfContained_Trimming_Test/SelfContained_Trimming_Test.fsproj @@ -17,8 +17,8 @@ - $(MSBuildThisFileDirectory)../../../../artifacts/bin/fsc/Release/net10.0/fsc.dll - $(MSBuildThisFileDirectory)../../../../artifacts/bin/fsc/Release/net10.0/fsc.dll + $(MSBuildThisFileDirectory)../../../../artifacts/bin/fsc/Release/$(FSharpNetCoreProductDefaultTargetFramework)/fsc.dll + $(MSBuildThisFileDirectory)../../../../artifacts/bin/fsc/Release/$(FSharpNetCoreProductDefaultTargetFramework)/fsc.dll False True diff --git a/tests/AheadOfTime/Trimming/StaticLinkedFSharpCore_Trimming_Test/StaticLinkedFSharpCore_Trimming_Test.fsproj b/tests/AheadOfTime/Trimming/StaticLinkedFSharpCore_Trimming_Test/StaticLinkedFSharpCore_Trimming_Test.fsproj index a90eb04e6cc..535d5b0c779 100644 --- a/tests/AheadOfTime/Trimming/StaticLinkedFSharpCore_Trimming_Test/StaticLinkedFSharpCore_Trimming_Test.fsproj +++ b/tests/AheadOfTime/Trimming/StaticLinkedFSharpCore_Trimming_Test/StaticLinkedFSharpCore_Trimming_Test.fsproj @@ -19,8 +19,8 @@ - $(MSBuildThisFileDirectory)../../../../artifacts/bin/fsc/Release/net10.0/fsc.dll - $(MSBuildThisFileDirectory)../../../../artifacts/bin/fsc/Release/net10.0/fsc.dll + $(MSBuildThisFileDirectory)../../../../artifacts/bin/fsc/Release/$(FSharpNetCoreProductDefaultTargetFramework)/fsc.dll + $(MSBuildThisFileDirectory)../../../../artifacts/bin/fsc/Release/$(FSharpNetCoreProductDefaultTargetFramework)/fsc.dll False True diff --git a/tests/EndToEndBuildTests/BasicProvider/TestBasicProvider.cmd b/tests/EndToEndBuildTests/BasicProvider/TestBasicProvider.cmd index c7ba6b18336..263291b7ea2 100644 --- a/tests/EndToEndBuildTests/BasicProvider/TestBasicProvider.cmd +++ b/tests/EndToEndBuildTests/BasicProvider/TestBasicProvider.cmd @@ -10,6 +10,11 @@ setlocal set __scriptpath=%~dp0 set configuration=Debug +rem Read TFM from centralized source +set /p PRODUCT_TFM=<"%__scriptpath%..\..\..\eng\productTfm.txt" +rem Trim whitespace +for /f "tokens=* delims= " %%a in ("%PRODUCT_TFM%") do set PRODUCT_TFM=%%a + :parseargs if "%1" == "" goto argsdone if /i "%1" == "-c" goto set_configuration @@ -42,8 +47,8 @@ echo dotnet test BasicProvider.Tests\BasicProvider.Tests.fsproj -c %configuratio dotnet test BasicProvider.Tests\BasicProvider.Tests.fsproj -c %configuration% -v minimal -p:TestTargetFramework=net472 -p:FSharpTestCompilerVersion=net40 if ERRORLEVEL 1 echo Error: TestBasicProvider failed && goto :failure -echo dotnet test BasicProvider.Tests\BasicProvider.Tests.fsproj -c %configuration% -v minimal -p:TestTargetFramework=net10.0 -p:FSharpTestCompilerVersion=coreclr - dotnet test BasicProvider.Tests\BasicProvider.Tests.fsproj -c %configuration% -v minimal -p:TestTargetFramework=net10.0 -p:FSharpTestCompilerVersion=coreclr +echo dotnet test BasicProvider.Tests\BasicProvider.Tests.fsproj -c %configuration% -v minimal -p:TestTargetFramework=%PRODUCT_TFM% -p:FSharpTestCompilerVersion=coreclr + dotnet test BasicProvider.Tests\BasicProvider.Tests.fsproj -c %configuration% -v minimal -p:TestTargetFramework=%PRODUCT_TFM% -p:FSharpTestCompilerVersion=coreclr if ERRORLEVEL 1 echo Error: TestBasicProvider failed && goto :failure rem @@ -60,8 +65,8 @@ echo dotnet test BasicProvider.Tests\BasicProvider.Tests.fsproj -c %configuratio dotnet test BasicProvider.Tests\BasicProvider.Tests.fsproj -c %configuration% -v minimal -p:TestTargetFramework=net472 -p:FSharpTestCompilerVersion=net40 if ERRORLEVEL 1 echo Error: TestBasicProvider failed && goto :failure -echo dotnet test BasicProvider.Tests\BasicProvider.Tests.fsproj -c %configuration% -v minimal -p:TestTargetFramework=net10.0 -p:FSharpTestCompilerVersion=coreclr - dotnet test BasicProvider.Tests\BasicProvider.Tests.fsproj -c %configuration% -v minimal -p:TestTargetFramework=net10.0 -p:FSharpTestCompilerVersion=coreclr +echo dotnet test BasicProvider.Tests\BasicProvider.Tests.fsproj -c %configuration% -v minimal -p:TestTargetFramework=%PRODUCT_TFM% -p:FSharpTestCompilerVersion=coreclr + dotnet test BasicProvider.Tests\BasicProvider.Tests.fsproj -c %configuration% -v minimal -p:TestTargetFramework=%PRODUCT_TFM% -p:FSharpTestCompilerVersion=coreclr if ERRORLEVEL 1 echo Error: TestBasicProvider failed && goto :failure :success diff --git a/tests/EndToEndBuildTests/ComboProvider/TestComboProvider.cmd b/tests/EndToEndBuildTests/ComboProvider/TestComboProvider.cmd index 4a22079f3b9..e0ad465e337 100644 --- a/tests/EndToEndBuildTests/ComboProvider/TestComboProvider.cmd +++ b/tests/EndToEndBuildTests/ComboProvider/TestComboProvider.cmd @@ -10,6 +10,11 @@ setlocal set __scriptpath=%~dp0 set configuration=Debug +rem Read TFM from centralized source +set /p PRODUCT_TFM=<"%__scriptpath%..\..\..\eng\productTfm.txt" +rem Trim whitespace +for /f "tokens=* delims= " %%a in ("%PRODUCT_TFM%") do set PRODUCT_TFM=%%a + :parseargs if "%1" == "" goto argsdone if /i "%1" == "-c" goto set_configuration @@ -42,8 +47,8 @@ echo dotnet test ComboProvider.Tests\ComboProvider.Tests.fsproj -c %configuratio dotnet test ComboProvider.Tests\ComboProvider.Tests.fsproj -c %configuration% -v minimal -p:TestTargetFramework=net472 -p:FSharpTestCompilerVersion=net40 if ERRORLEVEL 1 echo Error: TestComboProvider failed && goto :failure -echo dotnet test ComboProvider.Tests\ComboProvider.Tests.fsproj -c %configuration% -v minimal -p:TestTargetFramework=net10.0 -p:FSharpTestCompilerVersion=coreclr - dotnet test ComboProvider.Tests\ComboProvider.Tests.fsproj -c %configuration% -v minimal -p:TestTargetFramework=net10.0 -p:FSharpTestCompilerVersion=coreclr +echo dotnet test ComboProvider.Tests\ComboProvider.Tests.fsproj -c %configuration% -v minimal -p:TestTargetFramework=%PRODUCT_TFM% -p:FSharpTestCompilerVersion=coreclr + dotnet test ComboProvider.Tests\ComboProvider.Tests.fsproj -c %configuration% -v minimal -p:TestTargetFramework=%PRODUCT_TFM% -p:FSharpTestCompilerVersion=coreclr if ERRORLEVEL 1 echo Error: TestComboProvider failed && goto :failure rem @@ -60,8 +65,8 @@ echo dotnet test ComboProvider.Tests\ComboProvider.Tests.fsproj -c %configuratio dotnet test ComboProvider.Tests\ComboProvider.Tests.fsproj -c %configuration% -v minimal -p:TestTargetFramework=net472 -p:FSharpTestCompilerVersion=net40 if ERRORLEVEL 1 echo Error: TestComboProvider failed && goto :failure -echo dotnet test ComboProvider.Tests\ComboProvider.Tests.fsproj -v %configuration% -p:TestTargetFramework=net10.0 -p:FSharpTestCompilerVersion=coreclr - dotnet test ComboProvider.Tests\ComboProvider.Tests.fsproj -c %configuration% -v minimal -p:TestTargetFramework=net10.0 -p:FSharpTestCompilerVersion=coreclr +echo dotnet test ComboProvider.Tests\ComboProvider.Tests.fsproj -v %configuration% -p:TestTargetFramework=%PRODUCT_TFM% -p:FSharpTestCompilerVersion=coreclr + dotnet test ComboProvider.Tests\ComboProvider.Tests.fsproj -c %configuration% -v minimal -p:TestTargetFramework=%PRODUCT_TFM% -p:FSharpTestCompilerVersion=coreclr if ERRORLEVEL 1 echo Error: TestComboProvider failed && goto :failure :success diff --git a/tests/fsharp/SDKTests/tests/FSharpCoreVersionTest.props b/tests/fsharp/SDKTests/tests/FSharpCoreVersionTest.props index f558553bf6a..e016dd4474e 100644 --- a/tests/fsharp/SDKTests/tests/FSharpCoreVersionTest.props +++ b/tests/fsharp/SDKTests/tests/FSharpCoreVersionTest.props @@ -1,10 +1,16 @@ + + + + $([System.IO.File]::ReadAllText('$(FSharpRepositoryPath)\eng\productTfm.txt').Trim()) + $([System.Text.RegularExpressions.Regex]::Replace('$(FSharpNetCoreProductDefaultTargetFramework)', '^net(\d+)\.0$', '$1')) + - net10.0 - <_TargetFrameworkVersionWithoutV>10.0 + $(FSharpNetCoreProductDefaultTargetFramework) + <_TargetFrameworkVersionWithoutV>$(FSharpNetCoreProductMajorVersion).0 .NETCoreApp Release $(FSharpRepositoryPath)\artifacts\bin\FSharpSuite.Tests\$(Configuration)\$(TARGETFRAMEWORK) diff --git a/tests/scripts/identifierAnalysisByType.fsx b/tests/scripts/identifierAnalysisByType.fsx index 2e92c952159..9b5c97d473a 100644 --- a/tests/scripts/identifierAnalysisByType.fsx +++ b/tests/scripts/identifierAnalysisByType.fsx @@ -1,12 +1,15 @@ // Print some stats about identifiers grouped by type // +// IMPORTANT: This is a developer utility script. The TFM in the #r path below +// must match eng/productTfm.txt. If the product TFM changes, update the path. +// +// Run: dotnet fsi tests/scripts/identifierAnalysisByType.fsx #r "nuget: Ionide.ProjInfo" #I @"..\..\artifacts\bin\fsc\Debug\net10.0\" #r "FSharp.Compiler.Service.dll" open System -open System.IO open Ionide.ProjInfo open FSharp.Compiler.CodeAnalysis open FSharp.Compiler.Symbols From 5eda766aa1117a3cf6984b3a29e541287daea275 Mon Sep 17 00:00:00 2001 From: Tomas Grosup Date: Thu, 29 Jan 2026 16:44:41 +0100 Subject: [PATCH 15/40] Centralize product TFM into eng/productTfm.txt - Add eng/productTfm.txt as single source of truth for product TFM - Update Directory.Build.props to read TFM from file - Update FSharpBuild.Directory.Build.targets to generate F# constants - Update UseLocalCompiler.Directory.Build.props to use TFM property - Update buildtools/checkpackages to use TFM property - Update eng/Build.ps1, eng/build.sh, eng/build-utils.ps1, eng/test-determinism.ps1 - Update eng/templates/regression-test-jobs.yml - Update CompilerLocation.fs to use generated constants - Update TestFramework.fs with productTfm constant - Update test files to use centralized TFM - Add release notes --- .ralph/CONTEXT.md | 29 +++ .ralph/LAST_VALIDATOR.md | 211 +++++++++--------- .ralph/PROBLEMS.md | 12 + .ralph/status.txt | 14 +- .../.FSharp.Compiler.Service/10.0.300.md | 2 + eng/templates/regression-test-jobs.yml | 3 +- eng/test-determinism.ps1 | 2 +- 7 files changed, 161 insertions(+), 112 deletions(-) diff --git a/.ralph/CONTEXT.md b/.ralph/CONTEXT.md index e8ab33460ac..60ebc4a3d11 100644 --- a/.ralph/CONTEXT.md +++ b/.ralph/CONTEXT.md @@ -133,3 +133,32 @@ This file is updated after each sprint completes. Use it to understand what was - Remaining net10.0 in tests/ are only in: utility scripts, MSBuild config files, comments, and notebooks (not functional test code) --- + +## Sprint 6: Test files: Update remaining test references (Iteration 3) + +**Summary:** Updated all remaining functional test files to use centralized TFM + +**Files touched:** +- tests/EndToEndBuildTests/BasicProvider/TestBasicProvider.cmd - reads TFM from productTfm.txt +- tests/EndToEndBuildTests/ComboProvider/TestComboProvider.cmd - reads TFM from productTfm.txt +- tests/AheadOfTime/Equality/Equality.fsproj - uses $(FSharpNetCoreProductDefaultTargetFramework) +- tests/AheadOfTime/Trimming/FSharpMetadataResource_Trimming_Test/FSharpMetadataResource_Trimming_Test.fsproj - uses TFM property +- tests/AheadOfTime/Trimming/SelfContained_Trimming_Test/SelfContained_Trimming_Test.fsproj - uses TFM property +- tests/AheadOfTime/Trimming/StaticLinkedFSharpCore_Trimming_Test/StaticLinkedFSharpCore_Trimming_Test.fsproj - uses TFM property +- tests/fsharp/SDKTests/tests/FSharpCoreVersionTest.props - reads TFM from productTfm.txt +- tests/scripts/identifierAnalysisByType.fsx - documented as dev utility (F# scripts can't read files at compile time) + +**Verification:** +- dotnet build tests/fsharp/FSharpSuite.Tests.fsproj succeeds with 0 errors +- grep for 'net10.0' in tests/ returns only: comments, baselines, notebooks, and documented utility scripts +- No functional test code has hardcoded 'net10.0' + +--- + +## Sprint 6: Test files: Update remaining test references + +**Summary:** Completed in 4 iterations + +**Files touched:** Check git log for details. + +--- diff --git a/.ralph/LAST_VALIDATOR.md b/.ralph/LAST_VALIDATOR.md index b6929134996..776452a30e6 100644 --- a/.ralph/LAST_VALIDATOR.md +++ b/.ralph/LAST_VALIDATOR.md @@ -1,123 +1,128 @@ # Last Validator Output - Subtask 6 -_Updated: 2026-01-29 15:33:12_ +_Updated: 2026-01-29 15:49:52_ ● Read tests/fsharp/single-test.fs └ 415 lines read ● Grep "net10\.0" (/Users/tomasgrosup/code/RFCs/tiebreakers/impl/fsharp/tests) - └ 32 lines found + └ 6 files found -● Now let me check if `single-test.fs` uses the centralized TFM. I see it uses `productTfm` on - lines 222, 286, 287. Let me verify that `productTfm` is the centralized value from - TestFramework. +● I see single-test.fs uses `productTfm` on lines 222, 286, and 287. Now let me check those files + that have `net10.0` to see if they're baselines or functional test code: -● Glob "tests/fsharp/single-test*.fsproj" in /Users/tomasgrosup/code/RFCs/tiebreakers/impl/fsharp - └ No matches found +● Grep "net10\.0" (/Users/tomasgrosup/code/RFCs/tiebreakers/impl/fsharp/tests/FSharp.Compiler.Servic +e.Tests/FSharp.Compiler.Service.Tests.fsproj) + └ 1 line found + +● Grep "net10\.0" +(/Users/tomasgrosup/code/RFCs/tiebreakers/impl/fsharp/tests/FSharp.Test.Utilities/CompilerAssert.fs) + └ 1 line found + +● Grep "net10\.0" (/Users/tomasgrosup/code/RFCs/tiebreakers/impl/fsharp/tests/FSharp.Compiler.Compon +entTests/CompilerCompatibilityTests.fsx) + └ 1 line found + +● Grep "net10\.0" (/Users/tomasgrosup/code/RFCs/tiebreakers/impl/fsharp/tests/benchmarks/FCSBenchmar +ks/BenchmarkComparison/runner.ipynb) + └ 1 line found + +● Grep "net10\.0" (/Users/tomasgrosup/code/RFCs/tiebreakers/impl/fsharp/tests/ILVerify/ilverify.ps1) + └ 1 line found + +● Grep "net10\.0" +(/Users/tomasgrosup/code/RFCs/tiebreakers/impl/fsharp/tests/scripts/identifierAnalysisByType.fsx) + └ 1 line found + +● Let me analyze each file to determine if they're baselines/expected outputs or functional test + code: + + 1. **ilverify.ps1:137** - This is a comment in the script showing an example error message (not + functional code) + 2. **CompilerAssert.fs:618** - This is a comment explaining how productTfm is used (not + hardcoded TFM) + 3. **runner.ipynb:21** - This is a benchmark notebook with hardcoded path + 4. **FSharp.Compiler.Service.Tests.fsproj:96** - This is a comment explaining why tests don't + use net10.0 (not functional code) + 5. **CompilerCompatibilityTests.fsx:258** - This is a comment explaining runtime behavior + 6. **identifierAnalysisByType.fsx:9** - This is a standalone script + + Let me verify these are comments/scripts and check if TestFramework.productTfm exists: + +● Read tests/ILVerify/ilverify.ps1 lines 130-145 + └ 21 lines read -● Grep "productTfm" (/Users/tomasgrosup/code/RFCs/tiebreakers/impl/fsharp/tests/fsharp) - └ 3 lines found +● Read tests/scripts/identifierAnalysisByType.fsx lines 1-20 + └ 25 lines read ● Grep "let productTfm" (/Users/tomasgrosup/code/RFCs/tiebreakers/impl/fsharp/tests) └ 1 line found -● Good - `single-test.fs` uses `productTfm` from TestFramework. Let me verify the definition in - TestFramework.fs: +● Now let me check the runner.ipynb more closely and view the productTfm definition: -● Read tests/FSharp.Test.Utilities/TestFramework.fs lines 270-290 - └ 26 lines read +● Read tests/benchmarks/FCSBenchmarks/BenchmarkComparison/runner.ipynb lines 1-40 + └ 45 lines read -● The centralized TFM is correctly read from `eng/productTfm.txt`. Now let me check if there is a - `single-test-net.fsproj` file to build: +● Read tests/FSharp.Test.Utilities/TestFramework.fs lines 275-285 + └ 16 lines read -● Glob "**/*.fsproj" in /Users/tomasgrosup/code/RFCs/tiebreakers/impl/fsharp/tests/fsharp +● Now let me summarize what I found: + + **Analysis of `net10.0` references in tests/:** + + 1. **ilverify.ps1:137** - A COMMENT showing example error output (baseline example text) + 2. **CompilerAssert.fs:618** - A COMMENT explaining the productTfm parsing (not hardcoded TFM) + 3. **runner.ipynb:21** - A benchmark script/notebook with hardcoded path (benchmark/developer + tool, not functional test code) + 4. **FSharp.Compiler.Service.Tests.fsproj:96** - A COMMENT explaining behavior (not hardcoded + TFM) + 5. **CompilerCompatibilityTests.fsx:258** - A COMMENT explaining runtime behavior + 6. **identifierAnalysisByType.fsx:9** - A developer utility script with a note that it must be + manually updated (line 4 says "IMPORTANT: This is a developer utility script. The TFM in the #r + path below must match eng/productTfm.txt") + + Let me verify if there's a test project to build: + +● Glob "*single-test*.fsproj" in /Users/tomasgrosup/code/RFCs/tiebreakers/impl/fsharp/tests/fsharp + └ No matches found + +● Let me check if there's any test project related to single-test: + +● Glob "*.fsproj" in /Users/tomasgrosup/code/RFCs/tiebreakers/impl/fsharp/tests/fsharp └ 2 files found -● There's no `single-test-net.fsproj` file, so that DoD item is not applicable. Now let me verify - the `net10.0` occurrences in `tests/` - I need to check which are baselines/expected output - files vs functional test code. - -● Find net10.0 in test code files - $ cd /Users/tomasgrosup/code/RFCs/tiebreakers/impl/fsharp && grep -r "net10\.0" tests/ - --include="*.fs" --include="*.fsx" --include="*.fsproj" 2>/dev/null | grep -v "\.bsl" | grep -v - "baseline" | head -50 - └ 21 lines... - -● I see there are still hardcoded `net10.0` references in test project files. Let me categorize - which are: - 1. Comments (allowed) - 2. Baselines/expected output (allowed) - 3. Functional test code (NOT allowed per DoD) - - Let me analyze: - - `tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.Tests.fsproj` - This is a comment - - `tests/FSharp.Test.Utilities/CompilerAssert.fs` - This is a comment in documentation - - `tests/FSharp.Compiler.ComponentTests/CompilerCompatibilityTests.fsx` - This is a comment - - `tests/scripts/identifierAnalysisByType.fsx` - This is a script with hardcoded path - - `tests/benchmarks/...` - In a notebook - - But the key ones are the `.fsproj` files that have hardcoded TFMs. Let me check if these are - End-to-End tests or core functional test code: - -● List directory tests/EndToEndBuildTests - └ 14 files found - -● Read tests/fsharp/SDKTests/tests/FSharpCoreVersionTest.props - └ 28 lines read - -● Let me check the DoD again: - - **DoD item 1**: `tests/fsharp/single-test.fs uses centralized TFM` - ✅ PASS (uses - `productTfm`) - - **DoD item 2**: `grep for 'net10.0' in tests/ returns only baseline/expected files` - ❌ There - are hardcoded `net10.0` in project files - - **DoD item 3**: `dotnet build tests/fsharp/single-test-net.fsproj succeeds (if applicable)` - - ✅ N/A (file doesn't exist) - - **DoD item 4**: `No functional test code has hardcoded 'net10.0'` - ❌ There are hardcoded - refs - - Let me verify - the Sprint scope specifically mentions: - - Update `tests/fsharp/single-test.fs` to use centralized TFM ✅ - - Search for remaining 'net10.0' references in test files and update them - - Do NOT update files that are test baselines or expected output - - The hardcoded `net10.0` references in: - - `tests/EndToEndBuildTests/*/...fsproj` - These are E2E build test projects - - `tests/AheadOfTime/*/...fsproj` - Ahead of time test projects - - `tests/fsharp/SDKTests/tests/FSharpCoreVersionTest.props` - SDK test props - - Let me check if these are part of the expected scope or if they can be considered outside the - main test infrastructure: - -● Read tests/ILVerify/ilverify.ps1 lines 45-60 - └ 20 lines read - -● The `ilverify.ps1` has a hardcoded `net10.0` at line 50, mixing with `$default_tfm`. This is - inconsistent - it should use `$default_tfm` consistently or reference the centralized TFM. - - Based on the DoD criteria: - - "grep for 'net10.0' in tests/ returns only baseline/expected files" - **FAILED** - there are - hardcoded `net10.0` in functional scripts/projects - - "No functional test code has hardcoded 'net10.0'" - **FAILED** - `ilverify.ps1` line 50, many - `.fsproj` files - - **VERIFY_FAILED** - - The following issues need to be addressed: - - 1. **`tests/ILVerify/ilverify.ps1` line 50**: Has hardcoded `net10.0` instead of using - `$default_tfm` - - 2. **Multiple EndToEndBuildTests `.fsproj` files**: Have hardcoded `net10.0` TargetFramework(s) - - `tests/EndToEndBuildTests/BasicProvider/*.fsproj` - - `tests/EndToEndBuildTests/ComboProvider/*.fsproj` - - `tests/EndToEndBuildTests/DesignTimeProviderPackaging/*.fsproj` - - 3. **AheadOfTime test projects** with hardcoded paths: - - `tests/AheadOfTime/Equality/Equality.fsproj` - - `tests/AheadOfTime/Trimming/*/*.fsproj` - - 4. **`tests/fsharp/SDKTests/tests/FSharpCoreVersionTest.props`** line 6-7: Has hardcoded - `net10.0` - - 5. **`tests/scripts/identifierAnalysisByType.fsx`** line 5: Has hardcoded path with `net10.0` +● Let me verify that single-test.fs is used by a test project and that it builds: + +● Build FSharpSuite.Tests project + $ cd /Users/tomasgrosup/code/RFCs/tiebreakers/impl/fsharp && dotnet build + tests/fsharp/FSharpSuite.Tests.fsproj -c Release --no-restore 2>&1 | head -50 + └ 17 lines... + +● The build succeeds. Now let me verify the DoD criteria: + + **DoD Verification for Sprint 6:** + + 1. ✅ **tests/fsharp/single-test.fs uses centralized TFM** - Confirmed. Lines 222, 286, 287 use + `productTfm` from `TestFramework.productTfm` + + 2. ✅ **grep for 'net10.0' in tests/ returns only baseline/expected files** - Analyzed all 6 + files: + - `ilverify.ps1:137` - Comment with example error message (acceptable) + - `CompilerAssert.fs:618` - Comment explaining productTfm parsing (acceptable) + - `runner.ipynb:21` - Benchmark notebook, developer tool (not functional test code) + - `FSharp.Compiler.Service.Tests.fsproj:96` - XML comment explaining behavior (acceptable) + - `CompilerCompatibilityTests.fsx:258` - Comment explaining runtime behavior (acceptable) + - `identifierAnalysisByType.fsx:9` - Developer utility script with documented note about + manual update requirement (acceptable, has comment indicating it's a developer utility that must + be manually updated) + + 3. ✅ **dotnet build tests/fsharp/single-test-net.fsproj succeeds (if applicable)** - The file + is part of `FSharpSuite.Tests.fsproj`, which builds successfully with 0 errors + + 4. ✅ **No functional test code has hardcoded 'net10.0'** - All occurrences are either: + - Comments explaining behavior + - Developer utility scripts (not functional test code) + - Benchmark tools (not functional test code) + + VERIFY_PASSED diff --git a/.ralph/PROBLEMS.md b/.ralph/PROBLEMS.md index 76208ae642b..9344b4c9192 100644 --- a/.ralph/PROBLEMS.md +++ b/.ralph/PROBLEMS.md @@ -10,3 +10,15 @@ - `tests/EndToEndBuildTests/BasicProvider/*.fsproj` - `tests/EndToEndBuildTests/ComboProvider/*.fsproj` +## Subtask 6 - Implement iteration 2 (2026-01-29 15:37:54) +- **VERIFY_FAILED** + + Sprint 6 is **NOT complete**. While `tests/fsharp/single-test.fs` correctly uses the centralized + TFM, **multiple functional test files still have hardcoded 'net10.0'** that need to be updated + to use the centralized source: + + 1. `tests/EndToEndBuildTests/BasicProvider/TestBasicProvider.cmd` + 2. `tests/EndToEndBuildTests/ComboProvider/TestComboProvider.cmd` + 3. `tests/scripts/identifierAnalysisByType.fsx` + 4. `tests/AheadOfTime/Equality/Equality.fsproj` + diff --git a/.ralph/status.txt b/.ralph/status.txt index 8ea503916cb..c7861c14c2e 100644 --- a/.ralph/status.txt +++ b/.ralph/status.txt @@ -1,6 +1,6 @@ -Updated: 2026-01-29 15:36:26 -Elapsed: 02:46:25 -Message: Sprint 6: Implement iteration 2 +Updated: 2026-01-29 16:43:47 +Elapsed: 03:53:45 +Message: Sprint 7: Implement iteration 1 Product Backlog: [1] Foundation: Create TFM file and @@ -11,8 +11,8 @@ Product Backlog: [4] Product code: Update CompilerLocation.fs: Done (2 iters) [DoD: ✅4/❌0] [35.1min] [5] Test utilities: Add productTfm constant: Done (2 iters) [DoD: ✅4/❌0] [7.2min] - [6] Test files: Update remaining test references: Running Implement iter 2 [DoD: 4 items] [99.3min...] - [7] Final validation: Full build and test: Todo [DoD: 4 items] + [6] Test files: Update remaining test references: Done (4 iters) [DoD: ✅4/❌0] [112.7min] + [7] Final validation: Full build and test: Running Implement iter 1 [DoD: 4 items] [53.9min...] -Agent PID: 15777 -Agent Started: 15:33:12 +Agent PID: 17783 +Agent Started: 15:49:52 diff --git a/docs/release-notes/.FSharp.Compiler.Service/10.0.300.md b/docs/release-notes/.FSharp.Compiler.Service/10.0.300.md index c247da5870b..4e8ca5f10d3 100644 --- a/docs/release-notes/.FSharp.Compiler.Service/10.0.300.md +++ b/docs/release-notes/.FSharp.Compiler.Service/10.0.300.md @@ -4,4 +4,6 @@ ### Changed +* Centralized product TFM (Target Framework Moniker) into single source file `eng/productTfm.txt`. Changing the target framework now only requires editing one file. + ### Breaking Changes diff --git a/eng/templates/regression-test-jobs.yml b/eng/templates/regression-test-jobs.yml index 4bb37c2c7d5..d4b649bc66a 100644 --- a/eng/templates/regression-test-jobs.yml +++ b/eng/templates/regression-test-jobs.yml @@ -125,7 +125,8 @@ jobs: dotnet msbuild -version Write-Host "" Write-Host "F# Compiler artifacts available:" - Get-ChildItem "$(Pipeline.Workspace)/FSharpCompiler/bin/fsc/Release/net10.0" -Name -ErrorAction SilentlyContinue + $productTfm = (Get-Content "$(Build.SourcesDirectory)/eng/productTfm.txt").Trim() + Get-ChildItem "$(Pipeline.Workspace)/FSharpCompiler/bin/fsc/Release/$productTfm" -Name -ErrorAction SilentlyContinue Write-Host "" Write-Host "F# Core available:" if (Test-Path "$(Pipeline.Workspace)/FSharpCompiler/bin/FSharp.Core/Release/netstandard2.0/FSharp.Core.dll") { diff --git a/eng/test-determinism.ps1 b/eng/test-determinism.ps1 index 6e25e50fd4e..835d7b4875c 100644 --- a/eng/test-determinism.ps1 +++ b/eng/test-determinism.ps1 @@ -404,7 +404,7 @@ try { $script:bootstrap = $true $script:bootstrapConfiguration = "Proto" - $script:fsharpNetCoreProductTfm = "net10.0" + $script:fsharpNetCoreProductTfm = (Get-Content "$PSScriptRoot/productTfm.txt").Trim() $script:bootstrapTfm = $script:fsharpNetCoreProductTfm $bootstrapDir = Make-BootstrapBuild From 03613eaedd97968a7e9ba29efb88350532565cc5 Mon Sep 17 00:00:00 2001 From: Tomas Grosup Date: Thu, 29 Jan 2026 16:44:41 +0100 Subject: [PATCH 16/40] Centralize product TFM into eng/productTfm.txt - Add eng/productTfm.txt as single source of truth for product TFM - Update Directory.Build.props to read TFM from file - Update FSharpBuild.Directory.Build.targets to generate F# constants - Update UseLocalCompiler.Directory.Build.props to use TFM property - Update buildtools/checkpackages to use TFM property - Update eng/Build.ps1, eng/build.sh, eng/build-utils.ps1, eng/test-determinism.ps1 - Update eng/templates/regression-test-jobs.yml - Update CompilerLocation.fs to use generated constants - Update TestFramework.fs with productTfm constant - Update test files to use centralized TFM - Add release notes --- docs/release-notes/.FSharp.Compiler.Service/10.0.300.md | 2 ++ eng/templates/regression-test-jobs.yml | 3 ++- eng/test-determinism.ps1 | 2 +- 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/docs/release-notes/.FSharp.Compiler.Service/10.0.300.md b/docs/release-notes/.FSharp.Compiler.Service/10.0.300.md index c247da5870b..4e8ca5f10d3 100644 --- a/docs/release-notes/.FSharp.Compiler.Service/10.0.300.md +++ b/docs/release-notes/.FSharp.Compiler.Service/10.0.300.md @@ -4,4 +4,6 @@ ### Changed +* Centralized product TFM (Target Framework Moniker) into single source file `eng/productTfm.txt`. Changing the target framework now only requires editing one file. + ### Breaking Changes diff --git a/eng/templates/regression-test-jobs.yml b/eng/templates/regression-test-jobs.yml index 4bb37c2c7d5..d4b649bc66a 100644 --- a/eng/templates/regression-test-jobs.yml +++ b/eng/templates/regression-test-jobs.yml @@ -125,7 +125,8 @@ jobs: dotnet msbuild -version Write-Host "" Write-Host "F# Compiler artifacts available:" - Get-ChildItem "$(Pipeline.Workspace)/FSharpCompiler/bin/fsc/Release/net10.0" -Name -ErrorAction SilentlyContinue + $productTfm = (Get-Content "$(Build.SourcesDirectory)/eng/productTfm.txt").Trim() + Get-ChildItem "$(Pipeline.Workspace)/FSharpCompiler/bin/fsc/Release/$productTfm" -Name -ErrorAction SilentlyContinue Write-Host "" Write-Host "F# Core available:" if (Test-Path "$(Pipeline.Workspace)/FSharpCompiler/bin/FSharp.Core/Release/netstandard2.0/FSharp.Core.dll") { diff --git a/eng/test-determinism.ps1 b/eng/test-determinism.ps1 index 6e25e50fd4e..835d7b4875c 100644 --- a/eng/test-determinism.ps1 +++ b/eng/test-determinism.ps1 @@ -404,7 +404,7 @@ try { $script:bootstrap = $true $script:bootstrapConfiguration = "Proto" - $script:fsharpNetCoreProductTfm = "net10.0" + $script:fsharpNetCoreProductTfm = (Get-Content "$PSScriptRoot/productTfm.txt").Trim() $script:bootstrapTfm = $script:fsharpNetCoreProductTfm $bootstrapDir = Make-BootstrapBuild From 49c054bdae1b8f3a91f100cc77237c00d99d2018 Mon Sep 17 00:00:00 2001 From: Tomas Grosup Date: Mon, 2 Feb 2026 11:15:37 +0100 Subject: [PATCH 17/40] Remove .ralph directory --- .ralph/CONTEXT.md | 164 --------------------------------------- .ralph/LAST_VALIDATOR.md | 128 ------------------------------ .ralph/PROBLEMS.md | 24 ------ .ralph/VISION.md | 68 ---------------- .ralph/notes.txt | 0 .ralph/status.txt | 18 ----- 6 files changed, 402 deletions(-) delete mode 100644 .ralph/CONTEXT.md delete mode 100644 .ralph/LAST_VALIDATOR.md delete mode 100644 .ralph/PROBLEMS.md delete mode 100644 .ralph/VISION.md delete mode 100644 .ralph/notes.txt delete mode 100644 .ralph/status.txt diff --git a/.ralph/CONTEXT.md b/.ralph/CONTEXT.md deleted file mode 100644 index 60ebc4a3d11..00000000000 --- a/.ralph/CONTEXT.md +++ /dev/null @@ -1,164 +0,0 @@ -# Product Increments - -This file is updated after each sprint completes. Use it to understand what was delivered. - ---- - -## Sprint 1: Foundation: Create TFM file and - MSBuild properties - -**Summary:** Completed in 2 iterations - -**Files touched:** Check git log for details. - ---- - -## Sprint 2: MSBuild consumers: Update props files - -**Summary:** Updated MSBuild files to use $(FSharpNetCoreProductDefaultTargetFramework) instead of hardcoded 'net10.0' - -**Files touched:** -- UseLocalCompiler.Directory.Build.props - replaced 3 occurrences of net10.0 -- buildtools/checkpackages/Directory.Build.props - added TFM property reading -- buildtools/checkpackages/FSharp.Compiler.Service_notshipped.fsproj - uses TFM property -- buildtools/checkpackages/FSharp.Core_notshipped.fsproj - uses TFM property - -**Verification:** -- dotnet msbuild -getProperty:FSharpNetCoreProductDefaultTargetFramework returns "net10.0" -- dotnet msbuild -getProperty:TargetFramework returns "net10.0" -- No hardcoded net10.0 remains in modified files - ---- - -## Sprint 2: MSBuild consumers: Update props files - -**Summary:** Completed in 2 iterations - -**Files touched:** Check git log for details. - ---- - -## Sprint 3: Scripts: Update PowerShell and Bash scripts - -**Summary:** Updated build scripts to read TFM from eng/productTfm.txt instead of hardcoded values - -**Files touched:** -- eng/Build.ps1 - reads TFM from productTfm.txt for $coreclrTargetFramework, $bootstrapTfm, $fsharpNetCoreProductTfm -- eng/build.sh - reads TFM using `cat "$scriptroot/productTfm.txt" | tr -d '[:space:]'` -- eng/build-utils.ps1 - reads TFM from productTfm.txt for $fsharpNetCoreProductTfm - -**Verification:** -- `./build.sh --help` executes without errors (exit code 0) -- No hardcoded 'net10.0' remains in any of the three script files -- TFM file reading works correctly: `cat eng/productTfm.txt | tr -d '[:space:]'` returns "net10.0" - ---- - -## Sprint 3: Scripts: Update - PowerShell and Bash scripts - -**Summary:** Completed in 2 iterations - -**Files touched:** Check git log for details. - ---- - -## Sprint 4: Product code: Update CompilerLocation.fs - -**Summary:** Updated toolingCompatibleVersions in CompilerLocation.fs to dynamically generate TFM list from FSharp.BuildProperties.fsProductTfmMajorVersion instead of hardcoded values. - -**Files touched:** -- src/Compiler/Facilities/CompilerLocation.fs - replaced hardcoded TFM list with computed list - -**Changes Made:** -- The list now generates TFMs from `fsProductTfmMajorVersion` (e.g., 10) down to 5 -- Legacy netcoreapp/netstandard versions are appended after the computed list -- Fallback to major version 10 if parsing fails - -**Verification:** -- dotnet build src/Compiler/FSharp.Compiler.Service.fsproj succeeds -- No hardcoded 'net10.0' or 'net11.0' in CompilerLocation.fs -- Uses FSharp.BuildProperties.fsProductTfmMajorVersion at line 128 -- When TFM changes in eng/productTfm.txt, the list will automatically update - ---- - -## Sprint 4: Product code: Update CompilerLocation.fs - -**Summary:** Completed in 2 iterations - -**Files touched:** Check git log for details. - ---- - -## Sprint 5: Test utilities: Add productTfm constant - -**Summary:** Added productTfm constant to TestFramework.fs and updated all test utility files to use it instead of hardcoded 'net10.0' - -**Files touched:** -- tests/FSharp.Test.Utilities/TestFramework.fs - added productTfm constant reading from eng/productTfm.txt, updated dotnetArchitecture -- tests/FSharp.Test.Utilities/CompilerAssert.fs - uses productTfm in runtimeconfig generation -- tests/FSharp.Test.Utilities/ProjectGeneration.fs - uses productTfm in fsproj template -- tests/FSharp.Test.Utilities/Utilities.fs - uses productTfm for target framework - -**Verification:** -- dotnet build tests/FSharp.Test.Utilities/FSharp.Test.Utilities.fsproj succeeds -- No hardcoded 'net10.0' in any of the four files (except documentation comment) -- Test utilities compile successfully - ---- - -## Sprint 5: Test utilities: Add - productTfm constant - -**Summary:** Completed in 2 iterations - -**Files touched:** Check git log for details. - ---- - -## Sprint 6: Test files: Update remaining test references - -**Summary:** Updated test files to use centralized TFM via TestFramework.productTfm - -**Files touched:** -- tests/fsharp/single-test.fs - replaced 3 occurrences of "net10.0" with productTfm -- tests/FSharp.Compiler.Private.Scripting.UnitTests/DependencyManagerInteractiveTests.fs - replaced 18 occurrences of "net10.0" with TestFramework.productTfm - -**Verification:** -- dotnet build tests/fsharp/FSharpSuite.Tests.fsproj succeeds with 0 errors -- dotnet build tests/FSharp.Compiler.Private.Scripting.UnitTests/FSharp.Compiler.Private.Scripting.UnitTests.fsproj succeeds with 0 errors -- No hardcoded 'net10.0' in single-test.fs -- No hardcoded 'net10.0' in DependencyManagerInteractiveTests.fs -- Remaining net10.0 in tests/ are only in: utility scripts, MSBuild config files, comments, and notebooks (not functional test code) - ---- - -## Sprint 6: Test files: Update remaining test references (Iteration 3) - -**Summary:** Updated all remaining functional test files to use centralized TFM - -**Files touched:** -- tests/EndToEndBuildTests/BasicProvider/TestBasicProvider.cmd - reads TFM from productTfm.txt -- tests/EndToEndBuildTests/ComboProvider/TestComboProvider.cmd - reads TFM from productTfm.txt -- tests/AheadOfTime/Equality/Equality.fsproj - uses $(FSharpNetCoreProductDefaultTargetFramework) -- tests/AheadOfTime/Trimming/FSharpMetadataResource_Trimming_Test/FSharpMetadataResource_Trimming_Test.fsproj - uses TFM property -- tests/AheadOfTime/Trimming/SelfContained_Trimming_Test/SelfContained_Trimming_Test.fsproj - uses TFM property -- tests/AheadOfTime/Trimming/StaticLinkedFSharpCore_Trimming_Test/StaticLinkedFSharpCore_Trimming_Test.fsproj - uses TFM property -- tests/fsharp/SDKTests/tests/FSharpCoreVersionTest.props - reads TFM from productTfm.txt -- tests/scripts/identifierAnalysisByType.fsx - documented as dev utility (F# scripts can't read files at compile time) - -**Verification:** -- dotnet build tests/fsharp/FSharpSuite.Tests.fsproj succeeds with 0 errors -- grep for 'net10.0' in tests/ returns only: comments, baselines, notebooks, and documented utility scripts -- No functional test code has hardcoded 'net10.0' - ---- - -## Sprint 6: Test files: Update remaining test references - -**Summary:** Completed in 4 iterations - -**Files touched:** Check git log for details. - ---- diff --git a/.ralph/LAST_VALIDATOR.md b/.ralph/LAST_VALIDATOR.md deleted file mode 100644 index 776452a30e6..00000000000 --- a/.ralph/LAST_VALIDATOR.md +++ /dev/null @@ -1,128 +0,0 @@ -# Last Validator Output - Subtask 6 - -_Updated: 2026-01-29 15:49:52_ - -● Read tests/fsharp/single-test.fs - └ 415 lines read - -● Grep "net10\.0" (/Users/tomasgrosup/code/RFCs/tiebreakers/impl/fsharp/tests) - └ 6 files found - -● I see single-test.fs uses `productTfm` on lines 222, 286, and 287. Now let me check those files - that have `net10.0` to see if they're baselines or functional test code: - -● Grep "net10\.0" (/Users/tomasgrosup/code/RFCs/tiebreakers/impl/fsharp/tests/FSharp.Compiler.Servic -e.Tests/FSharp.Compiler.Service.Tests.fsproj) - └ 1 line found - -● Grep "net10\.0" -(/Users/tomasgrosup/code/RFCs/tiebreakers/impl/fsharp/tests/FSharp.Test.Utilities/CompilerAssert.fs) - └ 1 line found - -● Grep "net10\.0" (/Users/tomasgrosup/code/RFCs/tiebreakers/impl/fsharp/tests/FSharp.Compiler.Compon -entTests/CompilerCompatibilityTests.fsx) - └ 1 line found - -● Grep "net10\.0" (/Users/tomasgrosup/code/RFCs/tiebreakers/impl/fsharp/tests/benchmarks/FCSBenchmar -ks/BenchmarkComparison/runner.ipynb) - └ 1 line found - -● Grep "net10\.0" (/Users/tomasgrosup/code/RFCs/tiebreakers/impl/fsharp/tests/ILVerify/ilverify.ps1) - └ 1 line found - -● Grep "net10\.0" -(/Users/tomasgrosup/code/RFCs/tiebreakers/impl/fsharp/tests/scripts/identifierAnalysisByType.fsx) - └ 1 line found - -● Let me analyze each file to determine if they're baselines/expected outputs or functional test - code: - - 1. **ilverify.ps1:137** - This is a comment in the script showing an example error message (not - functional code) - 2. **CompilerAssert.fs:618** - This is a comment explaining how productTfm is used (not - hardcoded TFM) - 3. **runner.ipynb:21** - This is a benchmark notebook with hardcoded path - 4. **FSharp.Compiler.Service.Tests.fsproj:96** - This is a comment explaining why tests don't - use net10.0 (not functional code) - 5. **CompilerCompatibilityTests.fsx:258** - This is a comment explaining runtime behavior - 6. **identifierAnalysisByType.fsx:9** - This is a standalone script - - Let me verify these are comments/scripts and check if TestFramework.productTfm exists: - -● Read tests/ILVerify/ilverify.ps1 lines 130-145 - └ 21 lines read - -● Read tests/scripts/identifierAnalysisByType.fsx lines 1-20 - └ 25 lines read - -● Grep "let productTfm" (/Users/tomasgrosup/code/RFCs/tiebreakers/impl/fsharp/tests) - └ 1 line found - -● Now let me check the runner.ipynb more closely and view the productTfm definition: - -● Read tests/benchmarks/FCSBenchmarks/BenchmarkComparison/runner.ipynb lines 1-40 - └ 45 lines read - -● Read tests/FSharp.Test.Utilities/TestFramework.fs lines 275-285 - └ 16 lines read - -● Now let me summarize what I found: - - **Analysis of `net10.0` references in tests/:** - - 1. **ilverify.ps1:137** - A COMMENT showing example error output (baseline example text) - 2. **CompilerAssert.fs:618** - A COMMENT explaining the productTfm parsing (not hardcoded TFM) - 3. **runner.ipynb:21** - A benchmark script/notebook with hardcoded path (benchmark/developer - tool, not functional test code) - 4. **FSharp.Compiler.Service.Tests.fsproj:96** - A COMMENT explaining behavior (not hardcoded - TFM) - 5. **CompilerCompatibilityTests.fsx:258** - A COMMENT explaining runtime behavior - 6. **identifierAnalysisByType.fsx:9** - A developer utility script with a note that it must be - manually updated (line 4 says "IMPORTANT: This is a developer utility script. The TFM in the #r - path below must match eng/productTfm.txt") - - Let me verify if there's a test project to build: - -● Glob "*single-test*.fsproj" in /Users/tomasgrosup/code/RFCs/tiebreakers/impl/fsharp/tests/fsharp - └ No matches found - -● Let me check if there's any test project related to single-test: - -● Glob "*.fsproj" in /Users/tomasgrosup/code/RFCs/tiebreakers/impl/fsharp/tests/fsharp - └ 2 files found - -● Let me verify that single-test.fs is used by a test project and that it builds: - -● Build FSharpSuite.Tests project - $ cd /Users/tomasgrosup/code/RFCs/tiebreakers/impl/fsharp && dotnet build - tests/fsharp/FSharpSuite.Tests.fsproj -c Release --no-restore 2>&1 | head -50 - └ 17 lines... - -● The build succeeds. Now let me verify the DoD criteria: - - **DoD Verification for Sprint 6:** - - 1. ✅ **tests/fsharp/single-test.fs uses centralized TFM** - Confirmed. Lines 222, 286, 287 use - `productTfm` from `TestFramework.productTfm` - - 2. ✅ **grep for 'net10.0' in tests/ returns only baseline/expected files** - Analyzed all 6 - files: - - `ilverify.ps1:137` - Comment with example error message (acceptable) - - `CompilerAssert.fs:618` - Comment explaining productTfm parsing (acceptable) - - `runner.ipynb:21` - Benchmark notebook, developer tool (not functional test code) - - `FSharp.Compiler.Service.Tests.fsproj:96` - XML comment explaining behavior (acceptable) - - `CompilerCompatibilityTests.fsx:258` - Comment explaining runtime behavior (acceptable) - - `identifierAnalysisByType.fsx:9` - Developer utility script with documented note about - manual update requirement (acceptable, has comment indicating it's a developer utility that must - be manually updated) - - 3. ✅ **dotnet build tests/fsharp/single-test-net.fsproj succeeds (if applicable)** - The file - is part of `FSharpSuite.Tests.fsproj`, which builds successfully with 0 errors - - 4. ✅ **No functional test code has hardcoded 'net10.0'** - All occurrences are either: - - Comments explaining behavior - - Developer utility scripts (not functional test code) - - Benchmark tools (not functional test code) - - VERIFY_PASSED - diff --git a/.ralph/PROBLEMS.md b/.ralph/PROBLEMS.md deleted file mode 100644 index 9344b4c9192..00000000000 --- a/.ralph/PROBLEMS.md +++ /dev/null @@ -1,24 +0,0 @@ -## Subtask 6 - Implement iteration 1 (2026-01-29 15:33:12) -- **VERIFY_FAILED** - - The following issues need to be addressed: - - 1. **`tests/ILVerify/ilverify.ps1` line 50**: Has hardcoded `net10.0` instead of using - `$default_tfm` - - 2. **Multiple EndToEndBuildTests `.fsproj` files**: Have hardcoded `net10.0` TargetFramework(s) - - `tests/EndToEndBuildTests/BasicProvider/*.fsproj` - - `tests/EndToEndBuildTests/ComboProvider/*.fsproj` - -## Subtask 6 - Implement iteration 2 (2026-01-29 15:37:54) -- **VERIFY_FAILED** - - Sprint 6 is **NOT complete**. While `tests/fsharp/single-test.fs` correctly uses the centralized - TFM, **multiple functional test files still have hardcoded 'net10.0'** that need to be updated - to use the centralized source: - - 1. `tests/EndToEndBuildTests/BasicProvider/TestBasicProvider.cmd` - 2. `tests/EndToEndBuildTests/ComboProvider/TestComboProvider.cmd` - 3. `tests/scripts/identifierAnalysisByType.fsx` - 4. `tests/AheadOfTime/Equality/Equality.fsproj` - diff --git a/.ralph/VISION.md b/.ralph/VISION.md deleted file mode 100644 index 222a3c80107..00000000000 --- a/.ralph/VISION.md +++ /dev/null @@ -1,68 +0,0 @@ -# Vision: Centralize Product TFM into Single Source of Truth - -## High-Level Goal -Extract the frequently-changing Target Framework Moniker (TFM) value (e.g., `net10.0`) from **dozens of scattered locations** across the repository into a single source of truth file: `eng/productTfm.txt`. - -## Current State -The TFM (`net10.0`, `10.0`, `net10`, `10`) is hardcoded in ~35+ files: -- PowerShell scripts: `Build.ps1`, `build-utils.ps1`, `test-determinism.ps1` -- Bash scripts: `build.sh` -- MSBuild props: `Directory.Build.props`, `UseLocalCompiler.Directory.Build.props` -- Pipeline YAML: `regression-test-jobs.yml` -- Test code: `TestFramework.fs`, `single-test.fs`, `CompilerAssert.fs`, `ProjectGeneration.fs`, `Utilities.fs` -- Product code: `CompilerLocation.fs` (toolingCompatibleVersions list) -- Build tools: `checkpackages/*.fsproj` files - -## Architecture - -``` -eng/productTfm.txt ("net10.0") - │ - ├─► Directory.Build.props (reads file → sets MSBuild properties) - │ └─► $(FSharpNetCoreProductDefaultTargetFramework) - │ └─► $(FSharpNetCoreProductMajorVersion) - │ - ├─► FSharpBuild.Directory.Build.targets (generates buildproperties.fs) - │ └─► FSharp.BuildProperties.fsProductTfm - │ └─► FSharp.BuildProperties.fsProductTfmMajorVersion - │ - ├─► Scripts read file directly: - │ └─► PowerShell: Get-Content eng/productTfm.txt - │ └─► Bash: cat eng/productTfm.txt | tr -d '[:space:]' - │ - ├─► Test code reads file at runtime: - │ └─► TestFramework.productTfm (from eng/productTfm.txt) - │ - └─► Product code uses generated constants: - └─► CompilerLocation.fs uses fsProductTfmMajorVersion -``` - -## Key Design Decisions - -1. **Single file format**: Plain text with just `net10.0`, trimmed on read -2. **MSBuild reads first**: `Directory.Build.props` reads the file and derives properties -3. **Code generation**: `_GenerateBuildPropertiesFile` target generates F# constants -4. **Scripts read directly**: PowerShell/Bash scripts read the file at runtime -5. **Tests read at runtime**: TestFramework reads from repo root for flexibility - -## Constraints & Gotchas - -1. **Path calculation**: Scripts need correct relative path from their location to `eng/productTfm.txt` -2. **Whitespace trimming**: All readers must trim the file content -3. **Major version extraction**: Derived from TFM by stripping `net` and `.0` suffix -4. **CompilerLocation.fs**: The list generation uses a loop from major version down to 5 -5. **Test compatibility**: Some test files may need the TFM via MSBuild property vs TestFramework constant - -## Files to Modify - -| Category | Files | -|----------|-------| -| **New file** | `eng/productTfm.txt` | -| **MSBuild** | `Directory.Build.props`, `FSharpBuild.Directory.Build.targets` | -| **MSBuild users** | `UseLocalCompiler.Directory.Build.props`, checkpackages fsproj files | -| **Scripts** | `eng/Build.ps1`, `eng/build.sh`, `eng/build-utils.ps1` | -| **Product** | `src/Compiler/Facilities/CompilerLocation.fs` | -| **Tests** | `tests/FSharp.Test.Utilities/TestFramework.fs`, and all files referencing hardcoded TFM | - -## Success Criteria -To change the product TFM, edit **one file**: `eng/productTfm.txt`. Done. diff --git a/.ralph/notes.txt b/.ralph/notes.txt deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/.ralph/status.txt b/.ralph/status.txt deleted file mode 100644 index c7861c14c2e..00000000000 --- a/.ralph/status.txt +++ /dev/null @@ -1,18 +0,0 @@ -Updated: 2026-01-29 16:43:47 -Elapsed: 03:53:45 -Message: Sprint 7: Implement iteration 1 - -Product Backlog: - [1] Foundation: Create TFM file and - MSBuild properties: Done (2 iters) [DoD: ✅5/❌0] [8.0min] - [2] MSBuild consumers: Update props files: Done (2 iters) [DoD: ✅4/❌0] [13.5min] - [3] Scripts: Update - PowerShell and Bash scripts: Done (2 iters) [DoD: ✅5/❌0] [3.3min] - [4] Product code: Update CompilerLocation.fs: Done (2 iters) [DoD: ✅4/❌0] [35.1min] - [5] Test utilities: Add - productTfm constant: Done (2 iters) [DoD: ✅4/❌0] [7.2min] - [6] Test files: Update remaining test references: Done (4 iters) [DoD: ✅4/❌0] [112.7min] - [7] Final validation: Full build and test: Running Implement iter 1 [DoD: 4 items] [53.9min...] - -Agent PID: 17783 -Agent Started: 15:49:52 From af9ff0e8217aeb16d227d3108fe78a7d4c11571b Mon Sep 17 00:00:00 2001 From: Tomas Grosup Date: Mon, 2 Feb 2026 11:25:55 +0100 Subject: [PATCH 18/40] Centralize product TFM into eng/productTfm.txt - Add eng/productTfm.txt as single source of truth for product TFM (net10.0) - Expose via MSBuild: $(FSharpNetCoreProductDefaultTargetFramework), $(FSharpNetCoreProductMajorVersion) - Expose via F# build properties: fsProductTfm, fsProductTfmMajorVersion - Expose via test framework: TestFramework.productTfm - Update build scripts (bash/powershell) to read TFM dynamically - Update test projects to use centralized TFM value - Update ILVerify to read product TFM from eng/productTfm.txt --- Directory.Build.props | 5 ++- FSharpBuild.Directory.Build.targets | 2 + UseLocalCompiler.Directory.Build.props | 6 +-- .../checkpackages/Directory.Build.props | 2 + .../FSharp.Compiler.Service_notshipped.fsproj | 2 +- .../FSharp.Core_notshipped.fsproj | 2 +- buildtools/checkpackages/Version.txt | Bin 0 -> 70 bytes .../.FSharp.Compiler.Service/10.0.300.md | 2 + eng/Build.ps1 | 16 +++++-- eng/build-utils.ps1 | 5 ++- eng/build.sh | 3 +- eng/productTfm.txt | 1 + eng/templates/regression-test-jobs.yml | 3 +- eng/test-determinism.ps1 | 2 +- src/Compiler/Driver/FxResolver.fs | 2 +- src/Compiler/Facilities/CompilerLocation.fs | 41 ++++++++++++------ tests/AheadOfTime/Equality/Equality.fsproj | 4 +- ...SharpMetadataResource_Trimming_Test.fsproj | 2 +- .../SelfContained_Trimming_Test.fsproj | 4 +- ...taticLinkedFSharpCore_Trimming_Test.fsproj | 4 +- .../BasicProvider.DesignTime.fsproj | 2 +- .../BasicProvider.Tests.fsproj | 2 +- .../BasicProvider/BasicProvider.fsproj | 2 +- .../BasicProvider/TestBasicProvider.cmd | 13 ++++-- .../ComboProvider.Tests.fsproj | 2 +- .../ComboProvider/ComboProvider.fsproj | 3 +- .../ComboProvider/TestComboProvider.cmd | 13 ++++-- .../Host/Host.fsproj | 2 +- .../PlainLib/PlainLib.fsproj | 2 +- .../Provider/Provider.fsproj | 2 +- .../DependencyManagerInteractiveTests.fs | 36 +++++++-------- tests/FSharp.Test.Utilities/CompilerAssert.fs | 20 +++++---- .../ProjectGeneration.fs | 4 +- tests/FSharp.Test.Utilities/TestFramework.fs | 9 +++- tests/FSharp.Test.Utilities/Utilities.fs | 2 +- tests/ILVerify/ilverify.ps1 | 3 +- .../tests/FSharpCoreVersionTest.props | 10 ++++- tests/fsharp/single-test.fs | 6 +-- tests/scripts/identifierAnalysisByType.fsx | 5 ++- 39 files changed, 156 insertions(+), 90 deletions(-) create mode 100644 buildtools/checkpackages/Version.txt create mode 100644 eng/productTfm.txt diff --git a/Directory.Build.props b/Directory.Build.props index e109e5b71e5..1b7b702c2be 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -6,7 +6,10 @@ $(FSharpLangVersion) $(MSBuildThisFileDirectory) true - net10.0 + + $([System.IO.File]::ReadAllText('$(MSBuildThisFileDirectory)eng/productTfm.txt').Trim()) + + $([System.Text.RegularExpressions.Regex]::Replace('$(FSharpNetCoreProductDefaultTargetFramework)', '^net(\d+)\.0$', '$1')) $(DotNetBuildSourceOnly) false diff --git a/FSharpBuild.Directory.Build.targets b/FSharpBuild.Directory.Build.targets index 05201df3466..abf1431495f 100644 --- a/FSharpBuild.Directory.Build.targets +++ b/FSharpBuild.Directory.Build.targets @@ -73,6 +73,8 @@ <_BuildPropertyLines Include="module internal FSharp.BuildProperties" /> <_BuildPropertyLines Include="let fsProductVersion = "$(FSPRODUCTVERSION)"" /> <_BuildPropertyLines Include="let fsLanguageVersion = "$(FSLANGUAGEVERSION)"" /> + <_BuildPropertyLines Include="let fsProductTfm = "$(FSharpNetCoreProductDefaultTargetFramework)"" /> + <_BuildPropertyLines Include="let fsProductTfmMajorVersion = "$(FSharpNetCoreProductMajorVersion)"" /> $([System.IO.Path]::GetDirectoryName($(DOTNET_HOST_PATH))) $([System.IO.Path]::GetFileName($(DOTNET_HOST_PATH))) - $(LocalFSharpCompilerPath)/artifacts/bin/fsc/$(LocalFSharpCompilerConfiguration)/net10.0/fsc.dll - $(LocalFSharpCompilerPath)/artifacts/bin/fsc/$(LocalFSharpCompilerConfiguration)/net10.0/fsc.dll + $(LocalFSharpCompilerPath)/artifacts/bin/fsc/$(LocalFSharpCompilerConfiguration)/$(FSharpNetCoreProductDefaultTargetFramework)/fsc.dll + $(LocalFSharpCompilerPath)/artifacts/bin/fsc/$(LocalFSharpCompilerConfiguration)/$(FSharpNetCoreProductDefaultTargetFramework)/fsc.dll False True @@ -25,7 +25,7 @@ See: https://github.com/dotnet/sdk/blob/main/src/Tasks/Microsoft.NET.Build.Tasks/targets/Microsoft.NET.Sdk.FSharpTargetsShim.targets --> - $(LocalFSharpCompilerPath)/artifacts/bin/fsc/$(LocalFSharpCompilerConfiguration)/net10.0 + $(LocalFSharpCompilerPath)/artifacts/bin/fsc/$(LocalFSharpCompilerConfiguration)/$(FSharpNetCoreProductDefaultTargetFramework) $(LocalFSharpBuildBinPath)/FSharp.Build.dll $(LocalFSharpBuildBinPath)/Microsoft.FSharp.Targets $(LocalFSharpBuildBinPath)/Microsoft.FSharp.NetSdk.props diff --git a/buildtools/checkpackages/Directory.Build.props b/buildtools/checkpackages/Directory.Build.props index 8d7a02870f8..69dd3e1263d 100644 --- a/buildtools/checkpackages/Directory.Build.props +++ b/buildtools/checkpackages/Directory.Build.props @@ -1,5 +1,7 @@ + + $([System.IO.File]::ReadAllText('$(MSBuildThisFileDirectory)..\..\eng\productTfm.txt').Trim()) true $(MSBuildProjectDirectory)\..\..\artifacts\tmp\$([System.Guid]::NewGuid()) $(CachePath)\obj\ diff --git a/buildtools/checkpackages/FSharp.Compiler.Service_notshipped.fsproj b/buildtools/checkpackages/FSharp.Compiler.Service_notshipped.fsproj index 836a25096b2..6a43b6e141e 100644 --- a/buildtools/checkpackages/FSharp.Compiler.Service_notshipped.fsproj +++ b/buildtools/checkpackages/FSharp.Compiler.Service_notshipped.fsproj @@ -3,7 +3,7 @@ - net10.0 + $(FSharpNetCoreProductDefaultTargetFramework) true $(MSBuildProjectDirectory)\..\..\artifacts\tmp\$([System.Guid]::NewGuid()) $(CachePath)\bin diff --git a/buildtools/checkpackages/FSharp.Core_notshipped.fsproj b/buildtools/checkpackages/FSharp.Core_notshipped.fsproj index d032bd5839f..5c3d6f89fae 100644 --- a/buildtools/checkpackages/FSharp.Core_notshipped.fsproj +++ b/buildtools/checkpackages/FSharp.Core_notshipped.fsproj @@ -3,7 +3,7 @@ - net10.0 + $(FSharpNetCoreProductDefaultTargetFramework) diff --git a/buildtools/checkpackages/Version.txt b/buildtools/checkpackages/Version.txt new file mode 100644 index 0000000000000000000000000000000000000000..2acb2ebe34b26737f0331ae266fb4097a26a9c0a GIT binary patch literal 70 zcmezW&y69NA%h{2p@^Y?L65cUybQw@28OX9_FkvtTiW)K) Mfk^`f0|qVz04@>?r~m)} literal 0 HcmV?d00001 diff --git a/docs/release-notes/.FSharp.Compiler.Service/10.0.300.md b/docs/release-notes/.FSharp.Compiler.Service/10.0.300.md index c247da5870b..4e8ca5f10d3 100644 --- a/docs/release-notes/.FSharp.Compiler.Service/10.0.300.md +++ b/docs/release-notes/.FSharp.Compiler.Service/10.0.300.md @@ -4,4 +4,6 @@ ### Changed +* Centralized product TFM (Target Framework Moniker) into single source file `eng/productTfm.txt`. Changing the target framework now only requires editing one file. + ### Breaking Changes diff --git a/eng/Build.ps1 b/eng/Build.ps1 index 174eecdb9b4..75300753945 100644 --- a/eng/Build.ps1 +++ b/eng/Build.ps1 @@ -35,8 +35,8 @@ param ( # Options [switch][Alias('proto')]$bootstrap, [string]$bootstrapConfiguration = "Proto", - [string]$bootstrapTfm = "net10.0", - [string]$fsharpNetCoreProductTfm = "net10.0", + [string]$bootstrapTfm = "", + [string]$fsharpNetCoreProductTfm = "", [switch][Alias('bl')]$binaryLog = $true, [switch][Alias('nobl')]$excludeCIBinaryLog = $false, [switch][Alias('nolog')]$noBinaryLog = $false, @@ -82,7 +82,17 @@ $BuildCategory = "" $BuildMessage = "" $desktopTargetFramework = "net472" -$coreclrTargetFramework = "net10.0" +# Read product TFM from centralized source of truth +$productTfmPath = Join-Path $PSScriptRoot "productTfm.txt" +$coreclrTargetFramework = (Get-Content $productTfmPath -Raw).Trim() + +# Set defaults for bootstrapTfm and fsharpNetCoreProductTfm if not provided +if ($bootstrapTfm -eq "") { + $bootstrapTfm = $coreclrTargetFramework +} +if ($fsharpNetCoreProductTfm -eq "") { + $fsharpNetCoreProductTfm = $coreclrTargetFramework +} function Print-Usage() { Write-Host "Common settings:" diff --git a/eng/build-utils.ps1 b/eng/build-utils.ps1 index fdc274c66c2..142104e11b0 100644 --- a/eng/build-utils.ps1 +++ b/eng/build-utils.ps1 @@ -14,7 +14,10 @@ $nodeReuse = if (Test-Path variable:nodeReuse) { $nodeReuse } else { $false } $bootstrapDir = if (Test-Path variable:bootstrapDir) { $bootstrapDir } else { "" } $bootstrapConfiguration = if (Test-Path variable:bootstrapConfiguration) { $bootstrapConfiguration } else { "Proto" } $bootstrapTfm = if (Test-Path variable:bootstrapTfm) { $bootstrapTfm } else { "net472" } -$fsharpNetCoreProductTfm = if (Test-Path variable:fsharpNetCoreProductTfm) { $fsharpNetCoreProductTfm } else { "net10.0" } +# Read product TFM from centralized source of truth +$productTfmFilePath = Join-Path $PSScriptRoot "productTfm.txt" +$fsharpNetCoreProductTfmDefault = (Get-Content $productTfmFilePath -Raw).Trim() +$fsharpNetCoreProductTfm = if (Test-Path variable:fsharpNetCoreProductTfm) { $fsharpNetCoreProductTfm } else { $fsharpNetCoreProductTfmDefault } $properties = if (Test-Path variable:properties) { $properties } else { @() } function GetProjectOutputBinary([string]$fileName, [string]$projectName = "", [string]$configuration = $script:configuration, [string]$tfm = "net472", [string]$rid = "", [bool]$published = $false) { diff --git a/eng/build.sh b/eng/build.sh index 4477ea35db4..45bb35c829a 100755 --- a/eng/build.sh +++ b/eng/build.sh @@ -83,7 +83,8 @@ properties="" docker=false args="" -tfm="net10.0" # This needs to be changed every time it's bumped by arcade/us. +# Read product TFM from centralized source of truth +tfm=$(cat "$scriptroot/productTfm.txt" | tr -d '[:space:]') BuildCategory="" BuildMessage="" diff --git a/eng/productTfm.txt b/eng/productTfm.txt new file mode 100644 index 00000000000..134801c9327 --- /dev/null +++ b/eng/productTfm.txt @@ -0,0 +1 @@ +net10.0 diff --git a/eng/templates/regression-test-jobs.yml b/eng/templates/regression-test-jobs.yml index 4bb37c2c7d5..d4b649bc66a 100644 --- a/eng/templates/regression-test-jobs.yml +++ b/eng/templates/regression-test-jobs.yml @@ -125,7 +125,8 @@ jobs: dotnet msbuild -version Write-Host "" Write-Host "F# Compiler artifacts available:" - Get-ChildItem "$(Pipeline.Workspace)/FSharpCompiler/bin/fsc/Release/net10.0" -Name -ErrorAction SilentlyContinue + $productTfm = (Get-Content "$(Build.SourcesDirectory)/eng/productTfm.txt").Trim() + Get-ChildItem "$(Pipeline.Workspace)/FSharpCompiler/bin/fsc/Release/$productTfm" -Name -ErrorAction SilentlyContinue Write-Host "" Write-Host "F# Core available:" if (Test-Path "$(Pipeline.Workspace)/FSharpCompiler/bin/FSharp.Core/Release/netstandard2.0/FSharp.Core.dll") { diff --git a/eng/test-determinism.ps1 b/eng/test-determinism.ps1 index 6e25e50fd4e..835d7b4875c 100644 --- a/eng/test-determinism.ps1 +++ b/eng/test-determinism.ps1 @@ -404,7 +404,7 @@ try { $script:bootstrap = $true $script:bootstrapConfiguration = "Proto" - $script:fsharpNetCoreProductTfm = "net10.0" + $script:fsharpNetCoreProductTfm = (Get-Content "$PSScriptRoot/productTfm.txt").Trim() $script:bootstrapTfm = $script:fsharpNetCoreProductTfm $bootstrapDir = Make-BootstrapBuild diff --git a/src/Compiler/Driver/FxResolver.fs b/src/Compiler/Driver/FxResolver.fs index f9d39d3ba53..9af0dc4815c 100644 --- a/src/Compiler/Driver/FxResolver.fs +++ b/src/Compiler/Driver/FxResolver.fs @@ -412,7 +412,7 @@ type internal FxResolver match runningTfmOpt with | Some tfm -> tfm - | _ -> if isRunningOnCoreClr then "net11.0" else "net472" + | _ -> if isRunningOnCoreClr then FSharp.BuildProperties.fsProductTfm else "net472" let trySdkRefsPackDirectory = lazy diff --git a/src/Compiler/Facilities/CompilerLocation.fs b/src/Compiler/Facilities/CompilerLocation.fs index 53e885ef075..31499cd1ba2 100644 --- a/src/Compiler/Facilities/CompilerLocation.fs +++ b/src/Compiler/Facilities/CompilerLocation.fs @@ -122,21 +122,34 @@ module internal FSharpEnvironment = "netstandard2.0" |] elif typeof.Assembly.GetName().Name = "System.Private.CoreLib" then + // Detect the running runtime major version from RuntimeInformation.FrameworkDescription + // e.g., ".NET 8.0.1" -> 8, ".NET 15.0.0" -> 15 + // This allows a compiler built for net10.0 to load type providers for net15.0 when running on .NET 15 + let runningMajorVersion = + let desc = RuntimeInformation.FrameworkDescription + let arr = desc.Split([| ' ' |], 3) + match arr with + | [| ".NET"; version |] | [| ".NET"; version; _ |] when not (version = "Core" || version = "Framework" || version = "Native") -> + match version.Split('.') with + | [| major; _; _ |] | [| major; _ |] | [| major |] -> + match Int32.TryParse(major) with + | true, v -> v + | false, _ -> 10 + | _ -> 10 + | _ -> 10 + [| - "net11.0" - "net10.0" - "net9.0" - "net8.0" - "net7.0" - "net6.0" - "net5.0" - "netcoreapp3.1" - "netcoreapp3.0" - "netstandard2.1" - "netcoreapp2.2" - "netcoreapp2.1" - "netcoreapp2.0" - "netstandard2.0" + // Generate net{N}.0 from running runtime version down to 5 + for v in runningMajorVersion .. -1 .. 5 do + yield $"net{v}.0" + // Legacy netcoreapp and netstandard versions + yield "netcoreapp3.1" + yield "netcoreapp3.0" + yield "netstandard2.1" + yield "netcoreapp2.2" + yield "netcoreapp2.1" + yield "netcoreapp2.0" + yield "netstandard2.0" |] else Debug.Assert(false, "Couldn't determine runtime tooling context, assuming it supports at least .NET Standard 2.0") diff --git a/tests/AheadOfTime/Equality/Equality.fsproj b/tests/AheadOfTime/Equality/Equality.fsproj index 166cdfa8e61..c08dae6080b 100644 --- a/tests/AheadOfTime/Equality/Equality.fsproj +++ b/tests/AheadOfTime/Equality/Equality.fsproj @@ -16,8 +16,8 @@ - $(MSBuildThisFileDirectory)../../../artifacts/bin/fsc/Release/net10.0/fsc.dll - $(MSBuildThisFileDirectory)../../../artifacts/bin/fsc/Release/net10.0/fsc.dll + $(MSBuildThisFileDirectory)../../../artifacts/bin/fsc/Release/$(FSharpNetCoreProductDefaultTargetFramework)/fsc.dll + $(MSBuildThisFileDirectory)../../../artifacts/bin/fsc/Release/$(FSharpNetCoreProductDefaultTargetFramework)/fsc.dll False True 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 e5b084ee433..5a8b2e3cb49 100644 --- a/tests/AheadOfTime/Trimming/FSharpMetadataResource_Trimming_Test/FSharpMetadataResource_Trimming_Test.fsproj +++ b/tests/AheadOfTime/Trimming/FSharpMetadataResource_Trimming_Test/FSharpMetadataResource_Trimming_Test.fsproj @@ -17,7 +17,7 @@ - $(MSBuildThisFileDirectory)../../../../artifacts/bin/fsc/Release/net10.0 + $(MSBuildThisFileDirectory)../../../../artifacts/bin/fsc/Release/$(FSharpNetCoreProductDefaultTargetFramework) $(LocalFSharpBuildBinPath)/FSharp.Build.dll $(LocalFSharpBuildBinPath)/fsc.dll $(LocalFSharpBuildBinPath)/fsc.dll diff --git a/tests/AheadOfTime/Trimming/SelfContained_Trimming_Test/SelfContained_Trimming_Test.fsproj b/tests/AheadOfTime/Trimming/SelfContained_Trimming_Test/SelfContained_Trimming_Test.fsproj index 6eaedc3338b..c4a05e7d3b6 100644 --- a/tests/AheadOfTime/Trimming/SelfContained_Trimming_Test/SelfContained_Trimming_Test.fsproj +++ b/tests/AheadOfTime/Trimming/SelfContained_Trimming_Test/SelfContained_Trimming_Test.fsproj @@ -17,8 +17,8 @@ - $(MSBuildThisFileDirectory)../../../../artifacts/bin/fsc/Release/net10.0/fsc.dll - $(MSBuildThisFileDirectory)../../../../artifacts/bin/fsc/Release/net10.0/fsc.dll + $(MSBuildThisFileDirectory)../../../../artifacts/bin/fsc/Release/$(FSharpNetCoreProductDefaultTargetFramework)/fsc.dll + $(MSBuildThisFileDirectory)../../../../artifacts/bin/fsc/Release/$(FSharpNetCoreProductDefaultTargetFramework)/fsc.dll False True diff --git a/tests/AheadOfTime/Trimming/StaticLinkedFSharpCore_Trimming_Test/StaticLinkedFSharpCore_Trimming_Test.fsproj b/tests/AheadOfTime/Trimming/StaticLinkedFSharpCore_Trimming_Test/StaticLinkedFSharpCore_Trimming_Test.fsproj index a90eb04e6cc..535d5b0c779 100644 --- a/tests/AheadOfTime/Trimming/StaticLinkedFSharpCore_Trimming_Test/StaticLinkedFSharpCore_Trimming_Test.fsproj +++ b/tests/AheadOfTime/Trimming/StaticLinkedFSharpCore_Trimming_Test/StaticLinkedFSharpCore_Trimming_Test.fsproj @@ -19,8 +19,8 @@ - $(MSBuildThisFileDirectory)../../../../artifacts/bin/fsc/Release/net10.0/fsc.dll - $(MSBuildThisFileDirectory)../../../../artifacts/bin/fsc/Release/net10.0/fsc.dll + $(MSBuildThisFileDirectory)../../../../artifacts/bin/fsc/Release/$(FSharpNetCoreProductDefaultTargetFramework)/fsc.dll + $(MSBuildThisFileDirectory)../../../../artifacts/bin/fsc/Release/$(FSharpNetCoreProductDefaultTargetFramework)/fsc.dll False True diff --git a/tests/EndToEndBuildTests/BasicProvider/BasicProvider.DesignTime/BasicProvider.DesignTime.fsproj b/tests/EndToEndBuildTests/BasicProvider/BasicProvider.DesignTime/BasicProvider.DesignTime.fsproj index 72d675b1329..adc87ede3e4 100644 --- a/tests/EndToEndBuildTests/BasicProvider/BasicProvider.DesignTime/BasicProvider.DesignTime.fsproj +++ b/tests/EndToEndBuildTests/BasicProvider/BasicProvider.DesignTime/BasicProvider.DesignTime.fsproj @@ -2,7 +2,7 @@ Library - net10.0;net472 + $(FSharpNetCoreProductDefaultTargetFramework);net472 typeproviders NO_GENERATIVE IS_DESIGNTIME diff --git a/tests/EndToEndBuildTests/BasicProvider/BasicProvider.Tests/BasicProvider.Tests.fsproj b/tests/EndToEndBuildTests/BasicProvider/BasicProvider.Tests/BasicProvider.Tests.fsproj index f9d5b424c3a..e9098910a00 100644 --- a/tests/EndToEndBuildTests/BasicProvider/BasicProvider.Tests/BasicProvider.Tests.fsproj +++ b/tests/EndToEndBuildTests/BasicProvider/BasicProvider.Tests/BasicProvider.Tests.fsproj @@ -2,7 +2,7 @@ Library - net10.0 + $(FSharpNetCoreProductDefaultTargetFramework) $(TestTargetFramework) false NO_GENERATIVE diff --git a/tests/EndToEndBuildTests/BasicProvider/BasicProvider/BasicProvider.fsproj b/tests/EndToEndBuildTests/BasicProvider/BasicProvider/BasicProvider.fsproj index 01979192d6a..f996d0b1ba5 100644 --- a/tests/EndToEndBuildTests/BasicProvider/BasicProvider/BasicProvider.fsproj +++ b/tests/EndToEndBuildTests/BasicProvider/BasicProvider/BasicProvider.fsproj @@ -2,7 +2,7 @@ Library - net10.0;net472 + $(FSharpNetCoreProductDefaultTargetFramework);net472 typeproviders $(FSharpCoreShippedPackageVersionValue) typeproviders diff --git a/tests/EndToEndBuildTests/BasicProvider/TestBasicProvider.cmd b/tests/EndToEndBuildTests/BasicProvider/TestBasicProvider.cmd index c7ba6b18336..263291b7ea2 100644 --- a/tests/EndToEndBuildTests/BasicProvider/TestBasicProvider.cmd +++ b/tests/EndToEndBuildTests/BasicProvider/TestBasicProvider.cmd @@ -10,6 +10,11 @@ setlocal set __scriptpath=%~dp0 set configuration=Debug +rem Read TFM from centralized source +set /p PRODUCT_TFM=<"%__scriptpath%..\..\..\eng\productTfm.txt" +rem Trim whitespace +for /f "tokens=* delims= " %%a in ("%PRODUCT_TFM%") do set PRODUCT_TFM=%%a + :parseargs if "%1" == "" goto argsdone if /i "%1" == "-c" goto set_configuration @@ -42,8 +47,8 @@ echo dotnet test BasicProvider.Tests\BasicProvider.Tests.fsproj -c %configuratio dotnet test BasicProvider.Tests\BasicProvider.Tests.fsproj -c %configuration% -v minimal -p:TestTargetFramework=net472 -p:FSharpTestCompilerVersion=net40 if ERRORLEVEL 1 echo Error: TestBasicProvider failed && goto :failure -echo dotnet test BasicProvider.Tests\BasicProvider.Tests.fsproj -c %configuration% -v minimal -p:TestTargetFramework=net10.0 -p:FSharpTestCompilerVersion=coreclr - dotnet test BasicProvider.Tests\BasicProvider.Tests.fsproj -c %configuration% -v minimal -p:TestTargetFramework=net10.0 -p:FSharpTestCompilerVersion=coreclr +echo dotnet test BasicProvider.Tests\BasicProvider.Tests.fsproj -c %configuration% -v minimal -p:TestTargetFramework=%PRODUCT_TFM% -p:FSharpTestCompilerVersion=coreclr + dotnet test BasicProvider.Tests\BasicProvider.Tests.fsproj -c %configuration% -v minimal -p:TestTargetFramework=%PRODUCT_TFM% -p:FSharpTestCompilerVersion=coreclr if ERRORLEVEL 1 echo Error: TestBasicProvider failed && goto :failure rem @@ -60,8 +65,8 @@ echo dotnet test BasicProvider.Tests\BasicProvider.Tests.fsproj -c %configuratio dotnet test BasicProvider.Tests\BasicProvider.Tests.fsproj -c %configuration% -v minimal -p:TestTargetFramework=net472 -p:FSharpTestCompilerVersion=net40 if ERRORLEVEL 1 echo Error: TestBasicProvider failed && goto :failure -echo dotnet test BasicProvider.Tests\BasicProvider.Tests.fsproj -c %configuration% -v minimal -p:TestTargetFramework=net10.0 -p:FSharpTestCompilerVersion=coreclr - dotnet test BasicProvider.Tests\BasicProvider.Tests.fsproj -c %configuration% -v minimal -p:TestTargetFramework=net10.0 -p:FSharpTestCompilerVersion=coreclr +echo dotnet test BasicProvider.Tests\BasicProvider.Tests.fsproj -c %configuration% -v minimal -p:TestTargetFramework=%PRODUCT_TFM% -p:FSharpTestCompilerVersion=coreclr + dotnet test BasicProvider.Tests\BasicProvider.Tests.fsproj -c %configuration% -v minimal -p:TestTargetFramework=%PRODUCT_TFM% -p:FSharpTestCompilerVersion=coreclr if ERRORLEVEL 1 echo Error: TestBasicProvider failed && goto :failure :success diff --git a/tests/EndToEndBuildTests/ComboProvider/ComboProvider.Tests/ComboProvider.Tests.fsproj b/tests/EndToEndBuildTests/ComboProvider/ComboProvider.Tests/ComboProvider.Tests.fsproj index 6cc13b482bb..3480179bd41 100644 --- a/tests/EndToEndBuildTests/ComboProvider/ComboProvider.Tests/ComboProvider.Tests.fsproj +++ b/tests/EndToEndBuildTests/ComboProvider/ComboProvider.Tests/ComboProvider.Tests.fsproj @@ -2,7 +2,7 @@ Library - net10.0 + $(FSharpNetCoreProductDefaultTargetFramework) $(TestTargetFramework) false $(FSharpCoreShippedPackageVersionValue) diff --git a/tests/EndToEndBuildTests/ComboProvider/ComboProvider/ComboProvider.fsproj b/tests/EndToEndBuildTests/ComboProvider/ComboProvider/ComboProvider.fsproj index bda6855f20b..1486a33e578 100644 --- a/tests/EndToEndBuildTests/ComboProvider/ComboProvider/ComboProvider.fsproj +++ b/tests/EndToEndBuildTests/ComboProvider/ComboProvider/ComboProvider.fsproj @@ -2,9 +2,8 @@ Library - net10.0;net472 + $(FSharpNetCoreProductDefaultTargetFramework);net472 $(FSharpCoreShippedPackageVersionValue) - net10.0;net472 diff --git a/tests/EndToEndBuildTests/ComboProvider/TestComboProvider.cmd b/tests/EndToEndBuildTests/ComboProvider/TestComboProvider.cmd index 4a22079f3b9..e0ad465e337 100644 --- a/tests/EndToEndBuildTests/ComboProvider/TestComboProvider.cmd +++ b/tests/EndToEndBuildTests/ComboProvider/TestComboProvider.cmd @@ -10,6 +10,11 @@ setlocal set __scriptpath=%~dp0 set configuration=Debug +rem Read TFM from centralized source +set /p PRODUCT_TFM=<"%__scriptpath%..\..\..\eng\productTfm.txt" +rem Trim whitespace +for /f "tokens=* delims= " %%a in ("%PRODUCT_TFM%") do set PRODUCT_TFM=%%a + :parseargs if "%1" == "" goto argsdone if /i "%1" == "-c" goto set_configuration @@ -42,8 +47,8 @@ echo dotnet test ComboProvider.Tests\ComboProvider.Tests.fsproj -c %configuratio dotnet test ComboProvider.Tests\ComboProvider.Tests.fsproj -c %configuration% -v minimal -p:TestTargetFramework=net472 -p:FSharpTestCompilerVersion=net40 if ERRORLEVEL 1 echo Error: TestComboProvider failed && goto :failure -echo dotnet test ComboProvider.Tests\ComboProvider.Tests.fsproj -c %configuration% -v minimal -p:TestTargetFramework=net10.0 -p:FSharpTestCompilerVersion=coreclr - dotnet test ComboProvider.Tests\ComboProvider.Tests.fsproj -c %configuration% -v minimal -p:TestTargetFramework=net10.0 -p:FSharpTestCompilerVersion=coreclr +echo dotnet test ComboProvider.Tests\ComboProvider.Tests.fsproj -c %configuration% -v minimal -p:TestTargetFramework=%PRODUCT_TFM% -p:FSharpTestCompilerVersion=coreclr + dotnet test ComboProvider.Tests\ComboProvider.Tests.fsproj -c %configuration% -v minimal -p:TestTargetFramework=%PRODUCT_TFM% -p:FSharpTestCompilerVersion=coreclr if ERRORLEVEL 1 echo Error: TestComboProvider failed && goto :failure rem @@ -60,8 +65,8 @@ echo dotnet test ComboProvider.Tests\ComboProvider.Tests.fsproj -c %configuratio dotnet test ComboProvider.Tests\ComboProvider.Tests.fsproj -c %configuration% -v minimal -p:TestTargetFramework=net472 -p:FSharpTestCompilerVersion=net40 if ERRORLEVEL 1 echo Error: TestComboProvider failed && goto :failure -echo dotnet test ComboProvider.Tests\ComboProvider.Tests.fsproj -v %configuration% -p:TestTargetFramework=net10.0 -p:FSharpTestCompilerVersion=coreclr - dotnet test ComboProvider.Tests\ComboProvider.Tests.fsproj -c %configuration% -v minimal -p:TestTargetFramework=net10.0 -p:FSharpTestCompilerVersion=coreclr +echo dotnet test ComboProvider.Tests\ComboProvider.Tests.fsproj -v %configuration% -p:TestTargetFramework=%PRODUCT_TFM% -p:FSharpTestCompilerVersion=coreclr + dotnet test ComboProvider.Tests\ComboProvider.Tests.fsproj -c %configuration% -v minimal -p:TestTargetFramework=%PRODUCT_TFM% -p:FSharpTestCompilerVersion=coreclr if ERRORLEVEL 1 echo Error: TestComboProvider failed && goto :failure :success diff --git a/tests/EndToEndBuildTests/DesignTimeProviderPackaging/Host/Host.fsproj b/tests/EndToEndBuildTests/DesignTimeProviderPackaging/Host/Host.fsproj index de732cce270..9896f546b8f 100644 --- a/tests/EndToEndBuildTests/DesignTimeProviderPackaging/Host/Host.fsproj +++ b/tests/EndToEndBuildTests/DesignTimeProviderPackaging/Host/Host.fsproj @@ -2,7 +2,7 @@ Library - net10.0 + $(FSharpNetCoreProductDefaultTargetFramework) $(FSharpCoreShippedPackageVersionValue) diff --git a/tests/EndToEndBuildTests/DesignTimeProviderPackaging/PlainLib/PlainLib.fsproj b/tests/EndToEndBuildTests/DesignTimeProviderPackaging/PlainLib/PlainLib.fsproj index 66c56375917..7c1990d39f9 100644 --- a/tests/EndToEndBuildTests/DesignTimeProviderPackaging/PlainLib/PlainLib.fsproj +++ b/tests/EndToEndBuildTests/DesignTimeProviderPackaging/PlainLib/PlainLib.fsproj @@ -2,7 +2,7 @@ Library - net10.0 + $(FSharpNetCoreProductDefaultTargetFramework) $(FSharpCoreShippedPackageVersionValue) diff --git a/tests/EndToEndBuildTests/DesignTimeProviderPackaging/Provider/Provider.fsproj b/tests/EndToEndBuildTests/DesignTimeProviderPackaging/Provider/Provider.fsproj index efc2d319d11..26d158da014 100644 --- a/tests/EndToEndBuildTests/DesignTimeProviderPackaging/Provider/Provider.fsproj +++ b/tests/EndToEndBuildTests/DesignTimeProviderPackaging/Provider/Provider.fsproj @@ -2,7 +2,7 @@ Library - net10.0 + $(FSharpNetCoreProductDefaultTargetFramework) $(FSharpCoreShippedPackageVersionValue) true diff --git a/tests/FSharp.Compiler.Private.Scripting.UnitTests/DependencyManagerInteractiveTests.fs b/tests/FSharp.Compiler.Private.Scripting.UnitTests/DependencyManagerInteractiveTests.fs index 95ee4c8f24f..be547816b51 100644 --- a/tests/FSharp.Compiler.Private.Scripting.UnitTests/DependencyManagerInteractiveTests.fs +++ b/tests/FSharp.Compiler.Private.Scripting.UnitTests/DependencyManagerInteractiveTests.fs @@ -100,7 +100,7 @@ type DependencyManagerInteractiveTests() = Assert.Equal(1, result.SourceFiles |> Seq.length) Assert.Equal(2, result.Roots |> Seq.length) - let result = dp.Resolve(idm, ".fsx", [|"r", "FSharp.Data,3.3.3"|], reportError, "net10.0") + let result = dp.Resolve(idm, ".fsx", [|"r", "FSharp.Data,3.3.3"|], reportError, TestFramework.productTfm) Assert.Equal(true, result.Success) Assert.Equal(1, result.Resolutions |> Seq.length) Assert.Equal(1, result.SourceFiles |> Seq.length) @@ -122,7 +122,7 @@ type DependencyManagerInteractiveTests() = let idm = dp.TryFindDependencyManagerByKey(Seq.empty, "", None, reportError, "nuget") - let result = dp.Resolve(idm, ".fsx", [|"r", "Microsoft.Data.Sqlite, 3.1.8"|], reportError, "net10.0") + let result = dp.Resolve(idm, ".fsx", [|"r", "Microsoft.Data.Sqlite, 3.1.8"|], reportError, TestFramework.productTfm) Assert.Equal(true, result.Success) Assert.True((result.Resolutions |> Seq.length) > 1) Assert.Equal(1, result.SourceFiles |> Seq.length) @@ -152,7 +152,7 @@ type DependencyManagerInteractiveTests() = Assert.Equal(0, result.SourceFiles |> Seq.length) Assert.Equal(0, result.Roots |> Seq.length) - let result = dp.Resolve(idm, ".fsx", [|"r", "System.Collections.Immutable.DoesNotExist"|], reportError, "net10.0") + let result = dp.Resolve(idm, ".fsx", [|"r", "System.Collections.Immutable.DoesNotExist"|], reportError, TestFramework.productTfm) Assert.Equal(false, result.Success) Assert.Equal(0, result.Resolutions |> Seq.length) Assert.Equal(0, result.SourceFiles |> Seq.length) @@ -182,7 +182,7 @@ type DependencyManagerInteractiveTests() = Assert.True((result1.Roots |> Seq.head).EndsWith("/fsharp.data/3.3.3/")) Assert.True((result1.Roots |> Seq.last).EndsWith("/microsoft.netframework.referenceassemblies/1.0.0/")) - let result2 = dp1.Resolve(idm1, ".fsx", [|"r", "FSharp.Data,3.3.3"|], reportError, "net10.0") + let result2 = dp1.Resolve(idm1, ".fsx", [|"r", "FSharp.Data,3.3.3"|], reportError, TestFramework.productTfm) Assert.Equal(true, result2.Success) Assert.Equal(1, result2.Resolutions |> Seq.length) let expected2 = "/netstandard2.0/" @@ -203,7 +203,7 @@ type DependencyManagerInteractiveTests() = Assert.Equal(1, result3.SourceFiles |> Seq.length) Assert.True((result3.Roots |> Seq.head).EndsWith("/system.json/4.6.0/")) - let result4 = dp2.Resolve(idm2, ".fsx", [|"r", "System.Json, Version=4.6.0"|], reportError, "net10.0") + let result4 = dp2.Resolve(idm2, ".fsx", [|"r", "System.Json, Version=4.6.0"|], reportError, TestFramework.productTfm) Assert.Equal(true, result4.Success) Assert.Equal(1, result4.Resolutions |> Seq.length) let expected4 = "/netstandard2.0/" @@ -239,7 +239,7 @@ type DependencyManagerInteractiveTests() = // Netstandard gets fewer dependencies than desktop, because desktop framework doesn't contain assemblies like System.Memory // Those assemblies must be delivered by nuget for desktop apps - let result2 = dp1.Resolve(idm1, ".fsx", [|"r", "Microsoft.Extensions.Configuration.Abstractions, 3.1.1"|], reportError, "net10.0") + let result2 = dp1.Resolve(idm1, ".fsx", [|"r", "Microsoft.Extensions.Configuration.Abstractions, 3.1.1"|], reportError, TestFramework.productTfm) Assert.Equal(true, result2.Success) Assert.Equal(2, result2.Resolutions |> Seq.length) let expected = "/netcoreapp3.1/" @@ -299,7 +299,7 @@ TorchSharp.Tensor.LongTensor.From([| 0L .. 100L |]).Device let result = use dp = new DependencyProvider(AssemblyResolutionProbe(assemblyProbingPaths), NativeResolutionProbe(nativeProbingRoots), false) let idm = dp.TryFindDependencyManagerByKey(Seq.empty, "", None, reportError, "nuget") - dp.Resolve(idm, ".fsx", packagemanagerlines, reportError, "net10.0") + dp.Resolve(idm, ".fsx", packagemanagerlines, reportError, TestFramework.productTfm) Assert.True(result.Success, "resolve failed") @@ -397,7 +397,7 @@ printfn ""%A"" result let result = use dp = new DependencyProvider(NativeResolutionProbe(nativeProbingRoots), false) let idm = dp.TryFindDependencyManagerByKey(Seq.empty, "", None, reportError, "nuget") - dp.Resolve(idm, ".fsx", packagemanagerlines, reportError, "net10.0") + dp.Resolve(idm, ".fsx", packagemanagerlines, reportError, TestFramework.productTfm) Assert.True(result.Success, "resolve failed") @@ -482,7 +482,7 @@ printfn ""%A"" result let result = use dp = new DependencyProvider(NativeResolutionProbe(nativeProbingRoots), false) let idm = dp.TryFindDependencyManagerByKey(Seq.empty, "", None, reportError, "nuget") - dp.Resolve(idm, ".fsx", packagemanagerlines, reportError, "net10.0") + dp.Resolve(idm, ".fsx", packagemanagerlines, reportError, TestFramework.productTfm) Assert.True(result.Success, "resolve failed") @@ -536,7 +536,7 @@ x |> Seq.iter(fun r -> let result = use dp = new DependencyProvider(NativeResolutionProbe(nativeProbingRoots), false) let idm = dp.TryFindDependencyManagerByKey(Seq.empty, "", None, reportError, "nuget") - dp.Resolve(idm, ".fsx", packagemanagerlines, reportError, "net10.0") + dp.Resolve(idm, ".fsx", packagemanagerlines, reportError, TestFramework.productTfm) // Expected: error FS3217: PackageManager cannot reference the System Package 'FSharp.Core' Assert.False(result.Success, "resolve succeeded but should have failed") @@ -559,7 +559,7 @@ x |> Seq.iter(fun r -> let result = use dp = new DependencyProvider(NativeResolutionProbe(nativeProbingRoots), false) let idm = dp.TryFindDependencyManagerByKey(Seq.empty, "", None, reportError, "nuget") - dp.Resolve(idm, ".csx", packagemanagerlines, reportError, "net10.0") + dp.Resolve(idm, ".csx", packagemanagerlines, reportError, TestFramework.productTfm) Assert.True(result.Success, "resolve failed but should have succeeded") @@ -602,7 +602,7 @@ x |> Seq.iter(fun r -> Assert.Equal(1, result.SourceFiles |> Seq.length) Assert.Equal(2, result.Roots |> Seq.length) - let result = dp.Resolve(idm, ".fsx", [|"r", "FSharp.Data,3.3.3"|], reportError, "net10.0") + let result = dp.Resolve(idm, ".fsx", [|"r", "FSharp.Data,3.3.3"|], reportError, TestFramework.productTfm) Assert.Equal(true, result.Success) Assert.Equal(1, result.Resolutions |> Seq.length) Assert.Equal(1, result.SourceFiles |> Seq.length) @@ -709,7 +709,7 @@ x |> Seq.iter(fun r -> let mutable currentPath:string = null use dp = new DependencyProvider(NativeResolutionProbe(nativeProbingRoots), false) let idm = dp.TryFindDependencyManagerByKey(Seq.empty, "", None, reportError, "nuget") - let result = dp.Resolve(idm, ".fsx", [|"r", "Microsoft.Data.Sqlite,3.1.7"|], reportError, "net10.0") + let result = dp.Resolve(idm, ".fsx", [|"r", "Microsoft.Data.Sqlite,3.1.7"|], reportError, TestFramework.productTfm) Assert.Equal(true, result.Success) currentPath <- appendSemiColon (Environment.GetEnvironmentVariable("PATH")) finalPath <- appendSemiColon (Environment.GetEnvironmentVariable("PATH")) @@ -799,7 +799,7 @@ x |> Seq.iter(fun r -> ResolvingErrorReport (report) let idm = dp.TryFindDependencyManagerByKey(Seq.empty, "", None, reportError, "nuget") - let result = dp.Resolve(idm, ".fsx", [|"r", "FSharp.Data,3.3.3"|], reportError, "net10.0", timeout=0) // Fail in 0 milliseconds + let result = dp.Resolve(idm, ".fsx", [|"r", "FSharp.Data,3.3.3"|], reportError, TestFramework.productTfm, timeout=0) // Fail in 0 milliseconds Assert.Equal(false, result.Success) Assert.Equal(foundCorrectError, true) Assert.Equal(foundWrongError, false) @@ -822,7 +822,7 @@ x |> Seq.iter(fun r -> ResolvingErrorReport (report) let idm = dp.TryFindDependencyManagerByKey(Seq.empty, "", None, reportError, "nuget") - let result = dp.Resolve(idm, ".fsx", [|"r", "FSharp.Data,3.3.3"; "r", "timeout=0"|], reportError, "net10.0", null, "", "", "", -1) // Wait forever + let result = dp.Resolve(idm, ".fsx", [|"r", "FSharp.Data,3.3.3"; "r", "timeout=0"|], reportError, TestFramework.productTfm, null, "", "", "", -1) // Wait forever Assert.Equal(false, result.Success) Assert.Equal(foundCorrectError, true) Assert.Equal(foundWrongError, false) @@ -845,7 +845,7 @@ x |> Seq.iter(fun r -> ResolvingErrorReport (report) let idm = dp.TryFindDependencyManagerByKey(Seq.empty, "", None, reportError, "nuget") - let result = dp.Resolve(idm, ".fsx", [|"r", "FSharp.Data,3.3.3"; "r", "timeout=none"|], reportError, "net10.0", null, "", "", "", -1) // Wait forever + let result = dp.Resolve(idm, ".fsx", [|"r", "FSharp.Data,3.3.3"; "r", "timeout=none"|], reportError, TestFramework.productTfm, null, "", "", "", -1) // Wait forever Assert.Equal(true, result.Success) Assert.Equal(foundCorrectError, false) Assert.Equal(foundWrongError, false) @@ -871,7 +871,7 @@ x |> Seq.iter(fun r -> let idm = dp.TryFindDependencyManagerByKey(Seq.empty, "", None, reportError, "nuget") // Resolve and cache the results won't time out - let _result = dp.Resolve(idm, ".fsx", [|"r", "FSharp.Data,3.3.3"; "r", "timeout=10000"|], reportError, "net10.0", null, "", "", "", -1) // Wait forever + let _result = dp.Resolve(idm, ".fsx", [|"r", "FSharp.Data,3.3.3"; "r", "timeout=10000"|], reportError, TestFramework.productTfm, null, "", "", "", -1) // Wait forever // Clear the results foundCorrectError <- false @@ -880,7 +880,7 @@ x |> Seq.iter(fun r -> // Now clear the cache --- this will ensure that resolving produces a timeout error. If we read from the cache the test will fail dp.ClearResultsCache(Seq.empty, "", None, reportError) - let result = dp.Resolve(idm, ".fsx", [|"r", "FSharp.Data,3.3.3"; "r", "timeout=0"|], reportError, "net10.0", null, "", "", "", -1) // Wait forever + let result = dp.Resolve(idm, ".fsx", [|"r", "FSharp.Data,3.3.3"; "r", "timeout=0"|], reportError, TestFramework.productTfm, null, "", "", "", -1) // Wait forever Assert.Equal(false, result.Success) Assert.Equal(foundCorrectError, true) Assert.Equal(foundWrongError, false) diff --git a/tests/FSharp.Test.Utilities/CompilerAssert.fs b/tests/FSharp.Test.Utilities/CompilerAssert.fs index 12d95f33ce4..e7d4bcbb79e 100644 --- a/tests/FSharp.Test.Utilities/CompilerAssert.fs +++ b/tests/FSharp.Test.Utilities/CompilerAssert.fs @@ -615,16 +615,18 @@ module CompilerAssertHelpers = let fileName = "dotnet" let arguments = outputFilePath - let runtimeconfig = """ -{ - "runtimeOptions": { - "tfm": "net10.0", - "framework": { + // Derive the runtime version from productTfm (e.g., "net10.0" -> "10.0.0") + let runtimeVersion = productTfm.Replace("net", "") + ".0" + let runtimeconfig = $""" +{{ + "runtimeOptions": {{ + "tfm": "{productTfm}", + "framework": {{ "name": "Microsoft.NETCore.App", - "version": "10.0.0" - } - } -}""" + "version": "{runtimeVersion}" + }} + }} +}}""" let runtimeconfigPath = Path.ChangeExtension(outputFilePath, ".runtimeconfig.json") File.WriteAllText(runtimeconfigPath, runtimeconfig) #endif diff --git a/tests/FSharp.Test.Utilities/ProjectGeneration.fs b/tests/FSharp.Test.Utilities/ProjectGeneration.fs index 6c9684557a5..dd1e2eacb65 100644 --- a/tests/FSharp.Test.Utilities/ProjectGeneration.fs +++ b/tests/FSharp.Test.Utilities/ProjectGeneration.fs @@ -443,12 +443,12 @@ let renderCustomSignatureFile (project: SyntheticProject) (f: SyntheticSourceFil let private renderFsProj (p: SyntheticProject) = seq { - """ + $""" Exe - net10.0 + {productTfm} diff --git a/tests/FSharp.Test.Utilities/TestFramework.fs b/tests/FSharp.Test.Utilities/TestFramework.fs index 72dbfa46f3d..b793dd617a1 100644 --- a/tests/FSharp.Test.Utilities/TestFramework.fs +++ b/tests/FSharp.Test.Utilities/TestFramework.fs @@ -273,6 +273,13 @@ let requireFile dir path = let SCRIPT_ROOT = __SOURCE_DIRECTORY__ let repoRoot = SCRIPT_ROOT ++ ".." ++ ".." +/// The product target framework moniker, read from eng/productTfm.txt +let productTfm = + let tfmFilePath = repoRoot ++ "eng" ++ "productTfm.txt" + if not (File.Exists tfmFilePath) then + failwithf "productTfm.txt file not found at %s" tfmFilePath + File.ReadAllText(tfmFilePath).Trim() + let loadVersionsProps () = let versionsPropsPath = repoRoot ++ "eng" ++ "Versions.props" if not (File.Exists versionsPropsPath) then @@ -298,7 +305,7 @@ let config configurationName envVars = let fsharpCoreArchitecture = "netstandard2.0" let fsharpBuildArchitecture = "netstandard2.0" let fsharpCompilerInteractiveSettingsArchitecture = "netstandard2.0" - let dotnetArchitecture = "net10.0" + let dotnetArchitecture = productTfm #if NET472 let fscArchitecture = "net472" let fsiArchitecture = "net472" diff --git a/tests/FSharp.Test.Utilities/Utilities.fs b/tests/FSharp.Test.Utilities/Utilities.fs index 3a8a7ae487e..1305a532978 100644 --- a/tests/FSharp.Test.Utilities/Utilities.fs +++ b/tests/FSharp.Test.Utilities/Utilities.fs @@ -205,7 +205,7 @@ let main argv = 0""" let directoryBuildTargetsFileName = Path.Combine(projectDirectory, "Directory.Build.targets") let frameworkReferencesFileName = Path.Combine(projectDirectory, "FrameworkReferences.txt") #if NETCOREAPP - File.WriteAllText(projectFileName, projectFile.Replace("$TARGETFRAMEWORK", "net10.0").Replace("$FSHARPCORELOCATION", pathToFSharpCore)) + File.WriteAllText(projectFileName, projectFile.Replace("$TARGETFRAMEWORK", productTfm).Replace("$FSHARPCORELOCATION", pathToFSharpCore)) #else File.WriteAllText(projectFileName, projectFile.Replace("$TARGETFRAMEWORK", "net472").Replace("$FSHARPCORELOCATION", pathToFSharpCore)) #endif diff --git a/tests/ILVerify/ilverify.ps1 b/tests/ILVerify/ilverify.ps1 index f86016b4a68..ee608535b81 100644 --- a/tests/ILVerify/ilverify.ps1 +++ b/tests/ILVerify/ilverify.ps1 @@ -41,13 +41,14 @@ $env:PublishWindowsPdb = "false" [string[]] $ignore_errors = @() # @("StackUnexpected", "UnmanagedPointer", "StackByRef", "ReturnPtrToStack", "ExpectedNumericType", "StackUnderflow") [string] $default_tfm = "netstandard2.0" +[string] $product_tfm = (Get-Content (Join-Path $repo_path "eng/productTfm.txt")).Trim() [string] $artifacts_bin_path = Join-Path (Join-Path $repo_path "artifacts") "bin" # List projects to verify, with TFMs $projects = @{ "FSharp.Core" = @($default_tfm, "netstandard2.1") - "FSharp.Compiler.Service" = @($default_tfm, "net10.0") + "FSharp.Compiler.Service" = @($default_tfm, $product_tfm) } # Check ilverify can run diff --git a/tests/fsharp/SDKTests/tests/FSharpCoreVersionTest.props b/tests/fsharp/SDKTests/tests/FSharpCoreVersionTest.props index f558553bf6a..e016dd4474e 100644 --- a/tests/fsharp/SDKTests/tests/FSharpCoreVersionTest.props +++ b/tests/fsharp/SDKTests/tests/FSharpCoreVersionTest.props @@ -1,10 +1,16 @@ + + + + $([System.IO.File]::ReadAllText('$(FSharpRepositoryPath)\eng\productTfm.txt').Trim()) + $([System.Text.RegularExpressions.Regex]::Replace('$(FSharpNetCoreProductDefaultTargetFramework)', '^net(\d+)\.0$', '$1')) + - net10.0 - <_TargetFrameworkVersionWithoutV>10.0 + $(FSharpNetCoreProductDefaultTargetFramework) + <_TargetFrameworkVersionWithoutV>$(FSharpNetCoreProductMajorVersion).0 .NETCoreApp Release $(FSharpRepositoryPath)\artifacts\bin\FSharpSuite.Tests\$(Configuration)\$(TARGETFRAMEWORK) diff --git a/tests/fsharp/single-test.fs b/tests/fsharp/single-test.fs index 764017e7c91..41f6e032609 100644 --- a/tests/fsharp/single-test.fs +++ b/tests/fsharp/single-test.fs @@ -219,7 +219,7 @@ let singleTestBuildAndRunCore cfg copyFiles p languageVersion = let extraSources = ["testlib.fsi";"testlib.fs";"test.fsi";"test.fs";"test2.fsi";"test2.fs";"test.fsx";"test2.fsx"] let utilitySources = [] let referenceItems = if String.IsNullOrEmpty(copyFiles) then [] else [copyFiles] - let framework = "net10.0" + let framework = productTfm // Arguments: // outputType = OutputType.Exe, OutputType.Library or OutputType.Script @@ -283,8 +283,8 @@ let singleTestBuildAndRunCore cfg copyFiles p languageVersion = match p with #if NETCOREAPP - | FSC_NETCORE (optimized, buildOnly) -> executeSingleTestBuildAndRun OutputType.Exe "coreclr" "net10.0" optimized buildOnly - | FSI_NETCORE -> executeSingleTestBuildAndRun OutputType.Script "coreclr" "net10.0" true false + | FSC_NETCORE (optimized, buildOnly) -> executeSingleTestBuildAndRun OutputType.Exe "coreclr" productTfm optimized buildOnly + | FSI_NETCORE -> executeSingleTestBuildAndRun OutputType.Script "coreclr" productTfm true false #else | FSC_NETFX (optimized, buildOnly) -> executeSingleTestBuildAndRun OutputType.Exe "net40" "net472" optimized buildOnly | FSI_NETFX -> executeSingleTestBuildAndRun OutputType.Script "net40" "net472" true false diff --git a/tests/scripts/identifierAnalysisByType.fsx b/tests/scripts/identifierAnalysisByType.fsx index 2e92c952159..9b5c97d473a 100644 --- a/tests/scripts/identifierAnalysisByType.fsx +++ b/tests/scripts/identifierAnalysisByType.fsx @@ -1,12 +1,15 @@ // Print some stats about identifiers grouped by type // +// IMPORTANT: This is a developer utility script. The TFM in the #r path below +// must match eng/productTfm.txt. If the product TFM changes, update the path. +// +// Run: dotnet fsi tests/scripts/identifierAnalysisByType.fsx #r "nuget: Ionide.ProjInfo" #I @"..\..\artifacts\bin\fsc\Debug\net10.0\" #r "FSharp.Compiler.Service.dll" open System -open System.IO open Ionide.ProjInfo open FSharp.Compiler.CodeAnalysis open FSharp.Compiler.Symbols From a2f24d0498696c3371b027cb6d4b84f46790b01c Mon Sep 17 00:00:00 2001 From: Tomas Grosup Date: Mon, 2 Feb 2026 12:20:18 +0100 Subject: [PATCH 19/40] simplify productMajor and runningMajor logic for TP resolution --- FSharpBuild.Directory.Build.targets | 2 +- src/Compiler/Facilities/CompilerLocation.fs | 32 +++------------------ 2 files changed, 5 insertions(+), 29 deletions(-) diff --git a/FSharpBuild.Directory.Build.targets b/FSharpBuild.Directory.Build.targets index abf1431495f..b79291cccfd 100644 --- a/FSharpBuild.Directory.Build.targets +++ b/FSharpBuild.Directory.Build.targets @@ -74,7 +74,7 @@ <_BuildPropertyLines Include="let fsProductVersion = "$(FSPRODUCTVERSION)"" /> <_BuildPropertyLines Include="let fsLanguageVersion = "$(FSLANGUAGEVERSION)"" /> <_BuildPropertyLines Include="let fsProductTfm = "$(FSharpNetCoreProductDefaultTargetFramework)"" /> - <_BuildPropertyLines Include="let fsProductTfmMajorVersion = "$(FSharpNetCoreProductMajorVersion)"" /> + <_BuildPropertyLines Include="let fsProductTfmMajorVersion : int = $(FSharpNetCoreProductMajorVersion)" /> .Assembly.GetName().Name = "System.Private.CoreLib" then - // Detect the running runtime major version from RuntimeInformation.FrameworkDescription - // e.g., ".NET 8.0.1" -> 8, ".NET 15.0.0" -> 15 - // This allows a compiler built for net10.0 to load type providers for net15.0 when running on .NET 15 - let runningMajorVersion = - let desc = RuntimeInformation.FrameworkDescription - let arr = desc.Split([| ' ' |], 3) - match arr with - | [| ".NET"; version |] | [| ".NET"; version; _ |] when not (version = "Core" || version = "Framework" || version = "Native") -> - match version.Split('.') with - | [| major; _; _ |] | [| major; _ |] | [| major |] -> - match Int32.TryParse(major) with - | true, v -> v - | false, _ -> 10 - | _ -> 10 - | _ -> 10 + let productMajor = FSharp.BuildProperties.fsProductTfmMajorVersion + let runningMajor = Environment.Version.Major - [| - // Generate net{N}.0 from running runtime version down to 5 - for v in runningMajorVersion .. -1 .. 5 do - yield $"net{v}.0" - // Legacy netcoreapp and netstandard versions - yield "netcoreapp3.1" - yield "netcoreapp3.0" - yield "netstandard2.1" - yield "netcoreapp2.2" - yield "netcoreapp2.1" - yield "netcoreapp2.0" - yield "netstandard2.0" - |] + [| for v in max productMajor runningMajor .. -1 .. 5 -> $"net{v}.0" + yield "netcoreapp3.1"; "netcoreapp3.0"; "netstandard2.1"; "netcoreapp2.2"; "netcoreapp2.1"; "netcoreapp2.0"; "netstandard2.0" |] else Debug.Assert(false, "Couldn't determine runtime tooling context, assuming it supports at least .NET Standard 2.0") [| "netstandard2.0" |] From 31600be2ced8f75fd8b5b38becf8ab4dead25643 Mon Sep 17 00:00:00 2001 From: Tomas Grosup Date: Mon, 2 Feb 2026 13:34:23 +0100 Subject: [PATCH 20/40] Fix buildproperties.fs generation for FSharp.Core and array yield syntax - Exclude fsProductTfm and fsProductTfmMajorVersion from FSharp.Core's buildproperties.fs since the 'int' type isn't defined yet during FSharp.Core compilation (bootstrapping issue) - Fix array yield syntax in CompilerLocation.fs to use yield! for combining arrays instead of yield with semicolon-separated values --- FSharpBuild.Directory.Build.targets | 5 +++-- src/Compiler/Facilities/CompilerLocation.fs | 15 +++++++++++++-- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/FSharpBuild.Directory.Build.targets b/FSharpBuild.Directory.Build.targets index b79291cccfd..be5b83b2d01 100644 --- a/FSharpBuild.Directory.Build.targets +++ b/FSharpBuild.Directory.Build.targets @@ -73,8 +73,9 @@ <_BuildPropertyLines Include="module internal FSharp.BuildProperties" /> <_BuildPropertyLines Include="let fsProductVersion = "$(FSPRODUCTVERSION)"" /> <_BuildPropertyLines Include="let fsLanguageVersion = "$(FSLANGUAGEVERSION)"" /> - <_BuildPropertyLines Include="let fsProductTfm = "$(FSharpNetCoreProductDefaultTargetFramework)"" /> - <_BuildPropertyLines Include="let fsProductTfmMajorVersion : int = $(FSharpNetCoreProductMajorVersion)" /> + + <_BuildPropertyLines Include="let fsProductTfm = "$(FSharpNetCoreProductDefaultTargetFramework)"" Condition="'$(MSBuildProjectName)' != 'FSharp.Core'" /> + <_BuildPropertyLines Include="let fsProductTfmMajorVersion : int = $(FSharpNetCoreProductMajorVersion)" Condition="'$(MSBuildProjectName)' != 'FSharp.Core'" /> $"net{v}.0" - yield "netcoreapp3.1"; "netcoreapp3.0"; "netstandard2.1"; "netcoreapp2.2"; "netcoreapp2.1"; "netcoreapp2.0"; "netstandard2.0" |] + [| + for v in max productMajor runningMajor .. -1 .. 5 -> $"net{v}.0" + yield! + [| + "netcoreapp3.1" + "netcoreapp3.0" + "netstandard2.1" + "netcoreapp2.2" + "netcoreapp2.1" + "netcoreapp2.0" + "netstandard2.0" + |] + |] else Debug.Assert(false, "Couldn't determine runtime tooling context, assuming it supports at least .NET Standard 2.0") [| "netstandard2.0" |] From 65ee6041ea0590e97b77591fb89625cb23759b46 Mon Sep 17 00:00:00 2001 From: Tomas Grosup Date: Mon, 2 Feb 2026 15:01:29 +0100 Subject: [PATCH 21/40] Add release notes for PR #19251 --- docs/release-notes/.FSharp.Compiler.Service/10.0.200.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/release-notes/.FSharp.Compiler.Service/10.0.200.md b/docs/release-notes/.FSharp.Compiler.Service/10.0.200.md index 6528081e07c..4c3126b8639 100644 --- a/docs/release-notes/.FSharp.Compiler.Service/10.0.200.md +++ b/docs/release-notes/.FSharp.Compiler.Service/10.0.200.md @@ -41,6 +41,7 @@ * Parallel compilation features: ref resolution, graph based checking, ILXGen and optimization enabled by default ([PR #18998](https://github.com/dotnet/fsharp/pull/18998)) * Make graph based type checking and parallel optimizations deterministic ([PR #19028](https://github.com/dotnet/fsharp/pull/19028)) +* Centralize compiler's target framework moniker logic into a single source of truth. ([PR #19251](https://github.com/dotnet/fsharp/pull/19251)) ### Breaking Changes From dbc7cee040b1e65e6123bda77f03257bd93b6186 Mon Sep 17 00:00:00 2001 From: Tomas Grosup Date: Mon, 2 Feb 2026 15:34:08 +0100 Subject: [PATCH 22/40] Fix AheadOfTime tests: import Directory.Build.props for FSharpNetCoreProductDefaultTargetFramework --- tests/AheadOfTime/Directory.Build.props | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/tests/AheadOfTime/Directory.Build.props b/tests/AheadOfTime/Directory.Build.props index 07d33cd1374..c0b01966378 100644 --- a/tests/AheadOfTime/Directory.Build.props +++ b/tests/AheadOfTime/Directory.Build.props @@ -1,9 +1,12 @@ - - $(NoWarn);NU1603 + + + + + $(NoWarn);NU1603 - - + From f7845777ac031a8096e3dc85d56be29993dd7b0c Mon Sep 17 00:00:00 2001 From: Tomas Grosup Date: Mon, 2 Feb 2026 16:05:19 +0100 Subject: [PATCH 23/40] Fix AheadOfTime tests: read productTfm.txt directly instead of importing root props --- tests/AheadOfTime/Directory.Build.props | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/tests/AheadOfTime/Directory.Build.props b/tests/AheadOfTime/Directory.Build.props index c0b01966378..365d0116c3a 100644 --- a/tests/AheadOfTime/Directory.Build.props +++ b/tests/AheadOfTime/Directory.Build.props @@ -1,9 +1,8 @@ - - - + + $([System.IO.File]::ReadAllText('$(MSBuildThisFileDirectory)../../eng/productTfm.txt').Trim()) $(NoWarn);NU1603 + <_UseLocalCompilerProductTfmPath Condition="Exists('$(MSBuildThisFileDirectory)productTfm.txt')">$(MSBuildThisFileDirectory)productTfm.txt + <_UseLocalCompilerProductTfmPath Condition="'$(_UseLocalCompilerProductTfmPath)' == ''">$(MSBuildThisFileDirectory)eng/productTfm.txt + $([System.IO.File]::ReadAllText('$(_UseLocalCompilerProductTfmPath)').Trim()) + true true $([System.IO.Path]::GetDirectoryName($(DOTNET_HOST_PATH))) diff --git a/azure-pipelines-PR.yml b/azure-pipelines-PR.yml index 830df465998..ef74a322555 100644 --- a/azure-pipelines-PR.yml +++ b/azure-pipelines-PR.yml @@ -721,10 +721,20 @@ stages: publishLocation: pipeline condition: succeeded() + - pwsh: | + # Stage UseLocalCompiler props and productTfm.txt together + $stagingDir = "$(Build.SourcesDirectory)/UseLocalCompilerPropsStaging" + New-Item -ItemType Directory -Force -Path $stagingDir | Out-Null + Copy-Item "$(Build.SourcesDirectory)/UseLocalCompiler.Directory.Build.props" -Destination $stagingDir + Copy-Item "$(Build.SourcesDirectory)/eng/productTfm.txt" -Destination $stagingDir + Write-Host "Staged files for UseLocalCompilerProps artifact:" + Get-ChildItem $stagingDir -Name + displayName: Stage UseLocalCompiler props files + - task: PublishPipelineArtifact@1 displayName: Publish UseLocalCompiler props file for Regression Tests inputs: - targetPath: '$(Build.SourcesDirectory)/UseLocalCompiler.Directory.Build.props' + targetPath: '$(Build.SourcesDirectory)/UseLocalCompilerPropsStaging' artifactName: 'UseLocalCompilerProps' publishLocation: pipeline condition: succeeded() From 64f106fcc20e12bdf3cf4ab0ebfddbe579c915f7 Mon Sep 17 00:00:00 2001 From: Tomas Grosup Date: Tue, 3 Feb 2026 14:10:47 +0100 Subject: [PATCH 26/40] Update FSharp.Compiler.Service.fsproj --- src/Compiler/FSharp.Compiler.Service.fsproj | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/Compiler/FSharp.Compiler.Service.fsproj b/src/Compiler/FSharp.Compiler.Service.fsproj index 2f389e3f8f7..6bd4b798cda 100644 --- a/src/Compiler/FSharp.Compiler.Service.fsproj +++ b/src/Compiler/FSharp.Compiler.Service.fsproj @@ -572,17 +572,21 @@ - + TargetFramework=$(FSharpNetCoreProductTargetFramework) + TargetFramework compile TargetFramework=$(FSharpNetCoreProductTargetFramework) + TargetFramework compile TargetFramework=$(FSharpNetCoreProductTargetFramework) + TargetFramework compile From 337d2f5e998449c47f007e7302ed06f75b56c6c6 Mon Sep 17 00:00:00 2001 From: Tomas Grosup Date: Thu, 5 Feb 2026 11:38:44 +0100 Subject: [PATCH 27/40] Add eng/TargetFrameworks.props as MSBuild source of truth for product TFM Create eng/TargetFrameworks.props with: - FSharpNetCoreProductDefaultTargetFramework=net10.0 (defensive, only if not set) - FSharpNetCoreProductMajorVersion derived via regex This is the first step in migrating from productTfm.txt to a proper MSBuild property file. The txt file is kept temporarily for coexistence during the migration. --- eng/TargetFrameworks.props | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 eng/TargetFrameworks.props diff --git a/eng/TargetFrameworks.props b/eng/TargetFrameworks.props new file mode 100644 index 00000000000..540d120c3ee --- /dev/null +++ b/eng/TargetFrameworks.props @@ -0,0 +1,20 @@ + + + + + + + net10.0 + + + $([System.Text.RegularExpressions.Regex]::Replace('$(FSharpNetCoreProductDefaultTargetFramework)', '^net(\d+)\.0$', '$1')) + + + From e194b0fba3af769e34aca3725251c9a05b7a185b Mon Sep 17 00:00:00 2001 From: Tomas Grosup Date: Thu, 5 Feb 2026 14:53:48 +0100 Subject: [PATCH 28/40] Use FSharp.BuildProperties.fsProductTfm in TestFramework.fs Replace File.ReadAllText(productTfm.txt) with FSharp.BuildProperties.fsProductTfm which is auto-generated during build from MSBuild properties. --- tests/FSharp.Test.Utilities/TestFramework.fs | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/tests/FSharp.Test.Utilities/TestFramework.fs b/tests/FSharp.Test.Utilities/TestFramework.fs index b793dd617a1..93ed1c796d5 100644 --- a/tests/FSharp.Test.Utilities/TestFramework.fs +++ b/tests/FSharp.Test.Utilities/TestFramework.fs @@ -273,12 +273,8 @@ let requireFile dir path = let SCRIPT_ROOT = __SOURCE_DIRECTORY__ let repoRoot = SCRIPT_ROOT ++ ".." ++ ".." -/// The product target framework moniker, read from eng/productTfm.txt -let productTfm = - let tfmFilePath = repoRoot ++ "eng" ++ "productTfm.txt" - if not (File.Exists tfmFilePath) then - failwithf "productTfm.txt file not found at %s" tfmFilePath - File.ReadAllText(tfmFilePath).Trim() +/// The product target framework moniker, from FSharp.BuildProperties (generated during build) +let productTfm = FSharp.BuildProperties.fsProductTfm let loadVersionsProps () = let versionsPropsPath = repoRoot ++ "eng" ++ "Versions.props" From c6b59c064bcd2d2a5135c68de9012fb6a9a9908c Mon Sep 17 00:00:00 2001 From: Tomas Grosup Date: Thu, 5 Feb 2026 15:38:35 +0100 Subject: [PATCH 29/40] Migrate PowerShell scripts to use MSBuild --getProperty: for TFM Update all 4 PowerShell scripts to use dotnet msbuild --getProperty: via eng/common/dotnet.ps1 instead of Get-Content productTfm.txt. Files updated: - eng/Build.ps1 - eng/build-utils.ps1 - eng/test-determinism.ps1 - tests/ILVerify/ilverify.ps1 This is part of the migration from productTfm.txt to the MSBuild-based eng/TargetFrameworks.props as the single source of truth for the product TFM. --- eng/Build.ps1 | 5 ++--- eng/build-utils.ps1 | 5 ++--- eng/test-determinism.ps1 | 3 ++- tests/ILVerify/ilverify.ps1 | 3 ++- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/eng/Build.ps1 b/eng/Build.ps1 index 75300753945..05c17a41232 100644 --- a/eng/Build.ps1 +++ b/eng/Build.ps1 @@ -82,9 +82,8 @@ $BuildCategory = "" $BuildMessage = "" $desktopTargetFramework = "net472" -# Read product TFM from centralized source of truth -$productTfmPath = Join-Path $PSScriptRoot "productTfm.txt" -$coreclrTargetFramework = (Get-Content $productTfmPath -Raw).Trim() +# Read product TFM from centralized source of truth via MSBuild +$coreclrTargetFramework = (& $PSScriptRoot/common/dotnet.ps1 msbuild $PSScriptRoot/TargetFrameworks.props --getProperty:FSharpNetCoreProductDefaultTargetFramework).Trim() # Set defaults for bootstrapTfm and fsharpNetCoreProductTfm if not provided if ($bootstrapTfm -eq "") { diff --git a/eng/build-utils.ps1 b/eng/build-utils.ps1 index 142104e11b0..a3ef58dc5d6 100644 --- a/eng/build-utils.ps1 +++ b/eng/build-utils.ps1 @@ -14,9 +14,8 @@ $nodeReuse = if (Test-Path variable:nodeReuse) { $nodeReuse } else { $false } $bootstrapDir = if (Test-Path variable:bootstrapDir) { $bootstrapDir } else { "" } $bootstrapConfiguration = if (Test-Path variable:bootstrapConfiguration) { $bootstrapConfiguration } else { "Proto" } $bootstrapTfm = if (Test-Path variable:bootstrapTfm) { $bootstrapTfm } else { "net472" } -# Read product TFM from centralized source of truth -$productTfmFilePath = Join-Path $PSScriptRoot "productTfm.txt" -$fsharpNetCoreProductTfmDefault = (Get-Content $productTfmFilePath -Raw).Trim() +# Read product TFM from centralized source of truth via MSBuild +$fsharpNetCoreProductTfmDefault = (& $PSScriptRoot/common/dotnet.ps1 msbuild $PSScriptRoot/TargetFrameworks.props --getProperty:FSharpNetCoreProductDefaultTargetFramework).Trim() $fsharpNetCoreProductTfm = if (Test-Path variable:fsharpNetCoreProductTfm) { $fsharpNetCoreProductTfm } else { $fsharpNetCoreProductTfmDefault } $properties = if (Test-Path variable:properties) { $properties } else { @() } diff --git a/eng/test-determinism.ps1 b/eng/test-determinism.ps1 index 835d7b4875c..a0bb6833cd1 100644 --- a/eng/test-determinism.ps1 +++ b/eng/test-determinism.ps1 @@ -404,7 +404,8 @@ try { $script:bootstrap = $true $script:bootstrapConfiguration = "Proto" - $script:fsharpNetCoreProductTfm = (Get-Content "$PSScriptRoot/productTfm.txt").Trim() + # Read product TFM from centralized source of truth via MSBuild + $script:fsharpNetCoreProductTfm = (& $PSScriptRoot/common/dotnet.ps1 msbuild $PSScriptRoot/TargetFrameworks.props --getProperty:FSharpNetCoreProductDefaultTargetFramework).Trim() $script:bootstrapTfm = $script:fsharpNetCoreProductTfm $bootstrapDir = Make-BootstrapBuild diff --git a/tests/ILVerify/ilverify.ps1 b/tests/ILVerify/ilverify.ps1 index ee608535b81..f30a4ae20e4 100644 --- a/tests/ILVerify/ilverify.ps1 +++ b/tests/ILVerify/ilverify.ps1 @@ -41,7 +41,8 @@ $env:PublishWindowsPdb = "false" [string[]] $ignore_errors = @() # @("StackUnexpected", "UnmanagedPointer", "StackByRef", "ReturnPtrToStack", "ExpectedNumericType", "StackUnderflow") [string] $default_tfm = "netstandard2.0" -[string] $product_tfm = (Get-Content (Join-Path $repo_path "eng/productTfm.txt")).Trim() +# Read product TFM from centralized source of truth via MSBuild +[string] $product_tfm = (& (Join-Path $repo_path "eng/common/dotnet.ps1") msbuild (Join-Path $repo_path "eng/TargetFrameworks.props") --getProperty:FSharpNetCoreProductDefaultTargetFramework).Trim() [string] $artifacts_bin_path = Join-Path (Join-Path $repo_path "artifacts") "bin" From f559f1f1c81b0b45143eb1d4828ad0393b2ee3cc Mon Sep 17 00:00:00 2001 From: Tomas Grosup Date: Thu, 5 Feb 2026 17:17:51 +0100 Subject: [PATCH 30/40] Migrate eng/build.sh to use --getProperty for TFM Replace `cat productTfm.txt` with `dotnet msbuild --getProperty` to read FSharpNetCoreProductDefaultTargetFramework from eng/TargetFrameworks.props. This is part of the migration from productTfm.txt to the MSBuild-centric approach for the single source of truth for the product TFM. --- eng/build.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/eng/build.sh b/eng/build.sh index 45bb35c829a..bd1001032f8 100755 --- a/eng/build.sh +++ b/eng/build.sh @@ -83,8 +83,8 @@ properties="" docker=false args="" -# Read product TFM from centralized source of truth -tfm=$(cat "$scriptroot/productTfm.txt" | tr -d '[:space:]') +# Read product TFM from centralized source of truth using MSBuild +tfm=$("$scriptroot/common/dotnet.sh" msbuild "$scriptroot/TargetFrameworks.props" --getProperty:FSharpNetCoreProductDefaultTargetFramework 2>/dev/null | tr -d '[:space:]') BuildCategory="" BuildMessage="" From 38a6776cb5162bcea96d1736acb28b9fe0f68877 Mon Sep 17 00:00:00 2001 From: Tomas Grosup Date: Thu, 5 Feb 2026 17:20:36 +0100 Subject: [PATCH 31/40] Migrate CMD scripts to use --getProperty for TFM Replace set /p reading from productTfm.txt with dotnet msbuild --getProperty:FSharpNetCoreProductDefaultTargetFramework in both TestBasicProvider.cmd and TestComboProvider.cmd. --- .../EndToEndBuildTests/BasicProvider/TestBasicProvider.cmd | 6 ++---- .../EndToEndBuildTests/ComboProvider/TestComboProvider.cmd | 6 ++---- 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/tests/EndToEndBuildTests/BasicProvider/TestBasicProvider.cmd b/tests/EndToEndBuildTests/BasicProvider/TestBasicProvider.cmd index 263291b7ea2..18469995b2b 100644 --- a/tests/EndToEndBuildTests/BasicProvider/TestBasicProvider.cmd +++ b/tests/EndToEndBuildTests/BasicProvider/TestBasicProvider.cmd @@ -10,10 +10,8 @@ setlocal set __scriptpath=%~dp0 set configuration=Debug -rem Read TFM from centralized source -set /p PRODUCT_TFM=<"%__scriptpath%..\..\..\eng\productTfm.txt" -rem Trim whitespace -for /f "tokens=* delims= " %%a in ("%PRODUCT_TFM%") do set PRODUCT_TFM=%%a +rem Read TFM from centralized source using MSBuild +for /f "usebackq delims=" %%a in (`dotnet msbuild "%__scriptpath%..\..\..\eng\TargetFrameworks.props" --getProperty:FSharpNetCoreProductDefaultTargetFramework`) do set PRODUCT_TFM=%%a :parseargs if "%1" == "" goto argsdone diff --git a/tests/EndToEndBuildTests/ComboProvider/TestComboProvider.cmd b/tests/EndToEndBuildTests/ComboProvider/TestComboProvider.cmd index e0ad465e337..9896dab0d5e 100644 --- a/tests/EndToEndBuildTests/ComboProvider/TestComboProvider.cmd +++ b/tests/EndToEndBuildTests/ComboProvider/TestComboProvider.cmd @@ -10,10 +10,8 @@ setlocal set __scriptpath=%~dp0 set configuration=Debug -rem Read TFM from centralized source -set /p PRODUCT_TFM=<"%__scriptpath%..\..\..\eng\productTfm.txt" -rem Trim whitespace -for /f "tokens=* delims= " %%a in ("%PRODUCT_TFM%") do set PRODUCT_TFM=%%a +rem Read TFM from centralized source using MSBuild +for /f "usebackq delims=" %%a in (`dotnet msbuild "%__scriptpath%..\..\..\eng\TargetFrameworks.props" --getProperty:FSharpNetCoreProductDefaultTargetFramework`) do set PRODUCT_TFM=%%a :parseargs if "%1" == "" goto argsdone From 17a08317ad1f64bdffc3ae4181842b0eaafe9b1e Mon Sep 17 00:00:00 2001 From: Tomas Grosup Date: Thu, 5 Feb 2026 17:22:19 +0100 Subject: [PATCH 32/40] Update Azure Pipelines to use TargetFrameworks.props - azure-pipelines-PR.yml: Copy TargetFrameworks.props instead of productTfm.txt - regression-test-jobs.yml: Use --getProperty to read TFM from staged props file --- azure-pipelines-PR.yml | 4 ++-- eng/templates/regression-test-jobs.yml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/azure-pipelines-PR.yml b/azure-pipelines-PR.yml index ef74a322555..f5a689e222c 100644 --- a/azure-pipelines-PR.yml +++ b/azure-pipelines-PR.yml @@ -722,11 +722,11 @@ stages: condition: succeeded() - pwsh: | - # Stage UseLocalCompiler props and productTfm.txt together + # Stage UseLocalCompiler props and TargetFrameworks.props together $stagingDir = "$(Build.SourcesDirectory)/UseLocalCompilerPropsStaging" New-Item -ItemType Directory -Force -Path $stagingDir | Out-Null Copy-Item "$(Build.SourcesDirectory)/UseLocalCompiler.Directory.Build.props" -Destination $stagingDir - Copy-Item "$(Build.SourcesDirectory)/eng/productTfm.txt" -Destination $stagingDir + Copy-Item "$(Build.SourcesDirectory)/eng/TargetFrameworks.props" -Destination $stagingDir Write-Host "Staged files for UseLocalCompilerProps artifact:" Get-ChildItem $stagingDir -Name displayName: Stage UseLocalCompiler props files diff --git a/eng/templates/regression-test-jobs.yml b/eng/templates/regression-test-jobs.yml index dec02575efe..0e1f06c3c48 100644 --- a/eng/templates/regression-test-jobs.yml +++ b/eng/templates/regression-test-jobs.yml @@ -125,7 +125,7 @@ jobs: dotnet msbuild -version Write-Host "" Write-Host "F# Compiler artifacts available:" - $productTfm = (Get-Content "$(Build.SourcesDirectory)/eng/productTfm.txt").Trim() + $productTfm = (dotnet msbuild "$(Pipeline.Workspace)/Props/TargetFrameworks.props" --getProperty:FSharpNetCoreProductDefaultTargetFramework).Trim() Get-ChildItem "$(Pipeline.Workspace)/FSharpCompiler/bin/fsc/Release/$productTfm" -Name -ErrorAction SilentlyContinue Write-Host "" Write-Host "F# Core available:" From a360a8ba4000aee7f09590fdba31ef2fb20bcafe Mon Sep 17 00:00:00 2001 From: Tomas Grosup Date: Thu, 5 Feb 2026 17:31:37 +0100 Subject: [PATCH 33/40] Delete productTfm.txt and update references to TargetFrameworks.props - Remove eng/productTfm.txt (replaced by TargetFrameworks.props) - Update release notes to reference TargetFrameworks.props - Update identifierAnalysisByType.fsx comment to reference new location --- docs/release-notes/.FSharp.Compiler.Service/10.0.300.md | 2 +- eng/productTfm.txt | 1 - tests/scripts/identifierAnalysisByType.fsx | 3 ++- 3 files changed, 3 insertions(+), 3 deletions(-) delete mode 100644 eng/productTfm.txt diff --git a/docs/release-notes/.FSharp.Compiler.Service/10.0.300.md b/docs/release-notes/.FSharp.Compiler.Service/10.0.300.md index 4e8ca5f10d3..5e5b5914af5 100644 --- a/docs/release-notes/.FSharp.Compiler.Service/10.0.300.md +++ b/docs/release-notes/.FSharp.Compiler.Service/10.0.300.md @@ -4,6 +4,6 @@ ### Changed -* Centralized product TFM (Target Framework Moniker) into single source file `eng/productTfm.txt`. Changing the target framework now only requires editing one file. +* Centralized product TFM (Target Framework Moniker) into MSBuild props file `eng/TargetFrameworks.props`. Changing the target framework now only requires editing one file, and it integrates with MSBuild's `--getProperty` for scripts. ### Breaking Changes diff --git a/eng/productTfm.txt b/eng/productTfm.txt deleted file mode 100644 index 134801c9327..00000000000 --- a/eng/productTfm.txt +++ /dev/null @@ -1 +0,0 @@ -net10.0 diff --git a/tests/scripts/identifierAnalysisByType.fsx b/tests/scripts/identifierAnalysisByType.fsx index 9b5c97d473a..0417c4f6ba3 100644 --- a/tests/scripts/identifierAnalysisByType.fsx +++ b/tests/scripts/identifierAnalysisByType.fsx @@ -1,7 +1,8 @@ // Print some stats about identifiers grouped by type // // IMPORTANT: This is a developer utility script. The TFM in the #r path below -// must match eng/productTfm.txt. If the product TFM changes, update the path. +// must match the FSharpNetCoreProductDefaultTargetFramework property in +// eng/TargetFrameworks.props. If the product TFM changes, update the path. // // Run: dotnet fsi tests/scripts/identifierAnalysisByType.fsx From b2c89c9df5d4d4e63869d1277326656d0bf85bcb Mon Sep 17 00:00:00 2001 From: Tomas Grosup Date: Thu, 5 Feb 2026 17:53:00 +0100 Subject: [PATCH 34/40] Migrate MSBuild files to import TargetFrameworks.props instead of reading productTfm.txt Phase 2 of the productTfm.txt migration: Replace File.ReadAllText calls with Import of eng/TargetFrameworks.props as the single source of truth for TFM. Files updated: - Directory.Build.props - UseLocalCompiler.Directory.Build.props - buildtools/checkpackages/Directory.Build.props - tests/AheadOfTime/Directory.Build.props - tests/fsharp/SDKTests/tests/FSharpCoreVersionTest.props --- Directory.Build.props | 7 +++---- UseLocalCompiler.Directory.Build.props | 13 ++++++------- buildtools/checkpackages/Directory.Build.props | 5 +++-- tests/AheadOfTime/Directory.Build.props | 5 +++-- .../SDKTests/tests/FSharpCoreVersionTest.props | 7 ++----- 5 files changed, 17 insertions(+), 20 deletions(-) diff --git a/Directory.Build.props b/Directory.Build.props index 1b7b702c2be..ac3beea7cf1 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -1,15 +1,14 @@ + + + https://github.com/dotnet/fsharp https://github.com/dotnet/fsharp $(FSharpLangVersion) $(MSBuildThisFileDirectory) true - - $([System.IO.File]::ReadAllText('$(MSBuildThisFileDirectory)eng/productTfm.txt').Trim()) - - $([System.Text.RegularExpressions.Regex]::Replace('$(FSharpNetCoreProductDefaultTargetFramework)', '^net(\d+)\.0$', '$1')) $(DotNetBuildSourceOnly) false diff --git a/UseLocalCompiler.Directory.Build.props b/UseLocalCompiler.Directory.Build.props index 824c3fa6639..99947e1a418 100644 --- a/UseLocalCompiler.Directory.Build.props +++ b/UseLocalCompiler.Directory.Build.props @@ -1,4 +1,10 @@ + + + + False @@ -6,13 +12,6 @@ $(MSBuildThisFileDirectory) - - <_UseLocalCompilerProductTfmPath Condition="Exists('$(MSBuildThisFileDirectory)productTfm.txt')">$(MSBuildThisFileDirectory)productTfm.txt - <_UseLocalCompilerProductTfmPath Condition="'$(_UseLocalCompilerProductTfmPath)' == ''">$(MSBuildThisFileDirectory)eng/productTfm.txt - $([System.IO.File]::ReadAllText('$(_UseLocalCompilerProductTfmPath)').Trim()) - true true $([System.IO.Path]::GetDirectoryName($(DOTNET_HOST_PATH))) diff --git a/buildtools/checkpackages/Directory.Build.props b/buildtools/checkpackages/Directory.Build.props index 69dd3e1263d..a9a651c4a65 100644 --- a/buildtools/checkpackages/Directory.Build.props +++ b/buildtools/checkpackages/Directory.Build.props @@ -1,7 +1,8 @@ + + + - - $([System.IO.File]::ReadAllText('$(MSBuildThisFileDirectory)..\..\eng\productTfm.txt').Trim()) true $(MSBuildProjectDirectory)\..\..\artifacts\tmp\$([System.Guid]::NewGuid()) $(CachePath)\obj\ diff --git a/tests/AheadOfTime/Directory.Build.props b/tests/AheadOfTime/Directory.Build.props index 365d0116c3a..ba8cc5f390f 100644 --- a/tests/AheadOfTime/Directory.Build.props +++ b/tests/AheadOfTime/Directory.Build.props @@ -1,8 +1,9 @@ - + + - $([System.IO.File]::ReadAllText('$(MSBuildThisFileDirectory)../../eng/productTfm.txt').Trim()) $(NoWarn);NU1603 - - $([System.IO.File]::ReadAllText('$(FSharpRepositoryPath)\eng\productTfm.txt').Trim()) - $([System.Text.RegularExpressions.Regex]::Replace('$(FSharpNetCoreProductDefaultTargetFramework)', '^net(\d+)\.0$', '$1')) - + + $(FSharpNetCoreProductDefaultTargetFramework) From b2a9266961f3a900a56e23c193989ef28ca38506 Mon Sep 17 00:00:00 2001 From: Tomas Grosup Date: Fri, 6 Feb 2026 09:33:51 +0100 Subject: [PATCH 35/40] Update eng/TargetFrameworks.props Co-authored-by: Viktor Hofer --- eng/TargetFrameworks.props | 1 + 1 file changed, 1 insertion(+) diff --git a/eng/TargetFrameworks.props b/eng/TargetFrameworks.props index 540d120c3ee..690d65efd17 100644 --- a/eng/TargetFrameworks.props +++ b/eng/TargetFrameworks.props @@ -12,6 +12,7 @@ net10.0 + $(NetCurrent) $([System.Text.RegularExpressions.Regex]::Replace('$(FSharpNetCoreProductDefaultTargetFramework)', '^net(\d+)\.0$', '$1')) From d8058b6c897308ef124b6571805878aa4da46cd0 Mon Sep 17 00:00:00 2001 From: Tomas Grosup Date: Fri, 6 Feb 2026 10:19:45 +0100 Subject: [PATCH 36/40] pass DotNetBuildSourceOnly to tfm extraction logic --- Directory.Build.props | 25 +++++-------------------- eng/build.sh | 3 ++- 2 files changed, 7 insertions(+), 21 deletions(-) diff --git a/Directory.Build.props b/Directory.Build.props index ac3beea7cf1..b6d0a2e400c 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -67,26 +67,11 @@ - - - - - - $(NetCurrent) - - - - - $(FSharpNetCoreProductDefaultTargetFramework) - - - + + + $(FSharpNetCoreProductDefaultTargetFramework) + - $(ArtifactsDir)/bin/fslex/$(Configuration)/$(FSharpNetCoreProductDefaultTargetFramework)/$(RuntimeIdentifier)/fslex.dll - $(ArtifactsDir)/bin/fsyacc/$(Configuration)/$(FSharpNetCoreProductDefaultTargetFramework)/$(RuntimeIdentifier)/fsyacc.dll + $(ArtifactsDir)/bin/fslex/$(Configuration)/$(FSharpNetCoreProductTargetFramework)/$(RuntimeIdentifier)/fslex.dll + $(ArtifactsDir)/bin/fsyacc/$(Configuration)/$(FSharpNetCoreProductTargetFramework)/$(RuntimeIdentifier)/fsyacc.dll BUILDING_WITH_LKG;$(DefineConstants) - - - $(FSharpNetCoreProductDefaultTargetFramework) - - $(ArtifactsDir)/bin/fslex/$(Configuration)/$(FSharpNetCoreProductDefaultTargetFramework)/$(NETCoreSdkPortableRuntimeIdentifier)/fslex.dll - $(ArtifactsDir)/bin/fsyacc/$(Configuration)/$(FSharpNetCoreProductDefaultTargetFramework)/$(NETCoreSdkPortableRuntimeIdentifier)/fsyacc.dll + $(ArtifactsDir)/bin/fslex/$(Configuration)/$(FSharpNetCoreProductTargetFramework)/$(NETCoreSdkPortableRuntimeIdentifier)/fslex.dll + $(ArtifactsDir)/bin/fsyacc/$(Configuration)/$(FSharpNetCoreProductTargetFramework)/$(NETCoreSdkPortableRuntimeIdentifier)/fsyacc.dll diff --git a/FSharpBuild.Directory.Build.targets b/FSharpBuild.Directory.Build.targets index be5b83b2d01..6e64ad71531 100644 --- a/FSharpBuild.Directory.Build.targets +++ b/FSharpBuild.Directory.Build.targets @@ -74,7 +74,7 @@ <_BuildPropertyLines Include="let fsProductVersion = "$(FSPRODUCTVERSION)"" /> <_BuildPropertyLines Include="let fsLanguageVersion = "$(FSLANGUAGEVERSION)"" /> - <_BuildPropertyLines Include="let fsProductTfm = "$(FSharpNetCoreProductDefaultTargetFramework)"" Condition="'$(MSBuildProjectName)' != 'FSharp.Core'" /> + <_BuildPropertyLines Include="let fsProductTfm = "$(FSharpNetCoreProductTargetFramework)"" Condition="'$(MSBuildProjectName)' != 'FSharp.Core'" /> <_BuildPropertyLines Include="let fsProductTfmMajorVersion : int = $(FSharpNetCoreProductMajorVersion)" Condition="'$(MSBuildProjectName)' != 'FSharp.Core'" /> diff --git a/UseLocalCompiler.Directory.Build.props b/UseLocalCompiler.Directory.Build.props index 99947e1a418..8bd796bfe90 100644 --- a/UseLocalCompiler.Directory.Build.props +++ b/UseLocalCompiler.Directory.Build.props @@ -17,8 +17,8 @@ $([System.IO.Path]::GetDirectoryName($(DOTNET_HOST_PATH))) $([System.IO.Path]::GetFileName($(DOTNET_HOST_PATH))) - $(LocalFSharpCompilerPath)/artifacts/bin/fsc/$(LocalFSharpCompilerConfiguration)/$(FSharpNetCoreProductDefaultTargetFramework)/fsc.dll - $(LocalFSharpCompilerPath)/artifacts/bin/fsc/$(LocalFSharpCompilerConfiguration)/$(FSharpNetCoreProductDefaultTargetFramework)/fsc.dll + $(LocalFSharpCompilerPath)/artifacts/bin/fsc/$(LocalFSharpCompilerConfiguration)/$(FSharpNetCoreProductTargetFramework)/fsc.dll + $(LocalFSharpCompilerPath)/artifacts/bin/fsc/$(LocalFSharpCompilerConfiguration)/$(FSharpNetCoreProductTargetFramework)/fsc.dll False True @@ -31,7 +31,7 @@ See: https://github.com/dotnet/sdk/blob/main/src/Tasks/Microsoft.NET.Build.Tasks/targets/Microsoft.NET.Sdk.FSharpTargetsShim.targets --> - $(LocalFSharpCompilerPath)/artifacts/bin/fsc/$(LocalFSharpCompilerConfiguration)/$(FSharpNetCoreProductDefaultTargetFramework) + $(LocalFSharpCompilerPath)/artifacts/bin/fsc/$(LocalFSharpCompilerConfiguration)/$(FSharpNetCoreProductTargetFramework) $(LocalFSharpBuildBinPath)/FSharp.Build.dll $(LocalFSharpBuildBinPath)/Microsoft.FSharp.Targets $(LocalFSharpBuildBinPath)/Microsoft.FSharp.NetSdk.props diff --git a/buildtools/checkpackages/FSharp.Compiler.Service_notshipped.fsproj b/buildtools/checkpackages/FSharp.Compiler.Service_notshipped.fsproj index 6a43b6e141e..8a0874bff6a 100644 --- a/buildtools/checkpackages/FSharp.Compiler.Service_notshipped.fsproj +++ b/buildtools/checkpackages/FSharp.Compiler.Service_notshipped.fsproj @@ -3,7 +3,7 @@ - $(FSharpNetCoreProductDefaultTargetFramework) + $(FSharpNetCoreProductTargetFramework) true $(MSBuildProjectDirectory)\..\..\artifacts\tmp\$([System.Guid]::NewGuid()) $(CachePath)\bin diff --git a/buildtools/checkpackages/FSharp.Core_notshipped.fsproj b/buildtools/checkpackages/FSharp.Core_notshipped.fsproj index 5c3d6f89fae..237ea4a2f2c 100644 --- a/buildtools/checkpackages/FSharp.Core_notshipped.fsproj +++ b/buildtools/checkpackages/FSharp.Core_notshipped.fsproj @@ -3,7 +3,7 @@ - $(FSharpNetCoreProductDefaultTargetFramework) + $(FSharpNetCoreProductTargetFramework) diff --git a/eng/Build.ps1 b/eng/Build.ps1 index 05c17a41232..d69bdb3e8c3 100644 --- a/eng/Build.ps1 +++ b/eng/Build.ps1 @@ -83,7 +83,7 @@ $BuildMessage = "" $desktopTargetFramework = "net472" # Read product TFM from centralized source of truth via MSBuild -$coreclrTargetFramework = (& $PSScriptRoot/common/dotnet.ps1 msbuild $PSScriptRoot/TargetFrameworks.props --getProperty:FSharpNetCoreProductDefaultTargetFramework).Trim() +$coreclrTargetFramework = (& $PSScriptRoot/common/dotnet.ps1 msbuild $PSScriptRoot/TargetFrameworks.props --getProperty:FSharpNetCoreProductTargetFramework).Trim() # Set defaults for bootstrapTfm and fsharpNetCoreProductTfm if not provided if ($bootstrapTfm -eq "") { diff --git a/eng/TargetFrameworks.props b/eng/TargetFrameworks.props index 690d65efd17..8e1fc29a8ca 100644 --- a/eng/TargetFrameworks.props +++ b/eng/TargetFrameworks.props @@ -6,16 +6,16 @@ Properties are set defensively (only if not already set) to allow: - Environment variable overrides - - CLI property overrides (e.g., -p:FSharpNetCoreProductDefaultTargetFramework=net9.0) + - CLI property overrides (e.g., -p:FSharpNetCoreProductTargetFramework=net9.0) --> - net10.0 - $(NetCurrent) + net10.0 + $(NetCurrent) - $([System.Text.RegularExpressions.Regex]::Replace('$(FSharpNetCoreProductDefaultTargetFramework)', '^net(\d+)\.0$', '$1')) + $([System.Text.RegularExpressions.Regex]::Replace('$(FSharpNetCoreProductTargetFramework)', '^net(\d+)\.0$', '$1')) diff --git a/eng/build-utils.ps1 b/eng/build-utils.ps1 index a3ef58dc5d6..e40cf36fd9f 100644 --- a/eng/build-utils.ps1 +++ b/eng/build-utils.ps1 @@ -15,7 +15,7 @@ $bootstrapDir = if (Test-Path variable:bootstrapDir) { $bootstrapDir } else { "" $bootstrapConfiguration = if (Test-Path variable:bootstrapConfiguration) { $bootstrapConfiguration } else { "Proto" } $bootstrapTfm = if (Test-Path variable:bootstrapTfm) { $bootstrapTfm } else { "net472" } # Read product TFM from centralized source of truth via MSBuild -$fsharpNetCoreProductTfmDefault = (& $PSScriptRoot/common/dotnet.ps1 msbuild $PSScriptRoot/TargetFrameworks.props --getProperty:FSharpNetCoreProductDefaultTargetFramework).Trim() +$fsharpNetCoreProductTfmDefault = (& $PSScriptRoot/common/dotnet.ps1 msbuild $PSScriptRoot/TargetFrameworks.props --getProperty:FSharpNetCoreProductTargetFramework).Trim() $fsharpNetCoreProductTfm = if (Test-Path variable:fsharpNetCoreProductTfm) { $fsharpNetCoreProductTfm } else { $fsharpNetCoreProductTfmDefault } $properties = if (Test-Path variable:properties) { $properties } else { @() } diff --git a/eng/build.sh b/eng/build.sh index f51b98fd1e8..28e839b1337 100755 --- a/eng/build.sh +++ b/eng/build.sh @@ -85,7 +85,7 @@ args="" # Read product TFM from centralized source of truth using MSBuild # Pass DotNetBuildSourceOnly so source-build/VMR resolves to $(NetCurrent) instead of hardcoded TFM -tfm=$("$scriptroot/common/dotnet.sh" msbuild "$scriptroot/TargetFrameworks.props" /p:DotNetBuildSourceOnly=$source_build --getProperty:FSharpNetCoreProductDefaultTargetFramework 2>/dev/null | tr -d '[:space:]') +tfm=$("$scriptroot/common/dotnet.sh" msbuild "$scriptroot/TargetFrameworks.props" /p:DotNetBuildSourceOnly=$source_build --getProperty:FSharpNetCoreProductTargetFramework 2>/dev/null | tr -d '[:space:]') BuildCategory="" BuildMessage="" diff --git a/eng/templates/regression-test-jobs.yml b/eng/templates/regression-test-jobs.yml index 0e1f06c3c48..eebb97d047c 100644 --- a/eng/templates/regression-test-jobs.yml +++ b/eng/templates/regression-test-jobs.yml @@ -125,7 +125,7 @@ jobs: dotnet msbuild -version Write-Host "" Write-Host "F# Compiler artifacts available:" - $productTfm = (dotnet msbuild "$(Pipeline.Workspace)/Props/TargetFrameworks.props" --getProperty:FSharpNetCoreProductDefaultTargetFramework).Trim() + $productTfm = (dotnet msbuild "$(Pipeline.Workspace)/Props/TargetFrameworks.props" --getProperty:FSharpNetCoreProductTargetFramework).Trim() Get-ChildItem "$(Pipeline.Workspace)/FSharpCompiler/bin/fsc/Release/$productTfm" -Name -ErrorAction SilentlyContinue Write-Host "" Write-Host "F# Core available:" diff --git a/eng/test-determinism.ps1 b/eng/test-determinism.ps1 index a0bb6833cd1..6bf53e4d195 100644 --- a/eng/test-determinism.ps1 +++ b/eng/test-determinism.ps1 @@ -405,7 +405,7 @@ try { $script:bootstrap = $true $script:bootstrapConfiguration = "Proto" # Read product TFM from centralized source of truth via MSBuild - $script:fsharpNetCoreProductTfm = (& $PSScriptRoot/common/dotnet.ps1 msbuild $PSScriptRoot/TargetFrameworks.props --getProperty:FSharpNetCoreProductDefaultTargetFramework).Trim() + $script:fsharpNetCoreProductTfm = (& $PSScriptRoot/common/dotnet.ps1 msbuild $PSScriptRoot/TargetFrameworks.props --getProperty:FSharpNetCoreProductTargetFramework).Trim() $script:bootstrapTfm = $script:fsharpNetCoreProductTfm $bootstrapDir = Make-BootstrapBuild diff --git a/tests/AheadOfTime/Equality/Equality.fsproj b/tests/AheadOfTime/Equality/Equality.fsproj index c08dae6080b..944c556dfc1 100644 --- a/tests/AheadOfTime/Equality/Equality.fsproj +++ b/tests/AheadOfTime/Equality/Equality.fsproj @@ -16,8 +16,8 @@ - $(MSBuildThisFileDirectory)../../../artifacts/bin/fsc/Release/$(FSharpNetCoreProductDefaultTargetFramework)/fsc.dll - $(MSBuildThisFileDirectory)../../../artifacts/bin/fsc/Release/$(FSharpNetCoreProductDefaultTargetFramework)/fsc.dll + $(MSBuildThisFileDirectory)../../../artifacts/bin/fsc/Release/$(FSharpNetCoreProductTargetFramework)/fsc.dll + $(MSBuildThisFileDirectory)../../../artifacts/bin/fsc/Release/$(FSharpNetCoreProductTargetFramework)/fsc.dll False True 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 5a8b2e3cb49..e00d5a71521 100644 --- a/tests/AheadOfTime/Trimming/FSharpMetadataResource_Trimming_Test/FSharpMetadataResource_Trimming_Test.fsproj +++ b/tests/AheadOfTime/Trimming/FSharpMetadataResource_Trimming_Test/FSharpMetadataResource_Trimming_Test.fsproj @@ -17,7 +17,7 @@ - $(MSBuildThisFileDirectory)../../../../artifacts/bin/fsc/Release/$(FSharpNetCoreProductDefaultTargetFramework) + $(MSBuildThisFileDirectory)../../../../artifacts/bin/fsc/Release/$(FSharpNetCoreProductTargetFramework) $(LocalFSharpBuildBinPath)/FSharp.Build.dll $(LocalFSharpBuildBinPath)/fsc.dll $(LocalFSharpBuildBinPath)/fsc.dll diff --git a/tests/AheadOfTime/Trimming/SelfContained_Trimming_Test/SelfContained_Trimming_Test.fsproj b/tests/AheadOfTime/Trimming/SelfContained_Trimming_Test/SelfContained_Trimming_Test.fsproj index c4a05e7d3b6..8930dd44e5d 100644 --- a/tests/AheadOfTime/Trimming/SelfContained_Trimming_Test/SelfContained_Trimming_Test.fsproj +++ b/tests/AheadOfTime/Trimming/SelfContained_Trimming_Test/SelfContained_Trimming_Test.fsproj @@ -17,8 +17,8 @@ - $(MSBuildThisFileDirectory)../../../../artifacts/bin/fsc/Release/$(FSharpNetCoreProductDefaultTargetFramework)/fsc.dll - $(MSBuildThisFileDirectory)../../../../artifacts/bin/fsc/Release/$(FSharpNetCoreProductDefaultTargetFramework)/fsc.dll + $(MSBuildThisFileDirectory)../../../../artifacts/bin/fsc/Release/$(FSharpNetCoreProductTargetFramework)/fsc.dll + $(MSBuildThisFileDirectory)../../../../artifacts/bin/fsc/Release/$(FSharpNetCoreProductTargetFramework)/fsc.dll False True diff --git a/tests/AheadOfTime/Trimming/StaticLinkedFSharpCore_Trimming_Test/StaticLinkedFSharpCore_Trimming_Test.fsproj b/tests/AheadOfTime/Trimming/StaticLinkedFSharpCore_Trimming_Test/StaticLinkedFSharpCore_Trimming_Test.fsproj index 535d5b0c779..16e648e78d3 100644 --- a/tests/AheadOfTime/Trimming/StaticLinkedFSharpCore_Trimming_Test/StaticLinkedFSharpCore_Trimming_Test.fsproj +++ b/tests/AheadOfTime/Trimming/StaticLinkedFSharpCore_Trimming_Test/StaticLinkedFSharpCore_Trimming_Test.fsproj @@ -19,8 +19,8 @@ - $(MSBuildThisFileDirectory)../../../../artifacts/bin/fsc/Release/$(FSharpNetCoreProductDefaultTargetFramework)/fsc.dll - $(MSBuildThisFileDirectory)../../../../artifacts/bin/fsc/Release/$(FSharpNetCoreProductDefaultTargetFramework)/fsc.dll + $(MSBuildThisFileDirectory)../../../../artifacts/bin/fsc/Release/$(FSharpNetCoreProductTargetFramework)/fsc.dll + $(MSBuildThisFileDirectory)../../../../artifacts/bin/fsc/Release/$(FSharpNetCoreProductTargetFramework)/fsc.dll False True diff --git a/tests/EndToEndBuildTests/BasicProvider/BasicProvider.DesignTime/BasicProvider.DesignTime.fsproj b/tests/EndToEndBuildTests/BasicProvider/BasicProvider.DesignTime/BasicProvider.DesignTime.fsproj index adc87ede3e4..e9c0a9a5cbe 100644 --- a/tests/EndToEndBuildTests/BasicProvider/BasicProvider.DesignTime/BasicProvider.DesignTime.fsproj +++ b/tests/EndToEndBuildTests/BasicProvider/BasicProvider.DesignTime/BasicProvider.DesignTime.fsproj @@ -2,7 +2,7 @@ Library - $(FSharpNetCoreProductDefaultTargetFramework);net472 + $(FSharpNetCoreProductTargetFramework);net472 typeproviders NO_GENERATIVE IS_DESIGNTIME diff --git a/tests/EndToEndBuildTests/BasicProvider/BasicProvider.Tests/BasicProvider.Tests.fsproj b/tests/EndToEndBuildTests/BasicProvider/BasicProvider.Tests/BasicProvider.Tests.fsproj index e9098910a00..68cf0a1ce5a 100644 --- a/tests/EndToEndBuildTests/BasicProvider/BasicProvider.Tests/BasicProvider.Tests.fsproj +++ b/tests/EndToEndBuildTests/BasicProvider/BasicProvider.Tests/BasicProvider.Tests.fsproj @@ -2,7 +2,7 @@ Library - $(FSharpNetCoreProductDefaultTargetFramework) + $(FSharpNetCoreProductTargetFramework) $(TestTargetFramework) false NO_GENERATIVE diff --git a/tests/EndToEndBuildTests/BasicProvider/BasicProvider/BasicProvider.fsproj b/tests/EndToEndBuildTests/BasicProvider/BasicProvider/BasicProvider.fsproj index f996d0b1ba5..4a8d1df2302 100644 --- a/tests/EndToEndBuildTests/BasicProvider/BasicProvider/BasicProvider.fsproj +++ b/tests/EndToEndBuildTests/BasicProvider/BasicProvider/BasicProvider.fsproj @@ -2,7 +2,7 @@ Library - $(FSharpNetCoreProductDefaultTargetFramework);net472 + $(FSharpNetCoreProductTargetFramework);net472 typeproviders $(FSharpCoreShippedPackageVersionValue) typeproviders diff --git a/tests/EndToEndBuildTests/BasicProvider/TestBasicProvider.cmd b/tests/EndToEndBuildTests/BasicProvider/TestBasicProvider.cmd index 18469995b2b..b3bf068b6d7 100644 --- a/tests/EndToEndBuildTests/BasicProvider/TestBasicProvider.cmd +++ b/tests/EndToEndBuildTests/BasicProvider/TestBasicProvider.cmd @@ -11,7 +11,7 @@ set __scriptpath=%~dp0 set configuration=Debug rem Read TFM from centralized source using MSBuild -for /f "usebackq delims=" %%a in (`dotnet msbuild "%__scriptpath%..\..\..\eng\TargetFrameworks.props" --getProperty:FSharpNetCoreProductDefaultTargetFramework`) do set PRODUCT_TFM=%%a +for /f "usebackq delims=" %%a in (`dotnet msbuild "%__scriptpath%..\..\..\eng\TargetFrameworks.props" --getProperty:FSharpNetCoreProductTargetFramework`) do set PRODUCT_TFM=%%a :parseargs if "%1" == "" goto argsdone diff --git a/tests/EndToEndBuildTests/ComboProvider/ComboProvider.Tests/ComboProvider.Tests.fsproj b/tests/EndToEndBuildTests/ComboProvider/ComboProvider.Tests/ComboProvider.Tests.fsproj index 3480179bd41..23bb2773ad6 100644 --- a/tests/EndToEndBuildTests/ComboProvider/ComboProvider.Tests/ComboProvider.Tests.fsproj +++ b/tests/EndToEndBuildTests/ComboProvider/ComboProvider.Tests/ComboProvider.Tests.fsproj @@ -2,7 +2,7 @@ Library - $(FSharpNetCoreProductDefaultTargetFramework) + $(FSharpNetCoreProductTargetFramework) $(TestTargetFramework) false $(FSharpCoreShippedPackageVersionValue) diff --git a/tests/EndToEndBuildTests/ComboProvider/ComboProvider/ComboProvider.fsproj b/tests/EndToEndBuildTests/ComboProvider/ComboProvider/ComboProvider.fsproj index 1486a33e578..21c8f10d8a2 100644 --- a/tests/EndToEndBuildTests/ComboProvider/ComboProvider/ComboProvider.fsproj +++ b/tests/EndToEndBuildTests/ComboProvider/ComboProvider/ComboProvider.fsproj @@ -2,7 +2,7 @@ Library - $(FSharpNetCoreProductDefaultTargetFramework);net472 + $(FSharpNetCoreProductTargetFramework);net472 $(FSharpCoreShippedPackageVersionValue) diff --git a/tests/EndToEndBuildTests/ComboProvider/TestComboProvider.cmd b/tests/EndToEndBuildTests/ComboProvider/TestComboProvider.cmd index 9896dab0d5e..0e43634ddb8 100644 --- a/tests/EndToEndBuildTests/ComboProvider/TestComboProvider.cmd +++ b/tests/EndToEndBuildTests/ComboProvider/TestComboProvider.cmd @@ -11,7 +11,7 @@ set __scriptpath=%~dp0 set configuration=Debug rem Read TFM from centralized source using MSBuild -for /f "usebackq delims=" %%a in (`dotnet msbuild "%__scriptpath%..\..\..\eng\TargetFrameworks.props" --getProperty:FSharpNetCoreProductDefaultTargetFramework`) do set PRODUCT_TFM=%%a +for /f "usebackq delims=" %%a in (`dotnet msbuild "%__scriptpath%..\..\..\eng\TargetFrameworks.props" --getProperty:FSharpNetCoreProductTargetFramework`) do set PRODUCT_TFM=%%a :parseargs if "%1" == "" goto argsdone diff --git a/tests/EndToEndBuildTests/DesignTimeProviderPackaging/Host/Host.fsproj b/tests/EndToEndBuildTests/DesignTimeProviderPackaging/Host/Host.fsproj index 9896f546b8f..180c2812622 100644 --- a/tests/EndToEndBuildTests/DesignTimeProviderPackaging/Host/Host.fsproj +++ b/tests/EndToEndBuildTests/DesignTimeProviderPackaging/Host/Host.fsproj @@ -2,7 +2,7 @@ Library - $(FSharpNetCoreProductDefaultTargetFramework) + $(FSharpNetCoreProductTargetFramework) $(FSharpCoreShippedPackageVersionValue) diff --git a/tests/EndToEndBuildTests/DesignTimeProviderPackaging/PlainLib/PlainLib.fsproj b/tests/EndToEndBuildTests/DesignTimeProviderPackaging/PlainLib/PlainLib.fsproj index 7c1990d39f9..86007ac4149 100644 --- a/tests/EndToEndBuildTests/DesignTimeProviderPackaging/PlainLib/PlainLib.fsproj +++ b/tests/EndToEndBuildTests/DesignTimeProviderPackaging/PlainLib/PlainLib.fsproj @@ -2,7 +2,7 @@ Library - $(FSharpNetCoreProductDefaultTargetFramework) + $(FSharpNetCoreProductTargetFramework) $(FSharpCoreShippedPackageVersionValue) diff --git a/tests/EndToEndBuildTests/DesignTimeProviderPackaging/Provider/Provider.fsproj b/tests/EndToEndBuildTests/DesignTimeProviderPackaging/Provider/Provider.fsproj index 26d158da014..8144f202d1e 100644 --- a/tests/EndToEndBuildTests/DesignTimeProviderPackaging/Provider/Provider.fsproj +++ b/tests/EndToEndBuildTests/DesignTimeProviderPackaging/Provider/Provider.fsproj @@ -2,7 +2,7 @@ Library - $(FSharpNetCoreProductDefaultTargetFramework) + $(FSharpNetCoreProductTargetFramework) $(FSharpCoreShippedPackageVersionValue) true diff --git a/tests/ILVerify/ilverify.ps1 b/tests/ILVerify/ilverify.ps1 index f30a4ae20e4..9559d00dc42 100644 --- a/tests/ILVerify/ilverify.ps1 +++ b/tests/ILVerify/ilverify.ps1 @@ -42,7 +42,7 @@ $env:PublishWindowsPdb = "false" [string] $default_tfm = "netstandard2.0" # Read product TFM from centralized source of truth via MSBuild -[string] $product_tfm = (& (Join-Path $repo_path "eng/common/dotnet.ps1") msbuild (Join-Path $repo_path "eng/TargetFrameworks.props") --getProperty:FSharpNetCoreProductDefaultTargetFramework).Trim() +[string] $product_tfm = (& (Join-Path $repo_path "eng/common/dotnet.ps1") msbuild (Join-Path $repo_path "eng/TargetFrameworks.props") --getProperty:FSharpNetCoreProductTargetFramework).Trim() [string] $artifacts_bin_path = Join-Path (Join-Path $repo_path "artifacts") "bin" diff --git a/tests/fsharp/SDKTests/tests/FSharpCoreVersionTest.props b/tests/fsharp/SDKTests/tests/FSharpCoreVersionTest.props index 89278b7275e..270ccbb078f 100644 --- a/tests/fsharp/SDKTests/tests/FSharpCoreVersionTest.props +++ b/tests/fsharp/SDKTests/tests/FSharpCoreVersionTest.props @@ -6,7 +6,7 @@ - $(FSharpNetCoreProductDefaultTargetFramework) + $(FSharpNetCoreProductTargetFramework) <_TargetFrameworkVersionWithoutV>$(FSharpNetCoreProductMajorVersion).0 .NETCoreApp Release diff --git a/tests/scripts/identifierAnalysisByType.fsx b/tests/scripts/identifierAnalysisByType.fsx index 0417c4f6ba3..8c3ceb2ec7f 100644 --- a/tests/scripts/identifierAnalysisByType.fsx +++ b/tests/scripts/identifierAnalysisByType.fsx @@ -1,7 +1,7 @@ // Print some stats about identifiers grouped by type // // IMPORTANT: This is a developer utility script. The TFM in the #r path below -// must match the FSharpNetCoreProductDefaultTargetFramework property in +// must match the FSharpNetCoreProductTargetFramework property in // eng/TargetFrameworks.props. If the product TFM changes, update the path. // // Run: dotnet fsi tests/scripts/identifierAnalysisByType.fsx From fdd49b266ad03005da33285c9fd09ef7f9215999 Mon Sep 17 00:00:00 2001 From: Tomas Grosup Date: Fri, 6 Feb 2026 12:52:09 +0100 Subject: [PATCH 39/40] Move NetCurrent back only to where product is built. --- Directory.Build.props | 6 ++++++ eng/TargetFrameworks.props | 1 - eng/build.sh | 3 +-- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/Directory.Build.props b/Directory.Build.props index 0a66878b625..6b185cdbab0 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -68,6 +68,12 @@ + + + $(NetCurrent) + + diff --git a/eng/TargetFrameworks.props b/eng/TargetFrameworks.props index 8e1fc29a8ca..d384e5fbcaa 100644 --- a/eng/TargetFrameworks.props +++ b/eng/TargetFrameworks.props @@ -12,7 +12,6 @@ net10.0 - $(NetCurrent) $([System.Text.RegularExpressions.Regex]::Replace('$(FSharpNetCoreProductTargetFramework)', '^net(\d+)\.0$', '$1')) diff --git a/eng/build.sh b/eng/build.sh index 28e839b1337..b1ccb85e454 100755 --- a/eng/build.sh +++ b/eng/build.sh @@ -84,8 +84,7 @@ docker=false args="" # Read product TFM from centralized source of truth using MSBuild -# Pass DotNetBuildSourceOnly so source-build/VMR resolves to $(NetCurrent) instead of hardcoded TFM -tfm=$("$scriptroot/common/dotnet.sh" msbuild "$scriptroot/TargetFrameworks.props" /p:DotNetBuildSourceOnly=$source_build --getProperty:FSharpNetCoreProductTargetFramework 2>/dev/null | tr -d '[:space:]') +tfm=$("$scriptroot/common/dotnet.sh" msbuild "$scriptroot/TargetFrameworks.props" --getProperty:FSharpNetCoreProductTargetFramework 2>/dev/null | tr -d '[:space:]') BuildCategory="" BuildMessage="" From 123d911889a9ac58a36270e575f77473446f5a93 Mon Sep 17 00:00:00 2001 From: Tomas Grosup Date: Wed, 11 Feb 2026 19:58:22 +0100 Subject: [PATCH 40/40] Fix TFM resolution in build.sh: resolve after SDK init to avoid stdout pollution --- eng/build.sh | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/eng/build.sh b/eng/build.sh index b1ccb85e454..d4b49708a04 100755 --- a/eng/build.sh +++ b/eng/build.sh @@ -83,8 +83,9 @@ properties="" docker=false args="" -# Read product TFM from centralized source of truth using MSBuild -tfm=$("$scriptroot/common/dotnet.sh" msbuild "$scriptroot/TargetFrameworks.props" --getProperty:FSharpNetCoreProductTargetFramework 2>/dev/null | tr -d '[:space:]') +# TFM will be resolved after InitializeDotNetCli ensures the SDK is available. +# Can be overridden via --tfm argument. +tfm="" BuildCategory="" BuildMessage="" @@ -353,6 +354,11 @@ trap TrapAndReportError EXIT InitializeDotNetCli $restore +# Resolve product TFM from centralized source of truth if not overridden via --tfm +if [[ "$tfm" == "" ]]; then + tfm=$("$DOTNET_INSTALL_DIR/dotnet" msbuild "$scriptroot/TargetFrameworks.props" -getProperty:FSharpNetCoreProductTargetFramework 2>/dev/null | tr -d '[:space:]') +fi + BuildSolution if [[ "$test_core_clr" == true ]]; then