@@ -34,6 +34,9 @@ public sealed class DependencyManager : IDisposable
34
34
private readonly TemporaryDirectory tempWorkingDirectory ;
35
35
private readonly bool cleanupTempWorkingDirectory ;
36
36
37
+ private readonly Lazy < Runtime > runtimeLazy ;
38
+ private Runtime Runtime => runtimeLazy . Value ;
39
+
37
40
/// <summary>
38
41
/// Performs C# dependency fetching.
39
42
/// </summary>
@@ -53,6 +56,7 @@ public DependencyManager(string srcDir, IDependencyOptions options, ILogger logg
53
56
try
54
57
{
55
58
this . dotnet = DotNet . Make ( options , progressMonitor , tempWorkingDirectory ) ;
59
+ runtimeLazy = new Lazy < Runtime > ( ( ) => new Runtime ( dotnet ) ) ;
56
60
}
57
61
catch
58
62
{
@@ -80,7 +84,6 @@ public DependencyManager(string srcDir, IDependencyOptions options, ILogger logg
80
84
81
85
if ( options . UseNuGet )
82
86
{
83
- dllDirNames . Add ( packageDirectory . DirInfo . FullName ) ;
84
87
try
85
88
{
86
89
var nuget = new NugetPackages ( sourceDir . FullName , packageDirectory , progressMonitor ) ;
@@ -91,37 +94,27 @@ public DependencyManager(string srcDir, IDependencyOptions options, ILogger logg
91
94
progressMonitor . MissingNuGet ( ) ;
92
95
}
93
96
94
- var restoredProjects = RestoreSolutions ( solutions ) ;
97
+ var restoredProjects = RestoreSolutions ( solutions , out var assets1 ) ;
95
98
var projects = allProjects . Except ( restoredProjects ) ;
96
- RestoreProjects ( projects ) ;
99
+ RestoreProjects ( projects , out var assets2 ) ;
100
+
101
+ var dependencies = Assets . GetCompilationDependencies ( progressMonitor , assets1 . Union ( assets2 ) ) ;
102
+
103
+ var paths = dependencies
104
+ . Select ( d => Path . Combine ( packageDirectory . DirInfo . FullName , d ) )
105
+ . ToList ( ) ;
106
+
107
+ // TODO: Rename the dllDirNames var - it's not only dirs anymore.
108
+ dllDirNames . AddRange ( paths ) ;
97
109
DownloadMissingPackages ( allNonBinaryFiles ) ;
98
110
}
99
111
100
- var existsNetCoreRefNugetPackage = false ;
101
- var existsNetFrameworkRefNugetPackage = false ;
102
- var existsNetstandardLibRefNugetPackage = false ;
103
- var existsNetstandardLibNugetPackage = false ;
104
-
105
112
// Find DLLs in the .Net / Asp.Net Framework
106
113
// This block needs to come after the nuget restore, because the nuget restore might fetch the .NET Core/Framework reference assemblies.
107
114
if ( options . ScanNetFrameworkDlls )
108
115
{
109
- existsNetCoreRefNugetPackage = IsNugetPackageAvailable ( "microsoft.netcore.app.ref" ) ;
110
- existsNetFrameworkRefNugetPackage = IsNugetPackageAvailable ( "microsoft.netframework.referenceassemblies" ) ;
111
- existsNetstandardLibRefNugetPackage = IsNugetPackageAvailable ( "netstandard.library.ref" ) ;
112
- existsNetstandardLibNugetPackage = IsNugetPackageAvailable ( "netstandard.library" ) ;
113
-
114
- if ( existsNetCoreRefNugetPackage
115
- || existsNetFrameworkRefNugetPackage
116
- || existsNetstandardLibRefNugetPackage
117
- || existsNetstandardLibNugetPackage )
118
- {
119
- progressMonitor . LogInfo ( "Found .NET Core/Framework DLLs in NuGet packages. Not adding installation directory." ) ;
120
- }
121
- else
122
- {
123
- AddNetFrameworkDlls ( dllDirNames ) ;
124
- }
116
+ AddNetFrameworkDlls ( dllDirNames ) ;
117
+ AddAspNetFrameworkDlls ( dllDirNames ) ;
125
118
}
126
119
127
120
assemblyCache = new AssemblyCache ( dllDirNames , progressMonitor ) ;
@@ -132,7 +125,7 @@ public DependencyManager(string srcDir, IDependencyOptions options, ILogger logg
132
125
UseReference ( filename ) ;
133
126
}
134
127
135
- RemoveUnnecessaryNugetPackages ( existsNetCoreRefNugetPackage , existsNetFrameworkRefNugetPackage , existsNetstandardLibRefNugetPackage , existsNetstandardLibNugetPackage ) ;
128
+ RemoveUnnecessaryNugetPackages ( ) ;
136
129
ResolveConflicts ( ) ;
137
130
138
131
// Output the findings
@@ -167,8 +160,7 @@ public DependencyManager(string srcDir, IDependencyOptions options, ILogger logg
167
160
DateTime . Now - startTime ) ;
168
161
}
169
162
170
- private void RemoveUnnecessaryNugetPackages ( bool existsNetCoreRefNugetPackage , bool existsNetFrameworkRefNugetPackage ,
171
- bool existsNetstandardLibRefNugetPackage , bool existsNetstandardLibNugetPackage )
163
+ private void RemoveUnnecessaryNugetPackages ( )
172
164
{
173
165
RemoveNugetAnalyzerReferences ( ) ;
174
166
RemoveRuntimeNugetPackageReferences ( ) ;
@@ -180,40 +172,6 @@ private void RemoveUnnecessaryNugetPackages(bool existsNetCoreRefNugetPackage, b
180
172
RemoveNugetPackageReference ( "microsoft.aspnetcore.app.ref" ) ;
181
173
}
182
174
183
- // Multiple dotnet framework packages could be present. We keep only one.
184
- // The order of the packages is important, we're keeping the first one that is present in the nuget cache.
185
- var packagesInPrioOrder = new ( bool isPresent , string prefix ) [ ]
186
- {
187
- // net7.0, ... net5.0, netcoreapp3.1, netcoreapp3.0
188
- ( existsNetCoreRefNugetPackage , "microsoft.netcore.app.ref" ) ,
189
- // net48, ..., net20
190
- ( existsNetFrameworkRefNugetPackage , "microsoft.netframework.referenceassemblies." ) ,
191
- // netstandard2.1
192
- ( existsNetstandardLibRefNugetPackage , "netstandard.library.ref" ) ,
193
- // netstandard2.0
194
- ( existsNetstandardLibNugetPackage , "netstandard.library" )
195
- } ;
196
-
197
- for ( var i = 0 ; i < packagesInPrioOrder . Length ; i ++ )
198
- {
199
- var ( isPresent , _) = packagesInPrioOrder [ i ] ;
200
- if ( ! isPresent )
201
- {
202
- continue ;
203
- }
204
-
205
- // Package is present, remove all the lower priority packages:
206
- for ( var j = i + 1 ; j < packagesInPrioOrder . Length ; j ++ )
207
- {
208
- var ( otherIsPresent , otherPrefix ) = packagesInPrioOrder [ j ] ;
209
- if ( otherIsPresent )
210
- {
211
- RemoveNugetPackageReference ( otherPrefix ) ;
212
- }
213
- }
214
- break ;
215
- }
216
-
217
175
// TODO: There could be multiple `microsoft.netframework.referenceassemblies` packages,
218
176
// we could keep the newest one, but this is covered by the conflict resolution logic
219
177
// (if the file names match)
@@ -258,35 +216,68 @@ private void RemoveNugetAnalyzerReferences()
258
216
}
259
217
}
260
218
}
219
+
261
220
private void AddNetFrameworkDlls ( List < string > dllDirNames )
262
221
{
263
- var runtime = new Runtime ( dotnet ) ;
222
+ // Multiple dotnet framework packages could be present.
223
+ // The order of the packages is important, we're adding the first one that is present in the nuget cache.
224
+ var packagesInPrioOrder = new string [ ]
225
+ {
226
+ "microsoft.netcore.app.ref" , // net7.0, ... net5.0, netcoreapp3.1, netcoreapp3.0
227
+ "microsoft.netframework.referenceassemblies." , // net48, ..., net20
228
+ "netstandard.library.ref" , // netstandard2.1
229
+ "netstandard.library" // netstandard2.0
230
+ } ;
231
+
232
+ var frameworkPath = packagesInPrioOrder
233
+ . Select ( GetPackageDirectory )
234
+ . FirstOrDefault ( dir => dir is not null ) ;
235
+
236
+ if ( frameworkPath is not null )
237
+ {
238
+ dllDirNames . Add ( frameworkPath ) ;
239
+ progressMonitor . LogInfo ( "Found .NET Core/Framework DLLs in NuGet packages. Not adding installation directory." ) ;
240
+ return ;
241
+ }
242
+
264
243
string ? runtimeLocation = null ;
265
244
266
245
if ( options . UseSelfContainedDotnet )
267
246
{
268
- runtimeLocation = runtime . ExecutingRuntime ;
247
+ runtimeLocation = Runtime . ExecutingRuntime ;
269
248
}
270
249
else if ( fileContent . IsNewProjectStructureUsed )
271
250
{
272
- runtimeLocation = runtime . NetCoreRuntime ;
251
+ runtimeLocation = Runtime . NetCoreRuntime ;
273
252
}
274
253
else if ( fileContent . IsLegacyProjectStructureUsed )
275
254
{
276
- runtimeLocation = runtime . DesktopRuntime ;
255
+ runtimeLocation = Runtime . DesktopRuntime ;
277
256
}
278
257
279
- runtimeLocation ??= runtime . ExecutingRuntime ;
258
+ runtimeLocation ??= Runtime . ExecutingRuntime ;
280
259
281
260
progressMonitor . LogInfo ( $ ".NET runtime location selected: { runtimeLocation } ") ;
282
261
dllDirNames . Add ( runtimeLocation ) ;
262
+ }
283
263
284
- if ( fileContent . IsNewProjectStructureUsed
285
- && fileContent . UseAspNetCoreDlls
286
- && runtime . AspNetCoreRuntime is string aspRuntime )
264
+ private void AddAspNetFrameworkDlls ( List < string > dllDirNames )
265
+ {
266
+ if ( ! fileContent . IsNewProjectStructureUsed || ! fileContent . UseAspNetCoreDlls )
267
+ {
268
+ return ;
269
+ }
270
+
271
+ // First try to find ASP.NET assemblies in the NuGet packages
272
+ if ( GetPackageDirectory ( "microsoft.aspnetcore.app.ref" ) is string aspNetCorePackage )
273
+ {
274
+ progressMonitor . LogInfo ( $ "Found ASP.NET Core in NuGet packages. Not adding installation directory.") ;
275
+ dllDirNames . Add ( aspNetCorePackage ) ;
276
+ }
277
+ else if ( Runtime . AspNetCoreRuntime is string aspNetCoreRuntime )
287
278
{
288
- progressMonitor . LogInfo ( $ "ASP.NET runtime location selected: { aspRuntime } ") ;
289
- dllDirNames . Add ( aspRuntime ) ;
279
+ progressMonitor . LogInfo ( $ "ASP.NET runtime location selected: { aspNetCoreRuntime } ") ;
280
+ dllDirNames . Add ( aspNetCoreRuntime ) ;
290
281
}
291
282
}
292
283
@@ -336,16 +327,17 @@ private void RemoveNugetPackageReference(params string[] packagePrefixes)
336
327
}
337
328
}
338
329
339
- private bool IsNugetPackageAvailable ( string packagePrefix )
330
+ private string ? GetPackageDirectory ( string packagePrefix )
340
331
{
341
332
if ( ! options . UseNuGet )
342
333
{
343
- return false ;
334
+ return null ;
344
335
}
345
336
346
337
return new DirectoryInfo ( packageDirectory . DirInfo . FullName )
347
338
. EnumerateDirectories ( packagePrefix + "*" , new EnumerationOptions { MatchCasing = MatchCasing . CaseInsensitive , RecurseSubdirectories = false } )
348
- . Any ( ) ;
339
+ . FirstOrDefault ( ) ?
340
+ . FullName ;
349
341
}
350
342
351
343
private void GenerateSourceFileFromImplicitUsings ( )
@@ -634,27 +626,38 @@ private bool RestoreSolution(string solution, out IEnumerable<string> projects,
634
626
/// As opposed to RestoreProjects this is not run in parallel using PLINQ
635
627
/// as `dotnet restore` on a solution already uses multiple threads for restoring
636
628
/// the projects (this can be disabled with the `--disable-parallel` flag).
629
+ /// Populates assets with the relative paths to the assets files generated by the restore.
637
630
/// Returns a list of projects that are up to date with respect to restore.
638
631
/// </summary>
639
632
/// <param name="solutions">A list of paths to solution files.</param>
640
- private IEnumerable < string > RestoreSolutions ( IEnumerable < string > solutions ) =>
641
- solutions . SelectMany ( solution =>
633
+ private IEnumerable < string > RestoreSolutions ( IEnumerable < string > solutions , out IEnumerable < string > assets )
634
+ {
635
+ var assetFiles = new List < string > ( ) ;
636
+ var projects = solutions . SelectMany ( solution =>
642
637
{
643
- RestoreSolution ( solution , out var restoredProjects , out var assets ) ;
638
+ RestoreSolution ( solution , out var restoredProjects , out var a ) ;
639
+ assetFiles . AddRange ( a ) ;
644
640
return restoredProjects ;
645
641
} ) ;
642
+ assets = assetFiles ;
643
+ return projects ;
644
+ }
646
645
647
646
/// <summary>
648
647
/// Executes `dotnet restore` on all projects in projects.
649
648
/// This is done in parallel for performance reasons.
649
+ /// Populates assets with the relative paths to the assets files generated by the restore.
650
650
/// </summary>
651
651
/// <param name="projects">A list of paths to project files.</param>
652
- private void RestoreProjects ( IEnumerable < string > projects )
652
+ private void RestoreProjects ( IEnumerable < string > projects , out IEnumerable < string > assets )
653
653
{
654
+ var assetFiles = new List < string > ( ) ;
654
655
Parallel . ForEach ( projects , new ParallelOptions { MaxDegreeOfParallelism = options . Threads } , project =>
655
656
{
656
- RestoreProject ( project , forceDotnetRefAssemblyFetching : true , out var assets ) ;
657
+ RestoreProject ( project , forceDotnetRefAssemblyFetching : true , out var a ) ;
658
+ assetFiles . AddRange ( a ) ;
657
659
} ) ;
660
+ assets = assetFiles ;
658
661
}
659
662
660
663
private void DownloadMissingPackages ( List < FileInfo > allFiles )
0 commit comments