Migrate to Uno.Sdk - #305
Conversation
b7fd380 to
5290b8f
Compare
25e6b65 to
e673abd
Compare
041c863 to
4fcc0c4
Compare
4fcc0c4 to
3d1928d
Compare
^ Conflicts: ^ .github/workflows/build.yml
The job runs on ubuntu-latest but installed ios/maui workloads which aren't supported on Linux, failing at the install step. Uno.Sdk auto-filters the iOS TFM on Linux, so only android + wasm-tools are needed for the desktop/browserwasm heads this job builds. Also renamed the job from the misleading "uno-windows" back to "uno-linux". Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The uno-linux job runs on ubuntu-latest and all its build steps use dotnet (slngen, dotnet build). The microsoft/setup-msbuild action is Windows-only and fails on Linux. Remove it. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
dotnet workload install ran at the repo root before global.json was copied there, so it installed android/wasm-tools for the runner's preinstalled SDK 10 band. The build is pinned to the 9.0.x band via global.json, where no workloads were present, causing NETSDK1147. Run the install from ./tooling so global.json scopes it to the right band. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The new Uno.Sdk head platform entry-point files (Desktop/WebAssembly/ Android/iOS) were missing the standard .NET Foundation license header. Consumers that enforce IDE0073 (file header required) as an error — like CommunityToolkit/Windows — fail to build the Uno head without them. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
ded6698 to
01a12c0
Compare
There was a problem hiding this comment.
Pull request overview
This PR migrates the tooling “project heads” to use Uno.Sdk (primarily for WinUI 3 / Uno 6.x), updating build scripts and CI to generate/build the new Uno head alongside existing multi-target heads.
Changes:
- Adds new Uno.Sdk-based heads for AllComponents and SingleComponent (desktop/wasm/android/ios scaffolding).
- Updates Uno package/version management to support Uno 5.x for WinUI 2 and Uno 6.x for WinUI 3 via conditional props.
- Updates generation scripts and GitHub Actions workflows to include/build the Uno.Sdk head and install required workloads.
Reviewed changes
Copilot reviewed 54 out of 63 changed files in this pull request and generated 6 comments.
Show a summary per file
| File | Description |
|---|---|
| ProjectHeads/SingleComponent/Wasm/Program.cs | Updates WinAppSDK WASM entrypoint to use UnoPlatformHostBuilder. |
| ProjectHeads/SingleComponent/Uno/ProjectTemplate.Uno.csproj | Adds new SingleComponent Uno.Sdk head project. |
| ProjectHeads/SingleComponent/Uno/Platforms/WebAssembly/WasmScripts/AppManifest.js | Adds Uno WASM app manifest (display name). |
| ProjectHeads/SingleComponent/Uno/Platforms/WebAssembly/Program.cs | Adds Uno WASM entrypoint for SingleComponent head. |
| ProjectHeads/SingleComponent/Uno/Platforms/WebAssembly/manifest.webmanifest | Adds web manifest for WASM PWA metadata. |
| ProjectHeads/SingleComponent/Uno/Platforms/WebAssembly/LinkerConfig.xml | Adds linker descriptor for WASM trimming behavior. |
| ProjectHeads/SingleComponent/Uno/Platforms/iOS/PrivacyInfo.xcprivacy | Adds iOS privacy manifest. |
| ProjectHeads/SingleComponent/Uno/Platforms/iOS/Media.xcassets/LaunchImages.launchimage/Contents.json | Adds iOS launch image asset metadata. |
| ProjectHeads/SingleComponent/Uno/Platforms/iOS/Main.iOS.cs | Adds iOS entry point using UnoPlatformHostBuilder. |
| ProjectHeads/SingleComponent/Uno/Platforms/iOS/Info.plist | Adds iOS app plist. |
| ProjectHeads/SingleComponent/Uno/Platforms/iOS/Entitlements.plist | Adds iOS entitlements placeholder. |
| ProjectHeads/SingleComponent/Uno/Platforms/Desktop/Program.cs | Adds desktop entrypoint enabling platform hosts (X11/Win32/etc.). |
| ProjectHeads/SingleComponent/Uno/Platforms/Android/Resources/values/Styles.xml | Adds Android styles scaffolding. |
| ProjectHeads/SingleComponent/Uno/Platforms/Android/Resources/values/Strings.xml | Adds Android strings scaffolding. |
| ProjectHeads/SingleComponent/Uno/Platforms/Android/MainActivity.Android.cs | Adds Android activity scaffold for Uno. |
| ProjectHeads/SingleComponent/Uno/Platforms/Android/Main.Android.cs | Adds Android application entry scaffold for Uno. |
| ProjectHeads/SingleComponent/Uno/Platforms/Android/environment.conf | Adds Mono GC tuning for Android. |
| ProjectHeads/SingleComponent/Uno/Platforms/Android/Assets/AboutAssets.txt | Adds Android assets readme. |
| ProjectHeads/SingleComponent/Uno/Platforms/Android/AndroidManifest.xml | Adds Android manifest scaffold. |
| ProjectHeads/SingleComponent/Uno/Assets/Splash/splash_screen.svg | Adds splash asset for Uno head. |
| ProjectHeads/SingleComponent/Uno/Assets/SharedAssets.md | Adds shared assets documentation. |
| ProjectHeads/SingleComponent/Uno/Assets/Icons/icon.svg | Adds app icon background asset. |
| ProjectHeads/SingleComponent/Uno/Assets/Icons/icon_foreground.svg | Adds app icon foreground asset. |
| ProjectHeads/GenerateSingleSampleHeads.ps1 | Adds -IncludeUnoSdkHead support for generation. |
| ProjectHeads/App.Head.Wasm.props | Adjusts wasm head output path behavior; aligns Uno adapter version selection. |
| ProjectHeads/App.Head.Uno.WinUI.Dependencies.props | Updates Uno.WinUI Lottie dependency to 6.x line. |
| ProjectHeads/App.Head.Uno.UI.Dependencies.props | Removes trailing blank lines. |
| ProjectHeads/App.Head.Uno.props | Makes dependency variant and dependency imports conditional on WinUI major version. |
| ProjectHeads/AllComponents/Wasm/Program.cs | Updates WinAppSDK WASM entrypoint to use UnoPlatformHostBuilder. |
| ProjectHeads/AllComponents/Uno/Platforms/WebAssembly/WasmScripts/AppManifest.js | Adds Uno WASM app manifest (display name). |
| ProjectHeads/AllComponents/Uno/Platforms/WebAssembly/Program.cs | Adds Uno WASM entrypoint for AllComponents head. |
| ProjectHeads/AllComponents/Uno/Platforms/WebAssembly/manifest.webmanifest | Adds web manifest for WASM PWA metadata. |
| ProjectHeads/AllComponents/Uno/Platforms/WebAssembly/LinkerConfig.xml | Adds linker descriptor for WASM trimming behavior. |
| ProjectHeads/AllComponents/Uno/Platforms/iOS/PrivacyInfo.xcprivacy | Adds iOS privacy manifest. |
| ProjectHeads/AllComponents/Uno/Platforms/iOS/Media.xcassets/LaunchImages.launchimage/Contents.json | Adds iOS launch image asset metadata. |
| ProjectHeads/AllComponents/Uno/Platforms/iOS/Main.iOS.cs | Adds iOS entry point using UnoPlatformHostBuilder. |
| ProjectHeads/AllComponents/Uno/Platforms/iOS/Info.plist | Adds iOS app plist. |
| ProjectHeads/AllComponents/Uno/Platforms/iOS/Entitlements.plist | Adds iOS entitlements placeholder. |
| ProjectHeads/AllComponents/Uno/Platforms/Desktop/Program.cs | Adds desktop entrypoint enabling platform hosts (X11/Win32/etc.). |
| ProjectHeads/AllComponents/Uno/Platforms/Android/Resources/values/Styles.xml | Adds Android styles scaffolding. |
| ProjectHeads/AllComponents/Uno/Platforms/Android/Resources/values/Strings.xml | Adds Android strings scaffolding. |
| ProjectHeads/AllComponents/Uno/Platforms/Android/MainActivity.Android.cs | Adds Android activity scaffold for Uno. |
| ProjectHeads/AllComponents/Uno/Platforms/Android/Main.Android.cs | Adds Android application entry scaffold for Uno. |
| ProjectHeads/AllComponents/Uno/Platforms/Android/environment.conf | Adds Mono GC tuning for Android. |
| ProjectHeads/AllComponents/Uno/Platforms/Android/Assets/AboutAssets.txt | Adds Android assets readme. |
| ProjectHeads/AllComponents/Uno/Platforms/Android/AndroidManifest.xml | Adds Android manifest scaffold. |
| ProjectHeads/AllComponents/Uno/CommunityToolkit.App.Uno.csproj | Adds new AllComponents Uno.Sdk head project. |
| ProjectHeads/AllComponents/Uno/Assets/Splash/splash_screen.svg | Adds splash asset for Uno head. |
| ProjectHeads/AllComponents/Uno/Assets/SharedAssets.md | Adds shared assets documentation. |
| ProjectHeads/AllComponents/Uno/Assets/Icons/icon.svg | Adds app icon background asset. |
| ProjectHeads/AllComponents/Uno/Assets/Icons/icon_foreground.svg | Adds app icon foreground asset. |
| MultiTarget/UseUnoWinUI.ps1 | Simplifies WinUI swap behavior (stops rewriting package IDs by string replace). |
| MultiTarget/Test-Component-Support.ps1 | Updates WinUI 3 multi-target support list. |
| MultiTarget/PackageReferences/Uno.props | Splits Uno.UI vs Uno.WinUI versions and conditions; adjusts wasm/devserver references. |
| MultiTarget/AvailableTargetFrameworks.props | Whitespace cleanup. |
| global.json | Registers Uno.Sdk as an MSBuild SDK reference. |
| GenerateVSCodeLaunchConfig.ps1 | Adds a separate VS Code launch config entry for Uno heads. |
| GenerateSingleSolution.ps1 | Adds -IncludeUnoSdkHead and skips classic WASM head when Uno.Sdk head is included. |
| GenerateAllSolution.ps1 | Adds -IncludeUnoSdkHead and includes Uno.Sdk head for all-components solution generation. |
| CommunityToolkit.App.Shared/Renderers/Markdown/MarkdownTextBlock.cs | Alters Uno WASM polyfill compilation conditions for Markdown rendering. |
| Build-Toolkit-Gallery.ps1 | Whitespace cleanup. |
| Build-Toolkit-Components.ps1 | Whitespace cleanup. |
| .github/workflows/build.yml | Adds workload installs, copies global.json to root, adds Uno.Sdk CI coverage (Windows matrix + Linux Uno builds). |
Comments suppressed due to low confidence (1)
CommunityToolkit.App.Shared/Renderers/Markdown/MarkdownTextBlock.cs:23
- The Uno WASM MarkdownTextBlock polyfill is now excluded for WINUI3 builds. For Uno.WinUI WebAssembly (the new Uno.Sdk head), this will fall back to the non-WASM implementation (a plain TextBlock), which prevents markdown from being rendered.
#if HAS_UNO_WASM && !WINUI3
using Markdig;
using Uno.Foundation.Interop;
using Uno.UI.Runtime.WebAssembly;
#endif
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| #if HAS_UNO_WASM && !WINUI3 | ||
| [HtmlElement("div")] | ||
| public partial class MarkdownTextBlock : TextBlock | ||
| { |
There was a problem hiding this comment.
Not so, WINUI3 in the WCT is defined for all multitargets that support it, whether it's Uno or native.
Although, a potential bigger issue here-- this change would disable the MarkdownTextBlock WASM polyfill for WinUI 3 on WASM.
This is fine if there's an actionable reason why, but there's no comment explaining this strange choice.
| `"args`": [ | ||
| `"run`", | ||
| `"build`", | ||
| `"/r`", | ||
| `"/p:UnoSourceGeneratorUseGenerationHost=true`", | ||
| `"/p:UnoSourceGeneratorUseGenerationController=false`", | ||
| `"/p:UnoRemoteControlPort=443`", | ||
| `"--project=`$`{workspaceFolder`}/components/$projectName/heads/Uno/$projectName.Uno.csproj`" | ||
| ], |
| - name: Install .NET workloads | ||
| run: dotnet workload install wasm-tools | ||
|
|
| - name: Install .NET workloads | ||
| if: ${{ matrix.multitarget == 'wasm' || matrix.multitarget == 'unosdk' }} | ||
| run: dotnet workload install wasm-tools ${{ matrix.multitarget == 'unosdk' && 'android ios maui' || '' }} | ||
|
|
| <linker> | ||
| <assembly fullname="CommunityToolkit.App.Uno" /> | ||
| </linker> |
| <IsPackable>false</IsPackable> | ||
| <UnoSingleProject>true</UnoSingleProject> | ||
|
|
||
| <!-- Platform flags for project reference conditions --> | ||
| <IsDeployableHead>true</IsDeployableHead> | ||
| <IsUno>true</IsUno> | ||
| <IsWasm>true</IsWasm> | ||
| <HasWinUI>true</HasWinUI> | ||
| <WinUIMajorVersion>3</WinUIMajorVersion> | ||
| <IsSingleExperimentHead>true</IsSingleExperimentHead> | ||
| <DependencyVariant>WinUI</DependencyVariant> | ||
|
|
||
| <DefineConstants>$(DefineConstants);WINUI3</DefineConstants> |
Previously CommunityToolkit.App.Uno.csproj (and the SingleComponent template) hardcoded TargetFrameworks to all four platforms (desktop/browserwasm/android/ios) regardless of what -MultiTargets was requested at solution-gen time, and forced every component ProjectReference to resolve at bare net9.0 regardless of which of the head's own TargetFrameworks was building. Requesting e.g. -MultiTargets android still produced wasm/desktop deploy options pointing at component builds that were never produced, and the head's own android/ios builds silently referenced components' shared net9.0 output instead of their net9.0-android/net9.0-ios build. - TargetFrameworks is now computed from MultiTarget/EnabledMultiTargets.props (the same file UseTargetFrameworks.ps1 already writes for every other head), so an unrequested platform never gets an orphaned entry. net9.0-desktop rides along whenever wasm/wpf/linuxgtk is requested, since it needs the same shared net9.0 component build. - SetTargetFramework on the component ProjectReference now maps to the head's own $(TargetFramework) for android/ios instead of a blanket net9.0. - The head's IsWasm/IsDroid/IsiOS platform flags (which gate whether Generated/*.Samples.props and *.Source.props even reference a given component) were hardcoded IsWasm=true unconditionally and never set IsDroid/IsiOS at all, so android/ios builds referenced zero components regardless of the two fixes above. These are now computed per the head's own TargetFramework. Verified: default (-MultiTargets wasm) still builds net9.0-desktop and net9.0-browserwasm clean; -MultiTargets android now builds net9.0-android end-to-end (previously failed with CS0103 on ToolkitSampleRegistry, since zero components were ever referenced); -MultiTargets ios correctly narrows to net9.0-ios only, excluding desktop. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017mBuXiEpiN6B1xFD7gYUAM
Previously the Uno.Sdk head's net9.0-desktop TFM rode along with the
net-common group (wasm/wpf/linuxgtk) and borrowed IsWasm=true to pick up
components. That meant desktop couldn't be requested independently -- asking
for e.g. -MultiTargets wasm always dragged the desktop head along, and there
was no way to ask for only the desktop head.
'desktop' is now a first-class MultiTarget:
- Selecting it auto-selects wpf + linuxgtk (the shared net9.0 desktop
component surface) so the head has components to reference. This happens at
the generation funnels (UseTargetFrameworks, GenerateAllProjectReferences,
Test-Component-Support), so NO component MultiTarget.props changes are
needed -- every desktop-capable component already declares wpf;linuxgtk.
- The head keys its net9.0-desktop TFM off EnabledMultiTargets.Contains('desktop')
and presents that TFM as IsWpf (not IsWasm), so reference gating, sample-doc
filtering, and MultiTargetIdentifier all reuse the existing wpf surface.
IsWpf's constants (HAS_UNO_SKIA/__SKIA__) are also more accurate for a Skia
desktop head than the previous __WASM__.
- AddMultiTargetCompatibleSampleDocs.targets gains wpf/linuxgtk
MultiTargetIdentifier cases so IsWpf yields a valid identifier.
- Test-Component-Support restores wpf/linuxgtk to the WinUI-3 supported set
(Uno 6 dropped the Skia WPF/GTK *packages*, but the desktop *surface* they
represented is now served by the unified Uno.Sdk desktop head). Verified
no-op for the current component set: every wpf/linuxgtk component also
declares wasm, so no package surface changes.
- CI uno-linux and GenerateAllSolution's default now request desktop explicitly.
Verified: -MultiTargets desktop -> only net9.0-desktop, builds end-to-end with
real component references (previously would have referenced zero components);
-MultiTargets wasm -> only net9.0-browserwasm (no desktop ride-along);
-MultiTargets wasm,desktop -> both; -MultiTargets android still narrows to
net9.0-android; default gallery builds both browserwasm + desktop clean.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017mBuXiEpiN6B1xFD7gYUAM
'unosdk' was never a MultiTarget - it existed only to flip -IncludeUnoSdkHead for the winui:3, multitarget:wasm combination, which meant matrix.multitarget held a value that no other part of the tooling recognises. The Uno.Sdk head is now a flag on the wasm/winui3 job instead: the fake entry and its two exclusions are gone, and an include: entry merges unoSdkHead: true into the existing combination. Steps gate on matrix.unoSdkHead rather than comparing matrix.multitarget against a value the MultiTarget system would reject. Same four jobs as before (uwp/2, wasm/2, wasdk/3, wasm/3+UnoSdk), and -MultiTargets no longer needs the unosdk -> wasm translation. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0111vdg6YNSNuoVkGdHyr2eX
'desktop' was a single bulk MultiTarget standing in for every desktop OS at once, so a consumer could not ask for (or a component declare) just one of them - the level of control the MultiTarget system exists to provide. The name also said nothing about which TFMs or packages it selected. It is replaced by three targets named after the platforms they run on: - macos - already existed. - linux - renamed from 'linuxgtk'. GTK is a WinUI 2 implementation detail, not the platform, and it disappears entirely under Uno 6. - win32 - new, complementing 'wpf' the same way linux complements gtk. On WinUI 3 all three map to Uno 6's single cross-platform net9.0-desktop head, which is why they can share one head while staying separately requestable. On WinUI 2 they keep the Uno.UI heads they always had. Consequences: - Test-Component-Support's WinUI sets now reflect reality: 'wpf' is WinUI 2 only again (Uno 6 dropped Uno.UI.Skia.Wpf), and win32/linux/macos are the WinUI 3 desktop surface. The previous commit had put wpf/linuxgtk in the WinUI 3 set to feed the 'desktop' head. - The auto-select shims that 'desktop' needed in UseTargetFrameworks, GenerateAllProjectReferences and Test-Component-Support are gone; the three targets stand on their own. - The Uno.Sdk head declares net9.0-desktop when any of win32/linux/macos is requested, and flags that TFM as IsDesktop (Uno.Sdk's own property) rather than borrowing IsWpf, which was also defining WINDOWS_WPF on a build that runs on Linux and macOS. - Project reference generation gained CanTargetWin32 plus an IsDesktop clause covering the trio, so the desktop head picks up a component that declares any one of them and still skips components that declare none. - CheckMultiTarget accepts a ';' separated MultiTargetIdentifier, so the one desktop head can match sample docs for all three. - macos joins the shared net9.0 group: without it, requesting only macos on WinUI 3 produces a desktop head whose components were built solely for maccatalyst. No-op in practice, since macos is always declared alongside wasm. - MultiTarget/ReadMe.md documents what every MultiTarget maps to per WinUI version. Components and the default template now declare win32 and linux. The matching MultiTarget.props updates in Labs and stable land alongside this. Verified: UseTargetFrameworks over 6 request sets; Test-Component-Support over 9 WinUI/target combinations; MSBuild evaluation of TargetFrameworks (win32 alone -> net9.0, macos alone -> net9.0 + net9.0-maccatalyst, wasdk alone -> windows only); and generated reference props, where -mt uwp excludes a component from the desktop head and -mt linux includes it. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0111vdg6YNSNuoVkGdHyr2eX
Uno Platform 7.0 drops Mac Catalyst support, so net{x}-maccatalyst has no
future on the Uno 6.x/WinUI 3 side. Carrying it through this migration
would mean removing a TFM from a published package later, on its own,
without the context that explains it.
macos now means what the review agreed it should: Mac Catalyst on WinUI 2
(Uno 5.x), and the unified Skia desktop head on WinUI 3, which consumes
the shared net{x} component build that macos already contributes to. This
is why macos joined the net-common group in the previous commit.
Consumers targeting Mac Catalyst against a WinUI 3 package keep working:
the package still ships a net{x} asset, which a net{x}-maccatalyst project
resolves, and no component has Catalyst-specific code (nothing in stable
or Labs references __MACOS__ or MACCATALYST), so the two assets were
behaviourally identical anyway.
Deciding a TFM per WinUI version means EnabledTargetFrameworks.props needs
WinUIMajorVersion, so WinUI.TargetVersion.props is imported ahead of it in
Library.props. That file only defines PackageIdVariant and
WinUIMajorVersion, so nothing else is affected by the move. The condition
is written as != '3' so an undefined WinUIMajorVersion keeps the previous
behaviour rather than silently dropping the TFM.
Verified by MSBuild evaluation through Library.props' import order:
macos on WinUI 3 yields net9.0 alone, macos on WinUI 2 yields net9.0 plus
net9.0-maccatalyst, and 'all' behaves the same way on each side.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0111vdg6YNSNuoVkGdHyr2eX
Depends on #304