Skip to content

Commit bae887b

Browse files
committed
Add output PackageDependenciesBetweenPackages to ResolvePackageAssets
1 parent 5fb49f4 commit bae887b

File tree

2 files changed

+105
-1
lines changed

2 files changed

+105
-1
lines changed

src/Tasks/Microsoft.NET.Build.Tasks/ResolvePackageAssets.cs

Lines changed: 104 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ namespace Microsoft.NET.Build.Tasks
2929
/// </summary>
3030
public sealed class ResolvePackageAssets : TaskBase
3131
{
32+
#region Input Items
33+
3234
/// <summary>
3335
/// Path to assets.json.
3436
/// </summary>
@@ -162,6 +164,10 @@ public sealed class ResolvePackageAssets : TaskBase
162164
/// </summary>
163165
public bool DesignTimeBuild { get; set; }
164166

167+
#endregion
168+
169+
#region Output Items
170+
165171
/// <summary>
166172
/// Full paths to assemblies from packages to pass to compiler as analyzers.
167173
/// </summary>
@@ -241,6 +247,13 @@ public sealed class ResolvePackageAssets : TaskBase
241247
[Output]
242248
public ITaskItem[] PackageDependencies { get; private set; }
243249

250+
/// <summary>
251+
/// All the dependencies between packages. Each package has metadata 'ParentPackage'
252+
/// to refer to the package that depends on it. For top level packages this value is blank.
253+
/// </summary>
254+
[Output]
255+
public ITaskItem[] PackageDependenciesBetweenPackages { get; private set; }
256+
244257
/// <summary>
245258
/// List of symbol files (.pdb) related to NuGet packages.
246259
/// </summary>
@@ -259,6 +272,8 @@ public sealed class ResolvePackageAssets : TaskBase
259272
[Output]
260273
public ITaskItem[] ReferenceDocumentationFiles { get; private set; }
261274

275+
#endregion
276+
262277
/// <summary>
263278
/// Messages from the assets file.
264279
/// These are logged directly and therefore not returned to the targets (note private here).
@@ -345,6 +360,7 @@ private void ReadItemGroups()
345360
NativeLibraries = reader.ReadItemGroup();
346361
PackageDefinitions = reader.ReadItemGroup();
347362
PackageDependencies = reader.ReadItemGroup();
363+
PackageDependenciesBetweenPackages = reader.ReadItemGroup();
348364
PackageFolders = reader.ReadItemGroup();
349365
ReferenceDocumentationFiles = reader.ReadItemGroup();
350366
ResourceAssemblies = reader.ReadItemGroup();
@@ -663,6 +679,8 @@ internal sealed class CacheWriter : IDisposable
663679
{
664680
private const int InitialStringTableCapacity = 32;
665681

682+
private HashSet<string> _projectFileDependencies;
683+
private Dictionary<string, string> _targetNameToAliasMap;
666684
private ResolvePackageAssets _task;
667685
private BinaryWriter _writer;
668686
private LockFile _lockFile;
@@ -693,7 +711,8 @@ public CacheWriter(ResolvePackageAssets task)
693711
_task = task;
694712
_lockFile = new LockFileCache(task).GetLockFile(task.ProjectAssetsFile);
695713
_packageResolver = NuGetPackageResolver.CreateResolver(_lockFile);
696-
714+
_targetNameToAliasMap = CreateTargetNameToAlisMap();
715+
ReadProjectFileDependencies(string.IsNullOrEmpty(_task.TargetFramework) || !_targetNameToAliasMap.ContainsKey(_task.TargetFramework) ? null : _targetNameToAliasMap[_task.TargetFramework]);
697716

698717
// If we are doing a design-time build, we do not want to fail the build if we can't find the
699718
// target framework and/or runtime identifier in the assets file. This is because the design-time
@@ -735,8 +754,26 @@ public CacheWriter(ResolvePackageAssets task)
735754
{
736755
ComputePackageExclusions();
737756
}
757+
758+
void ReadProjectFileDependencies(string frameworkAlias)
759+
{
760+
_projectFileDependencies = _lockFile.GetProjectFileDependencySet(frameworkAlias);
761+
}
738762
}
739763

764+
private Dictionary<string, string> CreateTargetNameToAlisMap() => _lockFile.Targets.ToDictionary(t => t.Name, t =>
765+
{
766+
var alias = _lockFile.GetLockFileTargetAlias(t);
767+
if (string.IsNullOrEmpty(t.RuntimeIdentifier))
768+
{
769+
return alias;
770+
}
771+
else
772+
{
773+
return alias + "/" + t.RuntimeIdentifier;
774+
}
775+
});
776+
740777
public void WriteToCacheFile()
741778
{
742779
Directory.CreateDirectory(Path.GetDirectoryName(_task.ProjectAssetsCacheFile));
@@ -817,6 +854,7 @@ private void WriteItemGroups()
817854
WriteItemGroup(WriteNativeLibraries);
818855
WriteItemGroup(WritePackageDefinitions);
819856
WriteItemGroup(WritePackageDependencies);
857+
WriteItemGroup(WritePackageDependenciesBetweenPackages);
820858
WriteItemGroup(WritePackageFolders);
821859
WriteItemGroup(WriteReferenceDocumentationFiles);
822860
WriteItemGroup(WriteResourceAssemblies);
@@ -1481,6 +1519,71 @@ private void WritePackageDependencies()
14811519
}
14821520
}
14831521

