Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

[release/10.0.1xx-preview6] Source code updates from dotnet/msbuild #1228

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 10 additions & 1 deletion 11 src/msbuild/.vsts-dotnet.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,17 @@ parameters:
displayName: Optional OptProfDrop Override
type: string
default: 'default'
- name: requireDefaultChannelsEnabled
displayName: Require Default Channels
type: boolean
default: true

variables:
# if OptProfDrop is not set, string '$(OptProfDrop)' will be passed to the build script.
- name: OptProfDrop
value: ''
- name: requireDefaultChannels
value: false
- name: SourceBranch
value: $(IbcSourceBranchName)
# If we're not on a vs* branch, use main as our optprof collection branch
Expand All @@ -33,6 +39,9 @@ variables:
value: ${{parameters.OptProfDropName}}
- name: SourceBranch
value: ''
- ${{ if and(not(startsWith(variables['Build.SourceBranch'], 'refs/heads/exp/')), not(startsWith(variables['Build.SourceBranch'], 'refs/heads/perf/'))) }}:
- name: requireDefaultChannels
value: ${{ parameters.requireDefaultChannelsEnabled }}
- name: EnableReleaseOneLocBuild
value: true # Enable loc for vs17.14
- name: Codeql.Enabled
Expand All @@ -44,7 +53,6 @@ variables:
value: none
- name: NugetSecurityAnalysisWarningLevel
value: none

resources:
repositories:
- repository: 1ESPipelineTemplates
Expand Down Expand Up @@ -328,3 +336,4 @@ extends:
enableSymbolValidation: true
enableSourceLinkValidation: false
enableNugetValidation: false
requireDefaultChannels: ${{ variables.requireDefaultChannels }}
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,12 @@ This is an internal engineering document. For general overview and user point of
|----------|:-------------|
| PM | @baronfel |
| Advisory/Leadership | @rainersigwald |
| Infrastructure | @jankrivanek |
| Configuration | @f-alizada |
| Infrastructure | @SimaTian |
| Configuration | @JanProvaznik |
| Custom Checks | @YuliiaKovalova |
| Inbox Checks | @ladipro |
| Inbox Checks | @YuliiaKovalova |
| Replay Mode | @surayya-MS |
| Tracing | @maridematte |
| Tracing | @surayya-MS |
| Perf Advisory | @AR-May |


Expand Down
111 changes: 95 additions & 16 deletions 111 src/msbuild/src/Build.UnitTests/BackEnd/Scheduler_Tests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,13 @@

