Implement IBuildProvider so that the BuildXL Integration VS extension can intercept SDK-style csproj builds

The BuildXL Integration VS extension intercepts non-SDK-style csproj builds. However, that mechanism does not work for SDK-style csproj builds. Per SharePoint Online's request, the Visual Studio team has designed a new interface IBuildProvider. See the email for more details - [SharePoint, BuildXL and SDK Style projects.pdf](https://dev.azure.com/mseng/9ed2c125-1cd5-4a17-886b-9d267f3a5fab/_apis/git/repositories/50d331c7-ea65-45eb-833f-0303c6c2387e/pullRequests/658304/attachments/SharePoint%2C%20BuildXL%20and%20SDK%20Style%20projects.pdf).
This commit is contained in:
Chad Su 2022-04-29 18:43:39 +00:00
Родитель 879dc5ba46
Коммит fe7b4e37d4
9 изменённых файлов: 194 добавлений и 3 удалений

Просмотреть файл

@ -0,0 +1,26 @@
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
import {Transformer} from "Sdk.Transformers";
import * as Managed from "Sdk.Managed";
// This is an empty facade for a Microsoft internal package.
namespace Contents {
export declare const qualifier: {
};
@@public
export const all: StaticDirectory = Transformer.sealPartialDirectory(d`.`, []);
}
@@public
export const pkg: Managed.ManagedNugetPackage =
Managed.Factory.createNugetPackage(
"Microsoft.VisualStudio.ProjectSystem",
"0.0.0",
Contents.all,
[],
[],
[]
);

Просмотреть файл

@ -0,0 +1,6 @@
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
module({
name: "Microsoft.VisualStudio.ProjectSystem"
});

Просмотреть файл

@ -1,6 +1,6 @@
<PackageManifest Version="2.0.0" xmlns="http://schemas.microsoft.com/developer/vsx-schema/2011">
<Metadata>
<Identity Id="76439c3a-9faf-4f38-9f54-f127e9be9171" Version="3.2" Language="en-US" Publisher="Microsoft" />
<Identity Id="76439c3a-9faf-4f38-9f54-f127e9be9171" Version="3.3" Language="en-US" Publisher="Microsoft" />
<DisplayName>BuildXL Integration</DisplayName>
<Description>Enables using BuildXL as the build engine for Visual Studio.</Description>
<MoreInfo>https://github.com/Microsoft/BuildXL</MoreInfo>

Просмотреть файл

@ -49,6 +49,7 @@ namespace BuildXL.VsPackage
internal const string DominoPackageDir = "DominoPackageDir";
internal const string DominoBuildFilterProp = "DominoBuildFilter";
internal const string CombinedDominoBuildFilterProp = "CombinedDominoBuildFilter";
internal const string DominoSpecFileProp = "DominoSpecFile";
internal const string DominoSolutionSettingsFileExtension = ".sln.dvs.props";

Просмотреть файл

