Skip to content

$(ParallelCompilation) never reaches the Fsc task — targets pass the item @(ParallelCompilation) instead of the property #19935

@marklam

Description

@marklam

Summary

Microsoft.FSharp.NetSdk.props defaults the property ParallelCompilation to true:

<!-- sdk/<version>/FSharp/Microsoft.FSharp.NetSdk.props, line 53 -->
<ParallelCompilation Condition=" '$(ParallelCompilation)' == '' ">true</ParallelCompilation>

but Microsoft.FSharp.Targets passes the item @(ParallelCompilation) — which is always
empty — to the Fsc task inside CoreCompile:

<!-- sdk/<version>/FSharp/Microsoft.FSharp.Targets, line 384 -->
ParallelCompilation="@(ParallelCompilation)"

So the value never reaches the compiler. Parallel compilation (graph-based type checking,
etc.) is silently off for every F# project built through the .NET SDK, despite the props
default saying true — and even an explicit -p:ParallelCompilation=true is a no-op.

Verified in .NET SDK 10.0.204 and 10.0.301 (F# compiler 15.2.204.0 / 15.2.301.0);
both contain the identical props/targets lines.

Repro

  1. Any F# project. Build with a binlog, explicitly opting in to be generous:

    dotnet build MyProject.fsproj -p:ParallelCompilation=true -bl
    
  2. Open msbuild.binlog and inspect the Fsc task invocation in CoreCompile.

Expected: the Fsc task receives ParallelCompilation=true and the generated
command line contains --parallelcompilation.

Actual: the Fsc task parameter list contains no ParallelCompilation entry at
all, and the fsc command line has no --parallelcompilation flag. (The binlog's
evaluation trace shows $(ParallelCompilation) = true as a property, confirming the
props default fires; it just never gets handed to the task.)

FSharp.Build.dll's Fsc task does support the parameter — its command-line builder
emits --parallelcompilation (visible in the task's string table and in
Fsc.fs) — so the
fix is a one-character-class change in the targets:

-              ParallelCompilation="@(ParallelCompilation)"
+              ParallelCompilation="$(ParallelCompilation)"

Impact

  • Graph-based type checking / parallel compilation is dead code for all SDK-style F#
    builds; nobody building with dotnet build has it on, regardless of the props default
    or any property they set.
  • Anyone benchmarking ParallelCompilation=true vs false measures zero difference and
    draws wrong conclusions about the feature itself.

Workaround

Pass the flag through OtherFlags instead, e.g. in Directory.Build.props:

<PropertyGroup Condition="'$(FscParallel)' == 'true' And '$(MSBuildProjectExtension)' == '.fsproj'">
  <OtherFlags>$(OtherFlags) --parallelcompilation</OtherFlags>
</PropertyGroup>

With that workaround the flag does reach fsc (confirmed via binlog), so only the
targets plumbing is broken, not the compiler option.

Environment

  • .NET SDK 10.0.204 and 10.0.301, Windows 11 x64
  • Microsoft (R) F# Compiler version 15.2.204.0 / 15.2.301.0 for F# 10.0

Metadata

Metadata

Assignees

No one assigned

    Type

    No fields configured for Bug.

    Projects

    Status
    New

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions