From d3c65ef85685fb209208084982c57c92cdce7b59 Mon Sep 17 00:00:00 2001 From: Tomas Grosup Date: Mon, 22 Jun 2026 10:43:05 +0200 Subject: [PATCH] Fix packaging of design-time providers referenced via ProjectReference Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../.FSharp.Compiler.Service/11.0.100.md | 1 + .../Microsoft.FSharp.NetSdk.targets | 52 ++++++++----------- .../TestDesignTimeProviderPackaging.cmd | 17 ++++-- .../TestDesignTimeProviderPackaging.sh | 16 ++++-- 4 files changed, 46 insertions(+), 40 deletions(-) diff --git a/docs/release-notes/.FSharp.Compiler.Service/11.0.100.md b/docs/release-notes/.FSharp.Compiler.Service/11.0.100.md index 194de518bcb..a06a05bd58e 100644 --- a/docs/release-notes/.FSharp.Compiler.Service/11.0.100.md +++ b/docs/release-notes/.FSharp.Compiler.Service/11.0.100.md @@ -1,5 +1,6 @@ ### Fixed +* Restore packaging of an F# design-time type provider that is activated via a `ProjectReference` carrying `IsFSharpDesignTimeProvider="true"`. The provider assembly is again included under `fsharp41` when packing (including `pack --no-build`); `PackageFSharpDesignTimeTools` now resolves the provider via `GetTargetPath`, which works in `dotnet pack`'s `BuildProjectReferences=false` content build without forcing an early `ResolveReferences`. ([Issue #18924](https://github.com/dotnet/fsharp/issues/18924), [PR #19979](https://github.com/dotnet/fsharp/pull/19979)) * Tooltip "Full name" now shows demangled companion module names (e.g. `MyType.func` instead of `MyTypeModule.func`). ([Issue #17335](https://github.com/dotnet/fsharp/issues/17335), [PR #19867](https://github.com/dotnet/fsharp/pull/19867)) * Fix internal error (FS0193) when calling an indexed property setter with a named argument that matches an indexer parameter. ([Issue #16034](https://github.com/dotnet/fsharp/issues/16034), [PR #19851](https://github.com/dotnet/fsharp/pull/19851)) * Fix missing FS1182 ("unused binding") warning for unused `let` function bindings inside class types. ([Issue #13849](https://github.com/dotnet/fsharp/issues/13849), [PR #19805](https://github.com/dotnet/fsharp/pull/19805)) diff --git a/src/FSharp.Build/Microsoft.FSharp.NetSdk.targets b/src/FSharp.Build/Microsoft.FSharp.NetSdk.targets index 3761a84fad5..c28119060cd 100644 --- a/src/FSharp.Build/Microsoft.FSharp.NetSdk.targets +++ b/src/FSharp.Build/Microsoft.FSharp.NetSdk.targets @@ -49,23 +49,11 @@ WARNING: DO NOT MODIFY this file unless you are knowledgeable about MSBuild and $(MSBuildProjectFullPath) - - + + $(TargetsForTfmSpecificContentInPackage);PackageFSharpDesignTimeTools - - - - - <_FSharpDesignTimeProviderProject Include="@(ProjectReference)" Condition="'%(ProjectReference.IsFSharpDesignTimeProvider)' == 'true'" /> - <_FSharpDesignTimeProviderPackage Include="@(PackageReference)" Condition="'%(PackageReference.IsFSharpDesignTimeProvider)' == 'true'" /> - - - $(TargetsForTfmSpecificContentInPackage);PackageFSharpDesignTimeTools - - - $(RestoreAdditionalProjectSources);$(_FSharpCoreLibraryPacksFolder) @@ -78,7 +66,9 @@ WARNING: DO NOT MODIFY this file unless you are knowledgeable about MSBuild and - + + fsharp41 tools @@ -87,22 +77,24 @@ WARNING: DO NOT MODIFY this file unless you are knowledgeable about MSBuild and + + + + + - <_ResolvedOutputFiles - Include="%(_ResolvedProjectReferencePaths.RootDir)%(_ResolvedProjectReferencePaths.Directory)/**/*" - Exclude="%(_ResolvedProjectReferencePaths.RootDir)%(_ResolvedProjectReferencePaths.Directory)/**/FSharp.Core.dll;%(_ResolvedProjectReferencePaths.RootDir)%(_ResolvedProjectReferencePaths.Directory)/**/System.ValueTuple.dll" - Condition="'%(_ResolvedProjectReferencePaths.IsFSharpDesignTimeProvider)' == 'true'"> - %(_ResolvedProjectReferencePaths.NearestTargetFramework) - - - <_ResolvedOutputFiles - Include="@(BuiltProjectOutputGroupKeyOutput)" - Condition=" '$(IsFSharpDesignTimeProvider)' == 'true' and '%(BuiltProjectOutputGroupKeyOutput->Filename)%(BuiltProjectOutputGroupKeyOutput->Extension)' != 'FSharp.Core.dll' and '%(BuiltProjectOutputGroupKeyOutput->Filename)%(BuiltProjectOutputGroupKeyOutput->Extension)' != 'System.ValueTuple.dll' "> - $(TargetFramework) - - - - $(FSharpToolsDirectory)/$(FSharpDesignTimeProtocol)/%(_ResolvedOutputFiles.NearestTargetFramework)/%(_ResolvedOutputFiles.FileName)%(_ResolvedOutputFiles.Extension) + + <_ResolvedOutputFiles Condition="'@(_FSharpDesignTimeProviderPath)' != ''" Include="%(_FSharpDesignTimeProviderPath.RootDir)%(_FSharpDesignTimeProviderPath.Directory)*.dll" /> + + + <_ResolvedOutputFiles Condition="'$(IsFSharpDesignTimeProvider)' == 'true'" Include="@(BuiltProjectOutputGroupKeyOutput)" /> + + + + $(FSharpToolsDirectory)/$(FSharpDesignTimeProtocol)/$(TargetFramework)/%(_ResolvedOutputFiles.FileName)%(_ResolvedOutputFiles.Extension) diff --git a/tests/EndToEndBuildTests/DesignTimeProviderPackaging/TestDesignTimeProviderPackaging.cmd b/tests/EndToEndBuildTests/DesignTimeProviderPackaging/TestDesignTimeProviderPackaging.cmd index cd3094901f1..34b79723462 100644 --- a/tests/EndToEndBuildTests/DesignTimeProviderPackaging/TestDesignTimeProviderPackaging.cmd +++ b/tests/EndToEndBuildTests/DesignTimeProviderPackaging/TestDesignTimeProviderPackaging.cmd @@ -84,8 +84,7 @@ echo [Test 2] PASSED: Provider test passed echo. echo === Test 3: Host with ProjectReference to Provider === -echo [Test 3] Packing Host with ProjectReference to Provider... -echo [Test 3] Note: This tests experimental execution-time reference checking +echo [Test 3] Packing Host that activates a design-time provider via ProjectReference metadata... echo [Test 3] Command: dotnet pack Host\Host.fsproj -o %~dp0artifacts -c %configuration% -v minimal -bl:%~dp0artifacts\host.binlog -p:FSharpTestCompilerVersion=coreclr dotnet pack Host\Host.fsproj -o %~dp0artifacts -c %configuration% -v minimal -bl:%~dp0artifacts\host.binlog -p:FSharpTestCompilerVersion=coreclr if ERRORLEVEL 1 ( @@ -94,9 +93,17 @@ if ERRORLEVEL 1 ( goto :failure ) -rem Note: This test may not work as expected due to MSBuild evaluation phase limitations -rem The current implementation only checks IsFSharpDesignTimeProvider property directly -echo [Test 3] PASSED: Host test completed (implementation limitation noted - may not check references correctly) +rem Check that tools folder exists in nupkg (provider activated via ProjectReference IsFSharpDesignTimeProvider metadata) +echo [Test 3] Checking that package contains tools/fsharp41 folder... +powershell -command "& { Add-Type -AssemblyName System.IO.Compression.FileSystem; $zip = [System.IO.Compression.ZipFile]::OpenRead('%~dp0artifacts\Host.1.0.0.nupkg'); $hasTools = $zip.Entries | Where-Object { $_.FullName -like 'tools/fsharp41/*' }; if ($hasTools) { exit 0 } else { exit 1 } }" +if ERRORLEVEL 1 ( + echo [Test 3] FAILED: Package does not contain tools/fsharp41 folder + echo [Test 3] Expected: provider referenced via ProjectReference should be packaged + echo [Test 3] Actual: No tools/fsharp41 folder found in Host.1.0.0.nupkg + goto :failure +) + +echo [Test 3] PASSED: Host (ProjectReference gesture) test passed echo. echo === Test 4: Pack with --no-build (No Provider) === diff --git a/tests/EndToEndBuildTests/DesignTimeProviderPackaging/TestDesignTimeProviderPackaging.sh b/tests/EndToEndBuildTests/DesignTimeProviderPackaging/TestDesignTimeProviderPackaging.sh index 9c10fa68ba5..bdff85c326c 100755 --- a/tests/EndToEndBuildTests/DesignTimeProviderPackaging/TestDesignTimeProviderPackaging.sh +++ b/tests/EndToEndBuildTests/DesignTimeProviderPackaging/TestDesignTimeProviderPackaging.sh @@ -73,8 +73,7 @@ echo "[Test 2] PASSED: Provider test passed" echo echo "=== Test 3: Host with ProjectReference to Provider ===" -echo "[Test 3] Packing Host with ProjectReference to Provider..." -echo "[Test 3] Note: This tests experimental execution-time reference checking" +echo "[Test 3] Packing Host that activates a design-time provider via ProjectReference metadata..." echo "[Test 3] Command: dotnet pack Host/Host.fsproj -o artifacts -c $configuration -v minimal -bl:artifacts/host.binlog -p:FSharpTestCompilerVersion=coreclr" if ! dotnet pack Host/Host.fsproj -o artifacts -c $configuration -v minimal -bl:artifacts/host.binlog -p:FSharpTestCompilerVersion=coreclr; then echo "[Test 3] FAILED: Pack command returned error code $?" @@ -82,9 +81,16 @@ if ! dotnet pack Host/Host.fsproj -o artifacts -c $configuration -v minimal -bl: exit 1 fi -# Note: This test may not work as expected due to MSBuild evaluation phase limitations -# The current implementation only checks IsFSharpDesignTimeProvider property directly -echo "[Test 3] PASSED: Host test completed (implementation limitation noted - may not check references correctly)" +# Check that tools folder exists in nupkg (provider activated via ProjectReference IsFSharpDesignTimeProvider metadata) +echo "[Test 3] Checking that package contains tools/fsharp41 folder..." +if ! unzip -l artifacts/Host.1.0.0.nupkg | grep -q "tools/fsharp41/"; then + echo "[Test 3] FAILED: Package does not contain tools/fsharp41 folder" + echo "[Test 3] Expected: provider referenced via ProjectReference should be packaged" + echo "[Test 3] Actual: No tools/fsharp41 folder found in Host.1.0.0.nupkg" + exit 1 +fi + +echo "[Test 3] PASSED: Host (ProjectReference gesture) test passed" echo echo "=== Test 4: Pack with --no-build (No Provider) ==="