Skip to content
Closed
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
94 changes: 61 additions & 33 deletions src/Tasks/Microsoft.NET.Build.Tasks/ProcessFrameworkReferences.cs
Original file line number Diff line number Diff line change
Expand Up @@ -127,17 +127,15 @@ public class ProcessFrameworkReferences : TaskBase

private Version _normalizedTargetFrameworkVersion;

protected override void ExecuteCore()
void AddPacksForFrameworkReferences(
List<ITaskItem> packagesToDownload,
List<ITaskItem> runtimeFrameworks,
List<ITaskItem> targetingPacks,
List<ITaskItem> runtimePacks,
List<ITaskItem> unavailableRuntimePacks,
out List<KnownRuntimePack> knownRuntimePacksForTargetFramework
)
{
// Perf optimization: If there are no FrameworkReference items, then don't do anything
// (This means that if you don't have any direct framework references, you won't get any transitive ones either
if (FrameworkReferences == null || FrameworkReferences.Length == 0)
{
return;
}

_normalizedTargetFrameworkVersion = NormalizeVersion(new Version(TargetFrameworkVersion));

var knownFrameworkReferencesForTargetFramework =
KnownFrameworkReferences
.Select(item => new KnownFrameworkReference(item))
Expand All @@ -147,7 +145,7 @@ protected override void ExecuteCore()
// Get known runtime packs from known framework references.
// Only use items where the framework reference name matches the RuntimeFrameworkName.
// This will filter out known framework references for "profiles", ie WindowsForms and WPF
var knownRuntimePacksForTargetFramework =
knownRuntimePacksForTargetFramework =
knownFrameworkReferencesForTargetFramework
.Where(kfr => kfr.Name.Equals(kfr.RuntimeFrameworkName, StringComparison.OrdinalIgnoreCase))
.Select(kfr => kfr.ToKnownRuntimePack())
Expand All @@ -160,12 +158,6 @@ protected override void ExecuteCore()

var frameworkReferenceMap = FrameworkReferences.ToDictionary(fr => fr.ItemSpec, StringComparer.OrdinalIgnoreCase);

List<ITaskItem> packagesToDownload = new List<ITaskItem>();
List<ITaskItem> runtimeFrameworks = new List<ITaskItem>();
List<ITaskItem> targetingPacks = new List<ITaskItem>();
List<ITaskItem> runtimePacks = new List<ITaskItem>();
List<ITaskItem> unavailableRuntimePacks = new List<ITaskItem>();

HashSet<string> unrecognizedRuntimeIdentifiers = new HashSet<string>(StringComparer.OrdinalIgnoreCase);

bool windowsOnlyErrorLogged = false;
Expand Down Expand Up @@ -367,6 +359,39 @@ var runtimeRequiredByDeployment
runtimeFrameworks.Add(runtimeFramework);
}
}
}

protected override void ExecuteCore()
{
List<ITaskItem> packagesToDownload = null;
List<ITaskItem> runtimeFrameworks = null;
List<ITaskItem> targetingPacks = null;
List<ITaskItem> runtimePacks = null;
List<ITaskItem> unavailableRuntimePacks = null;
List<KnownRuntimePack> knownRuntimePacksForTargetFramework = null;

// Perf optimization: If there are no FrameworkReference items, then don't do anything
// (This means that if you don't have any direct framework references, you won't get any transitive ones either
if (FrameworkReferences != null && FrameworkReferences.Length != 0)
{
_normalizedTargetFrameworkVersion = NormalizeVersion(new Version(TargetFrameworkVersion));

packagesToDownload = new List<ITaskItem>();
runtimeFrameworks = new List<ITaskItem>();
targetingPacks = new List<ITaskItem>();
runtimePacks = new List<ITaskItem>();
unavailableRuntimePacks = new List<ITaskItem>();
AddPacksForFrameworkReferences(
packagesToDownload,
runtimeFrameworks,
targetingPacks,
runtimePacks,
unavailableRuntimePacks,
out knownRuntimePacksForTargetFramework);
}

_normalizedTargetFrameworkVersion ??= NormalizeVersion(new Version(TargetFrameworkVersion));
packagesToDownload ??= new List<ITaskItem>();

List<ITaskItem> implicitPackageReferences = new List<ITaskItem>();

Expand Down Expand Up @@ -417,22 +442,22 @@ var runtimeRequiredByDeployment
PackagesToDownload = packagesToDownload.Distinct(new PackageToDownloadComparer<ITaskItem>()).ToArray();
}