namespace Microsoft.Build.UnitTests.BackEnd
{
using System.Linq;
using FluentAssertions;
using Microsoft.Build.Unittest;

/// <summary>
/// Tests of the scheduler.
/// </summary>
// Ignore: Causing issues with other tests
// NOTE: marked as "internal" to disable the entire test class, as was done for MSTest.
public class Scheduler_Tests : IDisposable
{
/// <summary>
Expand Down Expand Up @@ -57,6 +57,11 @@ public class Scheduler_Tests : IDisposable
/// </summary>
private BuildParameters _parameters;

/// <summary>
/// Configuration ID.
/// </summary>
private const int DefaultConfigId = 99;

/// <summary>
/// Set up
/// </summary>
Expand All @@ -70,8 +75,8 @@ public Scheduler_Tests()
_host = new MockHost();
_scheduler = new Scheduler();
_scheduler.InitializeComponent(_host);
CreateConfiguration(99, "parent.proj");
_defaultParentRequest = CreateBuildRequest(99, 99, Array.Empty<string>(), null);
CreateConfiguration(DefaultConfigId, "parent.proj");
_defaultParentRequest = CreateBuildRequest(99, DefaultConfigId, Array.Empty<string>(), null);

// Set up the scheduler with one node to start with.
_scheduler.ReportNodesCreated(new NodeInfo[] { new NodeInfo(1, NodeProviderType.InProc) });
Expand Down Expand Up @@ -386,8 +391,8 @@ public void VerifyRequestOrderingDoesNotAffectNodeCreationCountWithInProcAndAnyR
_parameters.ShutdownInProcNodeOnBuildFinish = true;
_buildManager = new BuildManager();

CreateConfiguration(99, "parent.proj");
_defaultParentRequest = CreateBuildRequest(99, 99, Array.Empty<string>(), null);
CreateConfiguration(DefaultConfigId, "parent.proj");
_defaultParentRequest = CreateBuildRequest(99, DefaultConfigId, Array.Empty<string>(), null);

CreateConfiguration(1, "foo.proj");
BuildRequest request1 = CreateBuildRequest(1, 1, new string[] { "foo" }, NodeAffinity.Any, _defaultParentRequest);
Expand Down Expand Up @@ -578,8 +583,8 @@ public void VerifyNoOverCreationOfNodesWithBuildLoop()
_parameters.ShutdownInProcNodeOnBuildFinish = true;
_buildManager = new BuildManager();

CreateConfiguration(99, "parent.proj");
_defaultParentRequest = CreateBuildRequest(99, 99, Array.Empty<string>(), null);
CreateConfiguration(DefaultConfigId, "parent.proj");
_defaultParentRequest = CreateBuildRequest(99, DefaultConfigId, Array.Empty<string>(), null);

CreateConfiguration(1, "foo.proj");
BuildRequest request1 = CreateBuildRequest(1, 1, new string[] { "foo" }, NodeAffinity.OutOfProc, _defaultParentRequest);
Expand Down Expand Up @@ -768,12 +773,13 @@ private BuildResult CacheBuildResult(BuildRequest request, string target, WorkUn
}

/// <summary>
/// Creates a build result for a request
/// Creates a build result for a request.
/// </summary>
private BuildResult CreateBuildResult(BuildRequest request, string target, WorkUnitResult workUnitResult)
{
BuildResult result = new BuildResult(request);
result.AddResultsForTarget(target, new TargetResult(Array.Empty<TaskItem>(), workUnitResult));

return result;
}

Expand All @@ -788,23 +794,30 @@ private BuildRequest CreateBuildRequest(int nodeRequestId, int configId)
/// <summary>
/// Creates a build request.
/// </summary>
private BuildRequest CreateBuildRequest(int nodeRequestId, int configId, string[] targets)
private BuildRequest CreateBuildRequest(int nodeRequestId, int configId, string[] targets, BuildRequestDataFlags buildRequestDataFlags = BuildRequestDataFlags.None)
{
return CreateBuildRequest(nodeRequestId, configId, targets, _defaultParentRequest);
return CreateBuildRequest(nodeRequestId, configId, targets, _defaultParentRequest, buildRequestDataFlags);
}

/// <summary>
/// Creates a build request.
/// </summary>
private BuildRequest CreateBuildRequest(int nodeRequestId, int configId, string[] targets, BuildRequest parentRequest)
private BuildRequest CreateBuildRequest(int nodeRequestId, int configId, string[] targets, BuildRequest parentRequest, BuildRequestDataFlags buildRequestDataFlags = BuildRequestDataFlags.None)
{
return CreateBuildRequest(nodeRequestId, configId, targets, NodeAffinity.Any, parentRequest);
return CreateBuildRequest(nodeRequestId, configId, targets, NodeAffinity.Any, parentRequest, buildRequestDataFlags: buildRequestDataFlags);
}

/// <summary>
/// Creates a build request.
/// </summary>
private BuildRequest CreateBuildRequest(int nodeRequestId, int configId, string[] targets, NodeAffinity nodeAffinity, BuildRequest parentRequest, ProxyTargets proxyTargets = null)
private BuildRequest CreateBuildRequest(
int nodeRequestId,
int configId,
string[] targets,
NodeAffinity nodeAffinity,
BuildRequest parentRequest,
ProxyTargets proxyTargets = null,
BuildRequestDataFlags buildRequestDataFlags = BuildRequestDataFlags.None)
{
(targets == null ^ proxyTargets == null).ShouldBeTrue();

Expand All @@ -825,16 +838,19 @@ private BuildRequest CreateBuildRequest(int nodeRequestId, int configId, string[
targets,
hostServices,
BuildEventContext.Invalid,
parentRequest);
parentRequest,
buildRequestDataFlags: buildRequestDataFlags);
}

parentRequest.ShouldBeNull();

return new BuildRequest(
submissionId: 1,
nodeRequestId,
configId,
proxyTargets,
hostServices);
hostServices,
buildRequestDataFlags: buildRequestDataFlags);
}

private BuildRequest CreateProxyBuildRequest(int nodeRequestId, int configId, ProxyTargets proxyTargets, BuildRequest parentRequest)
Expand All @@ -848,6 +864,69 @@ private BuildRequest CreateProxyBuildRequest(int nodeRequestId, int configId, Pr
proxyTargets);
}

