@@ -25,7 +25,7 @@ public class InstallDotNetCore : AppDomainIsolatedTask
2525 public class InstallDotNetCore : Microsoft . Build . Utilities . Task
2626 {
2727#endif
28- private static readonly char [ ] s_keyTrimChars = [ '$' , '(' , ')' ] ;
28+ private static readonly char [ ] s_keyTrimChars = [ '$' , '(' , ')' ] ;
2929
3030 public string VersionsPropsPath { get ; set ; }
3131
@@ -34,10 +34,12 @@ public class InstallDotNetCore : Microsoft.Build.Utilities.Task
3434 [ Required ]
3535 public string GlobalJsonPath { get ; set ; }
3636 [ Required ]
37+ public string DotNetPath { get ; set ; }
38+ [ Required ]
3739 public string Platform { get ; set ; }
3840
3941 public string RuntimeSourceFeed { get ; set ; }
40-
42+
4143 public string RuntimeSourceFeedKey { get ; set ; }
4244
4345 public override bool Execute ( )
@@ -125,7 +127,9 @@ public override bool Execute()
125127
126128 if ( version != null )
127129 {
128- string arguments = $ "-runtime \" { runtimeItem . Key } \" -version \" { version . ToNormalizedString ( ) } \" ";
130+ string normalizedVersion = version . ToNormalizedString ( ) ;
131+ string runtime = runtimeItem . Key ;
132+ string arguments = $ "-runtime \" { runtime } \" -version \" { normalizedVersion } \" ";
129133 if ( ! string . IsNullOrEmpty ( architecture ) )
130134 {
131135 arguments += $ " -architecture { architecture } ";
@@ -142,6 +146,20 @@ public override bool Execute()
142146 arguments += $ " -runtimeSourceFeedKey { RuntimeSourceFeedKey } ";
143147 }
144148
149+ // Null architecture means that the script should infer it, we don't want to re-implement too much logic here,
150+ // so we skip the quick check.
151+ if ( architecture != null )
152+ {
153+ // Quickly check if the runtime is already installed, skipping double process hop,
154+ // load of powershell, and load of tools.sh, or similar overhead for shell script.
155+ // Saving about 1 second per runtime.
156+ if ( CheckRuntimeDotnetInstalled ( DotNetPath , normalizedVersion , architecture , runtime ) )
157+
158+ {
159+ continue ;
160+ }
161+ }
162+
145163 Log . LogMessage ( MessageImportance . Low , $ "Executing: { DotNetInstallScript } { arguments } ") ;
146164 var process = Process . Start ( new ProcessStartInfo ( )
147165 {
@@ -228,5 +246,42 @@ private IEnumerable<KeyValuePair<string, string>> GetItemsFromJsonElementArray(J
228246 }
229247 return items . ToArray ( ) ;
230248 }
249+
250+ private static bool CheckRuntimeDotnetInstalled (
251+ string dotnetRoot ,
252+ string version ,
253+ string architecture ,
254+ string runtime )
255+ {
256+ // For performance this check is duplicated from InstallDotnet in tools.sh and tools.ps1
257+ // if you are making changes here, consider if you need to make changes there as well.
258+ if ( string . IsNullOrEmpty ( runtime ) && runtime == "sdk" )
259+ {
260+ throw new ArgumentException ( $ "{ nameof ( InstallDotNetCore ) } cannot be used for .NET SDK installation.") ;
261+ }
262+
263+ if ( ! string . Equals ( architecture , RuntimeInformation . OSArchitecture . ToString ( ) , StringComparison . OrdinalIgnoreCase ) )
264+ {
265+ // This istallation is not native to this OS, it will be installed into a subfolder with the architecture name.
266+ // See eng/common/dotnet-install.sh and eng/common/dotnet-install.ps1
267+ dotnetRoot = Path . Combine ( dotnetRoot , architecture . ToLowerInvariant ( ) ) ;
268+ }
269+
270+ string runtimePath = runtime switch
271+ {
272+ "dotnet" => Path . Combine ( dotnetRoot , "shared" , "Microsoft.NETCore.App" , version ) ,
273+ "aspnetcore" => Path . Combine ( dotnetRoot , "shared" , "Microsoft.AspNetCore.App" , version ) ,
274+ "windowsdesktop" => Path . Combine ( dotnetRoot , "shared" , "Microsoft.WindowsDesktop.App" , version ) ,
275+ _ => Path . Combine ( dotnetRoot , "shared" , version )
276+ } ;
277+
278+ if ( Directory . Exists ( runtimePath ) )
279+ {
280+ Console . WriteLine ( $ " Runtime toolset '{ runtime } /{ architecture } v{ version } ' already installed in directory '{ runtimePath } '.") ;
281+ return true ;
282+ }
283+
284+ return false ;
285+ }
231286 }
232287}
0 commit comments