@ -0,0 +1,156 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
#nullable enable
using System.Collections.Immutable;
using System.ComponentModel.Composition;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Build.Execution;
using Microsoft.VisualStudio.ProjectSystem;
using Microsoft.VisualStudio.ProjectSystem.Build;
using Microsoft.VisualStudio.ProjectSystem.VS.Build;
namespace BuildXL.VsPackage.VsProject
{
/// <summary>
/// Proffers the BuildXL BuildProvider which intercepts the SDK-style project build requests
/// and routes them to the BuildXL build manager.
/// </summary>
// Visual Studio will be able to discover this IBuildProvider thanks to this attribute together with
// the Microsoft.VisualStudio.MefComponent asset type declared in the extension.vsixmanifest.
[Export(typeof(IBuildProvider))]
// This IBuildProvider only applies to the .csproj that has the <ProjectCapability Include="BuildXL" /> item.
[AppliesTo("BuildXL")]
// 0 is the order of the default build provider implemented by CPS.
// Using any number greater than 0 means overriding the default.
[Order(1000, SuppressLowerPriority = true)]
public sealed class BuildProvider : IBuildProvider
{
private static BuildManager? s_buildManager;
[Import]
private UnconfiguredProject UnconfiguredProject { get; set; } = null!;
[Import]
private ConfiguredProject ConfiguredProject { get; set; } = null!;
/// <summary>
/// Sets the BuildManager.
/// </summary>
public static void SetBuildManager(BuildManager buildManager)
{
s_buildManager = buildManager;
}
/// <summary>
/// Constructor.
/// </summary>
public BuildProvider()
{
// An instance is created for each of the SDK-style projects.
}
/// <summary>
/// Implements IBuildProvider.SupportsMultiThreadedBuild.
/// </summary>
public bool SupportsMultiThreadedBuild => false;
/// <summary>
/// Implements IBuildProvider.IsBuildActionSupportedAsync.
/// </summary>
public Task<bool> IsBuildActionSupportedAsync(BuildAction buildAction, bool duringQueryStartBuild, CancellationToken cancellationToken = default)
{
return Task.FromResult(true);
}
/// <summary>
/// Implements IBuildProvider.BuildAsync.
/// </summary>
public async Task<IBuildResult> BuildAsync(TextWriter outputWriter, BuildAction buildAction, IImmutableDictionary<string, string>? properties = null, CancellationToken cancellationToken = default)
{
bool succ = false;
if (s_buildManager != null)
{
string projectName = UnconfiguredProject.FullPath;
var projectPropertiesProvider = ConfiguredProject.Services.ProjectPropertiesProvider;
if (projectPropertiesProvider != null)
{
string buildFilter = await projectPropertiesProvider.GetCommonProperties().GetEvaluatedPropertyValueAsync(Constants.CombinedDominoBuildFilterProp);
if (buildFilter == null)
{
s_buildManager.WriteIncompatibleMessage(Path.GetFileName(projectName));
}
if (!string.IsNullOrEmpty(projectName) && !string.IsNullOrEmpty(buildFilter))
{
succ = await s_buildManager.BuildProjectAsync(projectName, buildFilter);
}
}
else
{
outputWriter.WriteLine("BuildProvider: projectPropertiesProvider is null.");
}
}
else
{
outputWriter.WriteLine("BuildProvider: s_buildManager is null.");
}
return new BuildXLBuildResult(succ);
}
private class BuildXLBuildResult : IBuildResult
{
private readonly bool m_succ;
public BuildResult MSBuildResult => null!;
public BuildResultCode OverallResult => (m_succ ? BuildResultCode.Success : BuildResultCode.Failure);
public int Warnings => 0;
public int Errors => (m_succ ? 0 : 1);
public BuildXLBuildResult(bool succ)
{
m_succ = succ;
}
}
}
/// <summary>
/// Implements IBuildUpToDateCheckProvider.
/// We do not use the default IBuildUpToDateCheckProvider provided by the Common Project System (CPS).
/// We always return false from IsUpToDateAsync to let BuildXL decide whether to rebuild.
/// </summary>
[Export(typeof(IBuildUpToDateCheckProvider))]
[AppliesTo("BuildXL")]
[Order(1000, SuppressLowerPriority = true)]
[ExportMetadata("BeforeDrainCriticalTasks", true)]
public sealed class BuildUpToDateCheckProvider : IBuildUpToDateCheckProvider
{
/// <summary>
/// Implements IBuildUpToDateCheckProvider.IsUpToDateAsync.
/// </summary>
public Task<bool> IsUpToDateAsync(BuildAction buildAction, TextWriter logger, CancellationToken cancellationToken = default)
{
return Task.FromResult(false);
}
/// <summary>
/// Implements IBuildUpToDateCheckProvider.IsUpToDateCheckEnabledAsync.
/// </summary>
public Task<bool> IsUpToDateCheckEnabledAsync(CancellationToken cancellationToken = default)
{
return Task.FromResult(true);
}
}
}
#nullable restore

Просмотреть файл

@ -68,6 +68,7 @@ namespace BuildXL.VsPackage.VsProject
m_idleTaskScheduler = (TaskScheduler)taskSchedulerService.GetTaskScheduler((uint)VsTaskRunContext.UIThreadBackgroundPriority);
m_buildManager = new BuildManager(this);
buildManagerHolder.BuildManager = m_buildManager;
BuildProvider.SetBuildManager(m_buildManager);
IVsOutputWindowPane dominoDebugPane;
outputWindow.GetPane(ref guid, out dominoDebugPane);

Просмотреть файл

@ -2283,7 +2283,7 @@
"Type": "NuGet",
"NuGet": {
"Name": "Microsoft.VisualStudio.ProjectSystem",
"Version": "17.0.667-pre"
"Version": "17.3.74-pre"
}
}
},

Просмотреть файл

@ -91,6 +91,7 @@ export const pkgs = isMicrosoftInternal ? [
// Part of VSSDK used by IDE/VsIntegration
{ id: "Microsoft.Internal.VisualStudio.Interop", version: "17.2.32405.191" },
{ id: "Microsoft.VisualStudio.ProjectSystem", version: "17.3.74-pre" },
] : [
// Artifact packages and dependencies in OSS
@ -114,5 +115,6 @@ export const resolver = {
f`Private/InternalSdk/BuildXL.Tracing.AriaTenantToken/module.config.dsc`,
f`Private/InternalSdk/AnyBuild.SDK/module.config.dsc`,
f`Private/InternalSdk/Microsoft.Internal.VisualStudio.Interop/module.config.dsc`,
f`Private/InternalSdk/Microsoft.VisualStudio.ProjectSystem/module.config.dsc`,
]
};

Просмотреть файл

@ -10,7 +10,6 @@ export const pkgs = [
{ id: "Microsoft.VisualStudio.Imaging", version: "15.8.28010", dependentPackageIdsToSkip: ["Microsoft.VisualStudio.Utilities"] }, // Have to cut this dependency because it is 46 only and this package is 45 compatible
{ id: "Microsoft.VisualStudio.LanguageServer.Protocol", version: "17.0.4103-g225b54d231" },
{ id: "Microsoft.VisualStudio.ProjectAggregator", version: "17.0.0-previews-3-31605-261" },
{ id: "Microsoft.VisualStudio.ProjectSystem", version: "17.0.667-pre" },
{ id: "Microsoft.VisualStudio.SDK.EmbedInteropTypes", version: "15.0.26" },
{ id: "Microsoft.VisualStudio.SDK.VsixSuppression", version: "14.1.15" },
{ id: "Microsoft.VisualStudio.Shell.14.0", version: "14.3.25407", dependentPackageIdsToSkip: ["*"] }, // Have cut dependencies due to qualifier mismatches