diff --git a/src/Microsoft.DotNet.Build.Tasks.Workloads/src/GenerateManifestMsi.cs b/src/Microsoft.DotNet.Build.Tasks.Workloads/src/GenerateManifestMsi.cs index 384e46cfdde..ec049c9b3f7 100644 --- a/src/Microsoft.DotNet.Build.Tasks.Workloads/src/GenerateManifestMsi.cs +++ b/src/Microsoft.DotNet.Build.Tasks.Workloads/src/GenerateManifestMsi.cs @@ -17,6 +17,15 @@ public class GenerateManifestMsi : GenerateTaskBase { private Version _sdkFeaureBandVersion; + /// + /// Gets or sets whether a corresponding SWIX project should be generated for the MSI. + /// + public bool GenerateSwixAuthoring + { + get; + set; + } = true; + /// /// The path where the generated MSIs will be placed. /// @@ -30,7 +39,6 @@ public string OutputPath /// /// The ID of the workload manifest. /// - [Required] public string ManifestId { get; @@ -65,7 +73,6 @@ private Version SdkFeatureBandVersion /// /// The SDK version, e.g. 6.0.107. /// - [Required] public string SdkVersion { get; @@ -102,11 +109,35 @@ public override bool Execute() { try { - Log.LogMessage($"Generating workload manifest installer for {SdkFeatureBandVersion}"); - NugetPackage nupkg = new(WorkloadManifestPackage, Log); List msis = new(); + var manifestSeparator = ".Manifest-"; + if (string.IsNullOrWhiteSpace(ManifestId)) + { + if ($"{nupkg.Id}".IndexOf(manifestSeparator, StringComparison.OrdinalIgnoreCase) == -1) + { + Log.LogError($"Unable to parse a manifest ID from package ID: '{nupkg.Id}'. Please provide the 'ManifestId' parameter."); + } + else + { + ManifestId = $"{nupkg.Id}".Substring(0, $"{nupkg.Id}".IndexOf(manifestSeparator)); + } + } + if (string.IsNullOrWhiteSpace(SdkVersion)) + { + if ($"{nupkg.Id}".IndexOf(manifestSeparator, StringComparison.OrdinalIgnoreCase) == -1) + { + Log.LogError($"Unable to parse the SDK version from package ID: '{nupkg.Id}'. Please provide the 'SdkVersion' parameter."); + } + else + { + SdkVersion = $"{nupkg.Id}".Substring($"{nupkg.Id}".IndexOf(manifestSeparator) + manifestSeparator.Length); + } + } + + Log.LogMessage(MessageImportance.High, $"Generating workload manifest installer for {SdkFeatureBandVersion}"); + // MSI ProductName defaults to the package title and fallback to the package ID with a warning. string productName = nupkg.Title; @@ -116,6 +147,10 @@ public override bool Execute() productName = nupkg.Id; } + + + + // Extract once, but harvest multiple times because some generated attributes are platform dependent. string packageContentsDirectory = Path.Combine(PackageDirectory, $"{nupkg.Identity}"); nupkg.Extract(packageContentsDirectory, Enumerable.Empty()); @@ -252,6 +287,19 @@ public override bool Execute() msi.SetMetadata(Metadata.JsonProperties, msiJsonPath); msi.SetMetadata(Metadata.WixObj, candleIntermediateOutputPath); + if (GenerateSwixAuthoring && IsSupportedByVisualStudio(platform)) + { + string swixPackageId = $"{nupkg.Id}"; + + string swixProject = GenerateSwixPackageAuthoring(light.OutputFile, + swixPackageId, platform); + + if (!string.IsNullOrWhiteSpace(swixProject)) + { + msi.SetMetadata(Metadata.SwixProject, swixProject); + } + } + // Generate a .csproj to build a NuGet payload package to carry the MSI and JSON manifest msi.SetMetadata(Metadata.PackageProject, GeneratePackageProject(msi.ItemSpec, msiJsonPath, platform, nupkg)); @@ -268,7 +316,6 @@ public override bool Execute() return !Log.HasLoggedErrors; } - private string GeneratePackageProject(string msiPath, string msiJsonPath, string platform, NugetPackage nupkg) { string msiPackageProject = Path.Combine(MsiPackageDirectory, platform, nupkg.Id, "msi.csproj"); @@ -358,5 +405,24 @@ private void WriteItem(XmlWriter writer, string itemName, string include, string writer.WriteAttributeString("PackagePath", packagePath); writer.WriteEndElement(); } + + private string GenerateSwixPackageAuthoring(string msiPath, string packageId, string platform) + { + GenerateVisualStudioMsiPackageProject swixTask = new() + { + Chip = platform, + IntermediateBaseOutputPath = this.IntermediateBaseOutputPath, + PackageName = packageId, + MsiPath = msiPath, + BuildEngine = this.BuildEngine, + }; + + if (!swixTask.Execute()) + { + Log.LogError($"Failed to generate SWIX authoring for '{msiPath}'"); + } + + return swixTask.SwixProject; + } } } diff --git a/src/Microsoft.DotNet.Build.Tasks.Workloads/src/GenerateMsiBase.cs b/src/Microsoft.DotNet.Build.Tasks.Workloads/src/GenerateMsiBase.cs index 9e201639401..3f36c9d0a11 100644 --- a/src/Microsoft.DotNet.Build.Tasks.Workloads/src/GenerateMsiBase.cs +++ b/src/Microsoft.DotNet.Build.Tasks.Workloads/src/GenerateMsiBase.cs @@ -134,6 +134,7 @@ protected IEnumerable Generate(string sourcePackage, string swixPacka string packageContentsDirectory = Path.Combine(PackageDirectory, $"{nupkg.Identity}"); IEnumerable exclusions = GetExlusionPatterns(); string installDir = GetInstallDir(kind); + string packKind = kind.ToString().ToLowerInvariant(); if ((kind != WorkloadPackKind.Library) && (kind != WorkloadPackKind.Template)) { @@ -174,10 +175,14 @@ protected IEnumerable Generate(string sourcePackage, string swixPacka string packageContentWxs = Path.Combine(msiSourcePath, "PackageContent.wxs"); sourceFiles.Add(packageContentWxs); + string directoryReference = (kind == WorkloadPackKind.Library) || (kind == WorkloadPackKind.Template) + ? "InstallDir" + : PackageContentDirectoryReference; + HarvestToolTask heat = new(BuildEngine, WixToolsetPath) { ComponentGroupName = PackageContentComponentGroupName, - DirectoryReference = PackageContentDirectoryReference, + DirectoryReference = directoryReference, OutputFile = packageContentWxs, Platform = platform, SourceDirectory = packageContentsDirectory @@ -216,6 +221,7 @@ protected IEnumerable Generate(string sourcePackage, string swixPacka candle.PreprocessorDefinitions.Add($@"SourceDir={packageContentsDirectory}"); candle.PreprocessorDefinitions.Add($@"Manufacturer={manufacturer}"); candle.PreprocessorDefinitions.Add($@"EulaRtf={EulaRtfPath}"); + candle.PreprocessorDefinitions.Add($@"PackKind={packKind}"); // Compiler extension to process dependency provider authoring for package reference counting. candle.Extensions.Add("WixDependencyExtension"); diff --git a/src/Microsoft.DotNet.Build.Tasks.Workloads/src/MsiTemplate/Directories.wxs b/src/Microsoft.DotNet.Build.Tasks.Workloads/src/MsiTemplate/Directories.wxs index 574cbe373b1..709bbb08563 100644 --- a/src/Microsoft.DotNet.Build.Tasks.Workloads/src/MsiTemplate/Directories.wxs +++ b/src/Microsoft.DotNet.Build.Tasks.Workloads/src/MsiTemplate/Directories.wxs @@ -7,9 +7,11 @@ + +