1522+
private void WritePackageDependenciesBetweenPackages()
1523+
{
1524+
foreach(var target in _lockFile.Targets)
1525+
{
1526+
GetPackageDependencies(target);
1527+
}
1528+
1529+
void GetPackageDependencies(LockFileTarget target)
1530+
{
1531+
var resolvedPackageVersions = target.Libraries
1532+
.ToDictionary(pkg => pkg.Name, pkg => pkg.Version.ToNormalizedString(), StringComparer.OrdinalIgnoreCase);
1533+
1534+
string frameworkAlias = _targetNameToAliasMap[target.Name];
1535+
1536+
var transitiveProjectRefs = new HashSet<string>(
1537+
target.Libraries
1538+
.Where(lib => lib.IsTransitiveProjectReference(_lockFile, ref _projectFileDependencies, frameworkAlias))
1539+
.Select(pkg => pkg.Name),
1540+
StringComparer.OrdinalIgnoreCase);
1541+
1542+
foreach (var package in target.Libraries)
1543+
{
1544+
string packageId = $"{package.Name}/{package.Version.ToNormalizedString()}";
1545+
1546+
if (_projectFileDependencies.Contains(package.Name))
1547+
{
1548+
WriteItem(packageId);
1549+
WriteMetadata(MetadataKeys.ParentTarget, frameworkAlias); // Foreign Key
1550+
WriteMetadata(MetadataKeys.ParentPackage, string.Empty); // Foreign Key
1551+
}
1552+
1553+
// get sub package dependencies
1554+
GetDependencies(package, target.Name, resolvedPackageVersions, transitiveProjectRefs);
1555+
}
1556+
}
1557+
1558+
void GetDependencies(
1559+
LockFileTargetLibrary package,
1560+
string targetName,
1561+
Dictionary<string, string> resolvedPackageVersions,
1562+
HashSet<string> transitiveProjectRefs)
1563+
{
1564+
string packageId = $"{package.Name}/{package.Version.ToNormalizedString()}";
1565+
string frameworkAlias = _targetNameToAliasMap[targetName];
1566+
foreach (var deps in package.Dependencies)
1567+
{
1568+
if (!resolvedPackageVersions.TryGetValue(deps.Id, out string version))
1569+
{
1570+
continue;
1571+
}
1572+
1573+
string depsName = $"{deps.Id}/{version}";
1574+
1575+
WriteItem(depsName);
1576+
WriteMetadata(MetadataKeys.ParentTarget, frameworkAlias); // Foreign Key
1577+
WriteMetadata(MetadataKeys.ParentPackage, packageId); // Foreign Key
1578+
1579+
if (transitiveProjectRefs.Contains(deps.Id))
1580+
{
1581+
WriteMetadata(MetadataKeys.TransitiveProjectReference, "true");
1582+
}
1583+
}
1584+
}
1585+
}
1586+
14841587
private void WriteResourceAssemblies()
14851588
{
14861589
WriteItems(

src/Tasks/Microsoft.NET.Build.Tasks/targets/Microsoft.PackageDependencyResolution.targets

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -310,6 +310,7 @@ Copyright (c) .NET Foundation. All rights reserved.
310310
<Output TaskParameter="PackageFolders" ItemName="AssetsFilePackageFolder" />
311311
<Output TaskParameter="PackageDependencies" ItemName="PackageDependencies" />
312312
<Output TaskParameter="PackageDefinitions" ItemName="PackageDefinitions" />
313+
<Output TaskParameter="PackageDependenciesBetweenPackages" ItemName="PackageDependencies" />
313314
</ResolvePackageAssets>
314315

315316
<ItemGroup Condition="'$(CopyDebugSymbolFilesFromPackages)' == 'true'">

0 commit comments

Comments
 (0)