Skip to content

Conversation

Copy link
Contributor

Copilot AI commented Nov 13, 2025

Description

When building VisualFSharpDebug.vsix for local F# compiler development, the VSIX installs language service and editor components but MSBuild continues using the system-installed compiler from Common7/IDE/CommonExtensions/Microsoft/FSharp/Tools/. This PR adds automatic compiler path redirection to use the VSIX-bundled compiler.

Changes

  • Microsoft.FSharp.VSIX.Debug.Overrides.props (new): MSBuild props file that sets FSharpCompilerPath to VSIX Tools directory when not already set and compiler exists. Includes build warning to indicate override is active.

  • VisualFSharpDebug.csproj: Added ItemGroup to deploy props file to VSIX root with <IncludeInVSIX>true</IncludeInVSIX>.

  • Source.extension.vsixmanifest: Registered props file as Microsoft.VisualStudio.MsBuildProps asset for automatic import by Visual Studio.

Mechanism

The props file leverages $(MSBuildThisFileDirectory) to compute the VSIX Tools path and sets FSharpCompilerPath before the existing shim in Microsoft.FSharp.ShimHelpers.props evaluates (line 10 checks for pre-existing FSharpCompilerPath).

Debug VSIX only — production VSIX (VisualFSharpFull.csproj) unchanged.

Checklist

  • Test cases added

  • Performance benchmarks added in case of performance changes

  • Release notes entry updated:

    Please make sure to add an entry with short succinct description of the change as well as link to this pull request to the respective release notes file, if applicable.

    Release notes files:

    • If anything under src/Compiler has been changed, please make sure to make an entry in docs/release-notes/.FSharp.Compiler.Service/<version>.md, where <version> is usually "highest" one, e.g. 42.8.200
    • If language feature was added (i.e. LanguageFeatures.fsi was changed), please add it to docs/release-notes/.Language/preview.md
    • If a change to FSharp.Core was made, please make sure to edit docs/release-notes/.FSharp.Core/<version>.md where version is "highest" one, e.g. 8.0.200.

    Information about the release notes entries format can be found in the documentation.
    Example:

    If you believe that release notes are not necessary for this PR, please add NO_RELEASE_NOTES label to the pull request.

Original prompt

Enable VisualFSharpDebug VSIX to Override F# Compiler Path

Problem

When developers build and install VisualFSharpDebug.vsix for local F# development, the VSIX installs the language service and editor components but does NOT update the F# compiler (fscAnyCpu.exe) used by MSBuild when building F# projects.

Currently:

  • VSIX installs to: %LOCALAPPDATA%\Microsoft\VisualStudio\<version>\Extensions\...
  • MSBuild uses compiler from: C:\Program Files\Microsoft Visual Studio\<version>\Common7\IDE\CommonExtensions\Microsoft\FSharp\Tools\

This means locally built compiler changes are not used when building F# projects, which is a major pain point for F# compiler development.

Solution

Deploy an MSBuild .props file via the VSIX that automatically overrides the FSharpCompilerPath property to point to the VSIX's Tools directory where the custom-built compiler is located.

The F# build system uses a shim mechanism (in vsintegration/shims/Microsoft.FSharp.ShimHelpers.props) that checks for FSharpCompilerPath and uses it to load the compiler. By setting this property before the shims evaluate, we can redirect all F# builds to use the VSIX compiler.

Implementation Details

File 1: Create New Props File

Path: vsintegration/Vsix/VisualFSharpFull/Microsoft.FSharp.VSIX.Debug.Overrides.props

Content:

<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (c) Microsoft Corporation.  All Rights Reserved.  See License.txt in the project root for license information. -->
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  
  <PropertyGroup>
    <!-- Override FSharpCompilerPath to point to VSIX Tools directory -->
    <!-- This props file is deployed alongside the Tools directory in the VSIX -->
    <!-- Calculate path from this file's location to Tools -->
    <_FSharpDebugVsixPropsDir>$(MSBuildThisFileDirectory)</_FSharpDebugVsixPropsDir>
    <_FSharpDebugVsixToolsPath>$(_FSharpDebugVsixPropsDir)Tools\</_FSharpDebugVsixToolsPath>
    
    <!-- Override only if not already set and compiler exists -->
    <FSharpCompilerPath Condition="'$(FSharpCompilerPath)' == '' and Exists('$(_FSharpDebugVsixToolsPath)fscAnyCpu.exe')">$(_FSharpDebugVsixToolsPath)</FSharpCompilerPath>
  </PropertyGroup>
  
  <Target Name="WarnAboutDebugVsixCompiler" BeforeTargets="BeforeBuild" Condition="'$(FSharpCompilerPath)' == '$(_FSharpDebugVsixToolsPath)'">
    <Warning Text="🔧 [F# Debug VSIX] Using custom F# compiler from: $(FSharpCompilerPath)" />
  </Target>

