public PackInfo(string id, string version, WorkloadPackKind kind, string path) { Id = id; Version = version; Kind = kind; Path = path; }
public WorkloadPack(WorkloadPackId id, string version, WorkloadPackKind kind, Dictionary <string, WorkloadPackId>?aliasTo) { Id = id; Version = version; Kind = kind; AliasTo = aliasTo; }
public PackInfo(string id, string version, WorkloadPackKind kind, string path, string resolvedPackageId) { Id = id; Version = version; Kind = kind; Path = path; ResolvedPackageId = resolvedPackageId; }
/// <summary> /// Get the installation directory based on the kind of workload pack. /// </summary> /// <param name="kind">The workload pack kind.</param> /// <returns>The name of the root installation directory.</returns> internal static string GetInstallDir(WorkloadPackKind kind) { return(kind switch { WorkloadPackKind.Framework or WorkloadPackKind.Sdk => "packs", WorkloadPackKind.Library => "library-packs", WorkloadPackKind.Template => "template-packs", WorkloadPackKind.Tool => "tool-packs", _ => throw new ArgumentException($"Unknown package kind: {kind}"), });
/// <summary> /// Gets the installed workload packs of a particular kind /// </summary> /// <remarks> /// Used by MSBuild resolver to scan SDK packs for AutoImport.props files to be imported. /// Used by template engine to find templates to be added to hive. /// </remarks> public IEnumerable <PackInfo> GetInstalledWorkloadPacksOfKind(WorkloadPackKind kind) { foreach (var pack in _packs) { if (pack.Value.Kind != kind) { continue; } var aliasedPath = GetAliasedPackPath(pack.Value); if (PackExists(aliasedPath, pack.Value.Kind)) { yield return(CreatePackInfo(pack.Value, aliasedPath)); } } }
/// <summary> /// Gets the installed workload packs of a particular kind /// </summary> /// <remarks> /// Used by MSBuild resolver to scan SDK packs for AutoImport.props files to be imported. /// Used by template engine to find templates to be added to hive. /// </remarks> public IEnumerable <PackInfo> GetInstalledWorkloadPacksOfKind(WorkloadPackKind kind) { foreach (var pack in _packs) { if (pack.Value.Kind != kind) { continue; } var aliasedPath = ResolvePackPath(pack.Value); var resolvedPackageId = pack.Value.IsAlias ? pack.Value.TryGetAliasForRuntimeIdentifiers(_currentRuntimeIdentifiers)?.ToString() : pack.Value.Id.ToString(); if (aliasedPath != null && resolvedPackageId != null && PackExists(aliasedPath, pack.Value.Kind)) { yield return(CreatePackInfo(pack.Value, aliasedPath, resolvedPackageId)); } } }
private bool PackExists(string packPath, WorkloadPackKind packKind) { switch (packKind) { case WorkloadPackKind.Framework: case WorkloadPackKind.Sdk: case WorkloadPackKind.Tool: //can we do a more robust check than directory.exists? return(_directoryExistOverride?.Invoke(packPath) ?? Directory.Exists(packPath)); case WorkloadPackKind.Library: case WorkloadPackKind.Template: return(_fileExistOverride?.Invoke(packPath) ?? File.Exists(packPath)); default: throw new ArgumentException($"The package kind '{packKind}' is not known", nameof(packKind)); } }
public IEnumerable <WorkloadResolver.PackInfo> GetInstalledWorkloadPacks(WorkloadPackKind kind) => workloadResolver.GetInstalledWorkloadPacksOfKind(kind);
static PackInfo CreatePackInfo(string id, string version, WorkloadPackKind kind, string path, string resolvedPackageId) => new(new WorkloadPackId(id), version, kind, path, resolvedPackageId);
private string GetPackPath(string [] dotnetRootPaths, WorkloadPackId packageId, string packageVersion, WorkloadPackKind kind) { string packPath = ""; bool isFile; foreach (var rootPath in dotnetRootPaths) { switch (kind) { case WorkloadPackKind.Framework: case WorkloadPackKind.Sdk: packPath = Path.Combine(rootPath, "packs", packageId.ToString(), packageVersion); isFile = false; break; case WorkloadPackKind.Template: packPath = Path.Combine(rootPath, "template-packs", packageId.GetNuGetCanonicalId() + "." + packageVersion.ToLowerInvariant() + ".nupkg"); isFile = true; break; case WorkloadPackKind.Library: packPath = Path.Combine(rootPath, "library-packs", packageId.GetNuGetCanonicalId() + "." + packageVersion.ToLowerInvariant() + ".nupkg"); isFile = true; break; case WorkloadPackKind.Tool: packPath = Path.Combine(rootPath, "tool-packs", packageId.ToString(), packageVersion); isFile = false; break; default: throw new ArgumentException($"The package kind '{kind}' is not known", nameof(kind)); } bool packFound = isFile ? _fileExistOverride?.Invoke(packPath) ?? File.Exists(packPath) : _directoryExistOverride?.Invoke(packPath) ?? Directory.Exists(packPath);; if (packFound) { break; } } return(packPath); }
public IEnumerable <WorkloadResolver.PackInfo> GetInstalledWorkloadPacksOfKind(WorkloadPackKind kind) => throw new NotImplementedException();
private static string GetPackPath(string dotnetRootPath, WorkloadPackId packageId, string packageVersion, WorkloadPackKind kind) { switch (kind) { case WorkloadPackKind.Framework: case WorkloadPackKind.Sdk: return(Path.Combine(dotnetRootPath, "packs", packageId.ToString(), packageVersion)); case WorkloadPackKind.Template: return(Path.Combine(dotnetRootPath, "template-packs", packageId.GetNuGetCanonicalId() + "." + packageVersion.ToLowerInvariant() + ".nupkg")); case WorkloadPackKind.Library: return(Path.Combine(dotnetRootPath, "library-packs", packageId.GetNuGetCanonicalId() + "." + packageVersion.ToLowerInvariant() + ".nupkg")); case WorkloadPackKind.Tool: return(Path.Combine(dotnetRootPath, "tool-packs", packageId.ToString(), packageVersion)); default: throw new ArgumentException($"The package kind '{kind}' is not known", nameof(kind)); } }
/// <summary> /// Generate a set of MSIs for the specified platforms using the specified NuGet package. /// </summary> /// <param name="sourcePackage">The NuGet package to convert into an MSI.</param> /// <param name="outputPath">The output path of the generated MSI.</param> /// <param name="platforms"></param> protected IEnumerable <ITaskItem> Generate(string sourcePackage, string swixPackageId, string outputPath, WorkloadPackKind kind, params string[] platforms) { NugetPackage nupkg = new(sourcePackage, Log); List <TaskItem> msis = new(); // MSI ProductName defaults to the package title and fallback to the package ID with a warning. string productName = nupkg.Title; if (string.IsNullOrWhiteSpace(nupkg.Title)) { Log?.LogMessage(MessageImportance.High, $"'{sourcePackage}' should have a non-empty title. The MSI ProductName will be set to the package ID instead."); productName = nupkg.Id; } // Extract once, but harvest multiple times because some generated attributes are platform dependent. string packageContentsDirectory = Path.Combine(PackageDirectory, $"{nupkg.Identity}"); IEnumerable <string> exclusions = GetExlusionPatterns(); string installDir = GetInstallDir(kind); string packKind = kind.ToString().ToLowerInvariant(); if ((kind != WorkloadPackKind.Library) && (kind != WorkloadPackKind.Template)) { Log.LogMessage(MessageImportance.Low, $"Extracting '{sourcePackage}' to '{packageContentsDirectory}'"); nupkg.Extract(packageContentsDirectory, exclusions); } else { // Library and template packs are not extracted. We want to harvest the nupkg itself, // instead of the contents. The package is still copied to a separate folder for harvesting // to avoid accidentally pulling in additional files and directories. Log.LogMessage(MessageImportance.Low, $"Copying '{sourcePackage}' to '{packageContentsDirectory}'"); if (Directory.Exists(packageContentsDirectory)) { Directory.Delete(packageContentsDirectory, recursive: true); } Directory.CreateDirectory(packageContentsDirectory); File.Copy(sourcePackage, Path.Combine(packageContentsDirectory, Path.GetFileName(sourcePackage))); } System.Threading.Tasks.Parallel.ForEach(platforms, platform => { // Extract the MSI template and add it to the list of source files. List <string> sourceFiles = new(); string msiSourcePath = Path.Combine(MsiDirectory, $"{nupkg.Id}", $"{nupkg.Version}", platform); sourceFiles.Add(EmbeddedTemplates.Extract("DependencyProvider.wxs", msiSourcePath)); sourceFiles.Add(EmbeddedTemplates.Extract("Directories.wxs", msiSourcePath)); sourceFiles.Add(EmbeddedTemplates.Extract("Product.wxs", msiSourcePath)); sourceFiles.Add(EmbeddedTemplates.Extract("Registry.wxs", msiSourcePath)); string EulaRtfPath = Path.Combine(msiSourcePath, "eula.rtf"); File.WriteAllText(EulaRtfPath, Eula.Replace("__LICENSE_URL__", nupkg.LicenseUrl)); EmbeddedTemplates.Extract("Variables.wxi", msiSourcePath); // Harvest the package contents and add it to the source files we need to compile. 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 = directoryReference, OutputFile = packageContentWxs, Platform = platform, SourceDirectory = packageContentsDirectory }; if (!heat.Execute()) { throw new Exception($"Failed to harvest package contents."); } // Compile the MSI sources string candleIntermediateOutputPath = Path.Combine(IntermediateBaseOutputPath, "wixobj", $"{nupkg.Id}", $"{nupkg.Version}", platform); CompileToolTask candle = new(BuildEngine, WixToolsetPath) { // Candle expects the output path to end with a single '\' OutputPath = candleIntermediateOutputPath.TrimEnd(Path.DirectorySeparatorChar) + Path.DirectorySeparatorChar, SourceFiles = sourceFiles, Arch = platform }; // Configure preprocessor definitions. string manufacturer = "Microsoft Corporation"; if (!string.IsNullOrWhiteSpace(nupkg.Authors) && (nupkg.Authors.IndexOf("Microsoft", StringComparison.OrdinalIgnoreCase) < 0)) { manufacturer = nupkg.Authors; } Log.LogMessage(MessageImportance.Low, $"Setting Manufacturer to '{manufacturer}'"); candle.PreprocessorDefinitions.AddRange(GetPreprocessorDefinitions(nupkg, platform)); candle.PreprocessorDefinitions.Add($@"InstallDir={installDir}"); candle.PreprocessorDefinitions.Add($@"ProductName={productName}"); candle.PreprocessorDefinitions.Add($@"Platform={platform}"); 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"); if (!candle.Execute()) { throw new Exception($"Failed to compile MSI."); } // Link the MSI. The generated filename contains a the semantic version (excluding build metadata) and platform. // If the source package already contains a platform, e.g. an aliased package that has a RID, then we don't add // the platform again. string shortPackageName = Path.GetFileNameWithoutExtension(sourcePackage).Replace(ShortNames); string outputFile = sourcePackage.Contains(platform) ? Path.Combine(OutputPath, shortPackageName + ".msi") : Path.Combine(OutputPath, shortPackageName + $"-{platform}.msi"); LinkToolTask light = new(BuildEngine, WixToolsetPath) { OutputFile = Path.Combine(OutputPath, outputFile), SourceFiles = Directory.EnumerateFiles(candleIntermediateOutputPath, "*.wixobj"), SuppressIces = this.SuppressIces }; // Add WiX extensions light.Extensions.Add("WixDependencyExtension"); light.Extensions.Add("WixUIExtension"); if (!light.Execute()) { throw new Exception($"Failed to link MSI."); } // Generate metadata used for CLI based installations. string msiPath = light.OutputFile; MsiProperties msiProps = new MsiProperties { InstallSize = MsiUtils.GetInstallSize(msiPath), Language = Convert.ToInt32(MsiUtils.GetProperty(msiPath, "ProductLanguage")), Payload = Path.GetFileName(msiPath), ProductCode = MsiUtils.GetProperty(msiPath, "ProductCode"), ProductVersion = MsiUtils.GetProperty(msiPath, "ProductVersion"), ProviderKeyName = $"{nupkg.Id},{nupkg.Version},{platform}", UpgradeCode = MsiUtils.GetProperty(msiPath, "UpgradeCode"), RelatedProducts = MsiUtils.GetRelatedProducts(msiPath) }; string msiJsonPath = Path.Combine(Path.GetDirectoryName(msiPath), Path.GetFileNameWithoutExtension(msiPath) + ".json"); File.WriteAllText(msiJsonPath, JsonSerializer.Serialize <MsiProperties>(msiProps)); TaskItem msi = new(light.OutputFile); msi.SetMetadata(Metadata.Platform, platform); msi.SetMetadata(Metadata.Version, nupkg.ProductVersion); msi.SetMetadata(Metadata.JsonProperties, msiJsonPath); msi.SetMetadata(Metadata.WixObj, candleIntermediateOutputPath); if (GenerateSwixAuthoring && IsSupportedByVisualStudio(platform)) { string swixProject = GenerateSwixPackageAuthoring(light.OutputFile, !string.IsNullOrWhiteSpace(swixPackageId) ? swixPackageId : $"{nupkg.Id.Replace(ShortNames)}.{nupkg.Version}", 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)); msis.Add(msi); }); return(msis); }