Skip to content

Commit 746f86e

Browse files
authored
Fix deps.json trimming with xUnit v2 and allow opt-out (#49295)
2 parents 47d0bba + 322e007 commit 746f86e

File tree

6 files changed

+83
-21
lines changed

6 files changed

+83
-21
lines changed

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

Lines changed: 36 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ internal class DependencyContextBuilder
2929
private string _referenceAssembliesPath;
3030
private Dictionary<PackageIdentity, string> _filteredPackages;
3131
private bool _includeMainProjectInDepsFile = true;
32+
private bool _trimLibrariesWithoutAssets = true;
3233
private readonly Dictionary<string, DependencyLibrary> _dependencyLibraries;
3334
private readonly Dictionary<string, List<LibraryDependency>> _libraryDependencies;
3435
private readonly List<string> _mainProjectDependencies;
@@ -212,6 +213,12 @@ public DependencyContextBuilder WithMainProjectInDepsFile(bool includeMainProjec
212213
return this;
213214
}
214215

216+
public DependencyContextBuilder WithTrimLibrariesWithoutAssets(bool trimLibrariesWithoutAssets)
217+
{
218+
_trimLibrariesWithoutAssets = trimLibrariesWithoutAssets;
219+
return this;
220+
}
221+
215222
public DependencyContextBuilder WithRuntimePackAssets(IEnumerable<RuntimePackAssetInfo> runtimePackAssets)
216223
{
217224
_runtimePackAssets = new Dictionary<string, List<RuntimePackAssetInfo>>();
@@ -356,31 +363,43 @@ public DependencyContext Build(string[] userRuntimeAssemblies = null)
356363
}
357364
}
358365

