diff --git a/src/Tasks/Microsoft.NET.Build.Tasks.UnitTests/GivenAResolvePackageDependenciesTask.cs b/src/Tasks/Microsoft.NET.Build.Tasks.UnitTests/GivenAResolvePackageDependenciesTask.cs index bbacf673e4d8..9d078eb466e3 100644 --- a/src/Tasks/Microsoft.NET.Build.Tasks.UnitTests/GivenAResolvePackageDependenciesTask.cs +++ b/src/Tasks/Microsoft.NET.Build.Tasks.UnitTests/GivenAResolvePackageDependenciesTask.cs @@ -21,9 +21,9 @@ public class GivenAResolvePackageDependenciesTask [Theory] [MemberData(nameof(ItemCounts))] - public void ItRaisesLockFileToMSBuildItems(string projectName, int[] counts) + public void ItRaisesLockFileToMSBuildItems(string projectName, int[] counts, bool emitLegacyAssetsFileItems) { - var task = GetExecutedTaskFromPrefix(projectName, out _); + var task = GetExecutedTaskFromPrefix(projectName, out _, emitLegacyAssetsFileItems); task.PackageDefinitions .Count().Should().Be(counts[0]); task.FileDefinitions .Count().Should().Be(counts[1]); @@ -40,16 +40,36 @@ public static IEnumerable ItemCounts { new object[] { "dotnet.new", - new int[] { 110, 2536, 1, 845, 75 }, + new int[] { 110, 2536, 1, 846, 73 }, + true + }, + new object[] { + "dotnet.new", + new int[] { 110, 0, 0, 846, 0 }, + false + }, + new object[] { + "simple.dependencies", + new int[] { 113, 2613, 1, 878, 94 }, + true }, new object[] { "simple.dependencies", - new int[] { 113, 2613, 1, 877, 96 }, + new int[] { 113, 0, 0, 878, 0 }, + false }, }; } } + [Fact] + public void ItOmitsLegacyItemsByDefault() + { + var task = new ResolvePackageDependencies(); + + task.EmitLegacyAssetsFileItems.Should().Be(false); + } + [Theory] [InlineData("dotnet.new")] [InlineData("simple.dependencies")] @@ -564,7 +584,8 @@ public void ItAddsAnalyzerMetadataAndFileDependencies() { ProjectAssetsFile = lockFile.Path, ProjectPath = null, - ProjectLanguage = projectLanguage // set language + ProjectLanguage = projectLanguage, // set language + EmitLegacyAssetsFileItems = true }; task.Execute().Should().BeTrue(); @@ -648,7 +669,8 @@ public void ItFiltersAnalyzersByProjectLanguage() { ProjectAssetsFile = lockFile.Path, ProjectPath = null, - ProjectLanguage = projectLanguage // set language + ProjectLanguage = projectLanguage, // set language + EmitLegacyAssetsFileItems = true }; task.Execute().Should().BeTrue(); @@ -817,19 +839,19 @@ public void ItDoesNotThrowOnCrossTargetingWithTargetPlatforms() GetExecutedTaskFromContents(lockFileContent, out _); // Task should not fail on matching framework names } - private static ResolvePackageDependencies GetExecutedTaskFromPrefix(string lockFilePrefix, out LockFile lockFile, string target = null) + private static ResolvePackageDependencies GetExecutedTaskFromPrefix(string lockFilePrefix, out LockFile lockFile, bool emitLegacyAssetsFileItems = true, string target = null) { lockFile = TestLockFiles.GetLockFile(lockFilePrefix); - return GetExecutedTask(lockFile, target); + return GetExecutedTask(lockFile, emitLegacyAssetsFileItems, target); } - private static ResolvePackageDependencies GetExecutedTaskFromContents(string lockFileContents, out LockFile lockFile, string target = null) + private static ResolvePackageDependencies GetExecutedTaskFromContents(string lockFileContents, out LockFile lockFile, bool emitLegacyAssetsFileItems = true, string target = null) { lockFile = TestLockFiles.CreateLockFile(lockFileContents); - return GetExecutedTask(lockFile, target); + return GetExecutedTask(lockFile, emitLegacyAssetsFileItems, target); } - private static ResolvePackageDependencies GetExecutedTask(LockFile lockFile, string target) + private static ResolvePackageDependencies GetExecutedTask(LockFile lockFile, bool emitLegacyAssetsFileItems, string target) { var resolver = new MockPackageResolver(_packageRoot); @@ -838,6 +860,7 @@ private static ResolvePackageDependencies GetExecutedTask(LockFile lockFile, str ProjectAssetsFile = lockFile.Path, ProjectPath = _projectPath, ProjectLanguage = null, + EmitLegacyAssetsFileItems = emitLegacyAssetsFileItems, TargetFramework = target }; diff --git a/src/Tasks/Microsoft.NET.Build.Tasks/ResolvePackageAssets.cs b/src/Tasks/Microsoft.NET.Build.Tasks/ResolvePackageAssets.cs index 230a2887cf62..a9880dbd8fc7 100644 --- a/src/Tasks/Microsoft.NET.Build.Tasks/ResolvePackageAssets.cs +++ b/src/Tasks/Microsoft.NET.Build.Tasks/ResolvePackageAssets.cs @@ -12,8 +12,6 @@ using Microsoft.Build.Framework; using Microsoft.Build.Utilities; using NuGet.Common; -using NuGet.Frameworks; -using NuGet.Packaging; using NuGet.ProjectModel; using NuGet.Versioning; @@ -29,8 +27,6 @@ namespace Microsoft.NET.Build.Tasks /// public sealed class ResolvePackageAssets : TaskBase { - #region Input Items - /// /// Path to assets.json. /// @@ -164,10 +160,6 @@ public sealed class ResolvePackageAssets : TaskBase /// public bool DesignTimeBuild { get; set; } - #endregion - - #region Output Items - /// /// Full paths to assemblies from packages to pass to compiler as analyzers. /// @@ -238,22 +230,9 @@ public sealed class ResolvePackageAssets : TaskBase [Output] public ITaskItem[] ApphostsForShimRuntimeIdentifiers { get; private set; } - /// - /// All the libraries/packages in the lock file. - /// - [Output] - public ITaskItem[] PackageDefinitions { get; private set; } - [Output] public ITaskItem[] PackageDependencies { get; private set; } - /// - /// All the dependencies between packages. Each package has metadata 'ParentPackage' - /// to refer to the package that depends on it. For top level packages this value is blank. - /// - [Output] - public ITaskItem[] PackageDependenciesBetweenPackages { get; private set; } - /// /// List of symbol files (.pdb) related to NuGet packages. /// @@ -272,8 +251,6 @@ public sealed class ResolvePackageAssets : TaskBase [Output] public ITaskItem[] ReferenceDocumentationFiles { get; private set; } - #endregion - /// /// Messages from the assets file. /// These are logged directly and therefore not returned to the targets (note private here). @@ -358,9 +335,7 @@ private void ReadItemGroups() FrameworkAssemblies = reader.ReadItemGroup(); FrameworkReferences = reader.ReadItemGroup(); NativeLibraries = reader.ReadItemGroup(); - PackageDefinitions = reader.ReadItemGroup(); PackageDependencies = reader.ReadItemGroup(); - PackageDependenciesBetweenPackages = reader.ReadItemGroup(); PackageFolders = reader.ReadItemGroup(); ReferenceDocumentationFiles = reader.ReadItemGroup(); ResourceAssemblies = reader.ReadItemGroup(); @@ -679,8 +654,6 @@ internal sealed class CacheWriter : IDisposable { private const int InitialStringTableCapacity = 32; - private HashSet _projectFileDependencies; - private Dictionary _targetNameToAliasMap; private ResolvePackageAssets _task; private BinaryWriter _writer; private LockFile _lockFile; @@ -711,8 +684,7 @@ public CacheWriter(ResolvePackageAssets task) _task = task; _lockFile = new LockFileCache(task).GetLockFile(task.ProjectAssetsFile); _packageResolver = NuGetPackageResolver.CreateResolver(_lockFile); - _targetNameToAliasMap = CreateTargetNameToAlisMap(); - ReadProjectFileDependencies(string.IsNullOrEmpty(_task.TargetFramework) || !_targetNameToAliasMap.ContainsKey(_task.TargetFramework) ? null : _targetNameToAliasMap[_task.TargetFramework]); + // If we are doing a design-time build, we do not want to fail the build if we can't find the // target framework and/or runtime identifier in the assets file. This is because the design-time @@ -754,26 +726,8 @@ public CacheWriter(ResolvePackageAssets task) { ComputePackageExclusions(); } - - void ReadProjectFileDependencies(string frameworkAlias) - { - _projectFileDependencies = _lockFile.GetProjectFileDependencySet(frameworkAlias); - } } - private Dictionary CreateTargetNameToAlisMap() => _lockFile.Targets.ToDictionary(t => t.Name, t => - { - var alias = _lockFile.GetLockFileTargetAlias(t); - if (string.IsNullOrEmpty(t.RuntimeIdentifier)) - { - return alias; - } - else - { - return alias + "/" + t.RuntimeIdentifier; - } - }); - public void WriteToCacheFile() { Directory.CreateDirectory(Path.GetDirectoryName(_task.ProjectAssetsCacheFile)); @@ -852,9 +806,7 @@ private void WriteItemGroups() WriteItemGroup(WriteFrameworkAssemblies); WriteItemGroup(WriteFrameworkReferences); WriteItemGroup(WriteNativeLibraries); - WriteItemGroup(WritePackageDefinitions); WriteItemGroup(WritePackageDependencies); - WriteItemGroup(WritePackageDependenciesBetweenPackages); WriteItemGroup(WritePackageFolders); WriteItemGroup(WriteReferenceDocumentationFiles); WriteItemGroup(WriteResourceAssemblies); @@ -1205,13 +1157,17 @@ private void WriteDebugItems( foreach (string fileExtension in relatedExtensions.Split(RelatedPropertySeparator)) { - if (fileExtension.ToLowerInvariant() == extension) + if (fileExtension.ToLower() == extension) { string xmlFilePath = Path.ChangeExtension(itemSpec, fileExtension); if (File.Exists(xmlFilePath)) { WriteItem(xmlFilePath, library); } + else + { + _task.Log.LogWarning(Strings.AssetsFileNotFound, xmlFilePath); + } } } } @@ -1438,72 +1394,6 @@ private void WritePackageFolders() } } - private void WritePackageDefinitions() - { - // Get library and file definitions - foreach (var package in _lockFile.Libraries) - { - var packageName = package.Name; - var packageVersion = package.Version.ToNormalizedString(); - string packageId = $"{packageName}/{packageVersion}"; - - WriteItem(packageId); - WriteMetadata(MetadataKeys.Name, packageName); - WriteMetadata(MetadataKeys.Type, package.Type); - WriteMetadata(MetadataKeys.Version, packageVersion); - WriteMetadata(MetadataKeys.Path, package.Path ?? string.Empty); - - string resolvedPackagePath = ResolvePackagePath(package); - WriteMetadata(MetadataKeys.ResolvedPath, resolvedPackagePath ?? string.Empty); - - WriteMetadata(MetadataKeys.DiagnosticLevel, GetPackageDiagnosticLevel(package)); - } - - string ResolvePackagePath(LockFileLibrary package) - { - if (package.IsProject()) - { - var relativeMSBuildProjectPath = package.MSBuildProject; - - if (string.IsNullOrEmpty(relativeMSBuildProjectPath)) - { - throw new BuildErrorException(Strings.ProjectAssetsConsumedWithoutMSBuildProjectPath, package.Name, _task.ProjectAssetsFile); - } - - return GetAbsolutePathFromProjectRelativePath(relativeMSBuildProjectPath); - } - else - { - return _packageResolver.GetPackageDirectory(package.Name, package.Version); - } - } - - string GetAbsolutePathFromProjectRelativePath(string path) - { - return Path.GetFullPath(Path.Combine(Path.GetDirectoryName(_task.ProjectPath), path)); - } - - string GetPackageDiagnosticLevel(LockFileLibrary package) - { - string target = _task.TargetFramework ?? ""; - - var messages = _lockFile.LogMessages.Where(log => log.LibraryId == package.Name && log.TargetGraphs - .Select(tg => - { - var parsedTargetGraph = NuGetFramework.Parse(tg); - var alias = _lockFile.PackageSpec.TargetFrameworks.FirstOrDefault(tf => tf.FrameworkName == parsedTargetGraph)?.TargetAlias; - return alias ?? tg; - }).Contains(target)); - - if (!messages.Any()) - { - return string.Empty; - } - - return messages.Max(log => log.Level).ToString(); - } - } - private void WritePackageDependencies() { foreach (var library in _runtimeTarget.Libraries) @@ -1515,71 +1405,6 @@ private void WritePackageDependencies() } } - private void WritePackageDependenciesBetweenPackages() - { - foreach(var target in _lockFile.Targets) - { - GetPackageDependencies(target); - } - - void GetPackageDependencies(LockFileTarget target) - { - var resolvedPackageVersions = target.Libraries - .ToDictionary(pkg => pkg.Name, pkg => pkg.Version.ToNormalizedString(), StringComparer.OrdinalIgnoreCase); - - string frameworkAlias = _targetNameToAliasMap[target.Name]; - - var transitiveProjectRefs = new HashSet( - target.Libraries - .Where(lib => lib.IsTransitiveProjectReference(_lockFile, ref _projectFileDependencies, frameworkAlias)) - .Select(pkg => pkg.Name), - StringComparer.OrdinalIgnoreCase); - - foreach (var package in target.Libraries) - { - string packageId = $"{package.Name}/{package.Version.ToNormalizedString()}"; - - if (_projectFileDependencies.Contains(package.Name)) - { - WriteItem(packageId); - WriteMetadata(MetadataKeys.ParentTarget, frameworkAlias); // Foreign Key - WriteMetadata(MetadataKeys.ParentPackage, string.Empty); // Foreign Key - } - - // get sub package dependencies - GetDependencies(package, target.Name, resolvedPackageVersions, transitiveProjectRefs); - } - } - - void GetDependencies( - LockFileTargetLibrary package, - string targetName, - Dictionary resolvedPackageVersions, - HashSet transitiveProjectRefs) - { - string packageId = $"{package.Name}/{package.Version.ToNormalizedString()}"; - string frameworkAlias = _targetNameToAliasMap[targetName]; - foreach (var deps in package.Dependencies) - { - if (!resolvedPackageVersions.TryGetValue(deps.Id, out string version)) - { - continue; - } - - string depsName = $"{deps.Id}/{version}"; - - WriteItem(depsName); - WriteMetadata(MetadataKeys.ParentTarget, frameworkAlias); // Foreign Key - WriteMetadata(MetadataKeys.ParentPackage, packageId); // Foreign Key - - if (transitiveProjectRefs.Contains(deps.Id)) - { - WriteMetadata(MetadataKeys.TransitiveProjectReference, "true"); - } - } - } - } - private void WriteResourceAssemblies() { WriteItems( diff --git a/src/Tasks/Microsoft.NET.Build.Tasks/ResolvePackageDependencies.cs b/src/Tasks/Microsoft.NET.Build.Tasks/ResolvePackageDependencies.cs index 6e53163c3e42..be6e7e20b3da 100644 --- a/src/Tasks/Microsoft.NET.Build.Tasks/ResolvePackageDependencies.cs +++ b/src/Tasks/Microsoft.NET.Build.Tasks/ResolvePackageDependencies.cs @@ -18,6 +18,9 @@ namespace Microsoft.NET.Build.Tasks /// public sealed class ResolvePackageDependencies : TaskBase { + /// + /// Only used if is . + /// private readonly Dictionary _fileTypes = new Dictionary(StringComparer.OrdinalIgnoreCase); private HashSet _projectFileDependencies; @@ -34,6 +37,7 @@ public sealed class ResolvePackageDependencies : TaskBase /// /// All the targets in the lock file. + /// Only populated if is . /// [Output] public ITaskItem[] TargetDefinitions @@ -52,6 +56,7 @@ public ITaskItem[] PackageDefinitions /// /// All the files in the lock file. + /// Only populated if is . /// [Output] public ITaskItem[] FileDefinitions @@ -72,6 +77,7 @@ public ITaskItem[] PackageDependencies /// /// All the dependencies between files and packages, labeled by the group containing /// the file (e.g. CompileTimeAssembly, RuntimeAssembly, etc.). + /// Only populated if is . /// [Output] public ITaskItem[] FileDependencies @@ -108,6 +114,12 @@ public string ProjectLanguage get; set; } + /// + /// Setting this property restores pre-16.7 behaviour of populating , + /// and outputs. + /// + public bool EmitLegacyAssetsFileItems { get; set; } = false; + public string TargetFramework { get; set; } #endregion @@ -183,6 +195,11 @@ private void GetPackageAndFileDefinitions() _packageDefinitions.Add(item); + if (!EmitLegacyAssetsFileItems) + { + continue; + } + foreach (var file in package.Files) { if (NuGetUtils.IsPlaceholderFile(file)) @@ -259,15 +276,18 @@ private void RaiseLockFileTargets() { foreach (var target in LockFile.Targets) { - TaskItem item = new TaskItem(target.Name); - item.SetMetadata(MetadataKeys.RuntimeIdentifier, target.RuntimeIdentifier ?? string.Empty); - item.SetMetadata(MetadataKeys.TargetFramework, TargetFramework); - item.SetMetadata(MetadataKeys.TargetFrameworkMoniker, target.TargetFramework.DotNetFrameworkName); - item.SetMetadata(MetadataKeys.FrameworkName, target.TargetFramework.Framework); - item.SetMetadata(MetadataKeys.FrameworkVersion, target.TargetFramework.Version.ToString()); - item.SetMetadata(MetadataKeys.Type, "target"); - - _targetDefinitions.Add(item); + if (EmitLegacyAssetsFileItems) + { + TaskItem item = new TaskItem(target.Name); + item.SetMetadata(MetadataKeys.RuntimeIdentifier, target.RuntimeIdentifier ?? string.Empty); + item.SetMetadata(MetadataKeys.TargetFramework, TargetFramework); + item.SetMetadata(MetadataKeys.TargetFrameworkMoniker, target.TargetFramework.DotNetFrameworkName); + item.SetMetadata(MetadataKeys.FrameworkName, target.TargetFramework.Framework); + item.SetMetadata(MetadataKeys.FrameworkVersion, target.TargetFramework.Version.ToString()); + item.SetMetadata(MetadataKeys.Type, "target"); + + _targetDefinitions.Add(item); + } // raise each library in the target GetPackageAndFileDependencies(target); @@ -303,8 +323,11 @@ private void GetPackageAndFileDependencies(LockFileTarget target) // get sub package dependencies GetPackageDependencies(package, target.Name, resolvedPackageVersions, transitiveProjectRefs); - // get file dependencies on this package - GetFileDependencies(package, target.Name); + if (EmitLegacyAssetsFileItems) + { + // get file dependencies on this package + GetFileDependencies(package, target.Name); + } } } @@ -352,7 +375,7 @@ private void GetFileDependencies(LockFileTargetLibrary package, string targetNam string filePath = entry.Item1; IDictionary properties = entry.Item2; - if (NuGetUtils.IsPlaceholderFile(filePath)) + if (NuGetUtils.IsPlaceholderFile(filePath) || !EmitLegacyAssetsFileItems) { continue; } diff --git a/src/Tasks/Microsoft.NET.Build.Tasks/targets/Microsoft.PackageDependencyResolution.targets b/src/Tasks/Microsoft.NET.Build.Tasks/targets/Microsoft.PackageDependencyResolution.targets index de8be887d0db..2456989cbf34 100644 --- a/src/Tasks/Microsoft.NET.Build.Tasks/targets/Microsoft.PackageDependencyResolution.targets +++ b/src/Tasks/Microsoft.NET.Build.Tasks/targets/Microsoft.PackageDependencyResolution.targets @@ -196,12 +196,14 @@ Copyright (c) .NET Foundation. All rights reserved. ProjectPath="$(MSBuildProjectFullPath)" ProjectAssetsFile="$(ProjectAssetsFile)" ProjectLanguage="$(Language)" + EmitLegacyAssetsFileItems="$(EmitLegacyAssetsFileItems)" TargetFramework="$(TargetFramework)" - ContinueOnError="ErrorAndContinue" - Condition="'$(EmitLegacyAssetsFileItems)' == 'true'"> + ContinueOnError="ErrorAndContinue"> + + @@ -307,8 +309,6 @@ Copyright (c) .NET Foundation. All rights reserved. - -