diff --git a/build/Versions.props b/build/Versions.props index e7257f3ddb62..67eab5c794a6 100644 --- a/build/Versions.props +++ b/build/Versions.props @@ -28,7 +28,7 @@ 15.4.8 15.4.8 - 2.0.0 + 2.1.0-preview2-26306-03 2.0.1-servicing-26011-01 9.0.1 4.7.0-rtm.5081 diff --git a/src/Tasks/Microsoft.NET.Build.Tasks.UnitTests/GivenADependencyContextBuilder.cs b/src/Tasks/Microsoft.NET.Build.Tasks.UnitTests/GivenADependencyContextBuilder.cs index 0d4005b87be1..36bb92c9ab05 100644 --- a/src/Tasks/Microsoft.NET.Build.Tasks.UnitTests/GivenADependencyContextBuilder.cs +++ b/src/Tasks/Microsoft.NET.Build.Tasks.UnitTests/GivenADependencyContextBuilder.cs @@ -53,7 +53,7 @@ public void ItBuildsDependencyContextsFromProjectLockFiles( Constants.DefaultPlatformLibrary, isSelfContained: !string.IsNullOrEmpty(runtime)); - DependencyContext dependencyContext = new DependencyContextBuilder(mainProject, projectContext) + DependencyContext dependencyContext = new DependencyContextBuilder(mainProject, projectContext, includeRuntimeFileVersions: false) .WithDirectReferences(directReferences) .WithCompilationOptions(compilationOptions) .Build(); @@ -260,7 +260,7 @@ private DependencyContext BuildDependencyContextWithReferenceAssemblies(bool use useCompilationOptions ? CreateCompilationOptions() : null; - DependencyContext dependencyContext = new DependencyContextBuilder(mainProject, projectContext) + DependencyContext dependencyContext = new DependencyContextBuilder(mainProject, projectContext, includeRuntimeFileVersions: false) .WithReferenceAssemblies(ReferenceInfo.CreateReferenceInfos(referencePaths)) .WithCompilationOptions(compilationOptions) .Build(); diff --git a/src/Tasks/Microsoft.NET.Build.Tasks/DependencyContextBuilder.cs b/src/Tasks/Microsoft.NET.Build.Tasks/DependencyContextBuilder.cs index 82f14beaf6d1..92c303265851 100644 --- a/src/Tasks/Microsoft.NET.Build.Tasks/DependencyContextBuilder.cs +++ b/src/Tasks/Microsoft.NET.Build.Tasks/DependencyContextBuilder.cs @@ -20,6 +20,8 @@ internal class DependencyContextBuilder private readonly VersionFolderPathResolver _versionFolderPathResolver; private readonly SingleProjectInfo _mainProjectInfo; private readonly ProjectContext _projectContext; + private readonly bool _includeRuntimeFileVersions; + private readonly NuGetPackageResolver _packageResolver; private IEnumerable _referenceAssemblies; private IEnumerable _directReferences; private IEnumerable _dependencyReferences; @@ -32,13 +34,21 @@ internal class DependencyContextBuilder private HashSet _usedLibraryNames; private Dictionary _referenceLibraryNames; - public DependencyContextBuilder(SingleProjectInfo mainProjectInfo, ProjectContext projectContext) + public DependencyContextBuilder(SingleProjectInfo mainProjectInfo, ProjectContext projectContext, bool includeRuntimeFileVersions) { _mainProjectInfo = mainProjectInfo; _projectContext = projectContext; + _includeRuntimeFileVersions = includeRuntimeFileVersions; // This resolver is only used for building file names, so that base path is not required. _versionFolderPathResolver = new VersionFolderPathResolver(rootPath: null); + + if (_includeRuntimeFileVersions) + { + // This is used to look up the paths to package files on disk, which is only needed in this class if + // it needs to read the file versions + _packageResolver = NuGetPackageResolver.CreateResolver(projectContext.LockFile, mainProjectInfo.ProjectPath); + } } /// @@ -436,6 +446,27 @@ private Library GetLibrary( } } + private RuntimeFile CreateRuntimeFile(LockFileTargetLibrary library, LockFileItem item) + { + // _packageResolver will be null if _includeRuntimeFileVersions is false, hence the "?." + var itemFullPath = _packageResolver?.ResolvePackageAssetPath(library, item.Path); + return CreateRuntimeFile(item.Path, itemFullPath); + } + + private RuntimeFile CreateRuntimeFile(string path, string fullPath) + { + if (_includeRuntimeFileVersions) + { + string fileVersion = FileUtilities.GetFileVersion(fullPath).ToString(); + string assemblyVersion = FileUtilities.TryGetAssemblyVersion(fullPath)?.ToString(); + return new RuntimeFile(path, assemblyVersion, fileVersion); + } + else + { + return new RuntimeFile(path, null, null); + } + } + private IReadOnlyList CreateRuntimeAssemblyGroups(LockFileTargetLibrary targetLibrary, SingleProjectInfo referenceProjectInfo) { if (targetLibrary.IsProject()) @@ -450,14 +481,14 @@ private IReadOnlyList CreateRuntimeAssemblyGroups(LockFileTar assemblyGroups.Add( new RuntimeAssetGroup( string.Empty, - targetLibrary.RuntimeAssemblies.FilterPlaceholderFiles().Select(a => a.Path))); + targetLibrary.RuntimeAssemblies.FilterPlaceholderFiles().Select(a => CreateRuntimeFile(targetLibrary, a)))); foreach (var runtimeTargetsGroup in targetLibrary.GetRuntimeTargetsGroups("runtime")) { assemblyGroups.Add( new RuntimeAssetGroup( runtimeTargetsGroup.Key, - runtimeTargetsGroup.Select(t => t.Path))); + runtimeTargetsGroup.Select(t => CreateRuntimeFile(targetLibrary, t)))); } return assemblyGroups; @@ -471,14 +502,14 @@ private IReadOnlyList CreateNativeLibraryGroups(LockFileTarge nativeGroups.Add( new RuntimeAssetGroup( string.Empty, - export.NativeLibraries.FilterPlaceholderFiles().Select(a => a.Path))); + export.NativeLibraries.FilterPlaceholderFiles().Select(a => CreateRuntimeFile(export, a)))); foreach (var runtimeTargetsGroup in export.GetRuntimeTargetsGroups("native")) { nativeGroups.Add( new RuntimeAssetGroup( runtimeTargetsGroup.Key, - runtimeTargetsGroup.Select(t => t.Path))); + runtimeTargetsGroup.Select(t => CreateRuntimeFile(export, t)))); } return nativeGroups; @@ -560,7 +591,7 @@ private IEnumerable GetReferenceRuntimeLibraries(IEnumerable(), diff --git a/src/Tasks/Microsoft.NET.Build.Tasks/GenerateDepsFile.cs b/src/Tasks/Microsoft.NET.Build.Tasks/GenerateDepsFile.cs index 6e9de5c9b545..d9888e76df94 100644 --- a/src/Tasks/Microsoft.NET.Build.Tasks/GenerateDepsFile.cs +++ b/src/Tasks/Microsoft.NET.Build.Tasks/GenerateDepsFile.cs @@ -73,6 +73,8 @@ public class GenerateDepsFile : TaskBase public bool IsSelfContained { get; set; } + public bool IncludeRuntimeFileVersions { get; set; } + List _filesWritten = new List(); [Output] @@ -138,7 +140,7 @@ protected override void ExecuteCore() PlatformLibraryName, IsSelfContained); - DependencyContext dependencyContext = new DependencyContextBuilder(mainProject, projectContext) + DependencyContext dependencyContext = new DependencyContextBuilder(mainProject, projectContext, IncludeRuntimeFileVersions) .WithMainProjectInDepsFile(IncludeMainProject) .WithReferenceAssemblies(referenceAssemblyInfos) .WithDirectReferences(directReferences) @@ -229,7 +231,7 @@ private IEnumerable TrimAssetGroups(IEnumerable TrimAssemblies(IEnumerable assemblies, ISet< } } } + + + private IEnumerable TrimRuntimeFiles(IEnumerable assemblies, ISet filesToTrim) + { + foreach (var assembly in assemblies) + { + if (!filesToTrim.Contains(assembly.Path)) + { + yield return assembly; + } + } + } } } diff --git a/src/Tasks/Microsoft.NET.Build.Tasks/NuGetPackageResolver.cs b/src/Tasks/Microsoft.NET.Build.Tasks/NuGetPackageResolver.cs index 16d59c0a2d6b..d727b9aecae2 100644 --- a/src/Tasks/Microsoft.NET.Build.Tasks/NuGetPackageResolver.cs +++ b/src/Tasks/Microsoft.NET.Build.Tasks/NuGetPackageResolver.cs @@ -41,6 +41,15 @@ public string GetPackageDirectory(string packageId, NuGetVersion version, out st return _packagePathResolver.GetPackageDirectory(packageId, version); } + public string ResolvePackageAssetPath(LockFileTargetLibrary package, string relativePath) + { + string packagePath = GetPackageDirectory(package.Name, package.Version); + return Path.Combine(packagePath, NormalizeRelativePath(relativePath)); + } + + public static string NormalizeRelativePath(string relativePath) + => relativePath.Replace('/', Path.DirectorySeparatorChar); + public static NuGetPackageResolver CreateResolver(LockFile lockFile, string projectPath) { NuGetPackageResolver packageResolver; diff --git a/src/Tasks/Microsoft.NET.Build.Tasks/ResolvePackageAssets.cs b/src/Tasks/Microsoft.NET.Build.Tasks/ResolvePackageAssets.cs index aa80879635c5..7fa380ff2f82 100644 --- a/src/Tasks/Microsoft.NET.Build.Tasks/ResolvePackageAssets.cs +++ b/src/Tasks/Microsoft.NET.Build.Tasks/ResolvePackageAssets.cs @@ -671,7 +671,7 @@ private void WriteAnalyzers() if (targetLibraries.TryGetValue(library.Name, out var targetLibrary)) { - WriteItem(ResolvePackageAssetPath(targetLibrary, file), targetLibrary); + WriteItem(_packageResolver.ResolvePackageAssetPath(targetLibrary, file), targetLibrary); } } } @@ -925,7 +925,7 @@ private void WriteItems( continue; } - string itemSpec = ResolvePackageAssetPath(library, asset.Path); + string itemSpec = _packageResolver.ResolvePackageAssetPath(library, asset.Path); WriteItem(itemSpec, library); writeMetadata?.Invoke(asset); } @@ -968,12 +968,6 @@ private int GetMetadataIndex(string value) return index; } - private string ResolvePackageAssetPath(LockFileTargetLibrary package, string relativePath) - { - string packagePath = _packageResolver.GetPackageDirectory(package.Name, package.Version); - return Path.Combine(packagePath, NormalizeRelativePath(relativePath)); - } - private static Dictionary GetProjectReferencePaths(LockFile lockFile) { Dictionary paths = new Dictionary(); @@ -982,15 +976,12 @@ private static Dictionary GetProjectReferencePaths(LockFile lock { if (library.IsProject()) { - paths[library.Name] = NormalizeRelativePath(library.MSBuildProject); + paths[library.Name] = NuGetPackageResolver.NormalizeRelativePath(library.MSBuildProject); } } return paths; } - - private static string NormalizeRelativePath(string relativePath) - => relativePath.Replace('/', Path.DirectorySeparatorChar); } } } diff --git a/src/Tasks/Microsoft.NET.Build.Tasks/targets/Microsoft.NET.Publish.targets b/src/Tasks/Microsoft.NET.Build.Tasks/targets/Microsoft.NET.Publish.targets index d4d26c60689a..903eaf707ddc 100644 --- a/src/Tasks/Microsoft.NET.Build.Tasks/targets/Microsoft.NET.Publish.targets +++ b/src/Tasks/Microsoft.NET.Build.Tasks/targets/Microsoft.NET.Publish.targets @@ -532,7 +532,8 @@ Copyright (c) .NET Foundation. All rights reserved. CompilerOptions="@(DependencyFileCompilerOptions)" ExcludeFromPublishPackageReferences="@(_ExcludeFromPublishPackageReference)" RuntimeStorePackages="@(RuntimeStorePackages)" - IsSelfContained="$(SelfContained)" /> + IsSelfContained="$(SelfContained)" + IncludeRuntimeFileVersions="$(IncludeFileVersionsInDependencyFile)" /> diff --git a/src/Tasks/Microsoft.NET.Build.Tasks/targets/Microsoft.NET.Sdk.BeforeCommon.targets b/src/Tasks/Microsoft.NET.Build.Tasks/targets/Microsoft.NET.Sdk.BeforeCommon.targets index 711115cf929e..c42fa0bdcecb 100644 --- a/src/Tasks/Microsoft.NET.Build.Tasks/targets/Microsoft.NET.Sdk.BeforeCommon.targets +++ b/src/Tasks/Microsoft.NET.Build.Tasks/targets/Microsoft.NET.Sdk.BeforeCommon.targets @@ -56,6 +56,10 @@ Copyright (c) .NET Foundation. All rights reserved. true + + + true .dll diff --git a/src/Tasks/Microsoft.NET.Build.Tasks/targets/Microsoft.NET.Sdk.targets b/src/Tasks/Microsoft.NET.Build.Tasks/targets/Microsoft.NET.Sdk.targets index 797ce5df73af..3033892825b7 100644 --- a/src/Tasks/Microsoft.NET.Build.Tasks/targets/Microsoft.NET.Sdk.targets +++ b/src/Tasks/Microsoft.NET.Build.Tasks/targets/Microsoft.NET.Sdk.targets @@ -118,7 +118,7 @@ Copyright (c) .NET Foundation. All rights reserved. _ComputeReferenceAssemblies" BeforeTargets="CopyFilesToOutputDirectory" Condition=" '$(GenerateDependencyFile)' == 'true'" - Inputs="$(ProjectAssetsFile)" + Inputs="$(ProjectAssetsFile);$(MSBuildAllProjects)" Outputs="$(ProjectDepsFilePath)"> + diff --git a/src/Tests/Microsoft.NET.Publish.Tests/GivenThatAPublishedDepsJsonShouldContainVersionInformation.cs b/src/Tests/Microsoft.NET.Publish.Tests/GivenThatAPublishedDepsJsonShouldContainVersionInformation.cs new file mode 100644 index 000000000000..c34bb257bea2 --- /dev/null +++ b/src/Tests/Microsoft.NET.Publish.Tests/GivenThatAPublishedDepsJsonShouldContainVersionInformation.cs @@ -0,0 +1,266 @@ +// Copyright (c) .NET Foundation and contributors. All rights reserved. +// 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 System.Linq; +using System.Runtime.CompilerServices; +using System.Text; +using FluentAssertions; +using Microsoft.DotNet.Cli.Utils; +using Microsoft.Extensions.DependencyModel; +using Microsoft.NET.TestFramework; +using Microsoft.NET.TestFramework.Assertions; +using Microsoft.NET.TestFramework.Commands; +using Microsoft.NET.TestFramework.ProjectConstruction; +using Newtonsoft.Json.Linq; +using Xunit; +using Xunit.Abstractions; + +namespace Microsoft.NET.Publish.Tests +{ + public class GivenThatAPublishedDepsJsonShouldContainVersionInformation : SdkTest + { + public GivenThatAPublishedDepsJsonShouldContainVersionInformation(ITestOutputHelper log) : base(log) + { + } + + private TestProject GetTestProject() + { + var testProject = new TestProject() + { + Name = "DepsJsonVersions", + TargetFrameworks = "netcoreapp2.0", + IsSdkProject = true, + IsExe = true, + }; + testProject.PackageReferences.Add(new TestPackageReference("System.Collections.Immutable", "1.5.0-preview1-26216-02")); + testProject.PackageReferences.Add(new TestPackageReference("Libuv", "1.10.0")); + + return testProject; + } + + [Fact] + public void Versions_are_included_in_deps_json() + { + var testProject = GetTestProject(); + + var testAsset = _testAssetsManager.CreateTestProject(testProject) + .Restore(Log, testProject.Name); + + var publishCommand = new PublishCommand(Log, Path.Combine(testAsset.TestRoot, testProject.Name)); + + publishCommand.Execute() + .Should() + .Pass(); + + var publishDirectory = publishCommand.GetOutputDirectory(testProject.TargetFrameworks, runtimeIdentifier: testProject.RuntimeIdentifier); + publishDirectory.Should().HaveFile(testProject.Name + ".deps.json"); + + var depsFilePath = Path.Combine(publishDirectory.FullName, $"{testProject.Name}.deps.json"); + CheckVersionsInDepsFile(depsFilePath); + } + + void CheckVersionsInDepsFile(string depsFilePath) + { + DependencyContext dependencyContext; + using (var depsJsonFileStream = File.OpenRead(depsFilePath)) + { + dependencyContext = new DependencyContextJsonReader().Read(depsJsonFileStream); + } + + var libuvRuntimeLibrary = dependencyContext.RuntimeLibraries.Single(l => l.Name == "Libuv"); + var libuvRuntimeFiles = libuvRuntimeLibrary.NativeLibraryGroups.SelectMany(rag => rag.RuntimeFiles).ToList(); + libuvRuntimeFiles.Should().NotBeEmpty(); + foreach (var runtimeFile in libuvRuntimeFiles) + { + runtimeFile.AssemblyVersion.Should().BeNull(); + runtimeFile.FileVersion.Should().Be("0.0.0.0"); + } + + var immutableRuntimeLibrary = dependencyContext.RuntimeLibraries.Single(l => l.Name == "System.Collections.Immutable"); + var immutableRuntimeFiles = immutableRuntimeLibrary.RuntimeAssemblyGroups.SelectMany(rag => rag.RuntimeFiles).ToList(); + immutableRuntimeFiles.Should().NotBeEmpty(); + foreach (var runtimeFile in immutableRuntimeFiles) + { + runtimeFile.AssemblyVersion.Should().Be("1.2.3.0"); + runtimeFile.FileVersion.Should().Be("4.6.26216.2"); + } + } + + [Fact] + public void Versions_are_included_for_self_contained_apps() + { + Versions_are_included(build: false); + } + + [Fact] + public void Versions_are_included_for_build() + { + Versions_are_included(build: true); + } + + private void Versions_are_included(bool build, [CallerMemberName] string callingMethod = "") + { + var testProject = GetTestProject(); + testProject.RuntimeIdentifier = EnvironmentInfo.GetCompatibleRid(testProject.TargetFrameworks); + + var testAsset = _testAssetsManager.CreateTestProject(testProject, callingMethod) + .Restore(Log, testProject.Name); + + MSBuildCommand command; + if (build) + { + command = new BuildCommand(Log, Path.Combine(testAsset.TestRoot, testProject.Name)); + } + else + { + command = new PublishCommand(Log, Path.Combine(testAsset.TestRoot, testProject.Name)); + } + + command.Execute() + .Should() + .Pass(); + + var outputDirectory = command.GetOutputDirectory(testProject.TargetFrameworks, runtimeIdentifier: testProject.RuntimeIdentifier); + outputDirectory.Should().HaveFile(testProject.Name + ".deps.json"); + + var depsFilePath = Path.Combine(outputDirectory.FullName, $"{testProject.Name}.deps.json"); + CheckVersionsInDepsFile(depsFilePath); + } + + [Fact(Skip = "Host deps.json doesn't have runtime file version info yet: https://github.com/dotnet/sdk/issues/2124")] + public void Inbox_version_of_assembly_is_loaded_over_applocal_version() + { + var (coreDir, publishDir, immutableDir) = TestConflictResult(); + immutableDir.Should().BeEquivalentTo(coreDir, "immutable collections library from Framework should win"); + } + + [Fact] + public void Inbox_version_is_loaded_if_runtime_file_versions_arent_in_deps() + { + void testProjectChanges(TestProject testProject) + { + testProject.AdditionalProperties["IncludeRuntimeFileVersions"] = "false"; + } + + var (coreDir, publishDir, immutableDir) = TestConflictResult(testProjectChanges); + immutableDir.Should().BeEquivalentTo(publishDir, "published immutable collections library from should win"); + } + + [Fact] + public void Local_version_of_assembly_with_higher_version_is_loaded_over_inbox_version() + { + void publishFolderChanges(string publishFolder) + { + var depsJsonPath = Path.Combine(publishFolder, "DepsJsonVersions.deps.json"); + var depsJson = JObject.Parse(File.ReadAllText(depsJsonPath)); + var target = ((JProperty)depsJson["targets"].First).Value; + var file = target["System.Collections.Immutable/1.5.0-preview1-26216-02"]["runtime"]["lib/netstandard2.0/System.Collections.Immutable.dll"]; + // Set fileVersion in deps.json to 4.7.0.0, which should be bigger than in box 4.6.x version + file["fileVersion"] = "4.7.0.0"; + File.WriteAllText(depsJsonPath, depsJson.ToString()); + } + + var (coreDir, publishDir, immutableDir) = TestConflictResult(publishFolderChanges: publishFolderChanges); + immutableDir.Should().BeEquivalentTo(publishDir, "published immutable collections library from should win"); + } + + private (string coreDir, string publishDir, string immutableDir) TestConflictResult( + Action testProjectChanges = null, Action publishFolderChanges = null) + { + var testProject = GetTestProject(); + + testProject.SourceFiles["Program.cs"] = @" +using System; + +static class Program +{ + public static void Main() + { + Console.WriteLine(typeof(object).Assembly.Location); + Console.WriteLine(typeof(System.Collections.Immutable.ImmutableList).Assembly.Location); + } +} +"; + if (testProjectChanges != null) + { + testProjectChanges(testProject); + } + + + var testAsset = _testAssetsManager.CreateTestProject(testProject) + .Restore(Log, testProject.Name); + + var publishCommand = new PublishCommand(Log, Path.Combine(testAsset.TestRoot, testProject.Name)); + + publishCommand.Execute() + .Should() + .Pass(); + + var publishDirectory = publishCommand.GetOutputDirectory(testProject.TargetFrameworks, runtimeIdentifier: testProject.RuntimeIdentifier); + + if (publishFolderChanges != null) + { + publishFolderChanges(publishDirectory.FullName); + } + + // Assembly from package should be deployed, as it is newer than the in-box version for netcoreapp2.0, + // which is what the app targets + publishDirectory.Should().HaveFile("System.Collections.Immutable.dll"); + + var exePath = Path.Combine(publishDirectory.FullName, testProject.Name + ".dll"); + + // We want to test a .NET Core 2.0 app rolling forward to .NET Core 2.1. + // This wouldn't happen in our test environment as we also have the .NET Core 2.0 shared + // framework installed. So we get the RuntimeFrameworkVersion of an app + // that targets .NET Core 2.1, and then use the --fx-version parameter to the host + // to force the .NET Core 2.0 app to run on that version + string rollForwardVersion = GetRollForwardNetCoreAppVersion(); + + var foo = TestContext.Current.ToolsetUnderTest.CliVersionForBundledVersions; + var runAppCommand = Command.Create(TestContext.Current.ToolsetUnderTest.DotNetHostPath, + new string[] { "exec", "--fx-version", rollForwardVersion, exePath }); + + var runAppResult = runAppCommand + .CaptureStdOut() + .CaptureStdErr() + .Execute(); + + runAppResult + .Should() + .Pass(); + + var stdOutLines = runAppResult.StdOut.Split(Environment.NewLine); + + string coreDir = Path.GetDirectoryName(stdOutLines[0]); + string immutableDir = Path.GetDirectoryName(stdOutLines[1]); + + return (coreDir, publishDirectory.FullName, immutableDir); + + } + + string GetRollForwardNetCoreAppVersion() + { + var testProject = new TestProject() + { + Name = nameof(GetRollForwardNetCoreAppVersion), + TargetFrameworks = "netcoreapp2.1", + IsSdkProject = true, + IsExe = true + }; + var testAsset = _testAssetsManager.CreateTestProject(testProject) + .Restore(Log, testProject.Name); + var getValuesCommand = new GetValuesCommand(Log, Path.Combine(testAsset.TestRoot, testProject.Name), + testProject.TargetFrameworks, "RuntimeFrameworkVersion") + { + ShouldCompile = false + }; + + getValuesCommand.Execute().Should().Pass(); + + return getValuesCommand.GetValues().Single(); + } + } +} diff --git a/src/Tests/Microsoft.NET.Publish.Tests/Microsoft.NET.Publish.Tests.csproj b/src/Tests/Microsoft.NET.Publish.Tests/Microsoft.NET.Publish.Tests.csproj index 227ae3981a70..43ec75dcd6db 100644 --- a/src/Tests/Microsoft.NET.Publish.Tests/Microsoft.NET.Publish.Tests.csproj +++ b/src/Tests/Microsoft.NET.Publish.Tests/Microsoft.NET.Publish.Tests.csproj @@ -21,6 +21,7 @@ + diff --git a/src/Tests/Microsoft.NET.ToolPack.Tests/Microsoft.NET.ToolPack.Tests.csproj b/src/Tests/Microsoft.NET.ToolPack.Tests/Microsoft.NET.ToolPack.Tests.csproj index 632b9cf5971c..01cc7a9ad3ff 100644 --- a/src/Tests/Microsoft.NET.ToolPack.Tests/Microsoft.NET.ToolPack.Tests.csproj +++ b/src/Tests/Microsoft.NET.ToolPack.Tests/Microsoft.NET.ToolPack.Tests.csproj @@ -19,6 +19,10 @@ + + +