Skip to content

Commit

Permalink
Add requested targets to CacheContext (#9569)
Browse files Browse the repository at this point in the history
  • Loading branch information
dfederm authored Jan 3, 2024
1 parent 31f00ee commit 5ba78b7
Show file tree
Hide file tree
Showing 3 changed files with 31 additions and 6 deletions.
3 changes: 2 additions & 1 deletion src/Build/BackEnd/BuildManager/BuildManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1332,6 +1332,7 @@ internal void ExecuteSubmission(BuildSubmission submission, bool allowMainThread
_projectCacheService.InitializePluginsForVsScenario(
ProjectCacheDescriptors.Values,
resolvedConfiguration,
submission.BuildRequestData.TargetNames,
_executionCancellationTokenSource.Token);
}

Expand Down Expand Up @@ -1953,7 +1954,7 @@ private void ExecuteGraphBuildScheduler(GraphBuildSubmission submission)

if (submission.BuildRequestData.GraphBuildOptions.Build)
{
_projectCacheService.InitializePluginsForGraph(projectGraph, _executionCancellationTokenSource.Token);
_projectCacheService.InitializePluginsForGraph(projectGraph, submission.BuildRequestData.TargetNames, _executionCancellationTokenSource.Token);

var targetListTask = projectGraph.GetTargetLists(submission.BuildRequestData.TargetNames);

Expand Down
13 changes: 13 additions & 0 deletions src/Build/BackEnd/Components/ProjectCache/CacheContext.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// 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.Generic;
using Microsoft.Build.FileSystem;
using Microsoft.Build.Graph;
Expand All @@ -22,12 +23,23 @@ public class CacheContext
public IReadOnlyCollection<ProjectGraphEntryPoint>? GraphEntryPoints { get; }
public string? MSBuildExePath { get; }
public MSBuildFileSystemBase FileSystem { get; }
public IReadOnlyCollection<string> RequestedTargets { get; }

public CacheContext(
IReadOnlyDictionary<string, string> pluginSettings,
MSBuildFileSystemBase fileSystem,
ProjectGraph? graph = null,
IReadOnlyCollection<ProjectGraphEntryPoint>? graphEntryPoints = null)
: this(pluginSettings, fileSystem, requestedTargets: Array.Empty<string>(), graph, graphEntryPoints)
{
}

public CacheContext(
IReadOnlyDictionary<string, string> pluginSettings,
MSBuildFileSystemBase fileSystem,
IReadOnlyCollection<string> requestedTargets,
ProjectGraph? graph = null,
IReadOnlyCollection<ProjectGraphEntryPoint>? graphEntryPoints = null)
{
ErrorUtilities.VerifyThrow(
(graph != null) ^ (graphEntryPoints != null),
Expand All @@ -38,6 +50,7 @@ public CacheContext(
GraphEntryPoints = graphEntryPoints;
MSBuildExePath = BuildEnvironmentHelper.Instance.CurrentMSBuildExePath;
FileSystem = fileSystem;
RequestedTargets = requestedTargets;
}
}
}
21 changes: 16 additions & 5 deletions src/Build/BackEnd/Components/ProjectCache/ProjectCacheService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,10 @@ public ProjectCacheService(
/// <summary>
/// Optimization which frontloads plugin initialization since we have an entire graph.
/// </summary>
public void InitializePluginsForGraph(ProjectGraph projectGraph, CancellationToken cancellationToken)
public void InitializePluginsForGraph(
ProjectGraph projectGraph,
ICollection<string> requestedTargets,
CancellationToken cancellationToken)
{
EnsureNotDisposed();

Expand All @@ -111,7 +114,7 @@ public void InitializePluginsForGraph(ProjectGraph projectGraph, CancellationTok
foreach (ProjectCacheDescriptor projectCacheDescriptor in GetProjectCacheDescriptors(node.ProjectInstance))
{
// Intentionally fire-and-forget to asynchronously initialize the plugin. Any exceptions will bubble up later when querying.
_ = GetProjectCachePluginAsync(projectCacheDescriptor, projectGraph, buildRequestConfiguration: null, cancellationToken)
_ = GetProjectCachePluginAsync(projectCacheDescriptor, projectGraph, buildRequestConfiguration: null, requestedTargets, cancellationToken)
.ContinueWith(t => { }, TaskContinuationOptions.ExecuteSynchronously | TaskContinuationOptions.OnlyOnFaulted);
}
});
Expand All @@ -122,6 +125,7 @@ public void InitializePluginsForGraph(ProjectGraph projectGraph, CancellationTok
public void InitializePluginsForVsScenario(
IEnumerable<ProjectCacheDescriptor> projectCacheDescriptors,
BuildRequestConfiguration buildRequestConfiguration,
ICollection<string> requestedTargets,
CancellationToken cancellationToken)
{
EnsureNotDisposed();
Expand All @@ -144,7 +148,7 @@ public void InitializePluginsForVsScenario(
projectCacheDescriptor =>
{
// Intentionally fire-and-forget to asynchronously initialize the plugin. Any exceptions will bubble up later when querying.
_ = GetProjectCachePluginAsync(projectCacheDescriptor, projectGraph: null, buildRequestConfiguration, cancellationToken)
_ = GetProjectCachePluginAsync(projectCacheDescriptor, projectGraph: null, buildRequestConfiguration, requestedTargets, cancellationToken)
.ContinueWith(t => { }, TaskContinuationOptions.ExecuteSynchronously | TaskContinuationOptions.OnlyOnFaulted);
});
},
Expand All @@ -155,12 +159,13 @@ private Task<ProjectCachePlugin> GetProjectCachePluginAsync(
ProjectCacheDescriptor projectCacheDescriptor,
ProjectGraph? projectGraph,
BuildRequestConfiguration? buildRequestConfiguration,
ICollection<string> requestedTargets,
CancellationToken cancellationToken)
=> _projectCachePlugins.GetOrAdd(
projectCacheDescriptor,
// The use of Lazy is because ConcurrentDictionary doesn't guarantee the value factory executes only once if there are multiple simultaneous callers,
// so this ensures that CreateAndInitializePluginAsync is only called exactly once.
descriptor => new Lazy<Task<ProjectCachePlugin>>(() => CreateAndInitializePluginAsync(descriptor, projectGraph, buildRequestConfiguration, cancellationToken)))
descriptor => new Lazy<Task<ProjectCachePlugin>>(() => CreateAndInitializePluginAsync(descriptor, projectGraph, buildRequestConfiguration, requestedTargets, cancellationToken)))
.Value;

private IEnumerable<ProjectCacheDescriptor> GetProjectCacheDescriptors(ProjectInstance projectInstance)
Expand Down Expand Up @@ -189,6 +194,7 @@ private async Task<ProjectCachePlugin> CreateAndInitializePluginAsync(
ProjectCacheDescriptor projectCacheDescriptor,
ProjectGraph? projectGraph,
BuildRequestConfiguration? buildRequestConfiguration,
ICollection<string> requestedTargets,
CancellationToken cancellationToken)
{
BuildEventContext buildEventContext = BuildEventContext.Invalid;
Expand Down Expand Up @@ -241,6 +247,9 @@ private async Task<ProjectCachePlugin> CreateAndInitializePluginAsync(
? GetGraphEntryPoints(buildRequestConfiguration)
: null;

// In practice, the underlying type of the ICollection is a List<string> so attempt to cast first
IReadOnlyList<string> requestedTargetsList = requestedTargets as List<string> ?? requestedTargets.ToList();

_loggingService.LogComment(buildEventContext, MessageImportance.High, "LoadingProjectCachePlugin", pluginTypeName);
MSBuildEventSource.Log.ProjectCacheBeginBuildStart(pluginTypeName);

Expand All @@ -250,6 +259,7 @@ await pluginInstance.BeginBuildAsync(
new CacheContext(
projectCacheDescriptor.PluginSettings,
DefaultMSBuildFileSystem.Instance,
requestedTargetsList,
projectGraph,
graphEntryPoints),
pluginLogger,
Expand Down Expand Up @@ -517,7 +527,8 @@ private async Task<CacheResult> GetCacheResultAsync(BuildRequestData buildReques
continue;
}

ProjectCachePlugin plugin = await GetProjectCachePluginAsync(projectCacheDescriptor, projectGraph: null, buildRequestConfiguration, cancellationToken);
ICollection<string> requestedTargetsList = buildRequestConfiguration.RequestedTargets as ICollection<string> ?? buildRequestConfiguration.RequestedTargets.ToList();
ProjectCachePlugin plugin = await GetProjectCachePluginAsync(projectCacheDescriptor, projectGraph: null, buildRequestConfiguration, requestedTargetsList, cancellationToken);
try
{
// Rethrow any initialization exception.
Expand Down

0 comments on commit 5ba78b7

Please sign in to comment.