| File: ShowMissingWorkloads.cs | Web Access |
| Project: src\sdk\src\Tasks\Microsoft.NET.Build.Tasks\Microsoft.NET.Build.Tasks.csproj (Microsoft.NET.Build.Tasks) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. #nullable disable using System.Globalization; using Microsoft.Build.Framework; using Microsoft.Build.Utilities; using Microsoft.DotNet.Configurer; using Microsoft.NET.Sdk.WorkloadManifestReader; using static Microsoft.NET.Sdk.WorkloadManifestReader.WorkloadResolver; namespace Microsoft.NET.Build.Tasks { public class ShowMissingWorkloads : TaskBase { private static readonly string MauiCrossPlatTopLevelVSWorkloads = "Microsoft.VisualStudio.Workload.NetCrossPlat"; private static readonly string MauiComponentGroupVSWorkload = "Microsoft.VisualStudio.ComponentGroup.Maui.All"; private static readonly string WasmTopLevelVSWorkload = "Microsoft.VisualStudio.Workload.NetWeb"; private static readonly HashSet<string> MauiWorkloadIds = new(StringComparer.OrdinalIgnoreCase) { "android", "android-aot", "ios", "maccatalyst", "macos", "maui", "maui-android", "maui-desktop", "maui-ios", "maui-maccatalyst", "maui-mobile", "maui-windows", "tvos" }; private static readonly HashSet<string> WasmWorkloadIds = new(StringComparer.OrdinalIgnoreCase) { "wasm-tools", "wasm-tools-net6", "wasm-tools-net7", "wasm-tools-net8", "wasm-tools-net9" }; public ITaskItem[] MissingWorkloadPacks { get; set; } public string NetCoreRoot { get; set; } public string NETCoreSdkVersion { get; set; } public bool GenerateErrorsForMissingWorkloads { get; set; } [Output] public ITaskItem[] SuggestedWorkloads { get; set; } protected override void ExecuteCore() { if (MissingWorkloadPacks.Any()) { string userProfileDir = new CliFolderPathCalculatorCore().GetDotnetUserProfileFolderPath(); // When running MSBuild tasks, the current directory is always the project directory, so we can use that as the // starting point to search for global.json string globalJsonPath = SdkDirectoryWorkloadManifestProvider.GetGlobalJsonPath(Environment.CurrentDirectory); var workloadManifestProvider = new SdkDirectoryWorkloadManifestProvider(NetCoreRoot, NETCoreSdkVersion, userProfileDir, globalJsonPath); var workloadResolver = Create(workloadManifestProvider, NetCoreRoot, NETCoreSdkVersion, userProfileDir); var suggestedWorkloads = workloadResolver.GetWorkloadSuggestionForMissingPacks( MissingWorkloadPacks.Select(item => new WorkloadPackId(item.ItemSpec)).ToList(), out ISet<WorkloadPackId> unsatisfiablePacks ); if (GenerateErrorsForMissingWorkloads) { if (suggestedWorkloads is not null) { var errorMessage = string.Format(CultureInfo.CurrentCulture, Strings.WorkloadNotInstalled, string.Join(" ", suggestedWorkloads.Select(w => w.Id))); Log.LogError(errorMessage); } else { Log.LogError(Strings.WorkloadNotAvailable, string.Join(" ", unsatisfiablePacks)); } } if (suggestedWorkloads is not null) { SuggestedWorkloads = suggestedWorkloads.Select(suggestedWorkload => { var suggestedWorkloadsList = GetSuggestedWorkloadsList(suggestedWorkload); var taskItem = new TaskItem(suggestedWorkload.Id); taskItem.SetMetadata("VisualStudioComponentId", ToSafeId(suggestedWorkload.Id)); taskItem.SetMetadata("VisualStudioComponentIds", string.Join(";", suggestedWorkloadsList)); return taskItem; }).ToArray(); } } } internal static string ToSafeId(string id) { return id.Replace("-", ".").Replace(" ", ".").Replace("_", "."); } private static IEnumerable<string> GetSuggestedWorkloadsList(WorkloadInfo workloadInfo) { yield return ToSafeId(workloadInfo.Id); if (MauiWorkloadIds.Contains(workloadInfo.Id.ToString())) { yield return MauiCrossPlatTopLevelVSWorkloads; yield return MauiComponentGroupVSWorkload; } if (WasmWorkloadIds.Contains(workloadInfo.Id.ToString())) { yield return WasmTopLevelVSWorkload; } } } }