</Project>

File 2: Modify VisualFSharpDebug.csproj

Path: vsintegration/Vsix/VisualFSharpFull/VisualFSharpDebug.csproj

Change: Add the following ItemGroup after line 86 (before the closing </Project> tag):

  <ItemGroup>
    <!-- Deploy the override props file as an MSBuild asset -->
    <Content Include="Microsoft.FSharp.VSIX.Debug.Overrides.props">
      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
      <IncludeInVSIX>true</IncludeInVSIX>
      <VSixSubPath>.</VSixSubPath>
    </Content>
  </ItemGroup>

File 3: Modify VSIX Manifest

Path: vsintegration/Vsix/VisualFSharpFull/Source.extension.vsixmanifest

Change: Add the following Asset element in the <Assets> section (after the existing Asset elements, around line 43):

    <Asset Type="Microsoft.VisualStudio.MsBuildProps" 
           d:Source="File" 
           Path="Microsoft.FSharp.VSIX.Debug.Overrides.props" />

How It Works

  1. The new props file is deployed in the VSIX root directory (same level as Tools/)
  2. The VSIX manifest declares it as a Microsoft.VisualStudio.MsBuildProps asset
  3. Visual Studio automatically imports MSBuild props files registered this way
  4. The props file calculates the path to the VSIX Tools directory using $(MSBuildThisFileDirectory)
  5. It sets FSharpCompilerPath to point to the VSIX Tools directory (only if not already set)
  6. The F# shim mechanism (in vsintegration/shims/Microsoft.FSharp.ShimHelpers.props) uses FSharpCompilerPath to load the compiler
  7. All F# project builds now use the custom compiler from the VSIX
  8. A warning message appears in build output to indicate the override is active

Testing

