From 83912b834dc3faabe02d7ac76997bc9127473cb3 Mon Sep 17 00:00:00 2001 From: Nick Guerrera Date: Mon, 13 Nov 2017 16:25:52 -0800 Subject: [PATCH 1/2] Work around #1730 --- .../Microsoft.NET.Build.Extensions.Tasks.csproj | 2 +- .../Microsoft.NET.Build.Tasks/Microsoft.NET.Build.Tasks.csproj | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Tasks/Microsoft.NET.Build.Extensions.Tasks/Microsoft.NET.Build.Extensions.Tasks.csproj b/src/Tasks/Microsoft.NET.Build.Extensions.Tasks/Microsoft.NET.Build.Extensions.Tasks.csproj index d88227a6de0b..78348d529fdb 100644 --- a/src/Tasks/Microsoft.NET.Build.Extensions.Tasks/Microsoft.NET.Build.Extensions.Tasks.csproj +++ b/src/Tasks/Microsoft.NET.Build.Extensions.Tasks/Microsoft.NET.Build.Extensions.Tasks.csproj @@ -195,7 +195,7 @@ - + <_CopyLocalButNotPublished Include="@(AllCopyLocalItems)" Exclude="@(ResolvedAssembliesToPublish)" /> diff --git a/src/Tasks/Microsoft.NET.Build.Tasks/Microsoft.NET.Build.Tasks.csproj b/src/Tasks/Microsoft.NET.Build.Tasks/Microsoft.NET.Build.Tasks.csproj index fde184561237..f9782c0550c8 100644 --- a/src/Tasks/Microsoft.NET.Build.Tasks/Microsoft.NET.Build.Tasks.csproj +++ b/src/Tasks/Microsoft.NET.Build.Tasks/Microsoft.NET.Build.Tasks.csproj @@ -89,7 +89,7 @@ - + <_CopyLocalButNotPublished Include="@(AllCopyLocalItems)" Exclude="@(ResolvedAssembliesToPublish)" /> From 516c0d577292d5a4db380453057cda20c3f41a74 Mon Sep 17 00:00:00 2001 From: Nick Guerrera Date: Fri, 10 Nov 2017 15:54:19 -0800 Subject: [PATCH 2/2] Add reference metadata to indicate that RAR can skip dependency searching --- ....NET.Build.Extensions.NETFramework.targets | 9 ++ ...rosoft.PackageDependencyResolution.targets | 20 ++++ .../GivenThatWeWantToBuildADesktopLibrary.cs | 107 ++++++++++++++++++ .../GivenThatWeWantToBuildALibrary.cs | 49 ++++++++ 4 files changed, 185 insertions(+) diff --git a/src/Tasks/Microsoft.NET.Build.Extensions.Tasks/msbuildExtensions/Microsoft/Microsoft.NET.Build.Extensions/Microsoft.NET.Build.Extensions.NETFramework.targets b/src/Tasks/Microsoft.NET.Build.Extensions.Tasks/msbuildExtensions/Microsoft/Microsoft.NET.Build.Extensions/Microsoft.NET.Build.Extensions.NETFramework.targets index 2a6044540e2d..8e260fadbce7 100644 --- a/src/Tasks/Microsoft.NET.Build.Extensions.Tasks/msbuildExtensions/Microsoft/Microsoft.NET.Build.Extensions/Microsoft.NET.Build.Extensions.NETFramework.targets +++ b/src/Tasks/Microsoft.NET.Build.Extensions.Tasks/msbuildExtensions/Microsoft/Microsoft.NET.Build.Extensions/Microsoft.NET.Build.Extensions.NETFramework.targets @@ -65,6 +65,14 @@ Copyright (c) .NET Foundation. All rights reserved. + + + true + + + + true + + + + $(MarkPackageReferencesAsExternallyResolved) + + %(FullPath) + $(MarkPackageReferencesAsExternallyResolved) diff --git a/test/Microsoft.NET.Build.Tests/GivenThatWeWantToBuildADesktopLibrary.cs b/test/Microsoft.NET.Build.Tests/GivenThatWeWantToBuildADesktopLibrary.cs index 8af5e5fdac33..5eeeae7f9220 100644 --- a/test/Microsoft.NET.Build.Tests/GivenThatWeWantToBuildADesktopLibrary.cs +++ b/test/Microsoft.NET.Build.Tests/GivenThatWeWantToBuildADesktopLibrary.cs @@ -26,6 +26,39 @@ public GivenThatWeWantToBuildADesktopLibrary(ITestOutputHelper log) : base(log) { } + [WindowsOnlyFact] + public void It_gets_implicit_designtime_facades_when_package_reference_uses_system_runtime() + { + // The repro here is very sensitive to the target framework and packages used. This specific case + // net46 using only System.Collections.Immutable v1.4.0 will not pull in System.Runtime from a + // package or from Microsoft.NET.Build.Extensions as a primary reference and so RARs dependency + // walk needs to find it in order for ImplictlyExpandDesignTimeFacades to inject it. + + var netFrameworkLibrary = new TestProject() + { + Name = "NETFrameworkLibrary", + TargetFrameworks = "net46", + IsSdkProject = true, + }; + + netFrameworkLibrary.PackageReferences.Add(new TestPackageReference("System.Collections.Immutable", "1.4.0")); + + netFrameworkLibrary.SourceFiles["NETFramework.cs"] = @" + using System.Collections.Immutable; + public class NETFramework + { + public void Method1() + { + ImmutableList.Empty.Add(""""); + } + }"; + + var testAsset = _testAssetsManager.CreateTestProject(netFrameworkLibrary, "FacadesFromTargetFramework").Restore(Log, netFrameworkLibrary.Name); + var buildCommand = new BuildCommand(Log, Path.Combine(testAsset.TestRoot, netFrameworkLibrary.Name)); + buildCommand.Execute().Should().Pass(); + } + + [Fact] public void It_can_use_HttpClient_and_exchange_the_type_with_a_NETStandard_library() { @@ -372,5 +405,79 @@ public void It_uses_hintpath_when_replacing_simple_name_references(bool useFacad .metadata["HintPath"] .Should().Be(correctHttpReference); } + + [WindowsOnlyTheory] + [InlineData(null)] + [InlineData(true)] + [InlineData(false)] + public void It_marks_extension_references_as_externally_resolved(bool? markAsExternallyResolved) + { + var project = new TestProject + { + Name = "NETFrameworkLibrary", + TargetFrameworks = "net462", + IsSdkProject = true + }; + + var netStandard2Project = new TestProject + { + Name = "NETStandard20Project", + TargetFrameworks = "netstandard2.0", + IsSdkProject = true + }; + + project.ReferencedProjects.Add(netStandard2Project); + + var asset = _testAssetsManager.CreateTestProject( + project, + "ExternallyResolvedExtensions", + markAsExternallyResolved.ToString()) + .WithProjectChanges((path, p) => + { + if (markAsExternallyResolved != null) + { + var ns = p.Root.Name.Namespace; + p.Root.Add( + new XElement(ns + "PropertyGroup", + new XElement(ns + "MarkNETFrameworkExtensionAssembliesAsExternallyResolved", + markAsExternallyResolved))); + } + }) + .Restore(Log, project.Name); + + var command = new GetValuesCommand( + Log, + Path.Combine(asset.Path, project.Name), + project.TargetFrameworks, + "Reference", + GetValuesCommand.ValueType.Item); + + command.MetadataNames.AddRange(new[] { "ExternallyResolved", "HintPath" }); + command.Execute().Should().Pass(); + + int frameworkReferenceCount = 0; + int extensionReferenceCount = 0; + var references = command.GetValuesWithMetadata(); + + foreach (var (value, metadata) in references) + { + if (metadata["HintPath"] == "") + { + // implicit framework reference (not externally resolved) + metadata["ExternallyResolved"].Should().BeEmpty(); + frameworkReferenceCount++; + } + else + { + // reference added by Microsoft.NET.Build.Extensions + metadata["ExternallyResolved"].Should().BeEquivalentTo((markAsExternallyResolved ?? true).ToString()); + extensionReferenceCount++; + } + } + + // make sure both cases were encountered + frameworkReferenceCount.Should().BeGreaterThan(0); + extensionReferenceCount.Should().BeGreaterThan(0); + } } } diff --git a/test/Microsoft.NET.Build.Tests/GivenThatWeWantToBuildALibrary.cs b/test/Microsoft.NET.Build.Tests/GivenThatWeWantToBuildALibrary.cs index 3381bf386bab..3737cc2873eb 100644 --- a/test/Microsoft.NET.Build.Tests/GivenThatWeWantToBuildALibrary.cs +++ b/test/Microsoft.NET.Build.Tests/GivenThatWeWantToBuildALibrary.cs @@ -731,5 +731,54 @@ public void It_can_target_uwp_using_sdk_extras() .Should() .Pass(); } + + [Theory] + [InlineData(null)] + [InlineData(true)] + [InlineData(false)] + public void It_marks_package_references_as_externally_resolved(bool? markAsExternallyResolved) + { + var project = new TestProject + { + Name = "Library", + TargetFrameworks = "netstandard2.0", + IsSdkProject = true + }; + + var asset = _testAssetsManager.CreateTestProject( + project, + "ExternallyResolvedPackages", + markAsExternallyResolved.ToString()) + .WithProjectChanges((path, p) => + { + if (markAsExternallyResolved != null) + { + var ns = p.Root.Name.Namespace; + p.Root.Add( + new XElement(ns + "PropertyGroup", + new XElement(ns + "MarkPackageReferencesAsExternallyResolved", + markAsExternallyResolved))); + } + }) + .Restore(Log, project.Name); + + var command = new GetValuesCommand( + Log, + Path.Combine(asset.Path, project.Name), + project.TargetFrameworks, + "Reference", + GetValuesCommand.ValueType.Item); + + command.MetadataNames.Add("ExternallyResolved"); + command.Execute().Should().Pass(); + + var references = command.GetValuesWithMetadata(); + references.Should().NotBeEmpty(); + + foreach (var (value, metadata) in references) + { + metadata["ExternallyResolved"].Should().BeEquivalentTo((markAsExternallyResolved ?? true).ToString()); + } + } } }