/// <summary>
/// The test checks how scheduler handles the duplicated requests and cache MISS for this case.
/// It's expected to have the duplicated request rescheduled for the execution.
/// </summary>
[Fact]
public void ReportResultTest_NoCacheHitForDupes()
{
// Create a duplicate of the existing _defaultParentRequest, but with a different build request flag, so we can't get the result from the cache.
BuildRequest duplicateRequest = CreateBuildRequest(2, configId: DefaultConfigId, Array.Empty<string>(), parentRequest: null, BuildRequestDataFlags.ProvideSubsetOfStateAfterBuild);

// Schedule the duplicate request -> it goes to unscheduled request due to duplicated configId
_scheduler.ReportRequestBlocked(2, new BuildRequestBlocker(-1, Array.Empty<string>(), [duplicateRequest]));

// try to get a result for the parent request and see if we get a result for the duplicate request
var results = _scheduler.ReportResult(1, CreateBuildResult(_defaultParentRequest, "", BuildResultUtilities.GetSuccessResult()))
.ToList();

results.ShouldNotBeNull();
results.Count.ShouldBe(2);

// Completed _defaultParentRequest
results[0].BuildResult.ShouldNotBeNull();
results[0].BuildResult.BuildRequestDataFlags.ShouldBe(BuildRequestDataFlags.None);
results[0].Action.ShouldBe(ScheduleActionType.SubmissionComplete);

// The automatically scheduled duplicated request.
results[1].BuildResult.ShouldBeNull();
results[1].NodeId.Should().Be(1);
results[1].Action.ShouldBe(ScheduleActionType.Schedule);
results[1].BuildRequest.BuildRequestDataFlags.ShouldBe(BuildRequestDataFlags.ProvideSubsetOfStateAfterBuild);
}

/// <summary>
/// The test checks how scheduler handles the duplicated requests and cache HIT for this case.
/// It's expected to have an immediate result for the duplicated request.
/// </summary>
[Fact]
public void ReportResultTest_CacheHitForDupes()
{
// Create a duplicate of the existing _defaultParentRequest.
BuildRequest duplicateRequest = CreateBuildRequest(2, configId: DefaultConfigId, Array.Empty<string>(), parentRequest: null, BuildRequestDataFlags.None);

// Schedule the duplicate request -> it goes to unscheduled request due to duplicated configId
_scheduler.ReportRequestBlocked(1, new BuildRequestBlocker(-1, Array.Empty<string>(), [duplicateRequest]));

// try to get a result for the parent request and see if we get a result for the duplicate request.
var results = _scheduler.ReportResult(1, CreateBuildResult(duplicateRequest, "", BuildResultUtilities.GetSuccessResult()))
.ToList();

results.ShouldNotBeNull();
results.Count.ShouldBe(2);

// Completed _defaultParentRequest
results[0].BuildResult.ShouldNotBeNull();
results[0].BuildResult.BuildRequestDataFlags.ShouldBe(BuildRequestDataFlags.None);
results[0].Action.ShouldBe(ScheduleActionType.SubmissionComplete);

// We hit cache and completed the duplicate request.
results[1].BuildResult.ShouldNotBeNull();
results[1].BuildResult.BuildRequestDataFlags.ShouldBe(BuildRequestDataFlags.None);
results[1].Action.ShouldBe(ScheduleActionType.SubmissionComplete);
}

/// <summary>
/// Method that fakes the actions done by BuildManager.PerformSchedulingActions
/// </summary>
Expand Down
4 changes: 2 additions & 2 deletions 4 src/msbuild/src/Build/BackEnd/BuildManager/BuildManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2427,8 +2427,8 @@ private void HandleNewRequest(int node, BuildRequestBlocker blocker)
}
}

IEnumerable<ScheduleResponse> response = _scheduler!.ReportRequestBlocked(node, blocker);
PerformSchedulingActions(response);
IEnumerable<ScheduleResponse> responses = _scheduler!.ReportRequestBlocked(node, blocker);
PerformSchedulingActions(responses);
}

/// <summary>
Expand Down
15 changes: 7 additions & 8 deletions 15 src/msbuild/src/Build/BackEnd/BuildManager/BuildParameters.cs
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
// Licensed to the .NET Foundation under one or more agreements.
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System;
using System.Collections.Frozen;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.Threading;
Expand Down Expand Up @@ -129,7 +129,7 @@ public class BuildParameters : ITranslatable
/// <summary>
/// The original process environment.
/// </summary>
private Dictionary<string, string> _buildProcessEnvironment;
private FrozenDictionary<string, string> _buildProcessEnvironment;