After these changes:

  1. Build the solution in Debug configuration
  2. Press F5 on VisualFSharpDebug project (or install manually via VSIXInstaller)
  3. Build any F# project
  4. You should see: 🔧 [F# Debug VSIX] Using custom F# compiler from: <path to VSIX>\Tools\
  5. Verify the custom compiler is being used (check timestamps, add debug output, etc.)

Safety

  • ✅ Debug-only: Only affects VisualFSharpDebug.csproj, not VisualFSharpFull.csproj
  • ✅ Conditional: Only overrides if FSharpCompilerPath is not already set
  • ✅ Safe fallback: Checks if compiler exists before setting the property
  • ✅ Pure: No registry modifications, no environment variables
  • ✅ Self-cleaning: Uninstalling the VSIX removes all files automatically
  • ✅ Visible: Shows clear warning when acti...

This pull request was created as a result of the following prompt from Copilot chat.

Enable VisualFSharpDebug VSIX to Override F# Compiler Path

Problem

When developers build and install VisualFSharpDebug.vsix for local F# development, the VSIX installs the language service and editor components but does NOT update the F# compiler (fscAnyCpu.exe) used by MSBuild when building F# projects.

Currently:

  • VSIX installs to: %LOCALAPPDATA%\Microsoft\VisualStudio\<version>\Extensions\...
  • MSBuild uses compiler from: C:\Program Files\Microsoft Visual Studio\<version>\Common7\IDE\CommonExtensions\Microsoft\FSharp\Tools\

This means locally built compiler changes are not used when building F# projects, which is a major pain point for F# compiler development.

Solution

Deploy an MSBuild .props file via the VSIX that automatically overrides the FSharpCompilerPath property to point to the VSIX's Tools directory where the custom-built compiler is located.

The F# build system uses a shim mechanism (in vsintegration/shims/Microsoft.FSharp.ShimHelpers.props) that checks for FSharpCompilerPath and uses it to load the compiler. By setting this property before the shims evaluate, we can redirect all F# builds to use the VSIX compiler.

Implementation Details

File 1: Create New Props File

Path: vsintegration/Vsix/VisualFSharpFull/Microsoft.FSharp.VSIX.Debug.Overrides.props

Content:

<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (c) Microsoft Corporation.  All Rights Reserved.  See License.txt in the project root for license information. -->
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  
  <PropertyGroup>
    <!-- Override FSharpCompilerPath to point to VSIX Tools directory -->
    <!-- This props file is deployed alongside the Tools directory in the VSIX -->
    <!-- Calculate path from this file's location to Tools -->
    <_FSharpDebugVsixPropsDir>$(MSBuildThisFileDirectory)</_FSharpDebugVsixPropsDir>
    <_FSharpDebugVsixToolsPath>$(_FSharpDebugVsixPropsDir)Tools\</_FSharpDebugVsixToolsPath>
    
    <!-- Override only if not already set and compiler exists -->
    <FSharpCompilerPath Condition="'$(FSharpCompilerPath)' == '' and Exists('$(_FSharpDebugVsixToolsPath)fscAnyCpu.exe')">$(_FSharpDebugVsixToolsPath)</FSharpCompilerPath>
  </PropertyGroup>
  
  <Target Name="WarnAboutDebugVsixCompiler" BeforeTargets="BeforeBuild" Condition="'$(FSharpCompilerPath)' == '$(_FSharpDebugVsixToolsPath)'">
    <Warning Text="🔧 [F# Debug VSIX] Using custom F# compiler from: $(FSharpCompilerPath)" />
  </Target>

</Project>

File 2: Modify VisualFSharpDebug.csproj

Path: vsintegration/Vsix/VisualFSharpFull/VisualFSharpDebug.csproj

Change: Add the following ItemGroup after line 86 (before the closing </Project> tag):

  <ItemGroup>
    <!-- Deploy the override props file as an MSBuild asset -->
    <Content Include="Microsoft.FSharp.VSIX.Debug.Overrides.props">
      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
      <IncludeInVSIX>true</IncludeInVSIX>
      <VSixSubPath>.</VSixSubPath>
    </Content>
  </ItemGroup>

File 3: Modify VSIX Manifest

Path: vsintegration/Vsix/VisualFSharpFull/Source.extension.vsixmanifest

Change: Add the following Asset element in the <Assets> section (after the existing Asset elements, around line 43):

    <Asset Type="Microsoft.VisualStudio.MsBuildProps" 
           d:Source="File" 
           Path="Microsoft.FSharp.VSIX.Debug.Overrides.props" />

How It Works

  1. The new props file is deployed in the VSIX root directory (same level as Tools/)
  2. The VSIX manifest declares it as a Microsoft.VisualStudio.MsBuildProps asset
  3. Visual Studio automatically imports MSBuild props files registered this way
  4. The props file calculates the path to the VSIX Tools directory using $(MSBuildThisFileDirectory)
  5. It sets FSharpCompilerPath to point to the VSIX Tools directory (only if not already set)
  6. The F# shim mechanism (in vsintegration/shims/Microsoft.FSharp.ShimHelpers.props) uses FSharpCompilerPath to load the compiler
  7. All F# project builds now use the custom compiler from the VSIX
  8. A warning message appears in build output to indicate the override is active

Testing

After these changes:

  1. Build the solution in Debug configuration
  2. Press F5 on VisualFSharpDebug project (or install manually via VSIXInstaller)
  3. Build any F# project
  4. You should see: 🔧 [F# Debug VSIX] Using custom F# compiler from: <path to VSIX>\Tools\
  5. Verify the custom compiler is being used (check timestamps, add debug output, etc.)

Safety

  • ✅ Debug-only: Only affects VisualFSharpDebug.csproj, not VisualFSharpFull.csproj
  • ✅ Conditional: Only overrides if FSharpCompilerPath is not already set
  • ✅ Safe fallback: Checks if compiler exists before setting the property
  • ✅ Pure: No registry modifications, no environment variables
  • ✅ Self-cleaning: Uninstalling the VSIX removes all files automatically
  • ✅ Visible: Shows clear warning when active so developers know what's happening

Important Notes

  • This ONLY applies to VisualFSharpDebug.vsix (the debug variant used for F5 development)
  • VisualFSharpFull.csproj (the production VSIX) should NOT include these changes
  • The override uses the standard Microsoft-documented VSIX MSBuild integration mechanism
  • The Microsoft.VisualStudio.MsBuildProps asset type ensures automatic import by MSBuild

💬 We'd love your input! Share your thoughts on Copilot coding agent in our 2 minute survey.

Co-authored-by: T-Gro <46543583+T-Gro@users.noreply.github.com>
Copilot AI changed the title [WIP] Add support for overriding F# compiler path in VSIX Enable VisualFSharpDebug VSIX to override F# compiler path via MSBuild props Nov 13, 2025
Copilot AI requested a review from T-Gro November 13, 2025 13:46
Copilot finished work on behalf of T-Gro November 13, 2025 13:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: New

Development

Successfully merging this pull request may close these issues.

2 participants