if (runtimeFrameworks.Any())
if (runtimeFrameworks?.Any() == true)
{
RuntimeFrameworks = runtimeFrameworks.ToArray();
}

if (targetingPacks.Any())
if (targetingPacks?.Any() == true)
{
TargetingPacks = targetingPacks.ToArray();
}

if (runtimePacks.Any())
if (runtimePacks?.Any() == true)
{
RuntimePacks = runtimePacks.ToArray();
}

if (unavailableRuntimePacks.Any())
if (unavailableRuntimePacks?.Any() == true)
{
UnavailableRuntimePacks = unavailableRuntimePacks.ToArray();
}
Expand All @@ -442,22 +467,25 @@ var runtimeRequiredByDeployment
ImplicitPackageReferences = implicitPackageReferences.ToArray();
}

// Determine the known runtime identifier platforms based on all available Microsoft.NETCore.App packs
HashSet<string> knownRuntimeIdentifierPlatforms = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
var netCoreAppPacks = knownRuntimePacksForTargetFramework.Where(krp => krp.Name.Equals("Microsoft.NETCore.App", StringComparison.OrdinalIgnoreCase));
foreach (KnownRuntimePack netCoreAppPack in netCoreAppPacks)
if (knownRuntimePacksForTargetFramework?.Any() == true)
{
foreach (var runtimeIdentifier in netCoreAppPack.RuntimePackRuntimeIdentifiers.Split(';'))
// Determine the known runtime identifier platforms based on all available Microsoft.NETCore.App packs
HashSet<string> knownRuntimeIdentifierPlatforms = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
var netCoreAppPacks = knownRuntimePacksForTargetFramework!.Where(krp => krp.Name.Equals("Microsoft.NETCore.App", StringComparison.OrdinalIgnoreCase));
foreach (KnownRuntimePack netCoreAppPack in netCoreAppPacks)
{
int separator = runtimeIdentifier.LastIndexOf('-');
string platform = separator < 0 ? runtimeIdentifier : runtimeIdentifier.Substring(0, separator);
knownRuntimeIdentifierPlatforms.Add(platform);
foreach (var runtimeIdentifier in netCoreAppPack.RuntimePackRuntimeIdentifiers.Split(';'))
{
int separator = runtimeIdentifier.LastIndexOf('-');
string platform = separator < 0 ? runtimeIdentifier : runtimeIdentifier.Substring(0, separator);
knownRuntimeIdentifierPlatforms.Add(platform);
}
}
}