/// <summary>
/// The environment properties for the build.
Expand Down Expand Up @@ -282,9 +282,7 @@ internal BuildParameters(BuildParameters other, bool resetEnvironment = false)
_enableRarNode = other._enableRarNode;
_buildProcessEnvironment = resetEnvironment
? CommunicationsUtilities.GetEnvironmentVariables()
: other._buildProcessEnvironment != null
? new Dictionary<string, string>(other._buildProcessEnvironment)
: null;
: other._buildProcessEnvironment;
_environmentProperties = other._environmentProperties != null ? new PropertyDictionary<ProjectPropertyInstance>(other._environmentProperties) : null;
_forwardingLoggers = other._forwardingLoggers != null ? new List<ForwardingLoggerRecord>(other._forwardingLoggers) : null;
_globalProperties = other._globalProperties != null ? new PropertyDictionary<ProjectPropertyInstance>(other._globalProperties) : null;
Expand Down Expand Up @@ -356,8 +354,7 @@ public bool UseSynchronousLogging
/// <summary>
/// Gets the environment variables which were set when this build was created.
/// </summary>
public IDictionary<string, string> BuildProcessEnvironment => new ReadOnlyDictionary<string, string>(
_buildProcessEnvironment ?? new Dictionary<string, string>(0));
public IDictionary<string, string> BuildProcessEnvironment => BuildProcessEnvironmentInternal;

/// <summary>
/// The name of the culture to use during the build.
Expand Down Expand Up @@ -720,6 +717,8 @@ internal int BuildId
set => _buildId = value;
}

internal FrozenDictionary<string, string> BuildProcessEnvironmentInternal => _buildProcessEnvironment ?? FrozenDictionary<string, string>.Empty;

/// <summary>
/// Gets or sets the environment properties.
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

using System;
using System.Collections.Concurrent;
using System.Collections.Frozen;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
Expand Down Expand Up @@ -1378,7 +1379,7 @@ private void InitializeOperatingEnvironment()
else
{
// Restore the original build environment variables.
SetEnvironmentVariableBlock(_componentHost.BuildParameters.BuildProcessEnvironment);
SetEnvironmentVariableBlock(_componentHost.BuildParameters.BuildProcessEnvironmentInternal);
}
}

Expand All @@ -1401,17 +1402,17 @@ private void RestoreOperatingEnvironment()
/// <summary>
/// Sets the environment block to the set of saved variables.
/// </summary>
private void SetEnvironmentVariableBlock(IDictionary<string, string> savedEnvironment)
private void SetEnvironmentVariableBlock(FrozenDictionary<string, string> savedEnvironment)
{
IDictionary<string, string> currentEnvironment = CommunicationsUtilities.GetEnvironmentVariables();
FrozenDictionary<string, string> currentEnvironment = CommunicationsUtilities.GetEnvironmentVariables();
ClearVariablesNotInEnvironment(savedEnvironment, currentEnvironment);
UpdateEnvironmentVariables(savedEnvironment, currentEnvironment);
}

/// <summary>
/// Clears from the current environment any variables which do not exist in the saved environment
/// </summary>
private void ClearVariablesNotInEnvironment(IDictionary<string, string> savedEnvironment, IDictionary<string, string> currentEnvironment)
private void ClearVariablesNotInEnvironment(FrozenDictionary<string, string> savedEnvironment, FrozenDictionary<string, string> currentEnvironment)
{
foreach (KeyValuePair<string, string> entry in currentEnvironment)
{
Expand All @@ -1425,7 +1426,7 @@ private void ClearVariablesNotInEnvironment(IDictionary<string, string> savedEnv
/// <summary>
/// Updates the current environment with values in the saved environment which differ or are not yet set.
/// </summary>
private void UpdateEnvironmentVariables(IDictionary<string, string> savedEnvironment, IDictionary<string, string> currentEnvironment)
private void UpdateEnvironmentVariables(FrozenDictionary<string, string> savedEnvironment, FrozenDictionary<string, string> currentEnvironment)
{
foreach (KeyValuePair<string, string> entry in savedEnvironment)
{
Expand Down
Loading
Morty Proxy This is a proxified and sanitized view of the page, visit original site.