Skip to content
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

Add BuildOM forward compatibility #10394

Merged
merged 2 commits into from
Jul 18, 2024
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
117 changes: 117 additions & 0 deletions src/Build.UnitTests/BackEnd/BuildOMCompatibility_Tests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
// 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.Reflection;
using Microsoft.Build.Execution;
using Microsoft.Build.Graph;
using Shouldly;
using Xunit;

namespace Microsoft.Build.Engine.UnitTests.BackEnd
{
public class BuildOMCompatibility_Tests
{
[Theory]
[InlineData("ProjectInstance")]
[InlineData("ProjectFullPath")]
[InlineData("TargetNames")]
[InlineData("Flags")]
[InlineData("GlobalProperties")]
[InlineData("ExplicitlySpecifiedToolsVersion")]
[InlineData("HostServices")]
[InlineData("PropertiesToTransfer")]
[InlineData("RequestedProjectState")]
public void BuildRequestDataPropertyCompatTest(string propertyName)
=> VerifyPropertyExists(typeof(BuildRequestData), propertyName);

[Theory]
[InlineData("ProjectGraph")]
[InlineData("ProjectGraphEntryPoints")]
[InlineData("TargetNames")]
[InlineData("Flags")]
[InlineData("GraphBuildOptions")]
[InlineData("HostServices")]
public void GraphBuildRequestDataPropertyCompatTest(string propertyName)
=> VerifyPropertyExists(typeof(GraphBuildRequestData), propertyName);

[Theory]
[InlineData("BuildManager")]
[InlineData("SubmissionId")]
[InlineData("AsyncContext")]
[InlineData("WaitHandle")]
[InlineData("IsCompleted")]
[InlineData("BuildResult")]
public void BuildSubmissionDataPropertyCompatTest(string propertyName)
=> VerifyPropertyExists(typeof(BuildSubmission), propertyName);

[Theory]
[InlineData("Execute")]
[InlineData("ExecuteAsync")]
public void BuildSubmissionDataMethodCompatTest(string methodName)
=> VerifyMethodExists(typeof(BuildSubmission), methodName);

[Theory]
[InlineData("BuildManager")]
[InlineData("SubmissionId")]
[InlineData("AsyncContext")]
[InlineData("WaitHandle")]
[InlineData("IsCompleted")]
[InlineData("BuildResult")]
public void GraphBuildSubmissionDataPropertyCompatTest(string propertyName)
=> VerifyPropertyExists(typeof(BuildSubmission), propertyName);

[Theory]
[InlineData("Execute")]
[InlineData("ExecuteAsync")]
public void GraphBuildSubmissionDataMethodCompatTest(string methodName)
=> VerifyMethodExists(typeof(BuildSubmission), methodName);

[Theory]
[InlineData("SubmissionId")]
[InlineData("ConfigurationId")]
[InlineData("GlobalRequestId")]
[InlineData("ParentGlobalRequestId")]
[InlineData("NodeRequestId")]
[InlineData("Exception")]
[InlineData("CircularDependency")]
[InlineData("OverallResult")]
[InlineData("ResultsByTarget")]
[InlineData("ProjectStateAfterBuild")]
[InlineData("BuildRequestDataFlags")]
public void BuildResultPropertyCompatTest(string propertyName)
=> VerifyPropertyExists(typeof(BuildResult), propertyName);

[Theory]
[InlineData("AddResultsForTarget")]
[InlineData("MergeResults")]
[InlineData("HasResultsForTarget")]
public void BuildResultMethodCompatTest(string methodName)
=> VerifyMethodExists(typeof(BuildResult), methodName);

[Theory]
[InlineData("SubmissionId")]
[InlineData("Exception")]
[InlineData("CircularDependency")]
[InlineData("OverallResult")]
[InlineData("ResultsByNode")]
public void GraphBuildResultPropertyCompatTest(string propertyName)
=> VerifyPropertyExists(typeof(GraphBuildResult), propertyName);

private void VerifyPropertyExists(Type type, string propertyName)
{
type.GetProperty(
propertyName,
BindingFlags.Instance | BindingFlags.Public | BindingFlags.DeclaredOnly)
.ShouldNotBeNull();
}

private void VerifyMethodExists(Type type, string propertyName)
{
type.GetMethod(
propertyName,
BindingFlags.Instance | BindingFlags.Public | BindingFlags.DeclaredOnly)
.ShouldNotBeNull();
}
}
}
13 changes: 13 additions & 0 deletions src/Build/BackEnd/BuildManager/BuildRequestData.cs
Original file line number Diff line number Diff line change
Expand Up @@ -301,5 +301,18 @@ internal override BuildSubmissionBase<BuildRequestData, BuildResult> CreateSubmi
/// <inheritdoc cref="BuildRequestDataBase"/>
public override IReadOnlyDictionary<string, string?> GlobalPropertiesLookup => _globalPropertiesLookup ??=
Execution.GlobalPropertiesLookup.ToGlobalPropertiesLookup(GlobalPropertiesDictionary);

