-
Notifications
You must be signed in to change notification settings - Fork 1.4k
Description
Investigation Results: -mt mode breaks NuGet static graph restore for conditional ProjectReferences
Summary
When MSBuild runs with -mt (multithreaded) mode AND RestoreUseStaticGraphEvaluation=true, conditional ProjectReference items that depend on MSBuildRestoreSessionId are not properly evaluated during graph construction, causing those projects to be excluded from restore.
Reproduction
Environment: dotnet/runtime repo with RestoreUseStaticGraphEvaluation=true (default)
Problematic pattern in src/libraries/pretest.proj:
<ExternalsProject Include="externals.csproj" ... />
<ProjectReference Include="@(ExternalsProject)" Condition="'$(MSBuildRestoreSessionId)' != ''" />This pattern is intended to include externals.csproj as a ProjectReference only during restore (when MSBuildRestoreSessionId is set).
Test Results
| Test | -mt mode |
Static Graph Restore | externals.csproj Restored |
NETSDK1004 Error |
|---|---|---|---|---|
| 1 | ✅ Yes | ✅ Yes | ❌ No | ✅ Yes (BUG) |
| 2 | ✅ Yes | ❌ No | ✅ Yes | ❌ No |
| 3 | ❌ No | ✅ Yes | ✅ Yes | ❌ No |
Commands Used
# Test 1: FAILS - externals.csproj not restored
dotnet msbuild Build.proj -restore -t:Build -p:Subset=libs.pretest -p:Configuration=Release -mt -m
# Test 2: WORKS - externals.csproj restored
dotnet msbuild Build.proj -restore -t:Build -p:Subset=libs.pretest -p:Configuration=Release -p:RestoreUseStaticGraphEvaluation=false -mt -m
# Test 3: WORKS - externals.csproj restored
dotnet msbuild Build.proj -restore -t:Build -p:Subset=libs.pretest -p:Configuration=Release -mRoot Cause Analysis
NuGet's static graph restore uses an out-of-process tool (NuGet.Build.Tasks.Console) to evaluate projects and build the dependency graph. This tool receives global properties via IBuildEngine6.GetGlobalProperties().
When -mt mode is enabled, the MSBuildRestoreSessionId property appears to not be properly passed to the static graph evaluation, causing the condition '$(MSBuildRestoreSessionId)' != '' to evaluate as false during graph construction. This excludes the conditional ProjectReference from the restore graph.
Affected Code Paths
NuGet.Build.Tasks.RestoreTaskEx→StaticGraphRestoreTaskBaseNuGet.Build.Tasks.Console.MSBuildStaticGraphRestore.GetDependencyGraphSpec()- Global property serialization between MSBuild and the out-of-proc NuGet console
Workarounds
- Disable
-mtfor affected repos: Set<UseMSBuildMT>false</UseMSBuildMT>(current VMR approach) - Disable static graph restore: Set
RestoreUseStaticGraphEvaluation=false(slower) - Change project pattern: Remove the
MSBuildRestoreSessionIdcondition and always include theProjectReference
Recommendation
This appears to be a bug in NuGet's static graph restore implementation when combined with MSBuild -mt mode. The fix likely needs to be in NuGet.Build.Tasks to ensure global properties (including MSBuildRestoreSessionId) are properly passed to the out-of-process evaluation in all modes.