Migrating Projects to Uno.Sdk
The Uno.Sdk provides several enhancements to further simplify Uno Projects and a single location for updating the Uno Platform core packages version in global.json
.
Important
Migrating to the Uno.Sdk is not required. Existing projects continue to be supported in Uno Platform 5.1 or later.
What is the Uno.Sdk
The Uno.Sdk is designed to reduce the noise that you need in your projects, while still ensuring that you have the ability to customize the configuration to your needs.
This means that values such as the SupportedOSPlatformVersion
, which have been in the template's Directory.Build.props
in previous Uno Platform templates, now have a default value set to the minimum supported by Uno Platform.
If you need to be more restrictive for your specific project you can provide your overrides for the platform(s) that you need.
Upgrading an existing project to Uno.Sdk
The following sections detail how to upgrade an existing project to use the Uno.Sdk to simplify project files. Those modifications are made in-place and it is strongly recommended to work on a source-controlled environment.
While following this guide, you can compare with a new empty project created using our Wizard, or using dotnet new templates.
Create a global.json
It is recommended that you create a global.json in your solution root directory.
{
"msbuild-sdks": {
"Uno.Sdk": "{Current Version of Uno.WinUI/Uno.Sdk}",
"Microsoft.Build.NoTargets": "3.7.56"
}
}
Note
The Microsoft.Build.NoTargets Sdk has been used for the last several versions in the Uno Templates. Depending on which version of the templates this may have been called {YourProject}.Base
or {YourProject}.Shared
. With the introduction of the global.json
file, you may want to update the Sdk
in the csproj to remove the version and use the version provided by the global.json
instead. This centralizes your Sdk versions.
Using the Uno.Sdk
Modern .NET Projects use an Sdk, defined as on the root element of a csproj
file. By default your project's will target typically the Microsoft.NET.Sdk
.
Some projects such as the Wasm and Server projects in the Uno Templates will target Microsoft.NET.Sdk.Web
. As previously mentioned the .Shared
project targets the Microsoft.Build.NoTargets
Sdk. The difference between these Sdk's is the Microsoft.Build.NoTargets
much like the Uno.Sdk
are shipped and versioned on NuGet.org while the first two are shipped and installed as part of the larger .NET Sdk/Runtime itself.
To update your projects, replace Microsoft.NET.Sdk
(Microsoft.NET.Sdk.Web
in the case of the Wasm head) with Uno.Sdk
. You will do this in the projects that you would reference Uno from. As an example let's say that you called your project AwesomeProject
, you would update the following projects:
- AwesomeProject
- AwesomeProject.Mobile
- AwesomeProject.Skia.Gtk
- AwesomeProject.Skia.Linux.FrameBuffer
- AwesomeProject.Skia.WPF
- AwesomeProject.Wasm
- AwesomeProject.Windows
<Project Sdk="Uno.Sdk">
The UnoVersion Property
The core libraries that ship from the main Uno repo (these are versioned together with Uno.WinUI.*), can now be controlled by the version of the Uno.Sdk that you are using. This common version is available through the $(UnoVersion)
property set by the Uno.Sdk.
Note
The exception to this naming convention is the Uno.UI.Adapter.Microsoft.Extensions.Logging
NuGet package, which can also use $(UnoVersion)
.
If you are using Central Package Management (there is a Directory.Packages.props
in your solution) this will be very easy as you simply need to open the Directory.Packages.props
.
If you are not using Central Package Management you will need to open the various csproj files that have a Package Reference to one of the Uno NuGet's. You should do a Find/Replace for the version of Uno that you are using and replace it with the $(UnoVersion)
.
To update Uno Platform in the future simply update the version of the Uno.Sdk
that you are targeting in the global.json
as shown above.
Here is an example on how the Directory.Packages.props
should look like:
<PackageVersion Include="Uno.UI.Adapter.Microsoft.Extensions.Logging" Version="$(UnoVersion)" />
<PackageVersion Include="Uno.WinUI" Version="$(UnoVersion)" />
<PackageVersion Include="Uno.WinUI.Lottie" Version="$(UnoVersion)" />
<PackageVersion Include="Uno.WinUI.DevServer" Version="$(UnoVersion)" />
<PackageVersion Include="Uno.WinUI.Skia.Gtk" Version="$(UnoVersion)" />
<PackageVersion Include="Uno.WinUI.Skia.Linux.FrameBuffer" Version="$(UnoVersion)" />
<PackageVersion Include="Uno.WinUI.Skia.Wpf" Version="$(UnoVersion)" />
<PackageVersion Include="Uno.WinUI.WebAssembly" Version="$(UnoVersion)" />
Cleaning up the Directory.Build.props
There are several properties defined in the top of the Directory.Build.props
. The values shown below are the default values from the previous templates. If these are still the values you have in your Directory.Build.props you can remove them.
<PropertyGroup>
<DebugType>portable</DebugType>
<DebugSymbols>True</DebugSymbols>
<DefaultLanguage>en</DefaultLanguage>
<IsAndroid>false</IsAndroid>
<IsIOS>false</IsIOS>
<IsMac>false</IsMac>
<IsMacCatalyst>false</IsMacCatalyst>
<IsWinAppSdk>false</IsWinAppSdk>
</PropertyGroup>
Note
If you would like to continue to use the Is{Platform}
properties in your project you should leave these in your Directory.Build.props along with the Choose/When block to set them when they are true.
Beneath the PropertyGroup
is a Choose
block with conditions for various TargetFramework
's. This can be entirely removed with one exception. By default the Sdk will provide the following values for you automatically setting the SupportedOSPlatformVersion
and also the TargetPlatformMinVersion
on Windows. If these values differ for your project be sure to keep your overrides. Any ItemGroup
within the conditional blocks can be removed along with any other properties that are defined there.
Target | SupportedOSPlatformVersion |
---|---|
Android | 21 |
iOS | 14.2 |
macOS | 10.14 |
MacCatalyst | 14.0 |
WinUI | 10.0.18362.0 |
Lastly the solution-config.props
file is now automatically located and loaded for you if it exists. Be sure to remove the Import
at the bottom of the Directory.Build.props
.
Cleaning up the Directory.Build.targets
The Directory.Build.targets
in the Uno.Templates has only had a small block to remove native Platform Using's (shown below). This is now safe to remove as it is done directly in the Uno.Sdk.
<ItemGroup>
<!-- Removes native usings to avoid Ambiguous reference -->
<Using Remove="@(Using->HasMetadata('Platform'))" />
</ItemGroup>
Cleaning up the Common Shared project
The Uno.Sdk contains a number of Default Items to further reduce the clutter required inside of your projects. To start you can remove the block that replicates the same default includes that come from the Windows App Sdk:
<!-- Include all images by default - matches the __WindowsAppSdkDefaultImageIncludes property in the WindowsAppSDK -->
<Content Include="Assets\**;**/*.png;**/*.bmp;**/*.jpg;**/*.dds;**/*.tif;**/*.tga;**/*.gif" Exclude="bin\**;obj\**;**\*.svg" />
<Page Include="**\*.xaml" Exclude="bin\**\*.xaml;obj\**\*.xaml" />
<Compile Update="**\*.xaml.cs">
<DependentUpon>%(Filename)</DependentUpon>
</Compile>
<PRIResource Include="**\*.resw" />
Towards the bottom of your csproj you should also see the following items which should be removed:
<UnoImage Include="Assets\**\*.svg" />
<UpToDateCheckInput Include="**\*.xaml" Exclude="bin\**\*.xaml;obj\**\*.xaml" />
If you have a Windows target you will additionally want to update the Choose
block to remove the $(IsWinAppSdk)
:
<When Condition="$(TargetFramework.Contains('windows10'))">
Cleanup up the Mobile project
The Uno.Sdk
now provides defaults for the AndroidManifest
which make it unnecessary to provide the value in the Mobile project head. As a result you can remove this property.
<AndroidManifest>Android\AndroidManifest.xml</AndroidManifest>
After removing the Choose
block in the Directory.Build.props
you will find that the variables defined there are no longer available. You will need to update the Choose
block in the Mobile project to use the more verbose MSBuild lookup for the Target Platform Identifier like:
<When Condition=" $([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'android' ">
</When>
<When Condition=" $([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'ios' ">
</When>
<When Condition=" $([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'maccatalyst' ">
</When>
Cleaning up the Windows project
To start you can clean up the Windows project by removing any of the following properties. These are provided for you by default with the Uno.Sdk
. If you have customized them in any way you should keep these properties to override the default behavior provided by the Uno.Sdk
:
<ApplicationManifest>app.manifest</ApplicationManifest>
<RuntimeIdentifiers>win-x86;win-x64;win-arm64</RuntimeIdentifiers>
<PublishProfile>win-$(Platform).pubxml</PublishProfile>
<UseWinUI>true</UseWinUI>
<EnableMsixTooling>true</EnableMsixTooling>
<EnableWindowsTargeting>true</EnableWindowsTargeting>
Next you can remove the following ItemGroup which is no longer needed:
<ItemGroup>
<Content Include="Images\**" />
<Manifest Include="$(ApplicationManifest)" />
</ItemGroup>
Finally towards the bottom of the Windows project you will find two blocks that contain work around's for Visual Studio. These can both be removed as they are provided for you as part of the Uno.Sdk
.
<!--
Defining the "Msix" ProjectCapability here allows the Single-project MSIX Packaging
Tools extension to be activated for this project even if the Windows App SDK Nuget
package has not yet been restored.
-->
<ItemGroup Condition="'$(DisableMsixProjectCapabilityAddedByProject)'!='true' and '$(EnableMsixTooling)'=='true'">
<ProjectCapability Include="Msix"/>
</ItemGroup>
<!--
Defining the "HasPackageAndPublishMenuAddedByProject" property here allows the Solution
Explorer "Package and Publish" context menu entry to be enabled for this project even if
the Windows App SDK Nuget package has not yet been restored.
-->
<PropertyGroup Condition="'$(DisableHasPackageAndPublishMenuAddedByProject)'!='true' and '$(EnableMsixTooling)'=='true'">
<HasPackageAndPublishMenu>true</HasPackageAndPublishMenu>
</PropertyGroup>
Customizing the behavior of the Uno.Sdk
Disabling Default Items
As previously discussed, the Uno.Sdk
will automatically includes files that you previously needed to manage within your projects. These default item's include definitions for including files within the Content
, Page
, abd PRIResource
ItemGroup
's. Additionally if you have referenced the Uno.Resizetizer
it will add default items for the UnoImage
allowing you to more easily manage your image assets.
You may disable this behavior in one of two ways:
<PropertyGroup>
<!-- Globally disable all default includes from the `Uno.Sdk`, `Microsoft.NET.Sdk` and if building on WASM `Microsoft.NET.Sdk.Web` -->
<EnableDefaultItems>false</EnableDefaultItems>
<!-- Disable only default items provided by the `Uno.Sdk` -->
<EnableDefaultUnoItems>false</EnableDefaultUnoItems>
</PropertyGroup>
Configure the solution-config.props
By default the Uno.Sdk
will automatically import the solution-config.props
if one exists. To disable this behavior you can set the following property and the Uno.Sdk
will not import the solution-config.props
file.
<PropertyGroup>
<ImportSolutionConfigProps>false</ImportSolutionConfigProps>
</PropertyGroup>
To specify a specific location for the solution-config.props
you can set the following property with the path to the file.
<PropertyGroup>
<SolutionConfigPropsPath>path/to/solution-config.props</SolutionConfigPropsPath>
</Property>
Note
If you specify the SolutionConfigPropsPath
, it will still only be imported if the file exists which makes it safe to use with source control as it should not exist in CI and therefore would not be imported during a CI build.
WinAppSdk PRIResource Workaround
Many Uno projects and libraries make use of a winappsdk-workaround.targets
file that corrects a bug found in WinUI. When using the Uno.Sdk
these targets now are provided for you out of the box. This extra set of workaround targets can be disabled by setting the following property:
<PropertyGroup>
<DisableWinUI8857_Workaround>true</DisableWinUI8857_Workaround>
</PropertyGroup>
Cross Targeting Support
By Default when using the Uno.Sdk you get the added benefit of default includes for an easier time building Cross Targeted Applications. The supported file extensions are as shown below:
- *.crossruntime.cs (WASM, Skia, or Reference)
- *.wasm.cs
- *.skia.cs
- *.reference.cs
- *.iOS.cs (iOS & MacCatalyst)
- *.macOS.cs (MacOS not MacCatalyst)
- *.iOSmacOS.cs (iOS, MacCatalyst, & MacOS)
- *.Android.cs
As discussed above setting EnableDefaultUnoItems
to false will disable these includes.