Skip to content

/mt implies inline task factories out of proc#12614

Merged
JanProvaznik merged 8 commits intodotnet:mainfrom
JanProvaznik:mt-taskfactories-outofproc
Oct 14, 2025
Merged

/mt implies inline task factories out of proc#12614
JanProvaznik merged 8 commits intodotnet:mainfrom
JanProvaznik:mt-taskfactories-outofproc

Conversation

@JanProvaznik
Copy link
Member

@JanProvaznik JanProvaznik commented Oct 7, 2025

Fixes #12596

Context

Inline task factories must compile to disk (not in-memory) for out-of-process execution, but had no visibility into the /mt (multi-threaded) flag during initialization. This caused inline tasks to fail or fall back to in-process execution when /mt was used.

Solution: Add internal ITaskFactoryHostContext interface to expose BuildParameters.MultiThreaded to task factories, enabling compilation to disk when needed.

Changes Made

New Interface (src/Framework/ITaskFactoryHostContext.cs):

internal interface ITaskFactoryHostContext
{
    bool IsMultiThreadedBuild { get; }
}

Key Files Modified:

  • TaskFactoryLoggingHost - Implements interface, exposes multi-threaded state
  • TaskRegistry - Threads BuildParameters to factory initialization
  • RoslynCodeTaskFactory, CodeTaskFactory, XamlTaskFactory - Check ITaskFactoryHostContext.IsMultiThreadedBuild, set _compileForOutOfProcess flag
  • BuildManager - Cleanup uses _buildParameters.MultiThreaded
  • Test files - 11 unit tests added (7 running, 4 behind feature flag)

Testing

Unit Tests (11 added, all passing ✅):

  • Theory tests for both compilation modes (in-memory vs file-based)
  • Environment variable precedence validation
  • End-to-end integration tests with /mt flag verifying .inline_task.dll execution in external task host

Manual Test:

# Without /mt - in-memory (existing behavior)
dotnet artifacts\bin\bootstrap\core\MSBuild.dll test-inline-task.proj

# With /mt - file-based, out-of-process (new behavior)
dotnet artifacts\bin\bootstrap\core\MSBuild.dll test-inline-task.proj /mt

Notes

Performance Impact

  • Non-multithreaded builds: Zero impact (interface check returns false immediately, no behavior change)
  • Multithreaded builds: Single boolean check per inline task factory initialization (negligible overhead)
  • Compilation time: File-based compilation adds ~50-100ms per unique inline task (one-time cost, results are cached by MSBuild)

Backward Compatibility

Existing builds unaffected - Parameter defaults to false, existing behavior preserved
Environment variable still works - MSBUILDFORCEINLINETASKFACTORIESOUTOFPROC takes precedence
No public API changes - ITaskFactoryHostContext is internal
Graceful degradation - Null-safe with ?. operators, works if interface not implemented

Why This Approach?

✅ Pros:

  • Minimal scope: Only passes required boolean, not entire BuildParameters
  • Clean separation: Task factories decoupled from build engine internals
  • No serialization impact: Doesn't affect TaskRegistry (which is ITranslatable)
  • Testable: Easy to mock ITaskFactoryHostContext in unit tests
  • Extensible: Can add more host context properties in future

❌ Alternatives Rejected:

  • Threading BuildParameters everywhere: Large refactoring (10+ files), breaks serialization
  • Two-phase initialization (ITaskFactory3): Compilation happens in Initialize(), cannot be deferred
  • Environment variable only: Requires manual user configuration, not automatic with /mt

@baronfel
Copy link
Member

baronfel commented Oct 7, 2025

@JanProvaznik would it be possible to put the information about the 'force' flag on this new context as well, so that we could remove the use of the Trait check from the TaskHosts themselves? In general the use of Traits is harder to test than injecting the context object - it could allow for easier parallelization of tests.

@JanProvaznik
Copy link
Member Author

it's a good idea, though it does not help that much with testing since nontrivial amount of them are ~end to end so there is nowhere to inject the mockengine with that flag

@JanProvaznik JanProvaznik marked this pull request as ready for review October 8, 2025 08:42
Copilot AI review requested due to automatic review settings October 8, 2025 08:42
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR fixes an issue where inline task factories failed to compile for out-of-process execution when the /mt (multi-threaded) flag was used. The solution adds an internal ITaskFactoryHostContext interface to expose the multi-threaded build state to task factories during initialization, enabling them to compile to disk instead of in-memory when needed for proper out-of-process execution.

Key changes include:

  • Introduction of ITaskFactoryHostContext interface to expose build context to task factories
  • Updates to all inline task factories to check multi-threaded state and compile appropriately
  • Comprehensive test coverage for the new functionality

Reviewed Changes

Copilot reviewed 12 out of 12 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
src/Framework/ITaskFactoryHostContext.cs New internal interface exposing multi-threaded build state and force out-of-process flag
src/Build/Instance/TaskFactoryLoggingHost.cs Implements ITaskFactoryHostContext interface and stores build parameters
src/Build/Instance/TaskRegistry.cs Threads BuildParameters through task factory initialization chain
src/Tasks/RoslynCodeTaskFactory/RoslynCodeTaskFactory.cs Uses host context to determine compilation mode instead of relying solely on environment variables
src/Tasks/CodeTaskFactory.cs Uses host context to determine compilation mode instead of relying solely on environment variables
src/Tasks/XamlTaskFactory/XamlTaskFactory.cs Uses host context to determine compilation mode instead of relying solely on environment variables
src/UnitTests.Shared/MockEngine.cs Implements ITaskFactoryHostContext for testing with configurable properties
src/Tasks.UnitTests/RoslynCodeTaskFactory_Tests.cs Adds comprehensive unit tests for multi-threaded compilation behavior
src/Tasks.UnitTests/CodeTaskFactoryTests.cs Adds comprehensive unit tests for multi-threaded compilation behavior
src/Tasks.UnitTests/XamlTaskFactory_Tests.cs Adds comprehensive unit tests for multi-threaded compilation behavior
src/Build/BackEnd/TaskExecutionHost/TaskExecutionHost.cs Updates task instantiation logic to consider multi-threaded mode for out-of-process execution
src/Build/BackEnd/BuildManager/BuildManager.cs Updates cleanup logic to handle multi-threaded builds

Copy link
Member

@surayya-MS surayya-MS left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks great!

@JanProvaznik JanProvaznik requested a review from AR-May October 13, 2025 13:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

/mt should cause inline tasks to run out of process

6 participants