diff --git a/build-tools/xaprepare/xaprepare/Application/Context.cs b/build-tools/xaprepare/xaprepare/Application/Context.cs index 80cda24eda1..2b634fc9976 100644 --- a/build-tools/xaprepare/xaprepare/Application/Context.cs +++ b/build-tools/xaprepare/xaprepare/Application/Context.cs @@ -287,7 +287,12 @@ public string DebugFileExtension { /// public IEnumerable AndroidSdkPlatforms { get; set; } = Enumerable.Empty (); - // + /// + /// Path to a local .NET SDK archive to use instead of downloading. + /// + public string? LocalDotNetSdkArchive { get; set; } + + /// /// Set by if the archive has been downloaded and validated. /// public bool BuildToolsArchiveDownloaded { get; set; } diff --git a/build-tools/xaprepare/xaprepare/Main.cs b/build-tools/xaprepare/xaprepare/Main.cs index b225d0aa10f..8676b92d7a2 100644 --- a/build-tools/xaprepare/xaprepare/Main.cs +++ b/build-tools/xaprepare/xaprepare/Main.cs @@ -29,6 +29,7 @@ sealed class ParsedOptions public bool AutoProvisionUsesSudo { get; set; } public RefreshableComponent RefreshList { get; set; } public IEnumerable AndroidSdkPlatforms { get; set; } = new [] { "latest" }; + public string? LocalDotNetSdkArchive { get; set; } } public static int Main (string[] args) @@ -101,6 +102,7 @@ static async Task Run (string[] args) {"auto-provision=", $"Automatically install software required by .NET for Android", v => parsedOptions.AutoProvision = ParseBoolean (v)}, {"auto-provision-uses-sudo=", $"Allow use of sudo(1) when provisioning", v => parsedOptions.AutoProvisionUsesSudo = ParseBoolean (v)}, {"android-sdk-platforms=", "Comma separated list of Android SDK platform levels to be installed or 'latest' or 'all'. Defaults to 'latest' if no value is provided.", v => parsedOptions.AndroidSdkPlatforms = ParseAndroidSdkPlatformLevels (v?.Trim () ?? String.Empty) }, + {"dotnet-sdk-archive=", "Path to a local .NET SDK archive (zip or tar.gz) to use instead of downloading from the internet.", v => parsedOptions.LocalDotNetSdkArchive = v?.Trim () }, "", {"h|help", "Show this help message", v => parsedOptions.ShowHelp = true }, }; @@ -132,6 +134,7 @@ static async Task Run (string[] args) Context.Instance.AutoProvisionUsesSudo = parsedOptions.AutoProvisionUsesSudo; Context.Instance.ComponentsToRefresh = parsedOptions.RefreshList; Context.Instance.AndroidSdkPlatforms = parsedOptions.AndroidSdkPlatforms; + Context.Instance.LocalDotNetSdkArchive = parsedOptions.LocalDotNetSdkArchive; if (!String.IsNullOrEmpty (parsedOptions.Configuration)) Context.Instance.Configuration = parsedOptions.Configuration!; diff --git a/build-tools/xaprepare/xaprepare/Steps/Step_InstallDotNetPreview.cs b/build-tools/xaprepare/xaprepare/Steps/Step_InstallDotNetPreview.cs index 1207336cb64..1c0fb8e566e 100644 --- a/build-tools/xaprepare/xaprepare/Steps/Step_InstallDotNetPreview.cs +++ b/build-tools/xaprepare/xaprepare/Steps/Step_InstallDotNetPreview.cs @@ -21,7 +21,13 @@ protected override async Task Execute (Context context) var dotnetPath = Configurables.Paths.DotNetPreviewPath; dotnetPath = dotnetPath.TrimEnd (new char [] { Path.DirectorySeparatorChar }); - if (!await InstallDotNetAsync (context, dotnetPath, BuildToolVersion, useCachedInstallScript: true) && + // Check if a local SDK archive was specified + if (!String.IsNullOrEmpty (context.LocalDotNetSdkArchive)) { + if (!await InstallDotNetFromLocalArchiveAsync (context, dotnetPath, context.LocalDotNetSdkArchive!)) { + Log.ErrorLine ($"Installation of dotnet SDK from local archive '{context.LocalDotNetSdkArchive}' failed."); + return false; + } + } else if (!await InstallDotNetAsync (context, dotnetPath, BuildToolVersion, useCachedInstallScript: true) && !await InstallDotNetAsync (context, dotnetPath, BuildToolVersion, useCachedInstallScript: false)) { Log.ErrorLine ($"Installation of dotnet SDK '{BuildToolVersion}' failed."); return false; @@ -179,6 +185,21 @@ string[] GetInstallationScriptArgs (string version, string dotnetPath, string do return args.ToArray (); } + async Task InstallDotNetFromLocalArchiveAsync (Context context, string dotnetPath, string archivePath) + { + if (!File.Exists (archivePath)) { + Log.ErrorLine ($"Local .NET SDK archive not found: '{archivePath}'"); + return false; + } + + Log.StatusLine ($"Installing .NET SDK from local archive: {archivePath}"); + + // Always delete the bin/$(Configuration)/dotnet/ directory + Utilities.DeleteDirectory (dotnetPath); + + return await Utilities.Unpack (archivePath, dotnetPath); + } + async Task InstallDotNetAsync (Context context, string dotnetPath, string version, bool useCachedInstallScript, bool runtimeOnly = false) { string cacheDir = context.Properties.GetRequiredValue (KnownProperties.AndroidToolchainCacheDirectory);