// WARNING!: Do not remove the below proxy properties.
// They are required to make the OM forward compatible
// (code built against this OM should run against binaries with previous version of OM).

/// <inheritdoc cref="BuildRequestDataBase.TargetNames"/>
public new ICollection<string> TargetNames => base.TargetNames;

/// <inheritdoc cref="BuildRequestDataBase.Flags"/>
public new BuildRequestDataFlags Flags => base.Flags;

/// <inheritdoc cref="BuildRequestDataBase.HostServices"/>
public new HostServices? HostServices => base.HostServices;
}
}
22 changes: 22 additions & 0 deletions src/Build/BackEnd/BuildManager/BuildSubmission.cs
Original file line number Diff line number Diff line change
Expand Up @@ -232,5 +232,27 @@ protected internal override void OnCompletition()
BuildResult.SetOverallResult(overallResult: false);
}
}

// WARNING!: Do not remove the below proxy properties.
// They are required to make the OM forward compatible
// (code built against this OM should run against binaries with previous version of OM).

/// <inheritdoc cref="BuildSubmissionBase{BuildRequestData, BuildResult}.BuildResult"/>
public new BuildResult? BuildResult => base.BuildResult;

/// <inheritdoc cref="BuildSubmissionBase.BuildManager"/>
public new BuildManager BuildManager => base.BuildManager;

/// <inheritdoc cref="BuildSubmissionBase.SubmissionId"/>
public new int SubmissionId => base.SubmissionId;

/// <inheritdoc cref="BuildSubmissionBase.AsyncContext"/>
public new object? AsyncContext => base.AsyncContext;

/// <inheritdoc cref="BuildSubmissionBase.WaitHandle"/>
public new WaitHandle WaitHandle => base.WaitHandle;

/// <inheritdoc cref="BuildSubmissionBase.IsCompleted"/>
public new bool IsCompleted => base.IsCompleted;
}
}
15 changes: 14 additions & 1 deletion src/Build/Graph/GraphBuildRequestData.cs
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,7 @@ public GraphBuildRequestData(IEnumerable<ProjectGraphEntryPoint> projectGraphEnt
private GraphBuildRequestData(ICollection<string> targetsToBuild, HostServices? hostServices, BuildRequestDataFlags flags, GraphBuildOptions? graphBuildOptions = null)
: base(targetsToBuild, flags, hostServices)
{
Flags = flags;
base.Flags = flags;
GraphBuildOptions = graphBuildOptions ?? new GraphBuildOptions();
}

Expand Down Expand Up @@ -235,5 +235,18 @@ public override IEnumerable<string> EntryProjectsFullPath
/// Options for how the graph should be built.
/// </summary>
public GraphBuildOptions GraphBuildOptions { get; }

// WARNING!: Do not remove the below proxy properties.
// They are required to make the OM forward compatible
// (code built against this OM should run against binaries with previous version of OM).

/// <inheritdoc cref="BuildRequestDataBase.TargetNames"/>
public new ICollection<string> TargetNames => base.TargetNames;

/// <inheritdoc cref="BuildRequestDataBase.Flags"/>
public new BuildRequestDataFlags Flags => base.Flags;

/// <inheritdoc cref="BuildRequestDataBase.HostServices"/>
public new HostServices? HostServices => base.HostServices;
}
}
22 changes: 22 additions & 0 deletions src/Build/Graph/GraphBuildSubmission.cs
Original file line number Diff line number Diff line change
Expand Up @@ -70,5 +70,27 @@ protected internal override void CheckResultValidForCompletion(GraphBuildResult

protected internal override GraphBuildResult CreateFailedResult(Exception exception)
=> new(SubmissionId, exception);

// WARNING!: Do not remove the below proxy properties.
// They are required to make the OM forward compatible
// (code built against this OM should run against binaries with previous version of OM).

/// <inheritdoc cref="BuildSubmissionBase{GraphBuildRequestData, GraphBuildResult}.BuildResult"/>
public new GraphBuildResult? BuildResult => base.BuildResult;

/// <inheritdoc cref="BuildSubmissionBase.BuildManager"/>
public new BuildManager BuildManager => base.BuildManager;

/// <inheritdoc cref="BuildSubmissionBase.SubmissionId"/>
public new int SubmissionId => base.SubmissionId;

/// <inheritdoc cref="BuildSubmissionBase.AsyncContext"/>
public new object? AsyncContext => base.AsyncContext;

/// <inheritdoc cref="BuildSubmissionBase.WaitHandle"/>
public new WaitHandle WaitHandle => base.WaitHandle;

/// <inheritdoc cref="BuildSubmissionBase.IsCompleted"/>
public new bool IsCompleted => base.IsCompleted;
}
}