-
Notifications
You must be signed in to change notification settings - Fork 11
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add predictions for deps.json and runtimeconfig.json files (#121)
- Loading branch information
Showing
11 changed files
with
691 additions
and
18 deletions.
There are no files selected for viewing
31 changes: 31 additions & 0 deletions
31
src/BuildPrediction/Predictors/GenerateBuildDependencyFilePredictor.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
// Copyright (c) Microsoft. All rights reserved. | ||
// Licensed under the MIT license. See LICENSE file in the project root for full license information. | ||
|
||
using System; | ||
using Microsoft.Build.Execution; | ||
|
||
namespace Microsoft.Build.Prediction.Predictors; | ||
|
||
/// <summary> | ||
/// Makes predictions based on the GenerateBuildDependencyFile target. | ||
/// </summary> | ||
public sealed class GenerateBuildDependencyFilePredictor : IProjectPredictor | ||
{ | ||
internal const string GenerateDependencyFilePropertyName = "GenerateDependencyFile"; | ||
internal const string ProjectAssetsFilePropertyName = "ProjectAssetsFile"; | ||
internal const string ProjectDepsFilePathPropertyName = "ProjectDepsFilePath"; | ||
|
||
/// <inheritdoc/> | ||
public void PredictInputsAndOutputs( | ||
ProjectInstance projectInstance, | ||
ProjectPredictionReporter predictionReporter) | ||
{ | ||
if (!projectInstance.GetPropertyValue(GenerateDependencyFilePropertyName).Equals("true", StringComparison.OrdinalIgnoreCase)) | ||
{ | ||
return; | ||
} | ||
|
||
predictionReporter.ReportInputFile(projectInstance.GetPropertyValue(ProjectAssetsFilePropertyName)); | ||
predictionReporter.ReportOutputFile(projectInstance.GetPropertyValue(ProjectDepsFilePathPropertyName)); | ||
} | ||
} |
104 changes: 104 additions & 0 deletions
104
src/BuildPrediction/Predictors/GeneratePublishDependencyFilePredictor.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,104 @@ | ||
// Copyright (c) Microsoft. All rights reserved. | ||
// Licensed under the MIT license. See LICENSE file in the project root for full license information. | ||
|
||
using System; | ||
using Microsoft.Build.Execution; | ||
|
||
namespace Microsoft.Build.Prediction.Predictors; | ||
|
||
/// <summary> | ||
/// Makes predictions based on the GeneratePublishDependencyFile target. | ||
/// </summary> | ||
public sealed class GeneratePublishDependencyFilePredictor : IProjectPredictor | ||
{ | ||
internal const string PublishAotPropertyName = "PublishAot"; | ||
internal const string PublishDirPropertyName = "PublishDir"; | ||
internal const string PublishSingleFilePropertyName = "PublishSingleFile"; | ||
internal const string SelfContainedPropertyName = "SelfContained"; | ||
internal const string PreserveStoreLayoutPropertyName = "PreserveStoreLayout"; | ||
internal const string PublishTrimmedPropertyName = "PublishTrimmed"; | ||
internal const string RuntimeStorePackagesItemName = "RuntimeStorePackages"; | ||
internal const string PackageReferenceItemName = "PackageReference"; | ||
internal const string PrivateAssetsMetadataName = "PrivateAssets"; | ||
internal const string PublishMetadataName = "Publish"; | ||
internal const string PublishDepsFilePathPropertyName = "PublishDepsFilePath"; | ||
internal const string ProjectDepsFileNamePropertyName = "ProjectDepsFileName"; | ||
internal const string IntermediateOutputPathPropertyName = "IntermediateOutputPath"; | ||
|
||
/// <inheritdoc/> | ||
public void PredictInputsAndOutputs( | ||
ProjectInstance projectInstance, | ||
ProjectPredictionReporter predictionReporter) | ||
{ | ||
if (!projectInstance.GetPropertyValue(GenerateBuildDependencyFilePredictor.GenerateDependencyFilePropertyName).Equals("true", StringComparison.OrdinalIgnoreCase) | ||
|| ShouldUseBuildDependencyFile(projectInstance) | ||
|| projectInstance.GetPropertyValue(PublishAotPropertyName).Equals("true", StringComparison.OrdinalIgnoreCase)) | ||
{ | ||
return; | ||
} | ||
|
||
predictionReporter.ReportInputFile(projectInstance.GetPropertyValue(GenerateBuildDependencyFilePredictor.ProjectAssetsFilePropertyName)); | ||
|
||
string publishDepsFilePath = GetEffectivePublishDepsFilePath(projectInstance); | ||
string intermediateDepsFilePath = publishDepsFilePath is not null | ||
? publishDepsFilePath | ||
: projectInstance.GetPropertyValue(IntermediateOutputPathPropertyName) + projectInstance.GetPropertyValue(ProjectDepsFileNamePropertyName); | ||
predictionReporter.ReportOutputFile(intermediateDepsFilePath); | ||
|
||
// Note: GetCopyToPublishDirectoryItemsGraphPredictor will predict the final (published) location for the publish deps file since that's the target which does that copy. | ||
} | ||
|
||
/// <summary> | ||
/// Determines the value of _UseBuildDependencyFile by emulating the behavior from the _ComputeUseBuildDependencyFile target (and the _ComputePackageReferencePublish target). | ||
/// </remarks> | ||
internal static bool ShouldUseBuildDependencyFile(ProjectInstance projectInstance) | ||
{ | ||
bool hasExcludeFromPublishPackageReference = false; | ||
foreach (ProjectItemInstance packageReference in projectInstance.GetItems(PackageReferenceItemName)) | ||
{ | ||
string packageReferencePublishMetadata = packageReference.GetMetadataValue(PublishMetadataName); | ||
if (packageReferencePublishMetadata.Equals("false", StringComparison.OrdinalIgnoreCase)) | ||
{ | ||
hasExcludeFromPublishPackageReference = true; | ||
break; | ||
} | ||
|
||
if (string.IsNullOrEmpty(packageReferencePublishMetadata) | ||
&& packageReference.GetMetadataValue(PrivateAssetsMetadataName).Equals("All", StringComparison.OrdinalIgnoreCase)) | ||
{ | ||
hasExcludeFromPublishPackageReference = true; | ||
break; | ||
} | ||
} | ||
|
||
bool trimRuntimeAssets = projectInstance.GetPropertyValue(PublishSingleFilePropertyName).Equals("true", StringComparison.OrdinalIgnoreCase) | ||
&& projectInstance.GetPropertyValue(SelfContainedPropertyName).Equals("true", StringComparison.OrdinalIgnoreCase); | ||
return !hasExcludeFromPublishPackageReference | ||
&& projectInstance.GetItems(RuntimeStorePackagesItemName).Count == 0 | ||
&& !projectInstance.GetPropertyValue(PreserveStoreLayoutPropertyName).Equals("true", StringComparison.OrdinalIgnoreCase) | ||
&& !projectInstance.GetPropertyValue(PublishTrimmedPropertyName).Equals("true", StringComparison.OrdinalIgnoreCase) | ||
&& !trimRuntimeAssets; | ||
} | ||
|
||
/// <summary> | ||
/// Calculates the effective value of $(PublishDepsFilePath). In unspecified, the default value is calculated inside the GeneratePublishDependencyFile target. | ||
/// </summary> | ||
/// <remarks> | ||
/// This can return null in the case of PublishSingleFile since the deps.json file is embedded within the single-file bundle. | ||
/// </remarks> | ||
internal static string GetEffectivePublishDepsFilePath(ProjectInstance projectInstance) | ||
{ | ||
string publishDepsFilePath = projectInstance.GetPropertyValue(PublishDepsFilePathPropertyName); | ||
if (!string.IsNullOrEmpty(publishDepsFilePath)) | ||
{ | ||
return publishDepsFilePath; | ||
} | ||
|
||
if (!projectInstance.GetPropertyValue(PublishSingleFilePropertyName).Equals("true", StringComparison.OrdinalIgnoreCase)) | ||
{ | ||
return projectInstance.GetPropertyValue(PublishDirPropertyName) + projectInstance.GetPropertyValue(ProjectDepsFileNamePropertyName); | ||
} | ||
|
||
return null; | ||
} | ||
} |
40 changes: 40 additions & 0 deletions
40
src/BuildPrediction/Predictors/GenerateRuntimeConfigurationFilesPredictor.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
// Copyright (c) Microsoft. All rights reserved. | ||
// Licensed under the MIT license. See LICENSE file in the project root for full license information. | ||
|
||
using System; | ||
using System.IO; | ||
using Microsoft.Build.Execution; | ||
|
||
namespace Microsoft.Build.Prediction.Predictors; | ||
|
||
/// <summary> | ||
/// Makes predictions based on the GenerateRuntimeConfigurationFiles target. | ||
/// </summary> | ||
public sealed class GenerateRuntimeConfigurationFilesPredictor : IProjectPredictor | ||
{ | ||
internal const string GenerateRuntimeConfigurationFilesPropertyName = "GenerateRuntimeConfigurationFiles"; | ||
internal const string UserRuntimeConfigPropertyName = "UserRuntimeConfig"; | ||
internal const string ProjectRuntimeConfigFilePathPropertyName = "ProjectRuntimeConfigFilePath"; | ||
internal const string ProjectRuntimeConfigDevFilePathPropertyName = "ProjectRuntimeConfigDevFilePath"; | ||
|
||
/// <inheritdoc/> | ||
public void PredictInputsAndOutputs( | ||
ProjectInstance projectInstance, | ||
ProjectPredictionReporter predictionReporter) | ||
{ | ||
if (!projectInstance.GetPropertyValue(GenerateRuntimeConfigurationFilesPropertyName).Equals("true", StringComparison.OrdinalIgnoreCase)) | ||
{ | ||
return; | ||
} | ||
|
||
string userRuntimeConfig = projectInstance.GetPropertyValue(UserRuntimeConfigPropertyName); | ||
string userRuntimeConfigFullPath = Path.Combine(projectInstance.Directory, userRuntimeConfig); | ||
if (File.Exists(userRuntimeConfigFullPath)) | ||
{ | ||
predictionReporter.ReportInputFile(userRuntimeConfigFullPath); | ||
} | ||
|
||
predictionReporter.ReportOutputFile(projectInstance.GetPropertyValue(ProjectRuntimeConfigFilePathPropertyName)); | ||
predictionReporter.ReportOutputFile(projectInstance.GetPropertyValue(ProjectRuntimeConfigDevFilePathPropertyName)); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
69 changes: 69 additions & 0 deletions
69
src/BuildPredictionTests/Predictors/GenerateBuildDependencyFilePredictorTests.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
// Copyright (c) Microsoft. All rights reserved. | ||
// Licensed under the MIT license. See LICENSE file in the project root for full license information. | ||
|
||
using System.IO; | ||
using Microsoft.Build.Construction; | ||
using Microsoft.Build.Execution; | ||
using Microsoft.Build.Prediction.Predictors; | ||
using Xunit; | ||
|
||
namespace Microsoft.Build.Prediction.Tests.Predictors; | ||
|
||
public class GenerateBuildDependencyFilePredictorTests | ||
{ | ||
[Fact] | ||
public void DoesNotGenerateDependencyFile() | ||
{ | ||
ProjectRootElement projectRootElement = ProjectRootElement.Create("project.csproj"); | ||
|
||
string projectAssetsFile = Path.Combine(projectRootElement.DirectoryPath, @"obj\project.assets.json"); | ||
projectRootElement.AddProperty(GenerateBuildDependencyFilePredictor.ProjectAssetsFilePropertyName, projectAssetsFile); | ||
|
||
string projectDepsFilePath = Path.Combine(projectRootElement.DirectoryPath, @"bin\x64\Debug\net8.0\project.deps.json"); | ||
projectRootElement.AddProperty(GenerateBuildDependencyFilePredictor.ProjectDepsFilePathPropertyName, projectDepsFilePath); | ||
|
||
ProjectInstance projectInstance = TestHelpers.CreateProjectInstanceFromRootElement(projectRootElement); | ||
|
||
new GenerateBuildDependencyFilePredictor() | ||
.GetProjectPredictions(projectInstance) | ||
.AssertPredictions( | ||
projectInstance, | ||
null, | ||
null, | ||
null, | ||
null); | ||
} | ||
|
||
[Fact] | ||
public void GeneratesDependencyFile() | ||
{ | ||
ProjectRootElement projectRootElement = ProjectRootElement.Create("project.csproj"); | ||
projectRootElement.AddProperty(GenerateBuildDependencyFilePredictor.GenerateDependencyFilePropertyName, "true"); | ||
|
||
string projectAssetsFile = Path.Combine(projectRootElement.DirectoryPath, @"obj\project.assets.json"); | ||
projectRootElement.AddProperty(GenerateBuildDependencyFilePredictor.ProjectAssetsFilePropertyName, projectAssetsFile); | ||
|
||
string projectDepsFilePath = Path.Combine(projectRootElement.DirectoryPath, @"bin\x64\Debug\net8.0\project.deps.json"); | ||
projectRootElement.AddProperty(GenerateBuildDependencyFilePredictor.ProjectDepsFilePathPropertyName, projectDepsFilePath); | ||
|
||
ProjectInstance projectInstance = TestHelpers.CreateProjectInstanceFromRootElement(projectRootElement); | ||
|
||
var expectedInputFiles = new[] | ||
{ | ||
new PredictedItem(projectAssetsFile, nameof(GenerateBuildDependencyFilePredictor)), | ||
}; | ||
var expectedOutputFiles = new[] | ||
{ | ||
new PredictedItem(projectDepsFilePath, nameof(GenerateBuildDependencyFilePredictor)), | ||
}; | ||
|
||
new GenerateBuildDependencyFilePredictor() | ||
.GetProjectPredictions(projectInstance) | ||
.AssertPredictions( | ||
projectInstance, | ||
expectedInputFiles, | ||
null, | ||
expectedOutputFiles, | ||
null); | ||
} | ||
} |
Oops, something went wrong.