Skip to content

[msbuild-quality] MSBuild file quality findings: DotnetFsiCompilerPath bug + unquoted conditionsΒ #19989

Description

@github-actions

πŸ”§ MSBuild File Quality Report β€” 2026-06-24

Files reviewed: 65
Findings: πŸ”΄ 2 errors Β· 🟑 4 warnings Β· πŸ”΅ 1 suggestion

πŸ”΄ Errors

src/FSharp.Build/Microsoft.FSharp.NetSdk.props

  • Rule B-1: Copy-paste bug β€” DotnetFsiCompilerPath condition checks wrong variable
    • Line: 79
    • Current: <DotnetFsiCompilerPath Condition="'$(DotnetFscCompilerPath)' == ''">
    • Suggested: <DotnetFsiCompilerPath Condition="'$(DotnetFsiCompilerPath)' == ''">
    • Impact: Since DotnetFscCompilerPath is set on line 75, its condition is always false by line 79, so DotnetFsiCompilerPath is never configured in the shipped SDK flow. Any scenario that routes through the Fsi MSBuild task (rather than dotnet fsi) would not find the FSI compiler path.

src/FSharp.Build/Microsoft.FSharp.NetSdk.targets

  • Rule B-2: Unquoted property references in shipped target condition
    • Line: 174
    • Current: Condition="$(DisableILLinkSubstitutions) != 'true' and $(AssemblyName) != 'FSharp.Core'"
    • Suggested: Condition="'$(DisableILLinkSubstitutions)' != 'true' and '$(AssemblyName)' != 'FSharp.Core'"
    • Impact: If either property contains spaces or special characters, condition evaluation could fail. This is a shipped SDK target imported by every F# project.

🟑 Warnings

src/FSharp.Build/Microsoft.FSharp.Targets

  • Rule B-2: Unquoted boolean literal in conditions
    • Lines: 333, 335
    • Current: '$(UsingXBuild)' == true / '$(UsingXBuild)' != true
    • Suggested: '$(UsingXBuild)' == 'true' / '$(UsingXBuild)' != 'true'

vsintegration/shims/Microsoft.FSharp.ShimHelpers.props

  • Stale workaround: Comment says "TBD: Remove before shipping" but the file ships with a hardcoded FSCorePackageVersion = 6.0.4 fallback
    • Lines: 35–39
    • Impact: If the fallback fires, projects get an outdated FSharp.Core version. The workaround may no longer be needed.

FSharp.Profiles.props

  • Rule B-2: Unquoted property references in conditions
    • Lines: 9, 14
    • $(TolerateUnusedBindings) != 'true' β†’ '$(TolerateUnusedBindings)' != 'true'

FSharpBuild.Directory.Build.props

  • Rule B-2: Unquoted property reference in condition
    • Line: 33
    • $(AdditionalFscCmdFlags) != '' β†’ '$(AdditionalFscCmdFlags)' != ''

πŸ”΅ Suggestions

src/FSharp.Build/Microsoft.FSharp.NetSdk.targets

  • Rule A-4: Missing FileWrites registration for GenerateFSharpILLinkSubstitutions
    • Lines: 174–180
    • The target generates an ILLink substitutions file via GenerateILLinkSubstitutions task but doesn't register the output with @(FileWrites), so dotnet clean won't remove it.
Files reviewed (no issues found)

Shipped SDK build logic (highest priority):

  • src/FSharp.Build/Microsoft.FSharp.Core.NetSdk.props β€” clean, good use of sentinel properties
  • src/FSharp.Build/Microsoft.FSharp.Overrides.NetSdk.targets β€” clean, properly registers FileWrites
  • src/FSharp.Build/Microsoft.Portable.FSharp.Targets β€” clean, uses Exists() guards on all imports
  • src/fsc/fsc.targets β€” clean, properly preserves $(NoWarn) and $(DefineConstants)
  • src/fsi/fsi.targets β€” clean, properly preserves $(NoWarn) and $(DefineConstants)
  • All 6 vsintegration/shims/ files β€” clean, proper sentinel patterns and Exists() guards
  • vsintegration/Vsix/VisualFSharpFull/VisualFSharp.Core.targets β€” clean

Repository infrastructure:

  • Directory.Build.props / Directory.Build.targets β€” clean
  • FSharpBuild.Directory.Build.targets β€” clean, targets properly use Inputs/Outputs and FileWrites
  • FSharpTests.Directory.Build.props / .targets β€” clean
  • CoordinateXliff.targets β€” clean
  • buildtools/buildtools.targets β€” clean, properly registers FileWrites for generated lex/yacc files
  • All eng/ files β€” clean
  • All tests/ Directory.Build files β€” clean
  • All vsintegration/ Directory.Build files β€” clean
  • All setup/ files β€” clean
  • All SDK test .props/.targets β€” clean

Review Rules Reference

This review checks against MSBuild canonical patterns for:

  • Target authoring: DependsOn chains, Returns vs Outputs, incremental build, FileWrites
  • Property patterns: Conditional defaults, quoted conditions, semicolon composition, path normalization
  • Item management: Include/Remove/Update, batching, generated file placement
  • Extension points: Import guards, CustomBefore/After hooks, cross-platform paths

Generated by MSBuild Quality Review

Generated by F# MSBuild File Quality Review Agent Β· opus46 15.3M Β· β—·

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    Status
    New

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions