diff --git a/DotnetCLIVersion.txt b/DotnetCLIVersion.txt
index ef8243bbefc0..38fa37cc7dee 100644
--- a/DotnetCLIVersion.txt
+++ b/DotnetCLIVersion.txt
@@ -1 +1 @@
-15.5.0-preview-007044
+2.1.1-preview-007089
diff --git a/src/Tasks/Microsoft.NET.Build.Extensions.Tasks/GetDependsOnNETStandard.cs b/src/Tasks/Microsoft.NET.Build.Extensions.Tasks/GetDependsOnNETStandard.cs
index 3e7b5908c6bd..16947e761996 100644
--- a/src/Tasks/Microsoft.NET.Build.Extensions.Tasks/GetDependsOnNETStandard.cs
+++ b/src/Tasks/Microsoft.NET.Build.Extensions.Tasks/GetDependsOnNETStandard.cs
@@ -22,6 +22,17 @@ public partial class GetDependsOnNETStandard : TaskBase
private const string SystemRuntimeAssemblyName = "System.Runtime";
private static readonly Version SystemRuntimeMinVersion = new Version(4, 1, 0, 0);
+ // Encountered conflict between 'Platform:System.IO.Compression.dll' and 'CopyLocal:C:\git\dotnet-sdk\packages\system.io.compression\4.3.0\runtimes\win\lib\net46\System.IO.Compression.dll'. Choosing 'CopyLocal:C:\git\dotnet-sdk\packages\system.io.compression\4.3.0\runtimes\win\lib\net46\System.IO.Compression.dll' because AssemblyVersion '4.1.2.0' is greater than '4.0.0.0'.
+ // .NET Standard facade version: 4.2.0.0
+ // Encountered conflict between 'Platform:System.Net.Http.dll' and 'CopyLocal:C:\git\dotnet-sdk\packages\system.net.http\4.3.0\runtimes\win\lib\net46\System.Net.Http.dll'. Choosing 'CopyLocal:C:\git\dotnet-sdk\packages\system.net.http\4.3.0\runtimes\win\lib\net46\System.Net.Http.dll' because AssemblyVersion '4.1.1.0' is greater than '4.0.0.0'.
+ // .NET Standard facade version: 4.2.0.0
+
+ private const string SystemIOCompressionAssemblyName = "System.IO.Compression";
+ private static readonly Version SystemIOCompressionMinVersion = new Version(4, 1, 0, 0);
+
+ private const string SystemNetHttpAssemblyName = "System.Net.Http";
+ private static readonly Version SystemNetHttpMinVersion = new Version(4, 1, 0, 0);
+
///
/// Set of reference items to analyze.
///
@@ -34,13 +45,29 @@ public partial class GetDependsOnNETStandard : TaskBase
[Output]
public bool DependsOnNETStandard { get; set; }
+ ///
+ /// True if any of the references depend on a version of System.IO.Compression at least 4.0.1.0 (ie from a NuGet package)
+ ///
+ [Output]
+ public bool DependsOnNuGetCompression { get; set; }
+
+ ///
+ /// True if any of the references depend on a version of System.Net.Http at least 4.0.1.0 (ie from a NuGet package)
+ ///
+ [Output]
+ public bool DependsOnNuGetHttp { get; set; }
+
protected override void ExecuteCore()
{
- DependsOnNETStandard = AnyReferenceDependsOnNETStandard();
+ ProcessReferences();
}
- private bool AnyReferenceDependsOnNETStandard()
+ private void ProcessReferences()
{
+ DependsOnNETStandard = false;
+ DependsOnNuGetCompression = false;
+ DependsOnNuGetHttp = false;
+
foreach (var reference in References)
{
var referenceSourcePath = ItemUtilities.GetSourcePath(reference);
@@ -49,10 +76,15 @@ private bool AnyReferenceDependsOnNETStandard()
{
try
{
- if (GetFileDependsOnNETStandard(referenceSourcePath))
- {
- return true;
- }
+ bool dependsOnNETStandard;
+ bool dependsOnNuGetCompression;
+ bool dependsOnNuGetHttp;
+
+ GetFileDependsOn(referenceSourcePath, out dependsOnNETStandard, out dependsOnNuGetCompression, out dependsOnNuGetHttp);
+
+ DependsOnNETStandard |= dependsOnNETStandard;
+ DependsOnNuGetCompression |= dependsOnNuGetCompression;
+ DependsOnNuGetHttp |= dependsOnNuGetHttp;
}
catch (Exception e) when (IsReferenceException(e))
{
@@ -62,7 +94,7 @@ private bool AnyReferenceDependsOnNETStandard()
}
}
- return false;
+
}
// ported from MSBuild's ReferenceTable.SetPrimaryAssemblyReferenceItem
diff --git a/src/Tasks/Microsoft.NET.Build.Extensions.Tasks/GetDependsOnNETStandard.net46.cs b/src/Tasks/Microsoft.NET.Build.Extensions.Tasks/GetDependsOnNETStandard.net46.cs
index 04109268f7af..34dc20bb82b5 100644
--- a/src/Tasks/Microsoft.NET.Build.Extensions.Tasks/GetDependsOnNETStandard.net46.cs
+++ b/src/Tasks/Microsoft.NET.Build.Extensions.Tasks/GetDependsOnNETStandard.net46.cs
@@ -19,8 +19,15 @@ public partial class GetDependsOnNETStandard
// - load / JIT cost of SRM and its closure
// - deal with bindingRedirects/unification needed to load SRM's closure.
- internal static bool GetFileDependsOnNETStandard(string filePath)
+ internal static void GetFileDependsOn(string filePath,
+ out bool dependsOnNETStandard,
+ out bool dependsOnNuGetCompression,
+ out bool dependsOnNuGetHttp)
{
+ dependsOnNETStandard = false;
+ dependsOnNuGetCompression = false;
+ dependsOnNuGetHttp = false;
+
// Ported from Microsoft.Build.Tasks.AssemblyInformation
if (Environment.OSVersion.Platform == PlatformID.Unix || Environment.OSVersion.Platform == PlatformID.MacOSX)
{
@@ -34,7 +41,22 @@ internal static bool GetFileDependsOnNETStandard(string filePath)
{
if (referencedAssembly.Name.Equals(NetStandardAssemblyName, StringComparison.Ordinal))
{
- return true;
+ dependsOnNETStandard = true;
+ }
+ else if (referencedAssembly.Name.Equals(SystemRuntimeAssemblyName, StringComparison.Ordinal) &&
+ referencedAssembly.Version >= SystemRuntimeMinVersion)
+ {
+ dependsOnNETStandard = true;
+ }
+ else if (referencedAssembly.Name.Equals(SystemIOCompressionAssemblyName, StringComparison.Ordinal) &&
+ referencedAssembly.Version >= SystemIOCompressionMinVersion)
+ {
+ dependsOnNuGetCompression = true;
+ }
+ else if (referencedAssembly.Name.Equals(SystemNetHttpAssemblyName, StringComparison.Ordinal) &&
+ referencedAssembly.Version >= SystemNetHttpMinVersion)
+ {
+ dependsOnNuGetHttp = true;
}
}
}
@@ -105,20 +127,26 @@ internal static bool GetFileDependsOnNETStandard(string filePath)
out flags);
var assemblyName = assemblyNameBuffer.ToString();
+ var assemblyVersion = new Version(assemblyMD.usMajorVersion, assemblyMD.usMinorVersion, assemblyMD.usBuildNumber, assemblyMD.usRevisionNumber);
if (assemblyName.Equals(NetStandardAssemblyName, StringComparison.Ordinal))
{
- return true;
+ dependsOnNETStandard = true;
}
-
- if (assemblyName.Equals(SystemRuntimeAssemblyName, StringComparison.Ordinal))
+ else if (assemblyName.Equals(SystemRuntimeAssemblyName, StringComparison.Ordinal) &&
+ assemblyVersion >= SystemRuntimeMinVersion)
{
- var assemblyVersion = new Version(assemblyMD.usMajorVersion, assemblyMD.usMinorVersion, assemblyMD.usBuildNumber, assemblyMD.usRevisionNumber);
-
- if (assemblyVersion >= SystemRuntimeMinVersion)
- {
- return true;
- }
+ dependsOnNETStandard = true;
+ }
+ else if (assemblyName.Equals(SystemIOCompressionAssemblyName, StringComparison.Ordinal) &&
+ assemblyVersion >= SystemIOCompressionMinVersion)
+ {
+ dependsOnNuGetCompression = true;
+ }
+ else if (assemblyName.Equals(SystemNetHttpAssemblyName, StringComparison.Ordinal) &&
+ assemblyVersion >= SystemNetHttpMinVersion)
+ {
+ dependsOnNuGetHttp = true;
}
}
} while (fetched > 0);
@@ -141,7 +169,6 @@ internal static bool GetFileDependsOnNETStandard(string filePath)
}
}
}
- return false;
}
#region Interop
diff --git a/src/Tasks/Microsoft.NET.Build.Extensions.Tasks/GetDependsOnNETStandard.netstandard.cs b/src/Tasks/Microsoft.NET.Build.Extensions.Tasks/GetDependsOnNETStandard.netstandard.cs
index b7ed956079be..a86e4c8725ff 100644
--- a/src/Tasks/Microsoft.NET.Build.Extensions.Tasks/GetDependsOnNETStandard.netstandard.cs
+++ b/src/Tasks/Microsoft.NET.Build.Extensions.Tasks/GetDependsOnNETStandard.netstandard.cs
@@ -11,8 +11,14 @@ namespace Microsoft.NET.Build.Tasks
{
public partial class GetDependsOnNETStandard
{
- internal static bool GetFileDependsOnNETStandard(string filePath)
+ internal static void GetFileDependsOn(string filePath,
+ out bool dependsOnNETStandard,
+ out bool dependsOnNuGetCompression,
+ out bool dependsOnNuGetHttp)
{
+ dependsOnNETStandard = false;
+ dependsOnNuGetCompression = false;
+ dependsOnNuGetHttp = false;
using (var assemblyStream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Delete | FileShare.Read))
using (PEReader peReader = new PEReader(assemblyStream, PEStreamOptions.LeaveOpen))
{
@@ -27,20 +33,30 @@ internal static bool GetFileDependsOnNETStandard(string filePath)
if (reader.StringComparer.Equals(reference.Name, NetStandardAssemblyName))
{
- return true;
+ dependsOnNETStandard = true;
}
if (reader.StringComparer.Equals(reference.Name, SystemRuntimeAssemblyName) &&
reference.Version >= SystemRuntimeMinVersion)
{
- return true;
+ dependsOnNETStandard = true;
+ }
+
+ if (reader.StringComparer.Equals(reference.Name, SystemIOCompressionAssemblyName) &&
+ reference.Version >= SystemIOCompressionMinVersion)
+ {
+ dependsOnNuGetCompression = true;
+ }
+
+ if (reader.StringComparer.Equals(reference.Name, SystemNetHttpAssemblyName) &&
+ reference.Version >= SystemNetHttpMinVersion)
+ {
+ dependsOnNuGetHttp = true;
}
}
}
}
}
-
- return false;
}
}
}
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 829b05771742..db4043f4f660 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
@@ -93,7 +93,7 @@
-
+
<_CopyLocalButNotPublished Include="@(AllCopyLocalItems)" Exclude="@(ResolvedAssembliesToPublish)" />
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 9dac343b3fbb..94450674381d 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
@@ -44,10 +44,20 @@ Copyright (c) .NET Foundation. All rights reserved.
true
+
+
+
+
+ <_RunGetDependsOnNETStandard Condition="'$(DependsOnNETStandard)' == '' AND '$(NETStandardInbox)' != 'true'">true
+
+ <_RunGetDependsOnNETStandard Condition="'$(_TargetFrameworkVersionWithoutV)' == '4.7.1'">true
+
-
+
+
@@ -57,8 +67,20 @@ Copyright (c) .NET Foundation. All rights reserved.
+
+
+ <_NETStandardLibraryNETFrameworkLib Include="$(MSBuildThisFileDirectory)\net461\lib\System.Net.Http.dll" Condition="'$(DependsOnNuGetHttp)' == 'true' Or '$(DependsOnNETStandard)' == 'true'"/>
+ <_NETStandardLibraryNETFrameworkLib Include="$(MSBuildThisFileDirectory)\net461\lib\System.IO.Compression.dll" Condition="'$(DependsOnNuGetCompression)' == 'true' Or '$(DependsOnNETStandard)' == 'true'"/>
+
+
-
+
<_NETStandardLibraryNETFrameworkLib Condition="'$(_TargetFrameworkVersionWithoutV)' >= '4.7'"
Include="$(MSBuildThisFileDirectory)net47\lib\*.dll" />
<_NETStandardLibraryNETFrameworkLib Condition="'$(_TargetFrameworkVersionWithoutV)' >= '4.6.2'"
@@ -67,7 +89,9 @@ Copyright (c) .NET Foundation. All rights reserved.
<_NETStandardLibraryNETFrameworkLib Condition="'$(_TargetFrameworkVersionWithoutV)' >= '4.6.1'"
Include="$(MSBuildThisFileDirectory)net461\lib\*.dll"
Exclude="@(_NETStandardLibraryNETFrameworkLib->'$(MSBuildThisFileDirectory)net461\lib\%(FileName).dll')" />
-
+
+
+
-
+
<_CopyLocalButNotPublished Include="@(AllCopyLocalItems)" Exclude="@(ResolvedAssembliesToPublish)" />
diff --git a/test/Microsoft.NET.Build.Tests/GivenThatWeWantToTargetNet471.cs b/test/Microsoft.NET.Build.Tests/GivenThatWeWantToTargetNet471.cs
index e35c5b50aee2..5489ac277d4e 100644
--- a/test/Microsoft.NET.Build.Tests/GivenThatWeWantToTargetNet471.cs
+++ b/test/Microsoft.NET.Build.Tests/GivenThatWeWantToTargetNet471.cs
@@ -2,6 +2,7 @@
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using FluentAssertions;
+using Microsoft.Build.Utilities;
using Microsoft.NET.TestFramework;
using Microsoft.NET.TestFramework.Assertions;
using Microsoft.NET.TestFramework.Commands;
@@ -10,6 +11,7 @@
using System.Collections.Generic;
using System.IO;
using System.Linq;
+using System.Reflection;
using System.Text;
using Xunit;
using Xunit.Abstractions;
@@ -24,9 +26,15 @@ public GivenThatWeWantToTargetNet471(ITestOutputHelper log) : base(log)
{
}
- [WindowsOnlyFact(Skip = "https://github.com/dotnet/sdk/issues/1625")]
+ [Fact]
public void It_builds_a_net471_app()
{
+ // https://github.com/dotnet/sdk/issues/1625
+ if (!Net471ReferenceAssembliesAreInstalled())
+ {
+ return;
+ }
+
var testProject = new TestProject()
{
Name = "Net471App",
@@ -55,9 +63,15 @@ public void It_builds_a_net471_app()
});
}
- [WindowsOnlyFact(Skip = "https://github.com/dotnet/sdk/issues/1625")]
+ [Fact]
public void It_builds_a_net471_app_referencing_netstandard20()
{
+ // https://github.com/dotnet/sdk/issues/1625
+ if (!Net471ReferenceAssembliesAreInstalled())
+ {
+ return;
+ }
+
var testProject = new TestProject()
{
Name = "Net471App_Referencing_NetStandard20",
@@ -94,12 +108,21 @@ public void It_builds_a_net471_app_referencing_netstandard20()
$"{testProject.Name}.pdb",
$"{netStandardProject.Name}.dll",
$"{netStandardProject.Name}.pdb",
+
+ "System.Net.Http.dll",
+ "System.IO.Compression.dll",
});
}
- [WindowsOnlyFact(Skip = "https://github.com/dotnet/sdk/issues/1625")]
+ [Fact]
public void It_does_not_include_facades_from_nuget_packages()
{
+ // https://github.com/dotnet/sdk/issues/1625
+ if (!Net471ReferenceAssembliesAreInstalled())
+ {
+ return;
+ }
+
var testProject = new TestProject()
{
Name = "Net471_NuGetFacades",
@@ -128,7 +151,6 @@ public void It_does_not_include_facades_from_nuget_packages()
$"{testProject.Name}.exe",
$"{testProject.Name}.pdb",
- // Remove these two once https://github.com/dotnet/sdk/issues/1647 is fixed
"System.Net.Http.dll",
"System.IO.Compression.dll",
@@ -136,5 +158,148 @@ public void It_does_not_include_facades_from_nuget_packages()
"System.Diagnostics.DiagnosticSource.dll",
});
}
+
+ [Theory]
+ [InlineData("netstandard1.4")]
+ [InlineData("netstandard2.0")]
+ public void It_uses_updated_httpClient_and_compression(string netstandardVersion)
+ {
+ // https://github.com/dotnet/sdk/issues/1625
+ if (!Net471ReferenceAssembliesAreInstalled())
+ {
+ return;
+ }
+
+ var testProject = new TestProject()
+ {
+ Name = "Net471_HttpClient",
+ TargetFrameworks = "net471",
+ IsSdkProject = true,
+ IsExe = true
+ };
+
+ testProject.References.Add("System.Net.Http");
+ testProject.References.Add("System.IO.Compression");
+
+ var referencedProject = new TestProject()
+ {
+ Name = "NetStandardProject",
+ TargetFrameworks = netstandardVersion,
+ IsSdkProject = true,
+ IsExe = false
+ };
+
+ testProject.ReferencedProjects.Add(referencedProject);
+
+ testProject.SourceFiles["Program.cs"] = @"
+using System;
+using System.Net.Http;
+using System.Net.Http.Headers;
+
+public static class Program
+{
+ public static void Main()
+ {
+ HttpClient httpClient = Class1.GetHttpClient();
+
+ // AuthenticationHeaderValue is IClonable in .NET Framework and in version 4.2.0.0 of the contract
+ // (which is the version from ImplicitlyExpandNETStandardFacades), but not in prior versions of the
+ // contract, which would come from the package closure of 1.x versions of NETStandard.Library
+ ICloneable cloneable = new AuthenticationHeaderValue(""scheme"");
+ }
+}";
+
+ referencedProject.SourceFiles["Class1.cs"] = @"
+using System.Net.Http;
+
+public class Class1
+{
+ public static HttpClient GetHttpClient()
+ {
+ return new HttpClient();
+ }
+}
+";
+
+ var testAsset = _testAssetsManager.CreateTestProject(testProject, testProject.Name, netstandardVersion)
+ .Restore(Log, testProject.Name);
+
+ var buildCommand = new BuildCommand(Log, Path.Combine(testAsset.TestRoot, testProject.Name));
+
+ buildCommand
+ .Execute("/v:normal")
+ .Should()
+ .Pass()
+ .And.NotHaveStdOutContaining("MSB3277") // MSB3277: Found conflicts between different versions of the same dependent assembly that could not be resolved.
+ .And.NotHaveStdOutContaining("Could not determine");
+
+ var outputDirectory = buildCommand.GetOutputDirectory(testProject.TargetFrameworks);
+
+ outputDirectory.Should().HaveFiles(new[]
+ {
+ "System.Net.Http.dll",
+ "System.IO.Compression.dll"
+ });
+
+ var httpAssemblyName = AssemblyName.GetAssemblyName(Path.Combine(outputDirectory.FullName, "System.Net.Http.dll"));
+ httpAssemblyName.Version.Should().Be(new Version(4, 2, 0, 0));
+
+ var compressionAssemblyName = AssemblyName.GetAssemblyName(Path.Combine(outputDirectory.FullName, "System.IO.Compression.dll"));
+ httpAssemblyName.Version.Should().Be(new Version(4, 2, 0, 0));
+ }
+
+ [Fact]
+ public void It_does_not_include_httpClient_and_compression_if_netstandard_isnt_referenced()
+ {
+ // https://github.com/dotnet/sdk/issues/1625
+ if (!Net471ReferenceAssembliesAreInstalled())
+ {
+ return;
+ }
+
+ var testProject = new TestProject()
+ {
+ Name = "Net471_No_NetStandard",
+ TargetFrameworks = "net471",
+ IsSdkProject = true,
+ IsExe = true
+ };
+
+ testProject.References.Add("System.Net.Http");
+ testProject.References.Add("System.IO.Compression");
+
+ var testAsset = _testAssetsManager.CreateTestProject(testProject, testProject.Name)
+ .Restore(Log, testProject.Name);
+
+ var buildCommand = new BuildCommand(Log, Path.Combine(testAsset.TestRoot, testProject.Name));
+
+ buildCommand
+ .Execute("/v:normal")
+ .Should()
+ .Pass()
+ .And.NotHaveStdOutContaining("MSB3277") // MSB3277: Found conflicts between different versions of the same dependent assembly that could not be resolved.
+ .And.NotHaveStdOutContaining("Could not determine");
+
+ var outputDirectory = buildCommand.GetOutputDirectory(testProject.TargetFrameworks);
+
+ outputDirectory.Should().NotHaveFiles(new[]
+ {
+ "System.Net.Http.dll",
+ "System.IO.Compression.dll"
+ });
+ }
+
+ static bool Net471ReferenceAssembliesAreInstalled()
+ {
+ var net461referenceAssemblies = ToolLocationHelper.GetPathToDotNetFrameworkReferenceAssemblies(TargetDotNetFrameworkVersion.Version461);
+ if (net461referenceAssemblies == null)
+ {
+ // 4.6.1 reference assemblies not found, assume that 4.7.1 isn't available either
+ return false;
+ }
+ var net471referenceAssemblies = Path.Combine(new DirectoryInfo(net461referenceAssemblies).Parent.FullName, "v4.7.1");
+ return Directory.Exists(net471referenceAssemblies);
+ }
+
}
}