Skip to content

Conversation

@YuliiaKovalova
Copy link
Member

@YuliiaKovalova YuliiaKovalova commented Jan 9, 2026

Fixes #12804

Summary

This PR implements the MSBUILD_LOGGING_ARGS environment variable feature as described in the design spec (#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 #12706

YuliiaKovalova and others added 7 commits January 9, 2026 11:00
Document the process for enabling binary logging in CI/CD pipelines
using environment variables, including supported arguments, argument
processing order, and implementation flow.

Fixes  #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 #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] <[email protected]>
Co-authored-by: baronfel <[email protected]>
Co-authored-by: YuliiaKovalova <[email protected]>
Co-authored-by: YuliiaKovalova <[email protected]>
Document the process for enabling binary logging in CI/CD pipelines
using environment variables, including supported arguments, argument
processing order, and implementation flow.

Fixes  #12804
@YuliiaKovalova YuliiaKovalova self-assigned this Jan 9, 2026
@YuliiaKovalova YuliiaKovalova marked this pull request as ready for review January 9, 2026 14:07
baronfel
baronfel previously approved these changes Jan 9, 2026
@baronfel baronfel dismissed their stale review January 9, 2026 16:33

Should have just commented

@baronfel
Copy link
Member

baronfel commented Jan 9, 2026

Worth noting that the branch protections preventing merge aren't active on this branch due to the naming - if we're going to use the servicing/XXX pattern more should we go ahead and enable those protections for it?

@YuliiaKovalova
Copy link
Member Author

Worth noting that the branch protections preventing merge aren't active on this branch due to the naming - if we're going to use the servicing/XXX pattern more should we go ahead and enable those protections for it?

it's a temp measure , we haven't agreed on this approach yet with @rainersigwald

@YuliiaKovalova YuliiaKovalova changed the base branch from servicing/18.3 to main January 14, 2026 19:02
@YuliiaKovalova YuliiaKovalova force-pushed the dev/ykovalova/binlog_18.3 branch from bc898d1 to 2a866d2 Compare January 15, 2026 15:56
Copilot AI review requested due to automatic review settings January 16, 2026 10:40
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 implements support for the MSBUILD_LOGGING_ARGS environment variable, allowing CI/CD pipelines to enable diagnostic logging (binary logs) without modifying project files or build scripts. Only -bl and -check arguments are supported through this environment variable.

Changes:

  • Added environment variable processing for MSBUILD_LOGGING_ARGS in CommandLineParser.GatherLoggingArgsEnvironmentVariableSwitches
  • Extended DeferredBuildMessage struct to support warning messages with error codes
  • Updated localization resource files with new error messages for the feature
  • Added comprehensive unit tests for the new functionality

Reviewed changes

Copilot reviewed 32 out of 32 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
src/MSBuild/XMake.cs Updated GatherAllSwitches calls to pass deferred build messages; changed s_globalMessagesToLogInBuildLoggers from readonly to mutable
src/MSBuild/CommandLine/CommandLineParser.cs Added GatherLoggingArgsEnvironmentVariableSwitches method to parse and validate logging args from environment variable
src/Framework/Traits.cs Added constants and properties for MSBUILD_LOGGING_ARGS environment variables
src/Build/BackEnd/BuildManager/BuildManager.cs Extended DeferredBuildMessage with severity enum and new constructor; updated LogDeferredMessages to handle warnings
src/MSBuild/Resources/Strings.resx Added three new localized strings for logging args diagnostics
src/MSBuild/Resources/xlf/*.xlf Updated all localization files with new strings marked as "new" state
src/Build/Resources/xlf/*.xlf Reset existing translation strings to "new" state for re-translation
src/MSBuild.UnitTests/XMake_BinlogSwitch_Tests.cs Added comprehensive test coverage for the new feature

@YuliiaKovalova YuliiaKovalova force-pushed the dev/ykovalova/binlog_18.3 branch from 04abbe9 to 5c273d7 Compare January 16, 2026 15:37
@YuliiaKovalova YuliiaKovalova merged commit 825180b into main Jan 19, 2026
10 checks passed
@YuliiaKovalova YuliiaKovalova deleted the dev/ykovalova/binlog_18.3 branch January 19, 2026 09:27
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.

Add Environment Variable for Binary Log Collection in MSBuild

4 participants