359-
var unprocessedLibraries = runtimeLibraries.ToHashSet();
360-
while (unprocessedLibraries.Any())
366+
if (_trimLibrariesWithoutAssets)
361367
{
362-
var lib = unprocessedLibraries.First();
363-
unprocessedLibraries.Remove(lib);
364-
365-
if (lib.Library.RuntimeAssemblyGroups.Count == 0 && lib.Library.NativeLibraryGroups.Count == 0 && lib.Library.ResourceAssemblies.Count == 0)
368+
var unprocessedLibraries = runtimeLibraries.ToHashSet();
369+
while (unprocessedLibraries.Any())
366370
{
367-
if (lib.Library.Dependencies.All(d => !libraries.TryGetValue(d.Name, out var dependency) || dependency.Dependents.Count > 1))
371+
var lib = unprocessedLibraries.First();
372+
unprocessedLibraries.Remove(lib);
373+
374+
if (lib.Library.Name.Equals("xunit", StringComparison.OrdinalIgnoreCase) ||
375+
lib.Library.Name.Equals("xunit.core", StringComparison.OrdinalIgnoreCase))
368376
{
369-
runtimeLibraries.Remove(lib);
370-
libraries.Remove(lib.Library.Name);
371-
foreach (var dependency in lib.Library.Dependencies)
377+
// Special case xunit and xunit.core, they should not be removed because the xUnit v2 runner looks for these libraries in the deps.json to
378+
// identify test projects.
379+
// See https://github.com/dotnet/sdk/issues/49248
380+
continue;
381+
}
382+
383+
if (lib.Library.RuntimeAssemblyGroups.Count == 0 && lib.Library.NativeLibraryGroups.Count == 0 && lib.Library.ResourceAssemblies.Count == 0)
384+
{
385+
if (lib.Library.Dependencies.All(d => !libraries.TryGetValue(d.Name, out var dependency) || dependency.Dependents.Count > 1))
372386
{
373-
if (libraries.TryGetValue(dependency.Name, out ModifiableRuntimeLibrary value))
387+
runtimeLibraries.Remove(lib);
388+
libraries.Remove(lib.Library.Name);
389+
foreach (var dependency in lib.Library.Dependencies)
374390
{
375-
value.Dependents.Remove(lib.Library.Name);
391+
if (libraries.TryGetValue(dependency.Name, out ModifiableRuntimeLibrary value))
392+
{
393+
value.Dependents.Remove(lib.Library.Name);
394+
}
376395
}
377-
}
378396

379-
foreach (var dependent in lib.Dependents)
380-
{
381-
if (libraries.TryGetValue(dependent, out var dep))
397+
foreach (var dependent in lib.Dependents)
382398
{
383-
unprocessedLibraries.Add(dep);
399+
if (libraries.TryGetValue(dependent, out var dep))
400+
{
401+
unprocessedLibraries.Add(dep);
402+
}
384403
}
385404
}
386405
}

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,8 @@ public class GenerateDepsFile : TaskBase
4949
[Required]
5050
public bool IncludeMainProject { get; set; }
5151

52+
public bool TrimDepsJsonLibrariesWithoutAssets { get; set; }
53+
5254
// @(ReferencePath) that will be passed to
5355
public ITaskItem[] ReferencePaths { get; set; } = Array.Empty<ITaskItem>();
5456

@@ -230,6 +232,7 @@ bool ShouldIncludeRuntimeAsset(ITaskItem item)
230232

231233
builder = builder
232234
.WithMainProjectInDepsFile(IncludeMainProject)
235+
.WithTrimLibrariesWithoutAssets(TrimDepsJsonLibrariesWithoutAssets)
233236
.WithReferenceAssemblies(referenceAssemblyInfos)
234237
.WithDirectReferences(directReferences)
235238
.WithDependencyReferences(dependencyReferences)

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ Copyright (c) .NET Foundation. All rights reserved.
5959
AssetsFilePath="$(ProjectAssetsFile)"
6060
DepsFilePath="$(_DesignerDepsFilePath)"
6161
IncludeMainProject="false"
62+
TrimDepsJsonLibrariesWithoutAssets="$(TrimDepsJsonLibrariesWithoutAssets)"
6263
IncludeRuntimeFileVersions="$(IncludeFileVersionsInDependencyFile)"
6364
IsSelfContained="false"
6465
PlatformLibraryName="$(MicrosoftNETPlatformLibrary)"

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1248,6 +1248,7 @@ Copyright (c) .NET Foundation. All rights reserved.
12481248
ReferenceAssemblies="@(_ReferenceAssemblies)"
12491249
RuntimePackAssets="@(RuntimePackAsset)"
12501250
IncludeMainProject="$(IncludeMainProjectInDepsFile)"
1251+
TrimDepsJsonLibrariesWithoutAssets="$(TrimDepsJsonLibrariesWithoutAssets)"
12511252
RuntimeIdentifier="$(RuntimeIdentifier)"
12521253
PlatformLibraryName="$(MicrosoftNETPlatformLibrary)"
12531254
RuntimeFrameworks="@(RuntimeFramework)"

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ Copyright (c) .NET Foundation. All rights reserved.
8888
<ProjectRuntimeConfigFilePath Condition="'$(ProjectRuntimeConfigFilePath)' == ''">$(TargetDir)$(ProjectRuntimeConfigFileName)</ProjectRuntimeConfigFilePath>
8989
<ProjectRuntimeConfigDevFilePath Condition="'$(ProjectRuntimeConfigDevFilePath)' == '' and $(GenerateRuntimeConfigDevFile) == 'true'">$(TargetDir)$(AssemblyName).runtimeconfig.dev.json</ProjectRuntimeConfigDevFilePath>
9090
<IncludeMainProjectInDepsFile Condition=" '$(IncludeMainProjectInDepsFile)' == '' ">true</IncludeMainProjectInDepsFile>
91+
<TrimDepsJsonLibrariesWithoutAssets Condition=" '$(TrimDepsJsonLibrariesWithoutAssets)' == '' ">true</TrimDepsJsonLibrariesWithoutAssets>
9192
</PropertyGroup>
9293

9394
<Import Project="Microsoft.NET.Sdk.Shared.targets" />
@@ -316,6 +317,7 @@ Copyright (c) .NET Foundation. All rights reserved.
316317
ReferenceAssemblies="@(_ReferenceAssemblies)"
317318
RuntimePackAssets="@(RuntimePackAsset)"
318319
IncludeMainProject="$(IncludeMainProjectInDepsFile)"
320+
TrimDepsJsonLibrariesWithoutAssets="$(TrimDepsJsonLibrariesWithoutAssets)"
319321
RuntimeIdentifier="$(RuntimeIdentifier)"
320322
PlatformLibraryName="$(MicrosoftNETPlatformLibrary)"
321323
RuntimeFrameworks="@(RuntimeFramework)"

test/Microsoft.NET.Build.Tests/GivenThatWeWantToBuildADesktopLibrary.cs

Lines changed: 40 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -136,24 +136,60 @@ public void PackageReferences_with_private_assets_do_not_appear_in_deps_file(str
136136
}
137137
}
138138

139-
[Fact]
140-
public void PackageWithoutAssets_ShouldNotShowUpInDepsJson()
139+
[Theory]
140+
[InlineData(true)]
141+
[InlineData(false)]
142+
public void PackageWithoutAssets_ShouldNotShowUpInDepsJson(bool trimLibrariesWithoutAssets)
141143
{
142144
var testProject = new TestProject()
143145
{
144146
TargetFrameworks = ToolsetInfo.CurrentTargetFramework
145147
};
146148
testProject.PackageReferences.Add(new TestPackageReference("Nerdbank.GitVersioning", "3.6.146"));
147149

150+
if (!trimLibrariesWithoutAssets)
151+
{
152+
testProject.AdditionalProperties["TrimDepsJsonLibrariesWithoutAssets"] = "False";
153+
}
154+
155+
var testAsset = _testAssetsManager.CreateTestProject(testProject);
156+
157+
var buildCommand = new BuildCommand(testAsset);
158+
buildCommand.Execute().Should().Pass();
159+
160+
using (var depsJsonFileStream = File.OpenRead(Path.Combine(buildCommand.GetOutputDirectory(ToolsetInfo.CurrentTargetFramework).FullName, $"{testProject.Name}.deps.json")))
161+
{
162+
var dependencyContext = new DependencyContextJsonReader().Read(depsJsonFileStream);
163+
if (trimLibrariesWithoutAssets)
164+
{
165+
dependencyContext.RuntimeLibraries.Any(l => l.Name.Equals("Nerdbank.GitVersioning")).Should().BeFalse();
166+
}
167+
else
168+
{
169+
dependencyContext.RuntimeLibraries.Any(l => l.Name.Equals("Nerdbank.GitVersioning")).Should().BeTrue();
170+
}
171+
}
172+
}
173+
174+
[Fact]
175+
public void XUnitCoreIsNotTrimmed()
176+
{
177+
// Regression test for https://github.com/dotnet/sdk/issues/49248
178+
179+
var testProject = new TestProject();
180+
testProject.PackageReferences.Add(new TestPackageReference("xunit.core", "2.9.3"));
181+
testProject.PackageReferences.Add(new TestPackageReference("xunit.extensibility.core", "2.9.3"));
182+
testProject.PackageReferences.Add(new TestPackageReference("xunit.extensibility.execution", "2.9.3"));
183+
148184
var testAsset = _testAssetsManager.CreateTestProject(testProject);
149185

150186
var buildCommand = new BuildCommand(testAsset);
151187
buildCommand.Execute().Should().Pass();
152188

153-
using (var depsJsonFileStream = File.OpenRead(Path.Combine(buildCommand.GetOutputDirectory(ToolsetInfo.CurrentTargetFramework).FullName, "PackageWithoutAssets_ShouldNotShowUpInDepsJson.deps.json")))
189+
using (var depsJsonFileStream = File.OpenRead(Path.Combine(buildCommand.GetOutputDirectory(ToolsetInfo.CurrentTargetFramework).FullName, $"{testProject.Name}.deps.json")))
154190
{
155191
var dependencyContext = new DependencyContextJsonReader().Read(depsJsonFileStream);
156-
dependencyContext.RuntimeLibraries.Any(l => l.Name.Equals("Nerdbank.GitVersioning")).Should().BeFalse();
192+
dependencyContext.RuntimeLibraries.Any(l => l.Name.Equals("xunit.core")).Should().BeTrue();
157193
}
158194
}
159195

0 commit comments

Comments
 (0)