Fix chained item function empty result comparison in conditions#10
Closed
Fix chained item function empty result comparison in conditions#10
Conversation
The issue is that when chaining item functions like:
@(TestItem->WithMetadataValue('Identity', 'Test1')->WithMetadataValue('Foo', 'Baz'))
The result incorrectly evaluates as non-empty when compared in a condition, even though the actual result is empty.
Initial hypothesis was that the BreakOnNotEmpty optimization in Transform() was breaking early after the first transform. However, testing revealed that the Transform() method is NOT being called at all for chained transforms with BreakOnNotEmpty option.
This suggests the bug is elsewhere - possibly in how ExpressionShredder parses chained transforms or in how they're evaluated separately.
Co-authored-by: JanProvaznik <25267098+JanProvaznik@users.noreply.github.com>
When chaining item functions like @(Item->Func1()->Func2()), and the final result is empty, the condition comparison with empty string was incorrectly evaluating to false. The bug was in the Transform method in Expander.cs. The original code checked for BreakOnNotEmpty after EACH intermediate transform, causing it to break early when an intermediate result was non-empty, even if subsequent transforms would filter to an empty result. The fix moves the BreakOnNotEmpty check to after ALL transforms in the chain complete, ensuring we only check the final result, not intermediate ones. Added a unit test to verify the fix works correctly. Co-authored-by: JanProvaznik <25267098+JanProvaznik@users.noreply.github.com>
Copilot
AI
changed the title
[WIP] Fix item function comparison returning incorrect result
Fix chained item function empty result comparison in conditions
Dec 5, 2025
ericstj
approved these changes
Dec 9, 2025
…th illegal path characters (dotnet#12841) ### Context `/getItem` and `/getTargetResult` throw an unhandled `InvalidOperationException` when serializing items whose item specs contain illegal path characters (e.g., compiler command line flags from ClangTidy's `GetCompileCommands` target). The JSON output formatter iterates over all metadata names including built-in metadata like `FullPath`, `Directory`, etc. When `GetMetadata()` is called on these, it attempts path computation which fails for non-path item specs. ### Changes Made - Wrapped metadata retrieval in `JsonOutputFormatter.cs` with try-catch for `InvalidOperationException` - Added `TryGetMetadata` and `TryGetMetadataValue` helper methods that return empty string on failure - Applied fix to all three affected methods: `AddTargetResultsInJsonFormat`, `AddItemInstancesInJsonFormat`, `AddItemsInJsonFormat` - Exception handling catches all `InvalidOperationException` instances to ensure compatibility across all locales (error messages are localized) ### Testing Added `GetTargetResultWithIllegalPathCharacters` test that verifies both `/getTargetResult` and `/getItem` succeed with items containing compiler flags as item specs. ### Notes On Linux, the test shows the path-like metadata is still computed (since `/` is valid in paths). On Windows, these would return empty strings. The key fix is preventing the unhandled exception crash. The exception handling is intentionally broad (catching all `InvalidOperationException` without message filtering) to ensure the fix works correctly in all locales, as error messages from MSBuild are localized and checking for specific English text would fail in non-English environments. <!-- START COPILOT CODING AGENT SUFFIX --> <details> <summary>Original prompt</summary> ---- *This section details on the original issue you should resolve* <issue_title>[Unhandled Exception]: /getItem and /getTargetResult fail for target GetCompileCommands</issue_title> <issue_description>### Issue Description There is an uncaught exception when trying to access certain information from the GetCompileCommands target (from ClangTidy), in particular `/getTargetResult:GetCompileCommands` and `/getTargetResult:GetCompileCommands` ### Steps to Reproduce [tidytest.zip](https://github.com/user-attachments/files/22645381/tidytest.zip) Run either of the following commands (You could also run with target `/t:ClangTidy` for the same result) ``` msbuild tidytest.vcxproj /t:GetCompileCommands /getTargetResult:GetCompileCommands msbuild tidytest.vcxproj /t:GetCompileCommands /getItem:CompileCommands ``` I expect to get a json formatted target result or item. ### Actual Behavior I get the following error when building ``` C:\Users\rp0656\source\repos\tidytest>msbuild tidytest.vcxproj /t:GetCompileCommands /getTargetResult:GetCompileCommands MSBUILD : error MSB1025: An internal failure occurred while running MSBuild. System.InvalidOperationException: The item metadata "%(FullPath)" cannot be applied to the path "/c /nologo /W3 /WX- /diagnostics:column /Od /D _DEBUG /D _CONSOLE /D _UNICODE /D UNICODE /EHsc /RTC1 /MDd /GS /fp:precise /permissive- /Fa"tidytest\x64\Debug\\" /Fo"tidytest\x64\Debug\\" /Gd --target=amd64-pc-windows-msvc /TP". Illegal characters in path. at Microsoft.Build.Shared.ErrorUtilities.ThrowInvalidOperation(String resourceName, Object[] args) at Microsoft.Build.Shared.FileUtilities.ItemSpecModifiers.GetItemSpecModifier(String currentDirectory, String itemSpec, String definingProjectEscaped, String modifier, String& fullPath) at Microsoft.Build.Evaluation.BuiltInMetadata.GetMetadataValueEscaped(String currentDirectory, String evaluatedIncludeBeforeWildcardExpansionEscaped, String evaluatedIncludeEscaped, String definingProjectEscaped, String name, String& fullPath) at Microsoft.Build.Execution.ProjectItemInstance.TaskItem.GetBuiltInMetadataEscaped(String name) at Microsoft.Build.Execution.ProjectItemInstance.TaskItem.GetMetadataEscaped(String metadataName) at Microsoft.Build.Execution.ProjectItemInstance.TaskItem.GetMetadata(String metadataName) at Microsoft.Build.CommandLine.JsonOutputFormatter.AddTargetResultsInJsonFormat(String[] targetNames, BuildResult result) at Microsoft.Build.CommandLine.MSBuildApp.OutputBuildInformationInJson(BuildResult result, String[] getProperty, String[] getItem, String[] getTargetResult, ILogger[] loggers, ExitType exitType, TextWriter outputStream) at Microsoft.Build.CommandLine.MSBuildApp.Execute(String commandLine) Unhandled Exception: System.InvalidOperationException: The item metadata "%(FullPath)" cannot be applied to the path "/c /nologo /W3 /WX- /diagnostics:column /Od /D _DEBUG /D _CONSOLE /D _UNICODE /D UNICODE /EHsc /RTC1 /MDd /GS /fp:precise /permissive- /Fa"tidytest\x64\Debug\\" /Fo"tidytest\x64\Debug\\" /Gd --target=amd64-pc-windows-msvc /TP". Illegal characters in path. at Microsoft.Build.Shared.ErrorUtilities.ThrowInvalidOperation(String resourceName, Object[] args) at Microsoft.Build.Shared.FileUtilities.ItemSpecModifiers.GetItemSpecModifier(String currentDirectory, String itemSpec, String definingProjectEscaped, String modifier, String& fullPath) at Microsoft.Build.Evaluation.BuiltInMetadata.GetMetadataValueEscaped(String currentDirectory, String evaluatedIncludeBeforeWildcardExpansionEscaped, String evaluatedIncludeEscaped, String definingProjectEscaped, String name, String& fullPath) at Microsoft.Build.Execution.ProjectItemInstance.TaskItem.GetBuiltInMetadataEscaped(String name) at Microsoft.Build.Execution.ProjectItemInstance.TaskItem.GetMetadataEscaped(String metadataName) at Microsoft.Build.Execution.ProjectItemInstance.TaskItem.GetMetadata(String metadataName) at Microsoft.Build.CommandLine.JsonOutputFormatter.AddTargetResultsInJsonFormat(String[] targetNames, BuildResult result) at Microsoft.Build.CommandLine.MSBuildApp.OutputBuildInformationInJson(BuildResult result, String[] getProperty, String[] getItem, String[] getTargetResult, ILogger[] loggers, ExitType exitType, TextWriter outputStream) at Microsoft.Build.CommandLine.MSBuildApp.Execute(String commandLine) at Microsoft.Build.CommandLine.MSBuildApp.Main() ``` ### Analysis The error suggests that it is trying to interpret the flags of the compile commands as a path, which causes an error when it can't be resolved. The function `%(FullPath)` is used, though it is not clear to me exactly where, but my best guess is it used on a variable that is supposed to just be the path to `cl`, but has been extended with flags. See the clang tidy targets file at something similar to `C:\Program Files\Microsoft Visual Studio\2022\Enterprise\MSBuild\Microsoft\VC\v170\Microsoft.Cpp.ClangTidy.targets` ### Versions & Co... </details> - Fixes dotnet#12589 <!-- START COPILOT CODING AGENT TIPS --> --- ✨ Let Copilot coding agent [set things up for you](https://github.com/dotnet/msbuild/issues/new?title=✨+Set+up+Copilot+instructions&body=Configure%20instructions%20for%20this%20repository%20as%20documented%20in%20%5BBest%20practices%20for%20Copilot%20coding%20agent%20in%20your%20repository%5D%28https://gh.io/copilot-coding-agent-tips%29%2E%0A%0A%3COnboard%20this%20repo%3E&assignees=copilot) — coding agent works faster and does higher quality work when set up for your repo. --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: JanProvaznik <25267098+JanProvaznik@users.noreply.github.com> Co-authored-by: Jan Provazník <janprovaznik@microsoft.com> Co-authored-by: YuliiaKovalova <95473390+YuliiaKovalova@users.noreply.github.com>
…#12918) ### Context Structured log viewer was cluttered with repeated non-actionable messages about SDK environment variables (e.g., `DOTNET_HOST_PATH`). These appeared for every project evaluation, reporting normal SDK behavior without providing value to users. ### Changes Made Modified `ProjectInstance.AddSdkResolvedEnvironmentVariable()` to only log messages when an SDK attempts to set an environment variable to a **different value** than what's already set: - **When values match** (common case): No message is logged, eliminating the clutter shown in the original issue - **When values differ** (conflict): A low-importance message is logged showing both the attempted value and the existing value for diagnostic purposes - **Code refactoring**: Extracted duplicate value comparison and logging logic into a helper method `LogIfValueDiffers` to improve code maintainability Updated string resources in `Strings.resx` and all 13 localized `.xlf` files: - `SdkEnvironmentVariableAlreadySet`: Now includes both attempted and existing values in the message - `SdkEnvironmentVariableAlreadySetBySdk`: Now includes both attempted and existing values in the message - Removed `SdkEnvironmentVariableSet` (no longer logging successful sets) The underlying functionality is unchanged—environment variables are still tracked and set correctly, and properties remain visible in the structured log viewer. ### Testing - Built MSBuild successfully - Verified messages no longer appear when values are the same (common case) - Messages would appear when values differ (preserves diagnostic value for conflicts) - Confirmed existing unit tests pass - Verified sample projects build successfully - Confirmed properties are still visible in structured log viewer (DOTNET_HOST_PATH, etc.) ### Notes This implementation balances two concerns: 1. **Eliminates noise**: Repeated messages about the same value being set multiple times no longer clutter logs 2. **Preserves diagnostics**: Actual conflicts (different values) are still logged with full context (both values shown) The messages log at `MessageImportance.Low` to provide diagnostic information without being intrusive in normal builds. Code quality was improved by extracting duplicate logic into a reusable helper method. <!-- START COPILOT ORIGINAL PROMPT --> <details> <summary>Original prompt</summary> > > ---- > > *This section details on the original issue you should resolve* > > <issue_title>Duplicated messages from SDK/environment resolution</issue_title> > <issue_description><img width="2860" height="1772" alt="Image" src="https://github.com/user-attachments/assets/f4d4871f-28e9-4cb5-9f58-42c4a0056979" /> > > There are a ton of these `An SDK attempted to set the environment variable "DOTNET_HOST_PATH"` messages that aren't particularly helpful, and they're not attributed to a project so they clutter up the top level of the viewer tool.</issue_description> > > ## Comments on the Issue (you are @copilot in this section) > > <comments> > </comments> > </details> <!-- START COPILOT CODING AGENT SUFFIX --> - Fixes dotnet#12915 <!-- START COPILOT CODING AGENT TIPS --> --- 💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more [Copilot coding agent tips](https://gh.io/copilot-coding-agent-tips) in the docs. --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: YuliiaKovalova <95473390+YuliiaKovalova@users.noreply.github.com>
…: Build ID 13036709
…: Build ID 13036709 (dotnet#12975) This is the pull request automatically created by the OneLocBuild task in the build process to check-in localized files generated based upon translation source files (.lcl files) handed-back from the downstream localization pipeline. If there are issues in translations, visit https://aka.ms/icxLocBug and log bugs for fixes. The OneLocBuild wiki is https://aka.ms/onelocbuild and the localization process in general is documented at https://aka.ms/AllAboutLoc.
…rrors (dotnet#12930) ### Context In quiet mode (`-v:q`), warnings and errors were rendered immediately without project context. Users saw diagnostic messages but couldn't identify which project they came from. ``` CSC : warning MSTEST0001: Explicitly enable or disable tests parallelization ``` ### Changes Made **Modified diagnostic accumulation logic** - `WarningRaised` and `ErrorRaised` now accumulate diagnostics in the project's `BuildMessages` collection regardless of verbosity - Removed verbosity check that caused immediate rendering in quiet mode - Preserved immediate rendering for auth provider warnings and immediate warnings (MSB3026) **Modified project summary rendering** - `ProjectFinished` now displays project summaries in quiet mode when `HasErrorsOrWarnings` is true - Projects without diagnostics remain hidden in quiet mode as expected - Simplified quiet mode detection logic: `Verbosity < LoggerVerbosity.Quiet || (Verbosity == LoggerVerbosity.Quiet && !project.HasErrorsOrWarnings)` - Skip `DisplayNodes()` call in quiet mode to avoid writing unnecessary cursor hide/show ANSI codes since there's no dynamic refresh **Result in quiet mode:** ``` project failed with 1 error(s) and 2 warning(s) (0.2s) directory/file(1,2,3,4): warning AA0000: Warning message directory/file(1,2,3,4): error AA0000: Error message ``` ### Testing - Updated snapshot files for `PrintBuildSummaryQuietVerbosity_FailedWithErrors` across Linux/OSX/Windows - All 69 TerminalLogger tests pass - Verified successful projects still produce no output in quiet mode - Verified no cursor control codes are written in quiet mode output ### Notes Uses the same project-grouping primitives as higher verbosity levels, toggled by runtime state per maintainer guidance. <!-- START COPILOT ORIGINAL PROMPT --> <details> <summary>Original prompt</summary> > > ---- > > *This section details on the original issue you should resolve* > > <issue_title>Terminal logger quiet mode hides projects</issue_title> > <issue_description>This was reported by @gao-artur in microsoft/testfx#7051 > > > Here is a new project created from the MSTest template without `MSTestSettings.cs` file + the binlog. Built with > > > > `dotnet build -bl -v q` > > [TestProject11.zip](https://github.com/user-attachments/files/23968849/TestProject11.zip) > > In that thread we determined that `-tl` status affects the usefulness of the output for messages that do not have a specific file associated with them: > > ```sh-session > ❯ dotnet build > Restore complete (4.0s) > TestProject11 net9.0 succeeded with 1 warning(s) (2.3s) → bin\Debug\net9.0\TestProject11.dll > CSC : warning MSTEST0001: Explicitly enable or disable tests parallelization (https://learn.microsoft.com/dotnet/core/testing/mstest-analyzers/mstest0001) > > Build succeeded with 1 warning(s) in 7.2s > > ❯ rm -r .\obj\ > > ❯ dotnet build -v:q > CSC : warning MSTEST0001: Explicitly enable or disable tests parallelization (https://learn.microsoft.com/dotnet/core/testing/mstest-analyzers/mstest0001) > ``` > > The associated project `TestProject11` is not mentioned anywhere in the latter. I think that's unreasonable even when the user has requested "quiet".</issue_description> > > <agent_instructions>Try to update the diagnostic/warning/error message rendering in quiet mode so that it doesn't use the 'immediate' mode formatting, the final output should only show the diagnostics for projects that failed or had warnings.</agent_instructions> > > ## Comments on the Issue (you are @copilot in this section) > > <comments> > <comment_new><author>@baronfel</author><body> > A few approaches to consider: > > * in quiet mode appending/prepending the project if it exists to the 'message formatting' part of the line > * in quiet mode using the same project-based grouping as we do in non-quiet mode, instead of assuming that quiet mode should trigger some kind of flat-list-only output</body></comment_new> > <comment_new><author>@rainersigwald</author><body> > Yeah I waffled between the two myself, I think I lean to the latter right now though.</body></comment_new> > <comment_new><author>@baronfel</author><body> > I do too - it feels more like a 'modular' approach - use the same 'primitives' that can be toggled on/off based on run-time state, etc.</body></comment_new> > </comments> > </details> <!-- START COPILOT CODING AGENT SUFFIX --> - Fixes dotnet#12929 <!-- START COPILOT CODING AGENT TIPS --> --- 💬 We'd love your input! Share your thoughts on Copilot coding agent in our [2 minute survey](https://gh.io/copilot-coding-agent-survey). --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: baronfel <573979+baronfel@users.noreply.github.com> Co-authored-by: Chet Husk <baronfel@users.noreply.github.com> Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
…: Build ID 13050856 (dotnet#12982) This is the pull request automatically created by the OneLocBuild task in the build process to check-in localized files generated based upon translation source files (.lcl files) handed-back from the downstream localization pipeline. If there are issues in translations, visit https://aka.ms/icxLocBug and log bugs for fixes. The OneLocBuild wiki is https://aka.ms/onelocbuild and the localization process in general is documented at https://aka.ms/AllAboutLoc.
> [!NOTE] > This is a codeflow update. It may contain both source code changes from > [the VMR](https://github.com/dotnet/dotnet) > as well as dependency updates. Learn more [here](https://github.com/dotnet/dotnet/tree/main/docs/Codeflow-PRs.md). This pull request brings the following source code changes [marker]: <> (Begin:91fa59f1-1864-46b1-b482-87955691317c) ## From https://github.com/dotnet/dotnet - **Subscription**: [91fa59f1-1864-46b1-b482-87955691317c](https://maestro.dot.net/subscriptions?search=91fa59f1-1864-46b1-b482-87955691317c) - **Build**: [20260105.2](https://dev.azure.com/dnceng/internal/_build/results?buildId=2872392) ([296040](https://maestro.dot.net/channel/8298/github:dotnet:dotnet/build/296040)) - **Date Produced**: January 6, 2026 12:20:56 AM UTC - **Commit**: [fb2e783fa530d337a56ef5c528a2807b7d63e46d](dotnet/dotnet@fb2e783) - **Commit Diff**: [5a69737...fb2e783](dotnet/dotnet@5a69737...fb2e783) - **Branch**: [main](https://github.com/dotnet/dotnet/tree/main) [marker]: <> (End:91fa59f1-1864-46b1-b482-87955691317c) [marker]: <> (Start:Footer:CodeFlow PR) ## Associated changes in source repos - dotnet/arcade@1c09acb...47a8a69 - dotnet/aspnetcore@70d8511...1b7269e - dotnet/deployment-tools@56c3d96...6ebef72 - dotnet/efcore@9a86835...5a68c09 - dotnet/emsdk@f8b8587...36e24b2 - dotnet/fsharp@3686818...6396a18 - dotnet/msbuild@228caa1...9263fe6 - NuGet/NuGet.Client@56f4657...cc8f616 - dotnet/roslyn@a01d6a0...bf35fe5 - dotnet/runtime@8eb90a6...bce6119 - dotnet/sdk@65384c6...ec5f7d9 - dotnet/source-build-reference-packages@d6738f1...a6113e0 - dotnet/sourcelink@c84e22b...d656e7b - dotnet/templating@41ef93a...413680c - microsoft/vstest@154e8ba...bbee830 - dotnet/winforms@1a8c138...01eefd4 - dotnet/wpf@6e486f4...37b9597 <details> <summary>Diff the source with this PR branch</summary> ```bash darc vmr diff --name-only https://github.com/dotnet/dotnet:fb2e783fa530d337a56ef5c528a2807b7d63e46d..https://github.com/dotnet/msbuild:darc-main-2911e53d-2584-4f82-bc52-e50ddaf06f9c ``` </details> [marker]: <> (End:Footer:CodeFlow PR) --------- Co-authored-by: dotnet-maestro[bot] <dotnet-maestro[bot]@users.noreply.github.com>
this pollutes context for agents running tests on cli --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: JanProvaznik <25267098+JanProvaznik@users.noreply.github.com>
…ole encoding (dotnet#12637) Fixes dotnet#11850 ### Context In non-English system especially like Japanese/Chinese, when redirecting the console output which is in UTF8 encoding to the pipe, the output is garbled. There is no way to detect the encoding of the destination. So add the feature flag that allows users to opt out automatic UTF8 console encoding. ### Changes Made Opt out automatic UTF8 console encoding by setting the environment variable `CONSOLE_USE_DEFAULT_ENCODING` to `1`. ### Testing Manually tested. For msbuild.exe <img width="1108" height="306" alt="image" src="https://github.com/user-attachments/assets/9f03eeef-dd72-4df4-9747-5f8a23796800" /> For `dotnet build`, it requires the change in SDK dotnet/sdk#51261. ### Notes --------- Co-authored-by: YuliiaKovalova <95473390+YuliiaKovalova@users.noreply.github.com>
This pull request represents a bit of clean up and should have no product impact. - a342950: I noticed that the `StringSyntaxAttribute` polyfill is declared in the wrong namespace. This attribute is only for IDE tooling support and probably doesn't actually work in non-.NET, since it was declared in the `System` namespace rather than `System.Diagnostics.CodeAnalysis`. I've fixed the polyfill and updated all of the files that had used conditional compilation gymnastics to deal with the incorrect namespace. - df61bee: Small changes to the `CallerArgumentExpressionAttribute` polyfill to match best practices. - 68b8bf2: Update links to the Compile and Content items in the `Microsoft.CodeAnalysis.*` source packages to display the items in separate folders rather than dumping them into the project root. This separates them in the Solution Explorer. <img width="300" height="620" alt="image" src="https://github.com/user-attachments/assets/012c9d54-db85-49bb-8eb5-266b20704741" />
…: Build ID 13052367 (dotnet#12984) This is the pull request automatically created by the OneLocBuild task in the build process to check-in localized files generated based upon translation source files (.lcl files) handed-back from the downstream localization pipeline. If there are issues in translations, visit https://aka.ms/icxLocBug and log bugs for fixes. The OneLocBuild wiki is https://aka.ms/onelocbuild and the localization process in general is documented at https://aka.ms/AllAboutLoc. Co-authored-by: YuliiaKovalova <95473390+YuliiaKovalova@users.noreply.github.com>
…12805) Document the process for enabling binary logging in CI/CD pipelines using environment variables, including supported arguments, argument processing order, and implementation flow. Fixes dotnet#12804
### Context Today it's possible to provide the `-bl` flag multiple times, but the behavior of the engine is that the last-provided flag wins. This is confusing, and in extreme cases can mean that tools that need binlogs and provide them via things like response files can be overridden by a user's invocation. Tools like CodeQL have a harder time adopting binlog usage for C# code analysis because they can't control where the binlog is generated. ### Changes Made Implemented support for writing multiple binlogs when supplied via command line arguments. The implementation intelligently handles two scenarios: 1. **Same Configuration (Optimized)**: When all `-bl` flags have the same configuration (only file paths differ), a single BinaryLogger writes to one location and copies to additional destinations at build completion for consistency and performance. 2. **Different Configurations**: When `-bl` flags have different configurations (e.g., `ProjectImports=None` vs `ProjectImports=Embed`), separate BinaryLogger instances are created to respect each configuration. **Key changes:** - Added `AdditionalFilePaths` property to BinaryLogger with `init` accessor (documented as internal-use only) - Added `BinaryLogger.ProcessParameters()` static method to process multiple parameter sets and return distinct paths with configuration info - Added `ProcessedBinaryLoggerParameters` readonly struct to encapsulate the processing results - Updated `Shutdown()` method to copy binlog to additional paths after stream close - Uses `LogMessage` to log copy destinations before stream close - Uses `Console.Error` to log copy errors (won't fail build on copy failures) - Updated `XMake.ProcessBinaryLogger()` to use the new BinaryLogger.ProcessParameters() method with object initializer syntax for `init` properties - Added error message resource for copy failures - Replaced hardcoded string literals with constants (BinlogFileExtension, LogFileParameterPrefix) - All new methods have XML documentation - Added `DuplicateFilePaths` property to track and report duplicate paths - Added message to inform users when duplicate binary log paths are filtered out - Refactored `TryInterpretPathParameter` methods to eliminate code duplication via shared core method - Optimized `ProcessParameters` to avoid redundant path extraction calls ### Testing - Added unit tests for multiple binlog files with same configuration - Added unit tests for multiple binlog files with different configurations - Added unit test for duplicate path deduplication - Added dedicated unit tests for `ExtractFilePathFromParameters`, `ExtractNonPathParameters`, and `ProcessParameters` - Manual verification confirms all specified binlog files are created with identical content - All tests passing with `init` accessor implementation ### Notes - The `AdditionalFilePaths` property uses `init` accessor to enforce immutability after object initialization, signaling it should only be set during construction - External code should create multiple logger instances instead of using AdditionalFilePaths - When MSBUILDDEBUGENGINE is set, the engine creates a separate BinaryLogger instance which operates independently (functionally correct behavior) - Duplicate paths specified via multiple `-bl` flags are automatically deduplicated - only the first occurrence is kept - Users are now informed when duplicate paths are detected and filtered out - Copy errors are logged to stderr but don't fail the build, ensuring builds succeed even if binlog copies fail <!-- START COPILOT CODING AGENT SUFFIX --> <details> <summary>Original prompt</summary> > > ---- > > *This section details on the original issue you should resolve* > > <issue_title>MSBuild.exe should support writing multiple binlogs if supplied as part of command line arguments</issue_title> > <issue_description>### Summary > > Today it's possible to provide the `-bl` flag multiple times, but the behavior of the engine is that the last-provided flag wins: > > ``` > > dotnet build -bl:1.binlog -bl:2.binlog > Restore complete (0.1s) > info NETSDK1057: You are using a preview version of .NET. See: https://aka.ms/dotnet-support-policy > lib2 net10.0 succeeded (0.1s) → D:\Code\scratch\bleh\lib2\bin\Debug\net10.0\lib2.dll > bleh net10.0 succeeded (0.1s) → bin\Debug\net10.0\bleh.dll > > Build succeeded in 0.5s > > ls *.binlog > > Directory: D:\Code\scratch\bleh\lib > > Mode LastWriteTime Length Name > ---- ------------- ------ ---- > -a--- 10/29/2025 11:14 AM 454756 2.binlog > ``` > This is confusing, and in extreme cases can mean that tools that need binlogs and provide them via things like response files can be overridden by a users invocation. > > ### Background and Motivation > > The inability to write more than one binlog file means that tools like codeql have a harder time adopting binlog usage for C# code analysis, because they can't control where the binlog is generated. > > ### Proposed Feature > > The command-line handling should accept _multiple_ bl flags, resolve them into their distinct binlog filenames, ensure that set is distinct, and then the binary logger should be able to write binary logs to all of those specified files. > > This file writing could be done in two ways (at least) > * multiple independent writers, each writing to a separate file > * one writer, writing the binlog file to a temp location and then atomically copying that file to the various destinations at build-finish > > We should use the second option for consistency. > > > ### Alternative Designs > > _No response_</issue_description> > > ## Comments on the Issue (you are @copilot in this section) > > <comments> > </comments> > </details> - Fixes dotnet#12705 <!-- START COPILOT CODING AGENT TIPS --> --- 💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more [Copilot coding agent tips](https://gh.io/copilot-coding-agent-tips) in the docs. --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: baronfel <573979+baronfel@users.noreply.github.com> Co-authored-by: YuliiaKovalova <95473390+YuliiaKovalova@users.noreply.github.com> Co-authored-by: YuliiaKovalova <ykovalova@microsoft.com>
During perf tests investigations I noticed that VcxprojReader doesn't
use NGENed image of Microsoft.Build.Framework.dll, resulting in ~485.0
extra JIT'd methods.
This PR fixes it by adding VcxprojReader.exe to ngenApplications.
<img width="2438" height="1484"
alt="{8A95DAD1-92AD-41B4-9194-AACE60EC9510}"
src="https://github.com/user-attachments/assets/41b175fe-d538-4c9a-9df6-1e5cd6d0dfe5"
/>
This PR fixes it.
Fixes: dotnet#11510 ## Summary This PR enables out-of-process task hosts to properly resolve host objects by passing HostServices and the target name through the task host communication protocol. Previously, tasks running in out-of-proc task hosts could not access host objects registered via HostServices.RegisterHostObject() because this information was not transmitted to the task host process. ## Changes ### Protocol Versioning & Negotiation - Introduced packet version negotiation during the handshake between parent and child nodes, Child nodes now send their supported PacketVersion during handshake, allowing backward/forward-compatible communication between different MSBuild versions - Incremented PacketVersion from 1 to 2 to support the new fields - HostServices and targetName. Both new fields are conditionally serialized only when NegotiatedPacketVersion >= 2. - Updated OutOfProcTaskAppDomainWrapperBase.ExecuteTask() to accept and use HostServices and targetName Task host now calls _hostServices.GetHostObject(taskFile, targetName, taskName) to resolve the host object before task execution - Fixed HostServices.GetAnyMatchingMonikerNameOrITaskHost() to handle fully-qualified task names by falling back to short name lookup ## Handshake Flow (Before vs After) ### Before <img width="1074" height="467" alt="{931109D5-7DF3-494B-BABB-C6123C778239}" src="https://github.com/user-attachments/assets/254f4204-05fc-4f2e-b99c-7aaecc42c897" /> ### After <img width="321" height="815" alt="{C4F482AC-D77A-4F06-8291-122990B0D488}" src="https://github.com/user-attachments/assets/5c48076a-1f2a-47d7-b8f6-3cc1d2b18f70" /> <img width="485" height="792" alt="{3FA2F583-8097-4D20-A8BE-0F7C41BA4AC1}" src="https://github.com/user-attachments/assets/293688c5-604f-4687-a927-a03e6d2b0ee1" /> --------- Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
This pull request updates the following dependencies [marker]: <> (Begin:8a4332aa-2543-4c51-b941-e73f31e22328) ## From https://github.com/dotnet/roslyn - **Subscription**: [8a4332aa-2543-4c51-b941-e73f31e22328](https://maestro.dot.net/subscriptions?search=8a4332aa-2543-4c51-b941-e73f31e22328) - **Build**: [20260110.1](https://dev.azure.com/dnceng/internal/_build/results?buildId=2876062) ([296778](https://maestro.dot.net/channel/548/github:dotnet:roslyn/build/296778)) - **Date Produced**: January 10, 2026 10:10:56 AM UTC - **Commit**: [19f995da648f0afdaffe499200e9c50dc0568eb2](dotnet/roslyn@19f995d) - **Branch**: [main](https://github.com/dotnet/roslyn/tree/main) [DependencyUpdate]: <> (Begin) - **Dependency Updates**: - From [5.3.0-2.26051.1 to 5.4.0-2.26060.1][1] - Microsoft.Net.Compilers.Toolset [1]: dotnet/roslyn@df7b5aa...19f995d [DependencyUpdate]: <> (End) [marker]: <> (End:8a4332aa-2543-4c51-b941-e73f31e22328) Co-authored-by: dotnet-maestro[bot] <dotnet-maestro[bot]@users.noreply.github.com>
This pull request updates the following dependencies [marker]: <> (Begin:369b758c-dad8-4fea-810a-64fb6b0308e9) ## From https://github.com/dotnet/arcade - **Subscription**: [369b758c-dad8-4fea-810a-64fb6b0308e9](https://maestro.dot.net/subscriptions?search=369b758c-dad8-4fea-810a-64fb6b0308e9) - **Build**: [20260107.1](https://dev.azure.com/dnceng/internal/_build/results?buildId=2873951) ([296298](https://maestro.dot.net/channel/8394/github:dotnet:arcade/build/296298)) - **Date Produced**: January 7, 2026 6:50:40 PM UTC - **Commit**: [13323fc374efc77953ec0ac9a0927da69f14a584](dotnet/arcade@13323fc) - **Branch**: [release/10.0](https://github.com/dotnet/arcade/tree/release/10.0) [DependencyUpdate]: <> (Begin) - **Dependency Updates**: - From [10.0.0-beta.25626.5 to 10.0.0-beta.26057.1][1] - Microsoft.DotNet.Arcade.Sdk - Microsoft.DotNet.XUnitExtensions [1]: dotnet/arcade@d8dca0b...13323fc [DependencyUpdate]: <> (End) [marker]: <> (End:369b758c-dad8-4fea-810a-64fb6b0308e9) Co-authored-by: dotnet-maestro[bot] <dotnet-maestro[bot]@users.noreply.github.com>
…: Build ID 13078382 (dotnet#13003) This is the pull request automatically created by the OneLocBuild task in the build process to check-in localized files generated based upon translation source files (.lcl files) handed-back from the downstream localization pipeline. If there are issues in translations, visit https://aka.ms/icxLocBug and log bugs for fixes. The OneLocBuild wiki is https://aka.ms/onelocbuild and the localization process in general is documented at https://aka.ms/AllAboutLoc.
[main] Source code updates from dotnet/dotnet
…: Build ID 13079827 (dotnet#13010) This is the pull request automatically created by the OneLocBuild task in the build process to check-in localized files generated based upon translation source files (.lcl files) handed-back from the downstream localization pipeline. If there are issues in translations, visit https://aka.ms/icxLocBug and log bugs for fixes. The OneLocBuild wiki is https://aka.ms/onelocbuild and the localization process in general is documented at https://aka.ms/AllAboutLoc.
Work item (Internal use): ### Summary Updates MSBuild version branding from 18.3 to 18.4 following the pattern established in dotnet#12786. **Changes:** - `eng/Versions.props`: Bump `VersionPrefix` from `18.3.0` to `18.4.0` - `azure-pipelines/vs-insertion.yml`: Add `rel/d18.4` target branch and `vs18.4` branch mapping - `.config/git-merge-flow-config.jsonc`: Configure merge flow chain as vs18.0 → vs18.3 → vs18.4 → main **Note:** Creating the `vs18.3` servicing branch requires write permissions and must be done separately. ### Customer Impact None. Branding update only affects internal version strings and CI/CD pipeline configuration for VS insertions and branch merge flows. ### Regression? No. Configuration-only changes to version strings, build pipeline mappings, and merge flow automation. ### Testing - Repository build successful - MSBuild version reports `18.4.0-dev` - Sample project builds without errors - JSONC syntax validation passed - Code review and security scans passed ### Risk Low. Minimal surface area—version string, pipeline configuration, and merge flow updates following established pattern from previous version bumps. <!-- START COPILOT ORIGINAL PROMPT --> <details> <summary>Original prompt</summary> > > ---- > > *This section details on the original issue you should resolve* > > <issue_title>Snap for vs18.3 and update branding to vs18.4</issue_title> > <issue_description>- [ ] Mimic what was done in dotnet#12786 but for vs18.4 instead of vs18.3 > - [ ] Create a vs18.3 branch with https://github.com/dotnet/msbuild/tree/fb775842a00d534aaf25466ff76e0d8fe86d2e7d as the HEAD SHA</issue_description> > > ## Comments on the Issue (you are @copilot in this section) > > <comments> > </comments> > </details> <!-- START COPILOT CODING AGENT SUFFIX --> - Fixes dotnet#13004 <!-- START COPILOT CODING AGENT TIPS --> --- 💬 We'd love your input! Share your thoughts on Copilot coding agent in our [2 minute survey](https://gh.io/copilot-coding-agent-survey). --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: ViktorHofer <7412651+ViktorHofer@users.noreply.github.com> Co-authored-by: Viktor Hofer <viktor.hofer@microsoft.com>
> [!NOTE] > This is a codeflow update. It may contain both source code changes from > [the VMR](https://github.com/dotnet/dotnet) > as well as dependency updates. Learn more [here](https://github.com/dotnet/dotnet/tree/main/docs/Codeflow-PRs.md). This pull request brings the following source code changes [marker]: <> (Begin:91fa59f1-1864-46b1-b482-87955691317c) ## From https://github.com/dotnet/dotnet - **Subscription**: [91fa59f1-1864-46b1-b482-87955691317c](https://maestro.dot.net/subscriptions?search=91fa59f1-1864-46b1-b482-87955691317c) - **Build**: [20260112.1](https://dev.azure.com/dnceng/internal/_build/results?buildId=2876967) ([296906](https://maestro.dot.net/channel/8298/github:dotnet:dotnet/build/296906)) - **Date Produced**: January 12, 2026 3:49:30 PM UTC - **Commit**: [7b9ad20ba1d45df5a99fdd9dedbf3bfe6a6fc24f](dotnet/dotnet@7b9ad20) - **Commit Diff**: [896160e...7b9ad20](dotnet/dotnet@896160e...7b9ad20) - **Branch**: [main](https://github.com/dotnet/dotnet/tree/main) [marker]: <> (End:91fa59f1-1864-46b1-b482-87955691317c) [marker]: <> (Start:Footer:CodeFlow PR) ## Associated changes in source repos - dotnet/aspnetcore@4718204...30d4d50 - dotnet/deployment-tools@6ebef72...c3dd160 - dotnet/efcore@5a68c09...347ab47 - dotnet/fsharp@95d5971...8413083 - dotnet/msbuild@fb77584...2392c79 - dotnet/roslyn@bf35fe5...e97b493 - dotnet/runtime@bce6119...891c183 - dotnet/source-build-reference-packages@cdd1ce5...70e51c1 <details> <summary>Diff the source with this PR branch</summary> ```bash darc vmr diff --name-only https://github.com/dotnet/dotnet:7b9ad20ba1d45df5a99fdd9dedbf3bfe6a6fc24f..https://github.com/dotnet/msbuild:darc-main-82150f35-e08a-412d-9913-0ca994390d47 ``` </details> [marker]: <> (End:Footer:CodeFlow PR) --------- Co-authored-by: dotnet-maestro[bot] <dotnet-maestro[bot]@users.noreply.github.com>
[Automated] Update the MicrosoftBuildVersion defaultValue in the template.json. Co-authored-by: github-actions <github-actions@github.com>
## Summary After this change the opt prof publishing stopped working and it causes internal pipeline failures dotnet#12931 ## Fix return buildNumber: 'ProfilingInputs/DevDiv/$(Build.Repository.Name)/$(Build.SourceBranchName)/$(Build.BuildNumber)'
…t#13036) ### Summary Fixes the MSB1025 ArgumentNullException error that occurs when using the `-dfl` (distributed file logger) flag with MSBuild 18. The issue was introduced in PR dotnet#12095 where distributed logger central loggers were passed to ProjectCollection without filtering out null values. ### Customer Impact Users running `msbuild -dfl` on MSBuild 18/VS 2026 encounter a blocking error: ``` MSBUILD : error MSB1025: An internal failure occurred while running MSBuild. System.ArgumentNullException: Value cannot be null. (Parameter 'logger') ``` This prevents builds from running when using the distributed file logger, which is commonly used for multi-node build logging. The `-dfl` flag worked correctly in MSBuild 17 and earlier versions. **Root Cause**: When using `-dfl`, the DistributedLoggerRecord intentionally has a null CentralLogger (as documented in XMake.cs line 4298-4299). PR dotnet#12095 introduced code that includes these central loggers in the evaluationLoggers array without filtering nulls, causing ProjectCollection.RegisterLoggerInternal() to throw ArgumentNullException. ### Regression? - **Yes** - Regression introduced in MSBuild 18 by PR dotnet#12095 - **Last working version**: MSBuild 17 ### Testing **Code Changes:** 1. **XMake.cs (line 1396)**: Added `.Where(l => l is not null)` to filter out null central loggers from the evaluationLoggers array 2. **XMake_Tests.cs**: Added regression test `TestNullCentralLoggerInDistributedLoggerRecord` to verify DistributedLoggerRecords with null CentralLogger don't cause exceptions **Verification:** - ✅ New unit test `TestNullCentralLoggerInDistributedLoggerRecord` passes - ✅ Build succeeded with no warnings or errors - ✅ Manual testing: `msbuild simple.proj -dfl -t:Build` now works correctly and creates distributed log file - ✅ Code review found no issues - ✅ No security vulnerabilities detected ### Risk **Low** - This is a minimal, surgical fix that: - Only filters out null loggers, which are intentionally null for distributed file loggers - Does not change behavior for non-null loggers - Restores MSBuild 17 functionality - Includes regression test to prevent future breakage <!-- START COPILOT ORIGINAL PROMPT --> <details> <summary>Original prompt</summary> ---- *This section details on the original issue you should resolve* <issue_title>MsBuild 18/VS 2026 MSB1025 error when using DistributedFileLogger - The 'logger' parameter cannot be null.</issue_title> <issue_description>### Issue Description When running `msbuild -dfl` i receive such error `MSBUILD : error MSB1025: podczas uruchamiania programu MSBuild wystąpił błąd wewnętrzny. System.ArgumentNullException: Parametr „logger” nie może być zerowy. w Microsoft.Build.Shared.ErrorUtilities.ThrowArgumentNull(String parameterName, String resourceName) w Microsoft.Build.Evaluation.ProjectCollection.RegisterLoggerInternal(ILogger logger) w Microsoft.Build.Evaluation.ProjectCollection.RegisterLoggers(IEnumerable`1 loggers) w Microsoft.Build.Evaluation.ProjectCollection..ctor(IDictionary`2 globalProperties, IEnumerable`1 loggers, IEnumerable`1 remoteLoggers, ToolsetDefinitionLocations toolsetDefinitionLocations, Int32 maxNodeCount, Boolean onlyLogCriticalEvents, Boolean loadProjectsReadOnly, Boolean useAsynchronousLogging, Boolean reuseProjectRootElementCache, Boolean enableTargetOutputLogging) w Microsoft.Build.CommandLine.MSBuildApp.BuildProject(String projectFile, String[] targets, String toolsVersion, Dictionary`2 globalProperties, Dictionary`2 restoreProperties, ILogger[] loggers, LoggerVerbosity verbosity, DistributedLoggerRecord[] distributedLoggerRecords, Boolean needToValidateProject, String schemaFile, Int32 cpuCount, Boolean multiThreaded, Boolean enableNodeReuse, TextWriter preprocessWriter, TextWriter targetsWriter, Boolean detailedSummary, ISet`1 warningsAsErrors, ISet`1 warningsNotAsErrors, ISet`1 warningsAsMessages, Boolean enableRestore, ProfilerLogger profilerLogger, Boolean enableProfiler, Boolean interactive, ProjectIsolationMode isolateProjects, GraphBuildOptions graphBuildOptions, Boolean lowPriority, Boolean question, Boolean isTaskAndTargetItemLoggingRequired, Boolean isBuildCheckEnabled, String[] inputResultsCaches, String outputResultsCache, Boolean saveProjectResult, BuildResult& result, Boolean reportFileAccesses, String commandLine) w Microsoft.Build.CommandLine.MSBuildApp.Execute(String commandLine)` ### Steps to Reproduce to reproduce i create simple .net framework console solution and i run `msbuild -dfl` in solution directory ### Expected Behavior Solution should build as in previous version of msbuild (17) ### Actual Behavior Blocking error `MSBUILD : error MSB1025: podczas uruchamiania programu MSBuild wystąpił błąd wewnętrzny. System.ArgumentNullException: Parametr „logger” nie może być zerowy.` ### Analysis I tried to find any information in documentation about breaking changes in DistributedFileLogger but with no success. Trying different fileLoggerParameters did not help Switching to fileLogger works as expected ### Versions & Configurations Wersja programu MSBuild 18.0.5+e22287bf1 dla .NET Framework 18.0.5.56406 ran from C:\Program Files\Microsoft Visual Studio\18\Professional\MSBuild\Current\Bin\amd64\MSBuild.rsp and C:\Program Files (x86)\Microsoft Visual Studio\18\BuildTools\MSBuild\Current\Bin\amd64\MSBuild.rsp Windows 11 </issue_description> <agent_instructions>Yes, this bug is very likely caused by the change in PR dotnet#12095. Here's the problematic code introduced in src/MSBuild/XMake.cs: csharpILogger[] evaluationLoggers = [ // all of the loggers that are single-node only .. loggers, // all of the central loggers for multi-node systems. These need to be resilient to multiple calls // to Initialize .. distributedLoggerRecords.Select(d => d.CentralLogger) ]; projectCollection = new ProjectCollection( globalProperties, evaluationLoggers, // <-- now includes distributed logger central loggers ... The problem: When you use -dfl (distributed file logger), the DistributedLoggerRecord.CentralLogger can be null. The code now blindly passes all CentralLogger values into the ProjectCollection constructor without filtering out nulls. When ProjectCollection.RegisterLoggers() iterates over these loggers and calls RegisterLoggerInternal(), it hits: csharpprivate void RegisterLoggerInternal(ILogger logger) { ErrorUtilities.VerifyThrowArgumentNull(logger); // <-- throws here when logger is null ... } The fix should filter out null loggers: csharpILogger[] evaluationLoggers = [ .. loggers, .. distributedLoggerRecords .Select(d => d.CentralLogger) .Where(l => l != null) // <-- add this filter ];</agent_instructions> ## Comments on the Issue (you are @copilot in this section) <comments> <comment_new><author>@YuliiaKovalova</author><body> Hi @kkapuscinski , Thank you for reporting the issue! It's likely to connected to dotnet#12095 change. We are working on the fix. cc: @baronfel </body></comment_new> </comments> </details> <!-- START COPILOT CODING AGENT SUFFIX --> - Fixes dotnet#13032 <!-- START COPILOT CODING AGENT TIPS --> --- ✨ Let Copilot coding agent [set things up for you](https://github.com/dotnet/msbuild/issues/new?title=✨+Set+up+Copilot+instructions&body=Configure%20instructions%20for%20this%20repository%20as%20documented%20in%20%5BBest%20practices%20for%20Copilot%20coding%20agent%20in%20your%20repository%5D%28https://gh.io/copilot-coding-agent-tips%29%2E%0A%0A%3COnboard%20this%20repo%3E&assignees=copilot) — coding agent works faster and does higher quality work when set up for your repo. --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: baronfel <573979+baronfel@users.noreply.github.com>
…sible to dotnet (attempt 2) (dotnet#12836) Fixes dotnet#839 ### Context In some cases dotnet needs to process MSBuild command line switches including response files (.rsp). ### Changes Made `FEATURE_GET_COMMANDLINE` workaround is no longer needed and it was removed. Parsing methods are now using `IEnumerable<string>` instead of `string`. Parsing logic was extracted from `XMake` to `CommandLineParser` class. ### Testing All existing tests are passing. VMR: https://dev.azure.com/dnceng/internal/_build/results?buildId=2879901&view=results ### Notes `MSBuildClient` shouldn't be used outside MSBuild. `OutOfProcServerNode.BuildCallback` delegate shouldn't be used anywhere. This delegate (and whole type) are public just because we are not able to expose internal types with MSBuild project due to shared sources in both projects. We had to use `Experimental` namespace instead. ## How to review All commits except the last one was a preparation - removing `FEATURE_GET_COMMANDLINE` constant and migration to vector of strings in our implementations. Last commit extracts the parsing logic to `CommandLineParser` class. --------- Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
### Context `TaskEnvironment.GetAbsolutePath` can throw exceptions during multi‑process execution. This issue can be avoided by using `Microsoft.IO.Path.Combine` in .NET Framework MSBuild and `System.IO.Path.Combine` in .NET Core MSBuild in the underlying implementations. ### Changes Made Start using `Path.Combine` for all `AsbolutePath` creations. ### Testing Added a unit test for this case.
### Context Test `TestTerminalLoggerTogetherWithOtherLoggers` fails intermittently in CI. The test executes MSBuild twice - once with terminal logger, once without - then compares binary logs to verify identical behavior. The test had two sources of flakiness: parallel builds causing non-deterministic event ordering, and a fragile assertion comparing all internal events. ### Changes Made - Removed `/m` flag from both MSBuild invocations to make builds deterministic - Removed `AllBuildEvents.Count` assertion that was checking internal implementation details - Test now runs sequentially and validates only meaningful build behavior (errors, warnings, items, properties) ### Testing - Built repository successfully - Test passed consistently across 10+ consecutive runs - Verified that all meaningful assertions continue to validate correct terminal logger behavior ### Notes The fix addresses both root causes of flakiness. The `AllBuildEvents.Count` comparison was too strict - internal events (like assembly loading, telemetry, logger initialization) can legitimately vary between runs based on environment and logger configuration without indicating a problem. The test now focuses on verifying that terminal logger doesn't affect build outcomes (errors, warnings, evaluation results) rather than internal event counts. <!-- START COPILOT ORIGINAL PROMPT --> <details> <summary>Original prompt</summary> > > ---- > > *This section details on the original issue you should resolve* > > <issue_title>Test TestTerminalLoggerTogetherWithOtherLoggers is flaky</issue_title> > <issue_description>In the recent runs the test TestTerminalLoggerTogetherWithOtherLoggers fails from time to time. > Fix it or disable if the root cause isn't clear.</issue_description> > > ## Comments on the Issue (you are @copilot in this section) > > <comments> > </comments> > </details> <!-- START COPILOT CODING AGENT SUFFIX --> - Fixes dotnet#13043 <!-- START COPILOT CODING AGENT TIPS --> --- 💬 We'd love your input! Share your thoughts on Copilot coding agent in our [2 minute survey](https://gh.io/copilot-coding-agent-survey). --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: YuliiaKovalova <95473390+YuliiaKovalova@users.noreply.github.com>
### Context This PR marks several simple tasks as multithreadable. ### Changes Made Marks several simple tasks as multithreadable by adding the MSBuildMultiThreadableTask attribute. These tasks are safe for concurrent execution because they: CombineTargetFrameworkInfoProperties, CombineXmlElements - Pure XML/string manipulation ErrorFromResources - only logs messages FindAppConfigFile, FindInvalidProjectReferences, GetCompatiblePlatform - Only reads metadata from ITaskItem objects; no file I/O ### Testing manual
This pull request updates the following dependencies [marker]: <> (Begin:8a4332aa-2543-4c51-b941-e73f31e22328) ## From https://github.com/dotnet/roslyn - **Subscription**: [8a4332aa-2543-4c51-b941-e73f31e22328](https://maestro.dot.net/subscriptions?search=8a4332aa-2543-4c51-b941-e73f31e22328) - **Build**: [20260118.1](https://dev.azure.com/dnceng/internal/_build/results?buildId=2881928) ([297746](https://maestro.dot.net/channel/548/github:dotnet:roslyn/build/297746)) - **Date Produced**: January 18, 2026 1:58:05 PM UTC - **Commit**: [a8d1f35c874c33cd877b4983c0a315b9437e77e3](dotnet/roslyn@a8d1f35) - **Branch**: [main](https://github.com/dotnet/roslyn/tree/main) [DependencyUpdate]: <> (Begin) - **Dependency Updates**: - From [5.4.0-2.26060.1 to 5.4.0-2.26068.1][1] - Microsoft.Net.Compilers.Toolset [1]: dotnet/roslyn@19f995d...a8d1f35 [DependencyUpdate]: <> (End) [marker]: <> (End:8a4332aa-2543-4c51-b941-e73f31e22328) Co-authored-by: dotnet-maestro[bot] <dotnet-maestro[bot]@users.noreply.github.com>
This pull request updates the following dependencies [marker]: <> (Begin:369b758c-dad8-4fea-810a-64fb6b0308e9) ## From https://github.com/dotnet/arcade - **Subscription**: [369b758c-dad8-4fea-810a-64fb6b0308e9](https://maestro.dot.net/subscriptions?search=369b758c-dad8-4fea-810a-64fb6b0308e9) - **Build**: [20260112.3](https://dev.azure.com/dnceng/internal/_build/results?buildId=2877128) ([296898](https://maestro.dot.net/channel/8394/github:dotnet:arcade/build/296898)) - **Date Produced**: January 12, 2026 1:42:08 PM UTC - **Commit**: [9f518f2be968c4c0102c2e3f8c793c5b7f28b731](dotnet/arcade@9f518f2) - **Branch**: [release/10.0](https://github.com/dotnet/arcade/tree/release/10.0) [DependencyUpdate]: <> (Begin) - **Dependency Updates**: - From [10.0.0-beta.26057.1 to 10.0.0-beta.26062.3][1] - Microsoft.DotNet.Arcade.Sdk - Microsoft.DotNet.XUnitExtensions [1]: dotnet/arcade@13323fc...9f518f2 [DependencyUpdate]: <> (End) [marker]: <> (End:369b758c-dad8-4fea-810a-64fb6b0308e9) Co-authored-by: dotnet-maestro[bot] <dotnet-maestro[bot]@users.noreply.github.com>
Fixes dotnet#12804 ### Summary This PR implements the MSBUILD_LOGGING_ARGS environment variable feature as described in the design spec (dotnet#12805). This allows enabling binary logging collection in CI/CD pipelines without modifying project files or build scripts. ### Motivation In CI/CD environments, it's often desirable to enable diagnostic logging (binary logs) for all builds without: Modifying project files or .rsp files on disk Changing build scripts Affecting local developer builds This feature enables centralized build diagnostics configuration through environment variables. ### Testing Add comprehensive UT coverage . connected to dotnet#12706 --------- Co-authored-by: Copilot <198982749+Copilot@users.noreply.github.com> Co-authored-by: baronfel <573979+baronfel@users.noreply.github.com>
I'm seeing this exception:
```
System.TypeInitializationException: The type initializer for 'Microsoft.Build.Eventing.MSBuildEventSource' threw an exception.
---> System.MissingMethodException: Method not found: 'Void System.Diagnostics.Tracing.EventSource..ctor(System.String, System.Guid)'.
at Microsoft.Build.Eventing.MSBuildEventSource..ctor()
at Microsoft.Build.Eventing.MSBuildEventSource..ctor()
at Microsoft.Build.Eventing.MSBuildEventSource..cctor()
--- End of inner exception stack trace ---
at Microsoft.Build.Graph.ProjectGraph.<>c__DisplayClass41_0.<.ctor>g__BeginMeasurement|1()
at Microsoft.Build.Graph.ProjectGraph..ctor(IEnumerable`1 entryPoints, ProjectCollection projectCollection, ProjectInstanceFactoryFunc projectInstanceFactory, Int32 degreeOfParallelism, CancellationToken cancellationToken)
at Microsoft.Build.Graph.ProjectGraph..ctor(IEnumerable`1 entryPoints, ProjectCollection projectCollection, ProjectInstanceFactoryFunc projectInstanceFactory)
```
In ILSpy I see Microsoft.Build.Framework.dll
`18.3.0-preview-26055-101+e64f84d6312cdaf227d26aeabfa4817862404d59`
having:
```cs
private MSBuildEventSource()
: base("Microsoft-Build", new Guid(3561627800u, 33311, 22536, 76, 234, 30, 36, 233, 130, 202, 55))
{
}
```
But in `C:\Program
Files\dotnet\shared\Microsoft.NETCore.App\10.0.1\System.Private.CoreLib.dll`
(loaded in .NET 10) I see:
```cs
internal EventSource(Guid eventSourceGuid, string eventSourceName)
: this(eventSourceGuid, eventSourceName, EventSourceSettings.EtwManifestEventFormat)
{
}
```
It's both internal and the args are backwards...
I believe this was introduced in dotnet#12886.
Which pulls in this change:
dotnet/runtime#121180
That seems to introduce a source generator which calls the internal ctor
of EventSource (and with different order). As that's internal to .NET, I
expect it was not intended to be applied here in MSBuild.
This change simply reverts the change to `MSBuildEventSource`.
Co-authored-by: AR-May <67507805+AR-May@users.noreply.github.com>
…: Build ID 13124182 (dotnet#13053) This is the pull request automatically created by the OneLocBuild task in the build process to check-in localized files generated based upon translation source files (.lcl files) handed-back from the downstream localization pipeline. If there are issues in translations, visit https://aka.ms/icxLocBug and log bugs for fixes. The OneLocBuild wiki is https://aka.ms/onelocbuild and the localization process in general is documented at https://aka.ms/AllAboutLoc.
JanProvaznik
pushed a commit
that referenced
this pull request
Mar 27, 2026
…tInMetadata performance (dotnet#13386) I recommend reviewing this pull request commit-by-commit. # Summary of Changes - Introduce new MSBuild.Benchmarks project for tackling performance investigations. - Add a few benchmarks for various methods on `ItemSpecModifiers`. - Make several performance fixes related to `ItemSpecModifiers` and `BuildInMetadata`. - General clean up. Across the board, most benchmarks are **3×–35× faster** with **allocations eliminated or reduced by 93–100%**. The largest wins are in repeated-access and multi-item scenarios, which are the most representative of real build workloads. The full details are below but here are the highlights. ## Highlights ### 🚀 Speed Improvements (.NET 10.0) | Benchmark | Before | After | Speedup | |---|---|---|---| | `IsItemSpecModifier_AllModifiers` | 151.4 ns | 38.5 ns | **3.9×** | | `GetItemSpecModifier_DefiningProjectDirectory` | 812.2 ns | 72.4 ns | **11.2×** | | `TaskItem_AllDerivableModifiers_Once` | 434.5 ns | 87.4 ns | **5.0×** | | `TaskItem_FilenameAndExtension_Repeated` | 908.5 ns | 173.7 ns | **5.2×** | | `TaskItem_Filename_ManyItems` | 9,651 ns | 1,857 ns | **5.2×** | | `TaskItem_FullPathDerivedModifiers_Repeated` | 2,128 ns | 321.6 ns | **6.6×** | | `TaskItem_DefiningProjectDirectory_Repeated` | 9,121 ns | 970.8 ns | **9.4×** | | `PI_DefiningProjectDirectory_Repeated` | 9,092 ns | 1,021 ns | **8.9×** | | `PI_DefiningProjectFullPath_AllItems_Multi` | 35,245 ns | 9,947 ns | **3.5×** | | `PI_DefiningProjectDir_AllItems_Multi_Repeated` | 878,931 ns | 103,961 ns | **8.5×** | | `PI_FilenameExtension_AllItems` | 22,698 ns | 5,343 ns | **4.2×** | | `PI_FilenameExtension_AllItems_Repeated` | 181,612 ns | 67,028 ns | **2.7×** | ### 🧹 Allocation Reductions (.NET 10.0) | Benchmark | Before | After | Reduction | |---|---|---|---| | `TaskItem_AllDerivableModifiers_Once` | 1,232 B | **0 B** | 100% | | `TaskItem_FilenameAndExtension_Repeated` | 640 B | **0 B** | 100% | | `TaskItem_Filename_ManyItems` | 7,920 B | **0 B** | 100% | | `TaskItem_FullPathDerivedModifiers_Repeated` | 7,120 B | **0 B** | 100% | | `TaskItem_DefiningProjectDirectory_Repeated` | 8,240 B | **0 B** | 100% | | `TaskItem_AllDefiningProjectModifiers_Once` | 912 B | **0 B** | 100% | | `TaskItem_DefiningProjectNameExtension_AllItems` | 8,800 B | **0 B** | 100% | | `GetItemSpecModifier_DefiningProjectDirectory` | 536 B | **0 B** | 100% | | `PI_FilenameExtension_AllItems_Repeated` | 143,840 B | **640 B** | 99.6% | | `PI_DefiningProjectDir_AllItems_Multi_Repeated` | 824,640 B | **640 B** | 99.9% | | `PI_FilenameExtension_AllItems` | 14,384 B | **64 B** | 99.6% | | `PI_DefiningProjectDirectory_Repeated` | 8,304 B | **64 B** | 99.2% | | `PI_AllDerivableModifiers_Once` | 1,296 B | **64 B** | 95.1% | | `PI_AllDefiningProjectModifiers_Once` | 976 B | **64 B** | 93.4% | ### 📊 .NET Framework 4.8.1 | Benchmark | Before | After | Speedup | |---|---|---|---| | `GetItemSpecModifier_DefiningProjectDirectory` | 5,467 ns | 156.8 ns | **34.9×** | | `TaskItem_DefiningProjectDirectory_Repeated` | 58,025 ns | 2,539 ns | **22.9×** | | `PI_DefiningProjectDir_AllItems_Multi_Repeated` | 6,399 μs | 282.3 μs | **22.7×** | | `TaskItem_Filename_ManyItems` | 110,078 ns | 6,916 ns | **15.9×** | | `TaskItem_FullPathDerivedModifiers_Repeated` | 26,619 ns | 2,262 ns | **11.8×** | | `PI_FilenameExtension_AllItems_Repeated` | 2,162 μs | 202.6 μs | **10.7×** | | `TaskItem_AllDerivableModifiers_Once` | 5,322 ns | 507.2 ns | **10.5×** | | `PI_FilenameExtension_AllItems` | 216,406 ns | 20,366 ns | **10.6×** | | `TaskItem_FilenameAndExtension_Repeated` | 10,238 ns | 664.7 ns | **15.4×** | | `PI_AllDerivableModifiers_Once` | 5,525 ns | 688.6 ns | **8.0×** | | `PI_DefiningProjectDirectory_Repeated` | 64,204 ns | 2,796 ns | **23.0×** | | `PI_AllDefiningProjectModifiers_Once` | 9,808 ns | 1,154 ns | **8.5×** | | `TaskItem_AllDefiningProjectModifiers_Once` | 8,636 ns | 965.3 ns | **8.9×** | ## 'Quick-and-Dirty' Telemetry I had Copilot write some "quick-and-dirty" telemetry to track information in `ItemSpecModifiers` and dump it to a file. I built MSBuild with that extra telemetry and then built Roslyn (starting from `Microsoft.VisualStudio.LanguageServices.CSharp.csproj`) using that MSBuild. This gave me a dump with loads of interesting details. For example, `IsItemSpecModifier` was called 901,057 times. <details> <summary><b>Full Quick-and-Dirty Telemetry Dump</b></summary> ``` === ItemSpecModifiers Telemetry (2026-03-12T09:38:41.0365991-07:00) === --- Top-level method calls --- IsItemSpecModifier: 901,057 IsDerivableItemSpecModifier: 144,857 GetItemSpecModifier: 180,890 --- Compute helper calls --- ComputeFullPath: 75,443 ComputeRootDir: 84 ComputeFilename: 57,426 ComputeExtension: 32,071 ComputeRelativeDir: 22 ComputeDirectory: 84 ComputeModifiedTime: 0 ComputeCreatedTime: 0 ComputeAccessedTime: 0 --- Per-modifier breakdown (inside GetItemSpecModifier) --- FullPath: 44,783 RootDir: 41 Filename: 57,426 Extension: 6,462 RelativeDir: 22 Directory: 41 RecursiveDir: 0 Identity: 15,814 ModifiedTime: 0 CreatedTime: 0 AccessedTime: 0 DefiningProjectFullPath: 30,535 DefiningProjectDirectory: 43 DefiningProjectName: 0 DefiningProjectExtension: 25,609 ========================================================== Per-ItemSpec Modifier Hit Matrix ========================================================== Unique item specs seen: 13,809 Item specs hit > 1 time: 13,005 Grand total modifier lookups: 180,890 --- Top 50 hottest item specs (by total modifier calls) --- #1 (1,502 calls): System.Runtime.CompilerServices.InternalsVisibleTo Identity 751 DefiningProjectFullPath 751 #2 (380 calls): D:\Projects\roslyn\artifacts\bin\Microsoft.CodeAnalysis\Debug\netstandard2.0\Microsoft.CodeAnalysis.dll FullPath 17 Filename 280 Extension 40 Identity 21 DefiningProjectFullPath 22 #3 (270 calls): D:\Projects\roslyn\artifacts\bin\Microsoft.CodeAnalysis.Scripting\Debug\netstandard2.0\Microsoft.CodeAnalysis.Scripting.dll FullPath 12 Filename 195 Extension 30 Identity 16 DefiningProjectFullPath 17 #4 (270 calls): D:\Projects\roslyn\artifacts\bin\Microsoft.CodeAnalysis.Workspaces\Debug\netstandard2.0\Microsoft.CodeAnalysis.Workspaces.dll FullPath 12 Filename 195 Extension 30 Identity 16 DefiningProjectFullPath 17 #5 (247 calls): D:\.nuget\packages\system.threading.tasks.extensions\4.6.3\lib\netstandard2.0\System.Threading.Tasks.Extensions.dll FullPath 13 Filename 221 Identity 13 #6 (247 calls): D:\.nuget\packages\system.memory\4.6.3\lib\netstandard2.0\System.Memory.dll FullPath 13 Filename 221 Identity 13 #7 (247 calls): D:\.nuget\packages\system.buffers\4.6.1\lib\netstandard2.0\System.Buffers.dll FullPath 13 Filename 221 Identity 13 #8 (247 calls): D:\.nuget\packages\system.numerics.vectors\4.6.1\lib\netstandard2.0\System.Numerics.Vectors.dll FullPath 13 Filename 221 Identity 13 #9 (247 calls): D:\.nuget\packages\system.text.encoding.codepages\8.0.0\lib\netstandard2.0\System.Text.Encoding.CodePages.dll FullPath 13 Filename 221 Identity 13 #10 (247 calls): D:\.nuget\packages\system.runtime.compilerservices.unsafe\6.1.2\lib\netstandard2.0\System.Runtime.CompilerServices.Unsafe.dll FullPath 13 Filename 221 Identity 13 #11 (245 calls): D:\.nuget\packages\microsoft.dotnet.arcade.sdk\10.0.0-beta.26160.1\tools\Assets\DotNetPackageIcon.png FullPath 48 Filename 40 Extension 70 Identity 2 DefiningProjectFullPath 37 DefiningProjectDirectory 8 DefiningProjectExtension 40 #12 (245 calls): D:\Projects\roslyn\eng\targets\..\..\src\NuGet\ThirdPartyNotices.rtf FullPath 48 Filename 40 Extension 70 Identity 2 DefiningProjectFullPath 37 DefiningProjectDirectory 8 DefiningProjectExtension 40 #13 (240 calls): D:\.nuget\packages\system.collections.immutable\10.0.1\lib\netstandard2.0\System.Collections.Immutable.dll FullPath 12 Filename 216 Identity 12 #14 (240 calls): D:\.nuget\packages\system.reflection.metadata\10.0.1\lib\netstandard2.0\System.Reflection.Metadata.dll FullPath 12 Filename 216 Identity 12 #15 (234 calls): D:\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.Web.dll FullPath 13 Filename 208 Identity 13 #16 (234 calls): D:\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.Threading.ThreadPool.dll FullPath 13 Filename 208 Identity 13 #17 (234 calls): D:\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.IO.FileSystem.Watcher.dll FullPath 13 Filename 208 Identity 13 #18 (234 calls): D:\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.Resources.ResourceManager.dll FullPath 13 Filename 208 Identity 13 #19 (234 calls): D:\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.IO.dll FullPath 13 Filename 208 Identity 13 dotnet#20 (234 calls): D:\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.IO.Pipes.dll FullPath 13 Filename 208 Identity 13 dotnet#21 (234 calls): D:\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.IO.MemoryMappedFiles.dll FullPath 13 Filename 208 Identity 13 dotnet#22 (234 calls): D:\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.ValueTuple.dll FullPath 13 Filename 208 Identity 13 dotnet#23 (234 calls): D:\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.Console.dll FullPath 13 Filename 208 Identity 13 dotnet#24 (234 calls): D:\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.Linq.Parallel.dll FullPath 13 Filename 208 Identity 13 dotnet#25 (234 calls): D:\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.Security.Claims.dll FullPath 13 Filename 208 Identity 13 dotnet#26 (234 calls): D:\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.IO.UnmanagedMemoryStream.dll FullPath 13 Filename 208 Identity 13 dotnet#27 (234 calls): D:\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.Threading.Overlapped.dll FullPath 13 Filename 208 Identity 13 dotnet#28 (234 calls): D:\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.Drawing.Primitives.dll FullPath 13 Filename 208 Identity 13 dotnet#29 (234 calls): D:\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.Net.WebSockets.dll FullPath 13 Filename 208 Identity 13 dotnet#30 (234 calls): D:\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.Security.Cryptography.Algorithms.dll FullPath 13 Filename 208 Identity 13 dotnet#31 (234 calls): D:\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.IO.FileSystem.DriveInfo.dll FullPath 13 Filename 208 Identity 13 dotnet#32 (234 calls): D:\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.Diagnostics.Tracing.dll FullPath 13 Filename 208 Identity 13 dotnet#33 (234 calls): D:\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.Linq.Expressions.dll FullPath 13 Filename 208 Identity 13 dotnet#34 (234 calls): D:\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.Security.Principal.dll FullPath 13 Filename 208 Identity 13 dotnet#35 (234 calls): D:\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.Globalization.Calendars.dll FullPath 13 Filename 208 Identity 13 dotnet#36 (234 calls): D:\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.Security.Cryptography.Primitives.dll FullPath 13 Filename 208 Identity 13 dotnet#37 (234 calls): D:\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.ObjectModel.dll FullPath 13 Filename 208 Identity 13 dotnet#38 (234 calls): D:\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.Xml.XDocument.dll FullPath 13 Filename 208 Identity 13 dotnet#39 (234 calls): D:\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.Collections.dll FullPath 13 Filename 208 Identity 13 dotnet#40 (234 calls): D:\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.ComponentModel.TypeConverter.dll FullPath 13 Filename 208 Identity 13 dotnet#41 (234 calls): D:\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.Runtime.InteropServices.dll FullPath 13 Filename 208 Identity 13 dotnet#42 (234 calls): D:\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.Collections.Concurrent.dll FullPath 13 Filename 208 Identity 13 dotnet#43 (234 calls): D:\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.Collections.Specialized.dll FullPath 13 Filename 208 Identity 13 dotnet#44 (234 calls): D:\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.Dynamic.Runtime.dll FullPath 13 Filename 208 Identity 13 dotnet#45 (234 calls): D:\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.Net.Requests.dll FullPath 13 Filename 208 Identity 13 dotnet#46 (234 calls): D:\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.Security.Cryptography.X509Certificates.dll FullPath 13 Filename 208 Identity 13 dotnet#47 (234 calls): D:\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.Net.dll FullPath 13 Filename 208 Identity 13 dotnet#48 (234 calls): D:\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.IO.Compression.ZipFile.dll FullPath 13 Filename 208 Identity 13 dotnet#49 (234 calls): D:\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.Xml.XmlSerializer.dll FullPath 13 Filename 208 Identity 13 dotnet#50 (234 calls): D:\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.Runtime.CompilerServices.VisualC.dll FullPath 13 Filename 208 Identity 13 --- Repetition histogram (total modifier calls per item spec → count of item specs) --- 1,502 calls → 1 item specs 380 calls → 1 item specs 270 calls → 2 item specs 247 calls → 6 item specs 245 calls → 2 item specs 240 calls → 2 item specs 234 calls → 112 item specs 226 calls → 1 item specs 224 calls → 2 item specs 204 calls → 4 item specs 196 calls → 1 item specs 164 calls → 13 item specs 160 calls → 2 item specs 151 calls → 3 item specs 144 calls → 53 item specs 140 calls → 6 item specs 138 calls → 4 item specs 134 calls → 1 item specs 132 calls → 7 item specs 122 calls → 2 item specs 117 calls → 14 item specs 113 calls → 124 item specs 111 calls → 1 item specs 110 calls → 2 item specs 109 calls → 1 item specs 101 calls → 3 item specs 100 calls → 2 item specs 99 calls → 1 item specs 98 calls → 1 item specs 91 calls → 5 item specs 89 calls → 59 item specs 86 calls → 2 item specs 84 calls → 1 item specs 82 calls → 2 item specs 80 calls → 7 item specs 78 calls → 1 item specs 76 calls → 2 item specs 75 calls → 1 item specs 74 calls → 5 item specs 73 calls → 3 item specs 72 calls → 2 item specs 70 calls → 1 item specs 66 calls → 5 item specs 65 calls → 5 item specs 60 calls → 10 item specs 58 calls → 8 item specs 57 calls → 1 item specs 56 calls → 1 item specs 54 calls → 6 item specs 52 calls → 3 item specs 51 calls → 8 item specs 50 calls → 1 item specs 49 calls → 2 item specs 48 calls → 3 item specs 47 calls → 1 item specs 46 calls → 1 item specs 45 calls → 13 item specs 44 calls → 20 item specs 41 calls → 2 item specs 40 calls → 8 item specs 39 calls → 1 item specs 37 calls → 4 item specs 36 calls → 51 item specs 35 calls → 5 item specs 34 calls → 1 item specs 33 calls → 1 item specs 32 calls → 2 item specs 30 calls → 4 item specs 29 calls → 11 item specs 28 calls → 20 item specs 27 calls → 11 item specs 26 calls → 16 item specs 24 calls → 30 item specs 23 calls → 3 item specs 22 calls → 153 item specs 21 calls → 1 item specs 20 calls → 26 item specs 19 calls → 1 item specs 18 calls → 109 item specs 16 calls → 30 item specs 15 calls → 35 item specs 14 calls → 383 item specs 13 calls → 166 item specs 12 calls → 1,051 item specs 11 calls → 1 item specs 10 calls → 70 item specs 9 calls → 43 item specs 8 calls → 7,012 item specs 7 calls → 50 item specs 6 calls → 910 item specs 5 calls → 1,420 item specs 4 calls → 449 item specs 3 calls → 32 item specs 2 calls → 340 item specs 1 calls → 804 item specs ``` </details> ## Initial Benchmark Results ### .NET 10.0 | Method | Mean | Error | StdDev | Gen0 | Allocated | |--------------------------------------------- |--------------:|------------:|------------:|-------:|----------:| | IsItemSpecModifier_AllModifiers | 151.425 ns | 0.1309 ns | 0.1161 ns | - | - | | IsDerivableItemSpecModifier_RecursiveDir | 2.522 ns | 0.0028 ns | 0.0025 ns | - | - | | GetItemSpecModifier_FullPath | 267.552 ns | 0.3441 ns | 0.3050 ns | - | - | | GetItemSpecModifier_Directory | 359.023 ns | 0.7603 ns | 0.6740 ns | 0.0224 | 376 B | | GetItemSpecModifier_ModifiedTime | 28,544.061 ns | 237.0185 ns | 221.7073 ns | - | 176 B | | GetItemSpecModifier_DefiningProjectDirectory | 812.229 ns | 3.3636 ns | 2.9817 ns | 0.0315 | 536 B | | TaskItem_AllDerivableModifiers_Once | 434.5 ns | 4.36 ns | 4.08 ns | 0.0734 | 1232 B | | TaskItem_FilenameAndExtension_Repeated | 908.5 ns | 1.13 ns | 1.00 ns | 0.0381 | 640 B | | TaskItem_Filename_ManyItems | 9,651.3 ns | 29.02 ns | 25.72 ns | 0.4730 | 7920 B | | TaskItem_FullPathDerivedModifiers_Repeated | 2,127.6 ns | 7.45 ns | 6.60 ns | 0.4234 | 7120 B | | ProjectItemInstance_AllDerivableModifiers_Once | 513.4 ns | 2.93 ns | 2.74 ns | 0.0772 | 1296 B | | ProjectItemInstance_FilenameExtension_AllItems | 22,697.6 ns | 68.62 ns | 64.19 ns | 0.8545 | 14384 B | | ProjectItemInstance_FilenameExtension_AllItems_Repeated | 181,612.2 ns | 1,125.69 ns | 940.00 ns | 8.5449 | 143840 B | | ProjectItemInstance_AllDefiningProjectModifiers_Once | 1.559 μs | 0.0047 μs | 0.0040 μs | 0.0572 | 976 B | | ProjectItemInstance_DefiningProjectDirectory_Repeated | 9.092 μs | 0.0654 μs | 0.0580 μs | 0.4883 | 8304 B | | ProjectItemInstance_DefiningProjectNameExtension_AllItems_SingleProject | 12.515 μs | 0.0297 μs | 0.0263 μs | 0.5188 | 8864 B | | ProjectItemInstance_DefiningProjectFullPath_AllItems_MultiProject | 35.245 μs | 0.0405 μs | 0.0379 μs | - | 64 B | | ProjectItemInstance_DefiningProjectDirectory_AllItems_MultiProject_Repeated | 878.931 μs | 3.1495 μs | 2.7919 μs | 48.8281 | 824640 B | | TaskItem_AllDefiningProjectModifiers_Once | 1.430 μs | 0.0027 μs | 0.0023 μs | 0.0534 | 912 B | | TaskItem_DefiningProjectNameExtension_AllItems | 11.628 μs | 0.0289 μs | 0.0241 μs | 0.5188 | 8800 B | | TaskItem_DefiningProjectDirectory_Repeated | 9.121 μs | 0.0192 μs | 0.0170 μs | 0.4883 | 8240 B | ### .NET Framework 4.8.1 | Method | Mean | Error | StdDev | Gen0 | Allocated | |--------------------------------------------- |-------------:|-----------:|----------:|-------:|----------:| | IsItemSpecModifier_AllModifiers | 227.45 ns | 0.297 ns | 0.264 ns | - | - | | IsDerivableItemSpecModifier_RecursiveDir | 10.49 ns | 0.019 ns | 0.018 ns | - | - | | GetItemSpecModifier_FullPath | 1,267.45 ns | 0.844 ns | 0.705 ns | - | - | | GetItemSpecModifier_Directory | 2,433.43 ns | 7.400 ns | 6.560 ns | 0.0954 | 517 B | | GetItemSpecModifier_ModifiedTime | 41,881.06 ns | 111.954 ns | 93.487 ns | 0.1221 | 878 B | | GetItemSpecModifier_DefiningProjectDirectory | 5,467.24 ns | 8.295 ns | 6.926 ns | 0.1602 | 857 B | | TaskItem_AllDerivableModifiers_Once | 5.322 μs | 0.0354 μs | 0.0331 μs | 0.3662 | 1923 B | | TaskItem_FilenameAndExtension_Repeated | 10.238 μs | 0.0108 μs | 0.0101 μs | 0.1373 | 761 B | | TaskItem_Filename_ManyItems | 110.078 μs | 0.1367 μs | 0.1212 μs | 2.3193 | 12379 B | | TaskItem_FullPathDerivedModifiers_Repeated | 26.619 μs | 0.1695 μs | 0.1585 μs | 2.1973 | 11578 B | | ProjectItemInstance_AllDerivableModifiers_Once | 5.525 μs | 0.0311 μs | 0.0276 μs | 0.3662 | 1959 B | | ProjectItemInstance_FilenameExtension_AllItems | 216.406 μs | 0.2767 μs | 0.2160 μs | 2.9297 | 16422 B | | ProjectItemInstance_FilenameExtension_AllItems_Repeated | 2,161.623 μs | 10.4073 μs | 9.2258 μs | 31.2500 | 164225 B | | ProjectItemInstance_AllDefiningProjectModifiers_Once | 9.808 μs | 0.0177 μs | 0.0165 μs | 0.2594 | 1418 B | | ProjectItemInstance_DefiningProjectDirectory_Repeated | 64.204 μs | 0.3983 μs | 0.3726 μs | 2.3193 | 12616 B | | ProjectItemInstance_DefiningProjectNameExtension_AllItems_SingleProject | 131.504 μs | 0.3383 μs | 0.3165 μs | 2.1973 | 12456 B | | ProjectItemInstance_DefiningProjectFullPath_AllItems_MultiProject | 173.171 μs | 0.7242 μs | 0.5654 μs | - | 38 B | | ProjectItemInstance_DefiningProjectDirectory_AllItems_MultiProject_Repeated | 6,399.063 μs | 71.6927 μs | 67.0614 μs | 234.3750 | 1242225 B | | TaskItem_AllDefiningProjectModifiers_Once | 8.636 μs | 0.0177 μs | 0.0147 μs | 0.2594 | 1382 B | | TaskItem_DefiningProjectNameExtension_AllItems | 126.982 μs | 0.2250 μs | 0.2104 μs | 2.1973 | 12420 B | | TaskItem_DefiningProjectDirectory_Repeated | 58.025 μs | 0.1388 μs | 0.1299 μs | 2.3804 | 12579 B | ## Final Benchmark Results ### .NET 10.0 | Method | Mean | Error | StdDev | Gen0 | Allocated | |--------------------------------------------- |--------------:|------------:|------------:|-------:|----------:| | IsItemSpecModifier_AllModifiers | 38.4923 ns | 0.5501 ns | 0.5145 ns | - | - | | IsDerivableItemSpecModifier_RecursiveDir | 0.0000 ns | 0.0000 ns | 0.0000 ns | - | - | | GetItemSpecModifier_FullPath | 260.1019 ns | 0.3623 ns | 0.3212 ns | - | - | | GetItemSpecModifier_Directory | 413.2121 ns | 1.9441 ns | 1.8185 ns | 0.0224 | 376 B | | GetItemSpecModifier_ModifiedTime | 30,272.3116 ns | 408.0450 ns | 381.6855 ns | - | 176 B | | GetItemSpecModifier_DefiningProjectDirectory | 72.3691 ns | 0.0289 ns | 0.0270 ns | - | - | | TaskItem_AllDerivableModifiers_Once | 87.41 ns | 0.226 ns | 0.200 ns | - | - | | TaskItem_FilenameAndExtension_Repeated | 173.68 ns | 1.812 ns | 1.695 ns | - | - | | TaskItem_Filename_ManyItems | 1,856.79 ns | 1.128 ns | 0.942 ns | - | - | | TaskItem_FullPathDerivedModifiers_Repeated | 321.57 ns | 0.301 ns | 0.267 ns | - | - | | ProjectItemInstance_AllDerivableModifiers_Once | 143.78 ns | 0.493 ns | 0.462 ns | 0.0038 | 64 B | | ProjectItemInstance_FilenameExtension_AllItems | 5,343.30 ns | 4.955 ns | 4.138 ns | - | 64 B | | ProjectItemInstance_FilenameExtension_AllItems_Repeated | 67,028.30 ns | 252.985 ns | 224.264 ns | - | 640 B | | ProjectItemInstance_AllDefiningProjectModifiers_Once | 459.4 ns | 0.34 ns | 0.31 ns | 0.0038 | 64 B | | ProjectItemInstance_DefiningProjectDirectory_Repeated | 1,020.5 ns | 0.56 ns | 0.47 ns | 0.0038 | 64 B | | ProjectItemInstance_DefiningProjectNameExtension_AllItems_SingleProject | 20,091.0 ns | 17.96 ns | 16.80 ns | - | 64 B | | ProjectItemInstance_DefiningProjectFullPath_AllItems_MultiProject | 9,946.7 ns | 5.28 ns | 4.68 ns | - | 64 B | | ProjectItemInstance_DefiningProjectDirectory_AllItems_MultiProject_Repeated | 103,960.5 ns | 57.74 ns | 48.21 ns | - | 640 B | | TaskItem_AllDefiningProjectModifiers_Once | 400.5 ns | 0.15 ns | 0.12 ns | - | - | | TaskItem_DefiningProjectNameExtension_AllItems | 19,150.3 ns | 11.55 ns | 10.24 ns | - | - | | TaskItem_DefiningProjectDirectory_Repeated | 970.8 ns | 0.62 ns | 0.55 ns | - | - | ### .NET Framework 4.8.1 | Method | Mean | Error | StdDev | Gen0 | Allocated | |--------------------------------------------- |-------------:|-----------:|----------:|-------:|----------:| | IsItemSpecModifier_AllModifiers | 106.532 ns | 0.4289 ns | 0.4012 ns | - | - | | IsDerivableItemSpecModifier_RecursiveDir | 5.067 ns | 0.0031 ns | 0.0024 ns | - | - | | GetItemSpecModifier_FullPath | 1,331.138 ns | 1.4666 ns | 1.3001 ns | - | - | | GetItemSpecModifier_Directory | 2,471.887 ns | 4.2333 ns | 3.7527 ns | 0.0954 | 517 B | | GetItemSpecModifier_ModifiedTime | 44,773.794 ns | 405.2647 ns | 359.2566 ns | 0.1221 | 878 B | | GetItemSpecModifier_DefiningProjectDirectory | 156.840 ns | 0.2242 ns | 0.1987 ns | - | - | | TaskItem_AllDerivableModifiers_Once | 507.2 ns | 1.19 ns | 1.11 ns | - | - | | TaskItem_FilenameAndExtension_Repeated | 664.7 ns | 0.39 ns | 0.35 ns | - | - | | TaskItem_Filename_ManyItems | 6,916.2 ns | 4.03 ns | 3.77 ns | - | - | | TaskItem_FullPathDerivedModifiers_Repeated | 2,261.6 ns | 3.34 ns | 2.96 ns | - | - | | ProjectItemInstance_AllDerivableModifiers_Once | 688.6 ns | 1.01 ns | 0.94 ns | 0.0067 | 36 B | | ProjectItemInstance_FilenameExtension_AllItems | 20,366.3 ns | 11.28 ns | 10.56 ns | - | 36 B | | ProjectItemInstance_FilenameExtension_AllItems_Repeated | 202,570.4 ns | 271.12 ns | 240.34 ns | - | 362 B | | ProjectItemInstance_AllDefiningProjectModifiers_Once | 1,153.5 ns | 13.83 ns | 12.26 ns | 0.0057 | 36 B | | ProjectItemInstance_DefiningProjectDirectory_Repeated | 2,795.7 ns | 17.33 ns | 16.21 ns | 0.0038 | 36 B | | ProjectItemInstance_DefiningProjectNameExtension_AllItems_SingleProject | 46,236.9 ns | 105.16 ns | 93.22 ns | - | 36 B | | ProjectItemInstance_DefiningProjectFullPath_AllItems_MultiProject | 28,362.1 ns | 34.50 ns | 30.58 ns | - | 36 B | | ProjectItemInstance_DefiningProjectDirectory_AllItems_MultiProject_Repeated | 282,316.9 ns | 1,944.00 ns | 1,818.42 ns | - | 364 B | | TaskItem_AllDefiningProjectModifiers_Once | 965.3 ns | 5.43 ns | 4.53 ns | - | - | | TaskItem_DefiningProjectNameExtension_AllItems | 42,707.8 ns | 179.84 ns | 168.23 ns | - | - | | TaskItem_DefiningProjectDirectory_Repeated | 2,539.1 ns | 9.64 ns | 8.05 ns | - | - |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Context
Chained item functions incorrectly evaluate as non-empty in conditions when the final result is empty. For example:
The first transform matches Test1, but the second filters it out (Foo='Bar' != 'Baz'). The final result is empty, yet the condition fails.
Changes Made
src/Build/Evaluation/Expander.cs
BreakOnNotEmptycheck inTransformmethod to execute after all chained transforms complete, not after each intermediate transformsrc/Build.UnitTests/Evaluation/Expander_Tests.cs
ChainedItemFunctionEmptyResultInConditiontest verifying the fixTesting
Unit test added to validate the specific scenario. Full test suite and manual verification pending.
Notes
The bug only manifested when using
BreakOnNotEmptyoptimization (condition evaluation path), not in normal property expansion.Original prompt
✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.