docs/design/NuGets.md
There are several artifacts in the .NET MAUI "universe":
Microsoft.NET.Sdk.Maui.Manifest - The workload manifest for the .NET SDKMicrosoft.Maui.Sdk - The actual .NET MAUI workload SDKMicrosoft.Maui.Templates.net* - The current set of templates for this build of .NET MAUIMicrosoft.Maui.Controls - The super/root package of .NET MAUI Controls
Microsoft.Maui.Controls.Core - The Controls assembliesMicrosoft.Maui.Controls.Xaml - The XAML parserMicrosoft.Maui.Controls.Build.Tasks - The real set of XAML[C|G] targets and globsMicrosoft.Maui.Resizetizer - The framework-and-platform-agnostic asset generator and integratorMicrosoft.Maui.Core - The base interfaces and handlers for all .NET MAUI thingsMicrosoft.Maui.Essentials - The core set of framework-agnostic, cross-platform APIsMicrosoft.Maui.Controls.Compatibility - The set of compatibility APIs for Xamarin.FormsMicrosoft.Maui.Controls.Maps - The set of XAML-based map controlsMicrosoft.Maui.Maps - The set of handlers and interfaces for mapping controlsMicrosoft.Maui.Controls.Foldable - The set of APIs and controls needed for dual-screen supportMicrosoft.Maui.Graphics - The core graphics engine of .NET MAUIMicrosoft.Maui.Graphics.Win2D.WinUI.Desktop - The Win2D-based version of the graphics engine (soon to be merged with the core engine)Microsoft.Maui.Graphics.Skia - The SkiaSharp-based version of the graphics engineMicrosoft.Maui.Graphics.Text.Markdig - The markdown support for the graphics engineMicrosoft.AspNetCore.Components.WebView.Maui - The BlazorWebView for .NET MAUI appsMicrosoft.AspNetCore.Components.WebView.WindowsForms - The BlazorWebView for Windows Forms appsMicrosoft.AspNetCore.Components.WebView.Wpf - The BlazorWebView for WPF appsA typical workload has all the targets in the "SDK" portion and then pulls in a bunch of RID-specific NuGet packages, but for MAUI this is not necessary as the size of the entire workload with all the packs is about 60MB - with about 38MB actually just being SkiaSharp for all the platforms in the Resizetizer SDK.
For MAUI, we decided to reduce the number of pack and msi downloads and just go with almost a 1 to 1 csproj to nuget.
Most nugets do not contain or need targets and/or props files, but some do. These include:
Microsoft.NET.Sdk.Maui.ManifestMicrosoft.Maui.SdkMicrosoft.Maui.Controls.Build.TasksMicrosoft.Maui.CoreMicrosoft.Maui.ResizetizerIn most cases, there are 4 types of targets/props files:
<PackageId>.propsDirectory.Build.props) and can set defaults for the csproj to use.<PackageId>.targets<PackageId>.Before.targets file that runs before any targets run (but after all props have run).<PackageId>.After.targets file in the $(AfterMicrosoftNETSdkTargets) MSBuild property to run after all the targets have been imported. If a nuget needs to have some targets run at this point, then that nuget can append the file to the property:
<PropertyGroup>
<AfterMicrosoftNETSdkTargets>$(AfterMicrosoftNETSdkTargets);$(MSBuildThisFileDirectory)Microsoft.Maui.[something].After.targets</AfterMicrosoftNETSdkTargets>
</PropertyGroup>
<PackageId>.Before.targets<PackageId>.targets, but is split out to make the organization of the targets easier.<PackageId>.After.targetsThere are 2 components in the workload:
Microsoft.NET.Sdk.Maui.ManifestMicrosoft.Maui.SdkThe workload manifest contains the WorkloadManifest.json and the WorkloadManifest.targets as required by .NET. The .json file is just a tree of all the various components and pack IDs that are needed as part of the MAUI workload. The .targets file is just the entrypoint to the SDK and contains the SDK pack imports for MSBuild.
The SDK pack contains the actual targets and props files. Using a structure similar to the section above, it includes the main parts of the workload things.
There are 2 key files that must be present in a workload:
AutoImport.propsSdk.targetsBundledVersions.targets and Microsoft.Maui.Sdk.targets files depending on the UseXxx MSBuild properties.The targets file can then import all the SDK:
BundledVersions.targetsUseXxx MSBuild properties.Microsoft.Maui.Sdk.targetsMicrosoft.Maui.Sdk.Before.targets file that runs before any MAUI targets run (but after all props have run).$(MicrosoftMauiSdkPlatformTargets) MSBuild property. If a nuget needs to have some targets run at this point, then that nuget can append the file to the property:
<PropertyGroup>
<MicrosoftMauiSdkPlatformTargets>$(MicrosoftMauiSdkPlatformTargets);$(MSBuildThisFileDirectory)Microsoft.Maui.Sdk.[platform].targets</MicrosoftMauiSdkPlatformTargets>
</PropertyGroup>
Microsoft.Maui.Sdk.After.targets file to run after all the targets have been imported.Microsoft.Maui.Sdk.Before.targetsMicrosoft.Maui.Sdk.targets, but is split out to make the organization of the targets easier.Microsoft.Maui.Sdk.After.targetsProjectCapability items are included based on the UseXxx MSBuild properties. These values are used by the IDE to determine what to do and how to restore. So, these must also be on disk prior to any nuget install.There are 3 packs today that need targets:
Microsoft.Maui.Controls.Build.TasksMicrosoft.Maui.CoreMicrosoft.Maui.ResizetizerThe Controls section of MAUI is the main set of libraries that a MAUI app uses. The targets and props needed but MAUI mostly live in the Microsoft.Maui.Controls.Build.Tasks nuget. This is mainly because of the dependency structure of MAUI.
Controls is the "library name" as well as the assembly name - but the bits we need for the MSBuild tasks depend on this. We could do some funky magic and merge all the components of Controls into a single NuGet, but this is maybe not as worth it. Right now we have a empty NuGet that just pulls in all the things.
But for the targets, this is very similar to the structure mentioned above, but with some platform targets too.
For the files we use, there are 3 areas:
Platform Files
If NuGet detects a platform folder in the nuget, then it skips all other imports and just uses the files in there. As a result, the targets files are just dummy/redirection to import the netstandard targets. the props files are where the real customization comes from and is used to set some platform-specific details.
When the targets were all in the workload, they all ran at a point where the TFM could be used. But, when in a NuGet, they run too early so we use the NuGet feature of the TFM loading.
.NET Standard Files
This is the real work folder and is just netstandard because that is the TFM of the build tasks assembly - and that is just because this needs to be loaded by both the full MSBuild and the dotnet core MSBuild.
These targets follow the structure outlined above with some props files and then the targets files importing a before and after targets. Some of the things that these files do is set the globs and include the various XAML compiler tasks. It also hooks up the analyzers and AOT profiles.
Root Files
Some platforms do not count netstandard as part of net7 - such as Windows - so it falls back to nothing. Not sure if this is a bug or a feature, but having files at the root makes sure that all things get something.
The targets and props for Core all live in the root of the buildTransitive so that all platforms can have access to them without having to have duplicates or files importing them per TFM. Windows is the exception to this because it has to set some platform-specific properties. There are some Windows-specific targets and tasks in the root, but they are conditioned to the Windows TFM. This makes maintenance easier if everything is in a single file.
Since we have added a Windows TFM folder, NuGet stops looking at the root of the buildTransitive folder for targets and props. As a result, the Windows targets and props just import the root files after setting any platform-specific properties.
The targets and tasks in this NuGet are pretty minimal and really just set some core platform defaults - mainly Windows App SDK properties to control how we want projects to work in .NET MAUI. It also adds some Windows App SDK workarounds for bugs that have not yet reached the public releases.
The targets and props in Resizetizer are pretty standard and really all fit into 1 file. However, to be consistent we have the 4 base files.
The properties, targets and tasks are all imported on all platforms and are conditioned per TFM.
The targets and props in the Blazor nugets are maintained by the Blazor team and they just have a single targets and props file for all platforms to share.