diff --git a/src/BuildPrediction/Predictors/GenerateBuildDependencyFilePredictor.cs b/src/BuildPrediction/Predictors/GenerateBuildDependencyFilePredictor.cs
new file mode 100644
index 0000000..5974613
--- /dev/null
+++ b/src/BuildPrediction/Predictors/GenerateBuildDependencyFilePredictor.cs
@@ -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;
+
+///
+/// Makes predictions based on the GenerateBuildDependencyFile target.
+///
+public sealed class GenerateBuildDependencyFilePredictor : IProjectPredictor
+{
+ internal const string GenerateDependencyFilePropertyName = "GenerateDependencyFile";
+ internal const string ProjectAssetsFilePropertyName = "ProjectAssetsFile";
+ internal const string ProjectDepsFilePathPropertyName = "ProjectDepsFilePath";
+
+ ///
+ 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));
+ }
+}
\ No newline at end of file
diff --git a/src/BuildPrediction/Predictors/GeneratePublishDependencyFilePredictor.cs b/src/BuildPrediction/Predictors/GeneratePublishDependencyFilePredictor.cs
new file mode 100644
index 0000000..bed8b8a
--- /dev/null
+++ b/src/BuildPrediction/Predictors/GeneratePublishDependencyFilePredictor.cs
@@ -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;
+
+///
+/// Makes predictions based on the GeneratePublishDependencyFile target.
+///
+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";
+
+ ///
+ 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.
+ }
+
+ ///
+ /// Determines the value of _UseBuildDependencyFile by emulating the behavior from the _ComputeUseBuildDependencyFile target (and the _ComputePackageReferencePublish target).
+ ///
+ 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;
+ }
+
+ ///
+ /// Calculates the effective value of $(PublishDepsFilePath). In unspecified, the default value is calculated inside the GeneratePublishDependencyFile target.
+ ///
+ ///
+ /// This can return null in the case of PublishSingleFile since the deps.json file is embedded within the single-file bundle.
+ ///
+ 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;
+ }
+}
\ No newline at end of file
diff --git a/src/BuildPrediction/Predictors/GenerateRuntimeConfigurationFilesPredictor.cs b/src/BuildPrediction/Predictors/GenerateRuntimeConfigurationFilesPredictor.cs
new file mode 100644
index 0000000..a7180b7
--- /dev/null
+++ b/src/BuildPrediction/Predictors/GenerateRuntimeConfigurationFilesPredictor.cs
@@ -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;
+
+///
+/// Makes predictions based on the GenerateRuntimeConfigurationFiles target.
+///
+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";
+
+ ///
+ 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));
+ }
+}
\ No newline at end of file
diff --git a/src/BuildPrediction/Predictors/GetCopyToOutputDirectoryItemsGraphPredictor.cs b/src/BuildPrediction/Predictors/GetCopyToOutputDirectoryItemsGraphPredictor.cs
index 9c1a95d..002d8fa 100644
--- a/src/BuildPrediction/Predictors/GetCopyToOutputDirectoryItemsGraphPredictor.cs
+++ b/src/BuildPrediction/Predictors/GetCopyToOutputDirectoryItemsGraphPredictor.cs
@@ -17,6 +17,7 @@ public sealed class GetCopyToOutputDirectoryItemsGraphPredictor : IProjectGraphP
internal const string UseCommonOutputDirectoryPropertyName = "UseCommonOutputDirectory";
internal const string OutDirPropertyName = "OutDir";
internal const string MSBuildCopyContentTransitivelyPropertyName = "MSBuildCopyContentTransitively";
+ internal const string HasRuntimeOutputPropertyName = "HasRuntimeOutput";
///
public void PredictInputsAndOutputs(ProjectGraphNode projectGraphNode, ProjectPredictionReporter predictionReporter)
@@ -62,6 +63,29 @@ private static void PredictInputsAndOutputs(
// Process each item type considered in GetCopyToOutputDirectoryXamlAppDefs
ReportCopyToOutputDirectoryItemsAsInputs(dependency.ProjectInstance, XamlAppDefPredictor.XamlAppDefItemName, outDir, predictionReporter);
+
+ // Process items added by AddDepsJsonAndRuntimeConfigToCopyItemsForReferencingProjects
+ bool hasRuntimeOutput = dependency.ProjectInstance.GetPropertyValue(HasRuntimeOutputPropertyName).Equals("true", StringComparison.OrdinalIgnoreCase);
+ if (hasRuntimeOutput)
+ {
+ if (dependency.ProjectInstance.GetPropertyValue(GenerateBuildDependencyFilePredictor.GenerateDependencyFilePropertyName).Equals("true", StringComparison.OrdinalIgnoreCase))
+ {
+ string projectDepsFilePath = dependency.ProjectInstance.GetPropertyValue(GenerateBuildDependencyFilePredictor.ProjectDepsFilePathPropertyName);
+ predictionReporter.ReportInputFile(projectDepsFilePath);
+ predictionReporter.ReportOutputFile(Path.Combine(outDir, Path.GetFileName(projectDepsFilePath)));
+ }
+
+ if (dependency.ProjectInstance.GetPropertyValue(GenerateRuntimeConfigurationFilesPredictor.GenerateRuntimeConfigurationFilesPropertyName).Equals("true", StringComparison.OrdinalIgnoreCase))
+ {
+ string projectRuntimeConfigFilePath = dependency.ProjectInstance.GetPropertyValue(GenerateRuntimeConfigurationFilesPredictor.ProjectRuntimeConfigFilePathPropertyName);
+ predictionReporter.ReportInputFile(projectRuntimeConfigFilePath);
+ predictionReporter.ReportOutputFile(Path.Combine(outDir, Path.GetFileName(projectRuntimeConfigFilePath)));
+
+ string projectRuntimeConfigDevFilePath = dependency.ProjectInstance.GetPropertyValue(GenerateRuntimeConfigurationFilesPredictor.ProjectRuntimeConfigDevFilePathPropertyName);
+ predictionReporter.ReportInputFile(projectRuntimeConfigDevFilePath);
+ predictionReporter.ReportOutputFile(Path.Combine(outDir, Path.GetFileName(projectRuntimeConfigDevFilePath)));
+ }
+ }
}
}
}
diff --git a/src/BuildPrediction/Predictors/GetCopyToPublishDirectoryItemsGraphPredictor.cs b/src/BuildPrediction/Predictors/GetCopyToPublishDirectoryItemsGraphPredictor.cs
index ec01839..f9fd669 100644
--- a/src/BuildPrediction/Predictors/GetCopyToPublishDirectoryItemsGraphPredictor.cs
+++ b/src/BuildPrediction/Predictors/GetCopyToPublishDirectoryItemsGraphPredictor.cs
@@ -79,6 +79,37 @@ private static void ReportCopyToPublishDirectoryItems(
ReportCopyToPublishDirectoryItems(projectInstance, EmbeddedResourceItemsPredictor.EmbeddedResourceItemName, publishDir, predictionReporter);
ReportCopyToPublishDirectoryItems(projectInstance, CompileItemsPredictor.CompileItemName, publishDir, predictionReporter);
ReportCopyToPublishDirectoryItems(projectInstance, NoneItemsPredictor.NoneItemName, publishDir, predictionReporter);
+
+ // Process items added by AddDepsJsonAndRuntimeConfigToPublishItemsForReferencingProjects
+ bool hasRuntimeOutput = projectInstance.GetPropertyValue(GetCopyToOutputDirectoryItemsGraphPredictor.HasRuntimeOutputPropertyName).Equals("true", StringComparison.OrdinalIgnoreCase);
+ if (hasRuntimeOutput)
+ {
+ if (projectInstance.GetPropertyValue(GenerateBuildDependencyFilePredictor.GenerateDependencyFilePropertyName).Equals("true", StringComparison.OrdinalIgnoreCase))
+ {
+ if (GeneratePublishDependencyFilePredictor.ShouldUseBuildDependencyFile(projectInstance))
+ {
+ string projectDepsFilePath = projectInstance.GetPropertyValue(GenerateBuildDependencyFilePredictor.ProjectDepsFilePathPropertyName);
+ predictionReporter.ReportInputFile(projectDepsFilePath);
+ predictionReporter.ReportOutputFile(Path.Combine(publishDir, Path.GetFileName(projectDepsFilePath)));
+ }
+ else
+ {
+ string publishDepsFilePath = GeneratePublishDependencyFilePredictor.GetEffectivePublishDepsFilePath(projectInstance);
+ if (publishDepsFilePath is not null)
+ {
+ predictionReporter.ReportInputFile(publishDepsFilePath);
+ predictionReporter.ReportOutputFile(Path.Combine(publishDir, Path.GetFileName(publishDepsFilePath)));
+ }
+ }
+ }
+
+ if (projectInstance.GetPropertyValue(GenerateRuntimeConfigurationFilesPredictor.GenerateRuntimeConfigurationFilesPropertyName).Equals("true", StringComparison.OrdinalIgnoreCase))
+ {
+ string projectRuntimeConfigFilePath = projectInstance.GetPropertyValue(GenerateRuntimeConfigurationFilesPredictor.ProjectRuntimeConfigFilePathPropertyName);
+ predictionReporter.ReportInputFile(projectRuntimeConfigFilePath);
+ predictionReporter.ReportOutputFile(Path.Combine(publishDir, Path.GetFileName(projectRuntimeConfigFilePath)));
+ }
+ }
}
private static void ReportCopyToPublishDirectoryItems(
diff --git a/src/BuildPrediction/ProjectPredictors.cs b/src/BuildPrediction/ProjectPredictors.cs
index e61f721..b4b91e5 100644
--- a/src/BuildPrediction/ProjectPredictors.cs
+++ b/src/BuildPrediction/ProjectPredictors.cs
@@ -61,6 +61,9 @@ public static class ProjectPredictors
///
///
///
+ ///
+ ///
+ ///
///
///
/// A collection of .
@@ -108,6 +111,9 @@ public static class ProjectPredictors
new CppContentFilesProjectOutputGroupPredictor(),
new LinkItemsPredictor(),
new DotnetSdkPredictor(),
+ new GenerateBuildDependencyFilePredictor(),
+ new GeneratePublishDependencyFilePredictor(),
+ new GenerateRuntimeConfigurationFilesPredictor(),
//// NOTE! When adding a new predictor here, be sure to update the doc comment above.
};
diff --git a/src/BuildPredictionTests/Predictors/GenerateBuildDependencyFilePredictorTests.cs b/src/BuildPredictionTests/Predictors/GenerateBuildDependencyFilePredictorTests.cs
new file mode 100644
index 0000000..60ed3bd
--- /dev/null
+++ b/src/BuildPredictionTests/Predictors/GenerateBuildDependencyFilePredictorTests.cs
@@ -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);
+ }
+}
\ No newline at end of file
diff --git a/src/BuildPredictionTests/Predictors/GeneratePublishDependencyFilePredictorTests.cs b/src/BuildPredictionTests/Predictors/GeneratePublishDependencyFilePredictorTests.cs
new file mode 100644
index 0000000..889cb5b
--- /dev/null
+++ b/src/BuildPredictionTests/Predictors/GeneratePublishDependencyFilePredictorTests.cs
@@ -0,0 +1,146 @@
+// 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 GeneratePublishDependencyFilePredictorTests
+{
+ [Fact]
+ public void DoesNotGenerateDependencyFile()
+ {
+ ProjectRootElement projectRootElement = ProjectRootElement.Create("project.csproj");
+
+ projectRootElement.AddProperty(GeneratePublishDependencyFilePredictor.IntermediateOutputPathPropertyName, @"obj\");
+ projectRootElement.AddProperty(GeneratePublishDependencyFilePredictor.PublishDirPropertyName, @"bin\x64\Debug\net8.0\publish\");
+ projectRootElement.AddProperty(GeneratePublishDependencyFilePredictor.ProjectDepsFileNamePropertyName, "project.deps.json");
+
+ 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 GeneratePublishDependencyFilePredictor()
+ .GetProjectPredictions(projectInstance)
+ .AssertPredictions(
+ projectInstance,
+ null,
+ null,
+ null,
+ null);
+ }
+
+ [Fact]
+ public void UseBuildDependencyFile()
+ {
+ ProjectRootElement projectRootElement = ProjectRootElement.Create("project.csproj");
+ projectRootElement.AddProperty(GenerateBuildDependencyFilePredictor.GenerateDependencyFilePropertyName, "true");
+
+ projectRootElement.AddProperty(GeneratePublishDependencyFilePredictor.IntermediateOutputPathPropertyName, @"obj\");
+ projectRootElement.AddProperty(GeneratePublishDependencyFilePredictor.PublishDirPropertyName, @"bin\x64\Debug\net8.0\publish\");
+ projectRootElement.AddProperty(GeneratePublishDependencyFilePredictor.ProjectDepsFileNamePropertyName, "project.deps.json");
+
+ 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 GeneratePublishDependencyFilePredictor()
+ .GetProjectPredictions(projectInstance)
+ .AssertPredictions(
+ projectInstance,
+ null,
+ null,
+ null,
+ null);
+ }
+
+ [Fact]
+ public void PublishTrimmed()
+ {
+ ProjectRootElement projectRootElement = ProjectRootElement.Create("project.csproj");
+ projectRootElement.AddProperty(GenerateBuildDependencyFilePredictor.GenerateDependencyFilePropertyName, "true");
+ projectRootElement.AddProperty(GeneratePublishDependencyFilePredictor.SelfContainedPropertyName, "true");
+ projectRootElement.AddProperty(GeneratePublishDependencyFilePredictor.PublishTrimmedPropertyName, "true");
+
+ projectRootElement.AddProperty(GeneratePublishDependencyFilePredictor.IntermediateOutputPathPropertyName, @"obj\");
+ projectRootElement.AddProperty(GeneratePublishDependencyFilePredictor.PublishDirPropertyName, @"bin\x64\Debug\net8.0\publish\");
+ projectRootElement.AddProperty(GeneratePublishDependencyFilePredictor.ProjectDepsFileNamePropertyName, "project.deps.json");
+
+ 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(GeneratePublishDependencyFilePredictor)),
+ };
+ var expectedOutputFiles = new[]
+ {
+ new PredictedItem(@"bin\x64\Debug\net8.0\publish\project.deps.json", nameof(GeneratePublishDependencyFilePredictor)),
+ };
+
+ new GeneratePublishDependencyFilePredictor()
+ .GetProjectPredictions(projectInstance)
+ .AssertPredictions(
+ projectInstance,
+ expectedInputFiles,
+ null,
+ expectedOutputFiles.MakeAbsolute(projectRootElement.DirectoryPath),
+ null);
+ }
+
+ [Fact]
+ public void PublishSingleFile()
+ {
+ ProjectRootElement projectRootElement = ProjectRootElement.Create("project.csproj");
+ projectRootElement.AddProperty(GenerateBuildDependencyFilePredictor.GenerateDependencyFilePropertyName, "true");
+ projectRootElement.AddProperty(GeneratePublishDependencyFilePredictor.SelfContainedPropertyName, "true");
+ projectRootElement.AddProperty(GeneratePublishDependencyFilePredictor.PublishSingleFilePropertyName, "true");
+
+ projectRootElement.AddProperty(GeneratePublishDependencyFilePredictor.IntermediateOutputPathPropertyName, @"obj\");
+ projectRootElement.AddProperty(GeneratePublishDependencyFilePredictor.PublishDirPropertyName, @"bin\x64\Debug\net8.0\publish\");
+ projectRootElement.AddProperty(GeneratePublishDependencyFilePredictor.ProjectDepsFileNamePropertyName, "project.deps.json");
+
+ 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(GeneratePublishDependencyFilePredictor)),
+ };
+ var expectedOutputFiles = new[]
+ {
+ new PredictedItem(@"obj\project.deps.json", nameof(GeneratePublishDependencyFilePredictor)),
+ };
+
+ new GeneratePublishDependencyFilePredictor()
+ .GetProjectPredictions(projectInstance)
+ .AssertPredictions(
+ projectInstance,
+ expectedInputFiles,
+ null,
+ expectedOutputFiles.MakeAbsolute(projectRootElement.DirectoryPath),
+ null);
+ }
+}
\ No newline at end of file
diff --git a/src/BuildPredictionTests/Predictors/GenerateRuntimeConfigurationFilesPredictorTests.cs b/src/BuildPredictionTests/Predictors/GenerateRuntimeConfigurationFilesPredictorTests.cs
new file mode 100644
index 0000000..8c07764
--- /dev/null
+++ b/src/BuildPredictionTests/Predictors/GenerateRuntimeConfigurationFilesPredictorTests.cs
@@ -0,0 +1,118 @@
+// 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.Construction;
+using Microsoft.Build.Execution;
+using Microsoft.Build.Prediction.Predictors;
+using Xunit;
+
+namespace Microsoft.Build.Prediction.Tests.Predictors;
+
+public class GenerateRuntimeConfigurationFilesPredictorTests
+{
+ private readonly string _rootDir;
+
+ public GenerateRuntimeConfigurationFilesPredictorTests()
+ {
+ // Isolate each test into its own folder
+ _rootDir = Path.Combine(Directory.GetCurrentDirectory(), nameof(GenerateRuntimeConfigurationFilesPredictorTests), Guid.NewGuid().ToString());
+ Directory.CreateDirectory(_rootDir);
+ }
+
+ [Fact]
+ public void DoesNotGenerateRuntimeConfigurationFiles()
+ {
+ ProjectRootElement projectRootElement = ProjectRootElement.Create(Path.Combine(_rootDir, @"src\project.csproj"));
+
+ string userRuntimeConfig = Path.Combine(projectRootElement.DirectoryPath, @"runtimeconfig.template.json");
+ projectRootElement.AddProperty(GenerateRuntimeConfigurationFilesPredictor.UserRuntimeConfigPropertyName, userRuntimeConfig);
+
+ string projectRuntimeConfigFilePath = Path.Combine(projectRootElement.DirectoryPath, @"bin\x64\Debug\net8.0\project.runtimeconfig.json");
+ projectRootElement.AddProperty(GenerateRuntimeConfigurationFilesPredictor.ProjectRuntimeConfigFilePathPropertyName, projectRuntimeConfigFilePath);
+
+ ProjectInstance projectInstance = TestHelpers.CreateProjectInstanceFromRootElement(projectRootElement);
+
+ new GenerateRuntimeConfigurationFilesPredictor()
+ .GetProjectPredictions(projectInstance)
+ .AssertPredictions(
+ projectInstance,
+ null,
+ null,
+ null,
+ null);
+ }
+
+ [Fact]
+ public void GeneratesRuntimeConfigurationFiles()
+ {
+ ProjectRootElement projectRootElement = ProjectRootElement.Create(Path.Combine(_rootDir, @"src\project.csproj"));
+ projectRootElement.AddProperty(GenerateRuntimeConfigurationFilesPredictor.GenerateRuntimeConfigurationFilesPropertyName, "true");
+
+ string userRuntimeConfig = Path.Combine(projectRootElement.DirectoryPath, @"runtimeconfig.template.json");
+ projectRootElement.AddProperty(GenerateRuntimeConfigurationFilesPredictor.UserRuntimeConfigPropertyName, userRuntimeConfig);
+
+ string projectRuntimeConfigFilePath = Path.Combine(projectRootElement.DirectoryPath, @"bin\x64\Debug\net8.0\project.runtimeconfig.json");
+ projectRootElement.AddProperty(GenerateRuntimeConfigurationFilesPredictor.ProjectRuntimeConfigFilePathPropertyName, projectRuntimeConfigFilePath);
+
+ string projectRuntimeConfigDevFilePath = Path.Combine(projectRootElement.DirectoryPath, @"bin\x64\Debug\net8.0\project.runtimeconfig.dev.json");
+ projectRootElement.AddProperty(GenerateRuntimeConfigurationFilesPredictor.ProjectRuntimeConfigDevFilePathPropertyName, projectRuntimeConfigDevFilePath);
+
+ ProjectInstance projectInstance = TestHelpers.CreateProjectInstanceFromRootElement(projectRootElement);
+
+ var expectedOutputFiles = new[]
+ {
+ new PredictedItem(projectRuntimeConfigFilePath, nameof(GenerateRuntimeConfigurationFilesPredictor)),
+ new PredictedItem(projectRuntimeConfigDevFilePath, nameof(GenerateRuntimeConfigurationFilesPredictor)),
+ };
+
+ new GenerateRuntimeConfigurationFilesPredictor()
+ .GetProjectPredictions(projectInstance)
+ .AssertPredictions(
+ projectInstance,
+ null,
+ null,
+ expectedOutputFiles,
+ null);
+ }
+
+ [Fact]
+ public void UserRuntimeConfigExists()
+ {
+ ProjectRootElement projectRootElement = ProjectRootElement.Create(Path.Combine(_rootDir, @"src\project.csproj"));
+ projectRootElement.AddProperty(GenerateRuntimeConfigurationFilesPredictor.GenerateRuntimeConfigurationFilesPropertyName, "true");
+
+ string userRuntimeConfig = Path.Combine(projectRootElement.DirectoryPath, @"runtimeconfig.template.json");
+ projectRootElement.AddProperty(GenerateRuntimeConfigurationFilesPredictor.UserRuntimeConfigPropertyName, userRuntimeConfig);
+ Directory.CreateDirectory(projectRootElement.DirectoryPath);
+ File.WriteAllText(userRuntimeConfig, "dummy");
+
+ string projectRuntimeConfigFilePath = Path.Combine(projectRootElement.DirectoryPath, @"bin\x64\Debug\net8.0\project.runtimeconfig.json");
+ projectRootElement.AddProperty(GenerateRuntimeConfigurationFilesPredictor.ProjectRuntimeConfigFilePathPropertyName, projectRuntimeConfigFilePath);
+
+ string projectRuntimeConfigDevFilePath = Path.Combine(projectRootElement.DirectoryPath, @"bin\x64\Debug\net8.0\project.runtimeconfig.dev.json");
+ projectRootElement.AddProperty(GenerateRuntimeConfigurationFilesPredictor.ProjectRuntimeConfigDevFilePathPropertyName, projectRuntimeConfigDevFilePath);
+
+ ProjectInstance projectInstance = TestHelpers.CreateProjectInstanceFromRootElement(projectRootElement);
+
+ var expectedInputFiles = new[]
+ {
+ new PredictedItem(userRuntimeConfig, nameof(GenerateRuntimeConfigurationFilesPredictor)),
+ };
+ var expectedOutputFiles = new[]
+ {
+ new PredictedItem(projectRuntimeConfigFilePath, nameof(GenerateRuntimeConfigurationFilesPredictor)),
+ new PredictedItem(projectRuntimeConfigDevFilePath, nameof(GenerateRuntimeConfigurationFilesPredictor)),
+ };
+
+ new GenerateRuntimeConfigurationFilesPredictor()
+ .GetProjectPredictions(projectInstance)
+ .AssertPredictions(
+ projectInstance,
+ expectedInputFiles,
+ null,
+ expectedOutputFiles,
+ null);
+ }
+}
\ No newline at end of file
diff --git a/src/BuildPredictionTests/Predictors/GetCopyToOutputDirectoryItemsGraphPredictorTests.cs b/src/BuildPredictionTests/Predictors/GetCopyToOutputDirectoryItemsGraphPredictorTests.cs
index 607690f..6f1ca15 100644
--- a/src/BuildPredictionTests/Predictors/GetCopyToOutputDirectoryItemsGraphPredictorTests.cs
+++ b/src/BuildPredictionTests/Predictors/GetCopyToOutputDirectoryItemsGraphPredictorTests.cs
@@ -33,7 +33,7 @@ public void NoCopy()
ProjectRootElement dep2 = CreateDependencyProject("dep2", shouldCopy);
ProjectRootElement dep3 = CreateDependencyProject("dep3", shouldCopy);
- // The main project depends on 1 and 2; 2 depends on 3; 3 depends on 1. Note that this predictor should *not* be transitive
+ // The main project depends on 1 and 2; 2 depends on 3; 3 depends on 1.
projectRootElement.AddItem("ProjectReference", @"..\dep1\dep1.proj");
projectRootElement.AddItem("ProjectReference", @"..\dep2\dep2.proj");
dep2.AddItem("ProjectReference", @"..\dep3\dep3.proj");
@@ -62,7 +62,7 @@ public void UseCommonOutputDirectory()
ProjectRootElement dep2 = CreateDependencyProject("dep2", shouldCopy);
ProjectRootElement dep3 = CreateDependencyProject("dep3", shouldCopy);
- // The main project depends on 1 and 2; 2 depends on 3; 3 depends on 1. Note that this predictor should *not* be transitive
+ // The main project depends on 1 and 2; 2 depends on 3; 3 depends on 1.
projectRootElement.AddItem("ProjectReference", @"..\dep1\dep1.proj");
projectRootElement.AddItem("ProjectReference", @"..\dep2\dep2.proj");
dep2.AddItem("ProjectReference", @"..\dep3\dep3.proj");
@@ -79,9 +79,11 @@ public void UseCommonOutputDirectory()
}
[Theory]
- [InlineData(false)]
- [InlineData(true)]
- public void WithCopy(bool copyContentTransitively)
+ [InlineData(false, false)]
+ [InlineData(true, false)]
+ [InlineData(false, true)]
+ [InlineData(true, true)]
+ public void WithCopy(bool copyContentTransitively, bool hasRuntimeOutput)
{
string projectFile = Path.Combine(_rootDir, @"src\project.csproj");
ProjectRootElement projectRootElement = ProjectRootElement.Create(projectFile);
@@ -92,10 +94,18 @@ public void WithCopy(bool copyContentTransitively)
ProjectRootElement dep2 = CreateDependencyProject("dep2", shouldCopy);
ProjectRootElement dep3 = CreateDependencyProject("dep3", shouldCopy);
- projectRootElement.AddProperty(GetCopyToOutputDirectoryItemsGraphPredictor.MSBuildCopyContentTransitivelyPropertyName, copyContentTransitively.ToString());
- dep1.AddProperty(GetCopyToOutputDirectoryItemsGraphPredictor.MSBuildCopyContentTransitivelyPropertyName, copyContentTransitively.ToString());
- dep2.AddProperty(GetCopyToOutputDirectoryItemsGraphPredictor.MSBuildCopyContentTransitivelyPropertyName, copyContentTransitively.ToString());
- dep3.AddProperty(GetCopyToOutputDirectoryItemsGraphPredictor.MSBuildCopyContentTransitivelyPropertyName, copyContentTransitively.ToString());
+ AddPropertyToAllProjects(GetCopyToOutputDirectoryItemsGraphPredictor.MSBuildCopyContentTransitivelyPropertyName, copyContentTransitively.ToString());
+
+ AddPropertyToAllProjects(GenerateBuildDependencyFilePredictor.ProjectDepsFilePathPropertyName, @"$(MSBuildProjectDirectory)\bin\$(MSBuildProjectName).deps.json");
+ AddPropertyToAllProjects(GenerateRuntimeConfigurationFilesPredictor.ProjectRuntimeConfigFilePathPropertyName, @"$(MSBuildProjectDirectory)\bin\$(MSBuildProjectName).runtimeconfig.json");
+ AddPropertyToAllProjects(GenerateRuntimeConfigurationFilesPredictor.ProjectRuntimeConfigDevFilePathPropertyName, @"$(MSBuildProjectDirectory)\bin\$(MSBuildProjectName).runtimeconfig.dev.json");
+
+ if (hasRuntimeOutput)
+ {
+ AddPropertyToAllProjects(GetCopyToOutputDirectoryItemsGraphPredictor.HasRuntimeOutputPropertyName, "true");
+ AddPropertyToAllProjects(GenerateBuildDependencyFilePredictor.GenerateDependencyFilePropertyName, "true");
+ AddPropertyToAllProjects(GenerateRuntimeConfigurationFilesPredictor.GenerateRuntimeConfigurationFilesPropertyName, "true");
+ }
// The main project depends on 1 and 2; 2 depends on 3; 3 depends on 1.
projectRootElement.AddItem("ProjectReference", @"..\dep1\dep1.proj");
@@ -136,6 +146,29 @@ public void WithCopy(bool copyContentTransitively)
new PredictedItem(@"src\bin\dep2.xaml", nameof(GetCopyToOutputDirectoryItemsGraphPredictor)),
];
+ if (hasRuntimeOutput)
+ {
+ expectedInputFiles.AddRange(
+ [
+ new PredictedItem(@"dep1\bin\dep1.deps.json", nameof(GetCopyToOutputDirectoryItemsGraphPredictor)),
+ new PredictedItem(@"dep1\bin\dep1.runtimeconfig.json", nameof(GetCopyToOutputDirectoryItemsGraphPredictor)),
+ new PredictedItem(@"dep1\bin\dep1.runtimeconfig.dev.json", nameof(GetCopyToOutputDirectoryItemsGraphPredictor)),
+ new PredictedItem(@"dep2\bin\dep2.deps.json", nameof(GetCopyToOutputDirectoryItemsGraphPredictor)),
+ new PredictedItem(@"dep2\bin\dep2.runtimeconfig.json", nameof(GetCopyToOutputDirectoryItemsGraphPredictor)),
+ new PredictedItem(@"dep2\bin\dep2.runtimeconfig.dev.json", nameof(GetCopyToOutputDirectoryItemsGraphPredictor)),
+ ]);
+
+ expectedOutputFiles.AddRange(
+ [
+ new PredictedItem(@"src\bin\dep1.deps.json", nameof(GetCopyToOutputDirectoryItemsGraphPredictor)),
+ new PredictedItem(@"src\bin\dep1.runtimeconfig.json", nameof(GetCopyToOutputDirectoryItemsGraphPredictor)),
+ new PredictedItem(@"src\bin\dep1.runtimeconfig.dev.json", nameof(GetCopyToOutputDirectoryItemsGraphPredictor)),
+ new PredictedItem(@"src\bin\dep2.deps.json", nameof(GetCopyToOutputDirectoryItemsGraphPredictor)),
+ new PredictedItem(@"src\bin\dep2.runtimeconfig.json", nameof(GetCopyToOutputDirectoryItemsGraphPredictor)),
+ new PredictedItem(@"src\bin\dep2.runtimeconfig.dev.json", nameof(GetCopyToOutputDirectoryItemsGraphPredictor)),
+ ]);
+ }
+
if (copyContentTransitively)
{
expectedInputFiles.AddRange(
@@ -155,6 +188,23 @@ public void WithCopy(bool copyContentTransitively)
new PredictedItem(@"src\bin\dep3.txt", nameof(GetCopyToOutputDirectoryItemsGraphPredictor)),
new PredictedItem(@"src\bin\dep3.xaml", nameof(GetCopyToOutputDirectoryItemsGraphPredictor)),
]);
+
+ if (hasRuntimeOutput)
+ {
+ expectedInputFiles.AddRange(
+ [
+ new PredictedItem(@"dep3\bin\dep3.deps.json", nameof(GetCopyToOutputDirectoryItemsGraphPredictor)),
+ new PredictedItem(@"dep3\bin\dep3.runtimeconfig.json", nameof(GetCopyToOutputDirectoryItemsGraphPredictor)),
+ new PredictedItem(@"dep3\bin\dep3.runtimeconfig.dev.json", nameof(GetCopyToOutputDirectoryItemsGraphPredictor)),
+ ]);
+
+ expectedOutputFiles.AddRange(
+ [
+ new PredictedItem(@"src\bin\dep3.deps.json", nameof(GetCopyToOutputDirectoryItemsGraphPredictor)),
+ new PredictedItem(@"src\bin\dep3.runtimeconfig.json", nameof(GetCopyToOutputDirectoryItemsGraphPredictor)),
+ new PredictedItem(@"src\bin\dep3.runtimeconfig.dev.json", nameof(GetCopyToOutputDirectoryItemsGraphPredictor)),
+ ]);
+ }
}
new GetCopyToOutputDirectoryItemsGraphPredictor()
@@ -165,6 +215,14 @@ public void WithCopy(bool copyContentTransitively)
null,
expectedOutputFiles,
null);
+
+ void AddPropertyToAllProjects(string propertyName, string propertyValue)
+ {
+ projectRootElement.AddProperty(propertyName, propertyValue);
+ dep1.AddProperty(propertyName, propertyValue);
+ dep2.AddProperty(propertyName, propertyValue);
+ dep3.AddProperty(propertyName, propertyValue);
+ }
}
private ProjectRootElement CreateDependencyProject(string projectName, bool shouldCopy)
diff --git a/src/BuildPredictionTests/Predictors/GetCopyToPublishDirectoryItemsGraphPredictorTests.cs b/src/BuildPredictionTests/Predictors/GetCopyToPublishDirectoryItemsGraphPredictorTests.cs
index 143cea3..de13944 100644
--- a/src/BuildPredictionTests/Predictors/GetCopyToPublishDirectoryItemsGraphPredictorTests.cs
+++ b/src/BuildPredictionTests/Predictors/GetCopyToPublishDirectoryItemsGraphPredictorTests.cs
@@ -2,6 +2,7 @@
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;
+using System.Collections.Generic;
using System.IO;
using Microsoft.Build.Construction;
using Microsoft.Build.Prediction.Predictors;
@@ -49,19 +50,33 @@ public void PublishNoCopy()
.AssertNoPredictions();
}
- [Fact]
- public void Publish()
+ [Theory]
+ [InlineData(false)]
+ [InlineData(true)]
+ public void Publish(bool hasRuntimeOutput)
{
string projectFile = Path.Combine(_rootDir, @"src\project.csproj");
ProjectRootElement projectRootElement = ProjectRootElement.Create(projectFile);
projectRootElement.DefaultTargets = "Publish";
- projectRootElement.AddProperty(GetCopyToPublishDirectoryItemsGraphPredictor.PublishDirPropertyName, @"bin\Publish");
const bool shouldCopy = true;
ProjectRootElement dep1 = CreateDependencyProject("dep1", shouldCopy);
ProjectRootElement dep2 = CreateDependencyProject("dep2", shouldCopy);
ProjectRootElement dep3 = CreateDependencyProject("dep3", shouldCopy);
+ AddPropertyToAllProjects(GetCopyToPublishDirectoryItemsGraphPredictor.PublishDirPropertyName, @"bin\Publish");
+ AddPropertyToAllProjects(GeneratePublishDependencyFilePredictor.ProjectDepsFileNamePropertyName, "$(MSBuildProjectName).deps.json");
+ AddPropertyToAllProjects(GenerateBuildDependencyFilePredictor.ProjectDepsFilePathPropertyName, @"$(MSBuildProjectDirectory)\bin\$(MSBuildProjectName).deps.json");
+ AddPropertyToAllProjects(GenerateRuntimeConfigurationFilesPredictor.ProjectRuntimeConfigFilePathPropertyName, @"$(MSBuildProjectDirectory)\bin\$(MSBuildProjectName).runtimeconfig.json");
+ AddPropertyToAllProjects(GenerateRuntimeConfigurationFilesPredictor.ProjectRuntimeConfigDevFilePathPropertyName, @"$(MSBuildProjectDirectory)\bin\$(MSBuildProjectName).runtimeconfig.dev.json");
+
+ if (hasRuntimeOutput)
+ {
+ AddPropertyToAllProjects(GetCopyToOutputDirectoryItemsGraphPredictor.HasRuntimeOutputPropertyName, "true");
+ AddPropertyToAllProjects(GenerateBuildDependencyFilePredictor.GenerateDependencyFilePropertyName, "true");
+ AddPropertyToAllProjects(GenerateRuntimeConfigurationFilesPredictor.GenerateRuntimeConfigurationFilesPropertyName, "true");
+ }
+
// The main project depends on 1 and 2; 2 depends on 3; 3 depends on 1. Note that this should *not* be transitive
projectRootElement.AddItem("ProjectReference", @"..\dep1\dep1.proj");
projectRootElement.AddItem("ProjectReference", @"..\dep2\dep2.proj");
@@ -73,8 +88,8 @@ public void Publish()
dep2.Save();
dep3.Save();
- var expectedInputFiles = new[]
- {
+ List expectedInputFiles =
+ [
new PredictedItem(@"dep1\dep1.xml", nameof(GetCopyToPublishDirectoryItemsGraphPredictor)),
new PredictedItem(@"dep1\dep1.resx", nameof(GetCopyToPublishDirectoryItemsGraphPredictor)),
new PredictedItem(@"dep1\dep1.cs", nameof(GetCopyToPublishDirectoryItemsGraphPredictor)),
@@ -83,10 +98,10 @@ public void Publish()
new PredictedItem(@"dep2\dep2.resx", nameof(GetCopyToPublishDirectoryItemsGraphPredictor)),
new PredictedItem(@"dep2\dep2.cs", nameof(GetCopyToPublishDirectoryItemsGraphPredictor)),
new PredictedItem(@"dep2\dep2.txt", nameof(GetCopyToPublishDirectoryItemsGraphPredictor)),
- };
+ ];
- var expectedOutputFiles = new[]
- {
+ List expectedOutputFiles =
+ [
new PredictedItem(@"src\bin\Publish\dep1.xml", nameof(GetCopyToPublishDirectoryItemsGraphPredictor)),
new PredictedItem(@"src\bin\Publish\dep1.resx", nameof(GetCopyToPublishDirectoryItemsGraphPredictor)),
new PredictedItem(@"src\bin\Publish\dep1.cs", nameof(GetCopyToPublishDirectoryItemsGraphPredictor)),
@@ -95,7 +110,30 @@ public void Publish()
new PredictedItem(@"src\bin\Publish\dep2.resx", nameof(GetCopyToPublishDirectoryItemsGraphPredictor)),
new PredictedItem(@"src\bin\Publish\dep2.cs", nameof(GetCopyToPublishDirectoryItemsGraphPredictor)),
new PredictedItem(@"src\bin\Publish\dep2.txt", nameof(GetCopyToPublishDirectoryItemsGraphPredictor)),
- };
+ ];
+
+ if (hasRuntimeOutput)
+ {
+ expectedInputFiles.AddRange(
+ [
+ new PredictedItem(@"src\bin\project.deps.json", nameof(GetCopyToPublishDirectoryItemsGraphPredictor)),
+ new PredictedItem(@"src\bin\project.runtimeconfig.json", nameof(GetCopyToPublishDirectoryItemsGraphPredictor)),
+ new PredictedItem(@"dep1\bin\dep1.deps.json", nameof(GetCopyToPublishDirectoryItemsGraphPredictor)),
+ new PredictedItem(@"dep1\bin\dep1.runtimeconfig.json", nameof(GetCopyToPublishDirectoryItemsGraphPredictor)),
+ new PredictedItem(@"dep2\bin\dep2.deps.json", nameof(GetCopyToPublishDirectoryItemsGraphPredictor)),
+ new PredictedItem(@"dep2\bin\dep2.runtimeconfig.json", nameof(GetCopyToPublishDirectoryItemsGraphPredictor)),
+ ]);
+
+ expectedOutputFiles.AddRange(
+ [
+ new PredictedItem(@"src\bin\Publish\project.deps.json", nameof(GetCopyToPublishDirectoryItemsGraphPredictor)),
+ new PredictedItem(@"src\bin\Publish\project.runtimeconfig.json", nameof(GetCopyToPublishDirectoryItemsGraphPredictor)),
+ new PredictedItem(@"src\bin\Publish\dep1.deps.json", nameof(GetCopyToPublishDirectoryItemsGraphPredictor)),
+ new PredictedItem(@"src\bin\Publish\dep1.runtimeconfig.json", nameof(GetCopyToPublishDirectoryItemsGraphPredictor)),
+ new PredictedItem(@"src\bin\Publish\dep2.deps.json", nameof(GetCopyToPublishDirectoryItemsGraphPredictor)),
+ new PredictedItem(@"src\bin\Publish\dep2.runtimeconfig.json", nameof(GetCopyToPublishDirectoryItemsGraphPredictor)),
+ ]);
+ }
new GetCopyToPublishDirectoryItemsGraphPredictor()
.GetProjectPredictions(projectFile)
@@ -105,6 +143,14 @@ public void Publish()
null,
expectedOutputFiles,
null);
+
+ void AddPropertyToAllProjects(string propertyName, string propertyValue)
+ {
+ projectRootElement.AddProperty(propertyName, propertyValue);
+ dep1.AddProperty(propertyName, propertyValue);
+ dep2.AddProperty(propertyName, propertyValue);
+ dep3.AddProperty(propertyName, propertyValue);
+ }
}
[Fact]