Working with Uno
📖 Overview
The Uno Platform is an open-source project that is released under the permissive Apache 2.0 license. The source code is provided to you, and you can do whatever you like with it, provided you comply with the license terms - e.g., preservation of copyright and license notices, the release of liability and warranty.
If you choose to use the Uno Platform (and we sincerely hope you do) it's important that you know how to work with the internals of the Uno Platform as, without a commercial support agreement in place, the Uno Platform is provided to you under a "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND basis. This is true for all open-source projects. Unfortunately, too many organizations forget this and inadvertently damage open-source software projects.
If your organization requires a deeper level of support beyond our community support, please contact us. Our professional support is more than a contract – it is a shared responsibility for your project success. Our engineering team will collaborate with you to ensure the success of your projects, and our custom application development team at nventive is also available to lend its expertise.
This module will introduce to the internals of the Uno Platform code-base. The team has built-in plenty of escape hatches that enables you to be autonomous without being dependant on pull-requests being merged. We hope that this knowledge will enable you to become self-reliant, to not push your pull-requests if you are ever caught in a jam and ultimately become a regular contributor to the open-source project. A growing open-source project is a healthy open-source project. 💖
💡 Walk through the codebase
What's implemented
- 🎯 Visit uno/src/Uno.UI/Generated to learn what features are implemented and consumed by the program that generates the Uno Platform's documentation.
- 📚 What is
Uno.NotImplemented
? Note that you can make not implemented APIs fatal exceptions by settingApiInformation.IsFailWhenNotImplemented = true
. - 📚 What is the UWP Sync Generator?
- 📚 What is the purpose of the Generated folder?
UI implementations
- 🎯 Visit the source code of where XAML controls can be found - uno/src/Uno.UI/UI/Xaml.
- 🎯 Note usage of partial classes and the naming the convention of
MyControl.cs
,MyControl.iOS.cs
,MyControl.Droid.cs
,MyControl.wasm.cs
.
Source code generation
- 🎯 Visit the source code at uno/src/SourceGenerators
- 🎯 Read https://github.com/unoplatform/uno/pull/1241/files
Integration Tests
- 🎯 Visit the samples app which is deployed from
master
after every commit. - 🎯 Visit source code at uno/src/SamplesApp
- 📚 If you contribute a pull-request, then we expect tests to be included. This is our north star golden example of automated integration test w/droid, ios, wasm heads, and screenshot targeting
Visual Studio Solution Filters
Visual Studio 2019 introduced a new feature called solution filtering which allows developers to load a subset of projects in a solution. The Uno Platform has solution filters for each one of the target framework monikers (also referred by the team as heads):
Uno.UI-Android-only.slnf
Uno.UI-UnitTests-only.slnf
Uno.UI-Wasm-only.slnf
Uno.UI-Windows-only.slnf
Uno.UI-iOS-only.slnf
When contributing to the Uno Platform or changing Uno's internals, we highly recommend that you load just the subset that you need instead of loading the full Uno.UI.sln
solution. Loading a subset of projects in a solution dramatically decreases solution load, build, and test run time, and enables you to be more productive. The team also recommends enabling the cross targeting override (see below) if appropriate.
Cross Targeting Override
One of the biggest productivity improvements, apart from using Visual Studio Solution Filters, is the usage of the cross targeting override escape hatch. It can be enabled by renaming crosstargeting_override.props.sample
to crosstargeting_override.props
.
There are two key knobs in the cross-targeting override:
- Controlling which platforms are built by Visual Studio.
- Overriding your local NuGet cache.
Controlling which platforms are built by Visual Studio
Unfortunately, Visual Studio for Windows does not support incremental builds on a per-target framework moniker (TFM) basis and builds all target framework monikers referenced in a project if a build is required, which means if you load the Uno Platform via the Uno.UI-Android-only.slnf
solution filter with the intention of only making changes to the Android platform and make a change to a project that defines multiple target framework monikers defined, such as Uno.UI
Visual Studio for Windows will compile the iOS
, WebAssembly
, and UWP
heads.
Inside of the cross targeting override file, you'll find a property called UnoTargetFrameworkOverride
which provides you with a way to selectively choose which target framework monikers are compiled by Visual Studio for Windows. It's really important that you close Visual Studio for Windows before making changes to UnoTargetFrameworkOverride
. Ensure that you do or Visual Studio for Windows may become unresponsive.
<!--
This property controls the platform built by Visual Studio.
Available build targets:
uap10.0.17763 (Windows)
xamarinios10 (iOS)
MonoAndroid90 (Android 9.0)
netstandard2.0 (WebAssembly)
net461 (Tests)
Only one target can be built, and the corresponding solution filter must
be loaded in Visual Studio (see next to Uno.UI.sln).
*** WARNING ***
Note that changing that property while the solution is opened leads to
unstable NuGet restore operations, and Visual Studio instabilities such
as caching issues or crashes.
Always unload the solution before changing or activating this property.
*** WARNING ***
-->
<!--<UnoTargetFrameworkOverride>netstandard2.0</UnoTargetFrameworkOverride>-->
Thus, if you wanted to hack on the internals of the Uno Platform for Android:
- Close Visual Studio for Windows.
- Enable the cross targeting override escape hatch.
- Change
<UnoTargetFrameworkOverride>
to<UnoTargetFrameworkOverride>MonoAndroid90</UnoTargetFrameworkOverride>
. - Open the
Uno.UI-Android-only.slnf
solution filter in Visual Studio for Windows.
Overriding your local NuGet cache
Inside of the cross targeting override file you'll find a property called UnoNugetOverrideVersion
which provides you with a way to generate a NuGet package at a specific version. If this version is found in your local NuGet cache, then it will be overridden. This escape hatch is extremely useful, and we wish that this feature existed in NuGet, Visual Studio and .NET.
Imagine you have an application that references Uno.UI
at version v1.45.0
and there's something in that particular version of the Uno Platform that needs to change because it's blocking you from shipping your application to your customers.
By enabling <UnoNugetOverrideVersion>1.45.0</UnoNugetOverrideVersion>
and building from source you'll never be in a situation where you are blocked waiting for pull-requests to be merged and a release to be cut. Here's how you do it:
- Clone Uno and checkout the appropriate commit (or from
master
if adding new functionality) of the source code. - Enable the escape hatch using the version defined in your application.
- Make the changes you need locally and build the Uno Platform.
UnoNugetOverrideVersion
will override the version in your local NuGet cache.- Your application can then consume the changes without needing to update the application.
<!--
This property allows the override of the NuGet local cache.
Set it to the version you want to override, used in another app.
You will see the override path in the build output.
The packages are located under this directory: "%USERPROFILE%\.nuget\packages".
-->
<!--<UnoNugetOverrideVersion>1.45.0</UnoNugetOverrideVersion>-->
If after enabling UnoNugetOverrideVersion
you don't see the expected results check the bin/obj
folder of your consuming application and check the file modification dates. When in doubt - delete bin/obj
and then start troubleshooting from a clean slate.
After you have finished with UnoNuGetOverrideVersion
you'll need to clear your NuGet cache which can be done via:
nuget locals all -clear
🎯 Vendoring Uno
- Fork the Uno Platform source code from GitHub.
- Configure the NuGet package override to use the same version used in the Todo app.
- Make the required changes to the Uno Platform source code.
- Commit your changes to your fork of the Uno Platform.
- Build the Uno Platform in Visual Studio for Windows.
- Load the Todo application in Visual Studio for Windows.
🎯 Source level step debugging
- Clone the Uno Platform source code from GitHub.
- Configure the NuGet package override to use the same version used in the Todo app.
- Build the Uno Platform in Visual Studio for Windows.
- Load the Todo application in Visual Studio for Windows.
- Set debug points, step in and out.
🎯 Debugging the source generator
- Create a side app and note which version of
Uno.UI
is used as aPackageReference
- Override the NuGet package cache and use the same version for
Uno.UI
as is used in the side app. - Build the side application which will start an initial
Uno.SourceGenerationHost.exe
process - Attach to all the
Uno.SourceGenerationHost.exe
processes (there may be many) from theUno.UI
solution - Rebuild the side app
- Your breakpoints in the source generators will hit
- Output from the generator is stored at
obj\Debug\netstandard2.0\g\XamlCodeGenerator
- If you need to restart debugging after making significant code changes to the source generator, then make sure you terminate all existing processes (
taskkill /fi "imagename eq Uno.SourceGeneration.Host.exe" /f /t
) in between development iterations.
📚 Additional Reading Material
Commercial Support:
If your organization requires a deeper level of support beyond our community support, please contact us. Our professional support is more than a contract – it is a shared responsibility for your project success. Our engineering team will collaborate with you to ensure the success of your projects, and our custom application development team at nventive is also available to lend its expertise.
Key areas of the Uno Platform source-code:
- What's implemented: uno/src/Uno.UI/Generated
- UI implementations: uno/src/Uno.UI/UI/Xaml
- Source code generation: uno/src/SourceGenerators
- Integration Tests: uno/src/SamplesApp
- Visual Studio Solution Filters: uno/src/*.slnf
- Productivity tricks, vendoring and monkey patching: uno/src/crosstargeting_override.props.sample
Visual Studio Features and Extensions:
- Filtered solutions in Visual Studio.
- MSBuild Binary and Structured Log Viewer.
- Microsoft Child Process Debugging Power Tool.
Open-Source Sustainability:
- Report: Roads and Bridges: The Unseen Labor Behind Our Digital Infrastructure
- Conference Talk: If you haven’t secured your supply chain, you're negligent
- Conference Talk: Rebuilding the Cathedral
- Conference Talk: Open-Source Maintainers are Jerks!