if (knownRuntimeIdentifierPlatforms.Count > 0)
{
KnownRuntimeIdentifierPlatforms = knownRuntimeIdentifierPlatforms.ToArray();
if (knownRuntimeIdentifierPlatforms.Count > 0)
{
KnownRuntimeIdentifierPlatforms = knownRuntimeIdentifierPlatforms.ToArray();
}
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<!--
<!--
***********************************************************************************************
Microsoft.NET.Sdk.FrameworkReferenceResolution.targets

Expand Down Expand Up @@ -60,7 +60,7 @@ Copyright (c) .NET Foundation. All rights reserved.

<Target Name="ProcessFrameworkReferences" BeforeTargets="_CheckForInvalidConfigurationAndPlatform;CollectPackageReferences;CollectPackageDownloads"
DependsOnTargets="AddWindowsSdkKnownFrameworkReferences"
Condition="'@(FrameworkReference)' != ''">
Condition="'@(FrameworkReference)' != '' Or '$(_RequiresILLinkPack)' == 'true'">

<CheckForDuplicateFrameworkReferences
FrameworkReferences="@(FrameworkReference)"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1104,7 +1104,7 @@ public void It_publishes_with_implicit_rid_with_rid_specific_properties(string e
var testProject = new TestProject()
{
Name = "PublishImplicitRid",
TargetFrameworks = $"net472;{ToolsetInfo.CurrentTargetFramework}",
TargetFrameworks = ToolsetInfo.CurrentTargetFramework
};
testProject.AdditionalProperties.Add("IsPublishable", "false");
var testAsset = _testAssetsManager.CreateTestProject(testProject, identifier: executeOptionsAndProperties);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ public void It_errors_when_publishing_single_file_lib()
var testProject = new TestProject()
{
Name = "ClassLib",
TargetFrameworks = "netstandard2.0",
TargetFrameworks = "netcoreapp3.0",
IsExe = false,
};

Expand Down Expand Up @@ -187,7 +187,9 @@ public void It_errors_when_targetting_netstandard()
.Should()
.Fail()
.And
.HaveStdOutContaining(Strings.CanOnlyHaveSingleFileWithNetCoreApp)
// Single-file depends on ILLink analyzers, so fails early when trying
// to add the analyzer reference for an unsupported TFM.
.HaveStdOutContaining(Strings.ILLinkNoValidRuntimePackageError)
.And
.NotHaveStdOutContaining(Strings.CannotHaveSingleFileWithoutExecutable);
}
Expand All @@ -210,7 +212,9 @@ public void It_errors_when_targetting_netcoreapp_2_x()
.Should()
.Fail()
.And
.HaveStdOutContaining(Strings.PublishSingleFileRequiresVersion30);
// Single-file depends on ILLink analyzers, so fails early when trying
// to add the analyzer reference for an unsupported TFM.
.HaveStdOutContaining(Strings.ILLinkNoValidRuntimePackageError);
}

[RequiresMSBuildVersionFact("16.8.0")]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -162,11 +162,33 @@ public void ILLink_fails_when_no_matching_pack_is_found(string targetFramework)
}

[RequiresMSBuildVersionTheory("17.0.0.32901")]
// TODO: enable netstandard2.0 once ProcessFrameworkReferences is fixed to run
// when tool packs are referenced. See https://github.com/dotnet/sdk/pull/33062.
// Currently netstandard2.0 skips ProcessFrameworkReference because FrameworkReference
// is empty.
// [InlineData("netstandard2.0")]
[InlineData("netstandard2.0")]
[InlineData("netstandard2.1")]
public void ILLink_fails_on_unsupported_target_framework(string targetFramework)
{
var projectName = "HelloWorld";
var rid = EnvironmentInfo.GetCompatibleRid(targetFramework);

var testProject = CreateTestProjectForILLinkTesting(targetFramework, projectName);
var testAsset = _testAssetsManager.CreateTestProject(testProject, identifier: targetFramework);

var buildCommand = new BuildCommand(testAsset);

buildCommand.Execute($"/p:RuntimeIdentifier={rid}", "/p:PublishTrimmed=true")
.Should().Fail()
.And.HaveStdOutContaining("error NETSDK1195");

buildCommand.Execute($"/p:RuntimeIdentifier={rid}", "/p:IsTrimmable=true")
.Should().Fail()
.And.HaveStdOutContaining("error NETSDK1195");

buildCommand.Execute($"/p:RuntimeIdentifier={rid}", "/p:EnableTrimAnalyzer=true")
.Should().Fail()
.And.HaveStdOutContaining("error NETSDK1195");
}

[RequiresMSBuildVersionTheory("17.0.0.32901")]
[InlineData("netstandard2.0")]
[InlineData("netstandard2.1")]
public void ILLink_can_use_latest_with_unsupported_target_framework(string targetFramework)
{
Expand Down Expand Up @@ -1789,9 +1811,11 @@ public void It_warns_when_targeting_netcoreapp_2_x_illink()

publishCommand.Execute($"/p:PublishTrimmed=true")
.Should()
.Pass()
.Fail()
.And
.HaveStdOutContaining(Strings.PublishTrimmedRequiresVersion30);
// Fails early when trying to add the illink pack for an
// unsupported TFM.
.HaveStdOutContaining(Strings.ILLinkNoValidRuntimePackageError);
}

private void SetMetadata(XDocument project, string assemblyName, string key, string value)
Expand Down