Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 36 additions & 0 deletions .github/workflows/ci-macos-appkit.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
name: CI - macOS AppKit

on:
push:
branches: [main]
paths:
- 'platforms/MacOS/**'
- 'eng/**'
- 'Directory.Build.props'
- 'Directory.Build.targets'
- 'Directory.Packages.props'
- 'global.json'
- 'NuGet.config'
pull_request:
types: [opened, synchronize, reopened, edited]
branches: [main]
paths:
- 'platforms/MacOS/**'
- 'eng/**'
- 'Directory.Build.props'
- 'Directory.Build.targets'
- 'Directory.Packages.props'
- 'global.json'
- 'NuGet.config'

jobs:
build:
uses: ./.github/workflows/_build.yml
with:
project-path: platforms/MacOS/MacOS.slnx
project-name: macos-appkit
os: '["macos-latest"]'
install-workloads: true
run-tests: false
pack: true
xcode-version: '26.3'
6 changes: 3 additions & 3 deletions Directory.Packages.props
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@
<ItemGroup Label="MAUI">
<PackageVersion Include="Microsoft.Maui.Controls" Version="$(MicrosoftMauiControlsVersion)" />
<PackageVersion Include="Microsoft.Maui.Controls.Compatibility" Version="$(MicrosoftMauiControlsCompatibilityVersion)" />
<PackageVersion Include="Microsoft.Maui.Core" Version="$(MicrosoftMauiControlsVersion)" />
<PackageVersion Include="Microsoft.Maui.Essentials" Version="$(MicrosoftMauiEssentialsVersion)" />
<PackageVersion Include="Microsoft.AspNetCore.Components.WebView" Version="$(MicrosoftAspNetCoreComponentsWebViewVersion)" />
<PackageVersion Include="Microsoft.Maui.Controls.Maps" Version="$(MicrosoftMauiControlsMapsVersion)" />
<PackageVersion Include="Microsoft.AspNetCore.Components.WebView.Maui" Version="$(MicrosoftAspNetCoreComponentsWebViewMauiVersion)" />
</ItemGroup>
Expand Down Expand Up @@ -40,6 +42,7 @@
<PackageVersion Include="XenoAtom.Terminal.UI" Version="$(XenoAtomTerminalUIVersion)" />
<PackageVersion Include="ModelContextProtocol" Version="$(ModelContextProtocolVersion)" />
<PackageVersion Include="Interop.UIAutomationClient" Version="$(InteropUIAutomationClientVersion)" />
<PackageVersion Include="AathifMahir.Maui.MauiIcons.Cupertino" Version="$(AathifMahirMauiIconsCupertinoVersion)" />
</ItemGroup>

<!-- MAUI Cli Tool dependencies -->
Expand All @@ -51,9 +54,6 @@

<!-- Platform extensions (pinned) -->
<ItemGroup Label="Platform">
<PackageVersion Include="Platform.Maui.MacOS" Version="$(PlatformMauiMacOSVersion)" />
<PackageVersion Include="Platform.Maui.MacOS.BlazorWebView" Version="$(PlatformMauiMacOSBlazorWebViewVersion)" />
<PackageVersion Include="Platform.Maui.MacOS.Essentials" Version="$(PlatformMauiMacOSEssentialsVersion)" />
<PackageVersion Include="Platform.Maui.Linux.Gtk4" Version="$(PlatformMauiLinuxGtk4Version)" />
<PackageVersion Include="Platform.Maui.Linux.Gtk4.BlazorWebView" Version="$(PlatformMauiLinuxGtk4BlazorWebViewVersion)" />
<PackageVersion Include="Platform.Maui.Linux.Gtk4.Essentials" Version="$(PlatformMauiLinuxGtk4EssentialsVersion)" />
Expand Down
5 changes: 5 additions & 0 deletions MauiLabs.slnx
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,11 @@
<Project Path="tests/AI/Microsoft.Maui.Essentials.AI.UnitTests/Microsoft.Maui.Essentials.AI.UnitTests.csproj" />
</Folder>
<Folder Name="/tests/DevFlow/" />
<Folder Name="/platforms/MacOS/">
<Project Path="platforms/MacOS/src/MacOS/MacOS.csproj" />
<Project Path="platforms/MacOS/src/MacOS.Essentials/MacOS.Essentials.csproj" />
<Project Path="platforms/MacOS/src/MacOS.BlazorWebView/MacOS.BlazorWebView.csproj" />
</Folder>
<Folder Name="/platforms/Windows.WPF/">
<Project Path="platforms/Windows.WPF/src/Windows.WPF/Windows.WPF.csproj" />
<Project Path="platforms/Windows.WPF/src/Windows.WPF.Essentials/Windows.WPF.Essentials.csproj" />
Expand Down
16 changes: 16 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,22 @@ A comprehensive MAUI testing, automation, and debugging toolkit. The DevFlow CLI
| `Microsoft.Maui.DevFlow.Driver` | Platform driver library |
| `Microsoft.Maui.DevFlow.Logging` | Buffered JSONL file logger |

### macOS AppKit Backend

A native macOS AppKit backend for .NET MAUI — run MAUI apps as true AppKit apps with NSWindow, NSButton, NSScrollView, native menu bar, sidebar flyout, and more. An alternative to Mac Catalyst.

- **Native AppKit controls** — NSTextField, NSButton, NSSwitch, NSSlider, NSImageView, and more
- **Navigation** — Shell, NavigationPage, TabbedPage, FlyoutPage with sidebar
- **Blazor WebView** — via WKWebView
- **MapKit** — native MapView integration
- **Essentials** — AppInfo, Battery, Clipboard, Geolocation, Preferences, SecureStorage, Sensors

| Package | Description |
|---------|-------------|
| `Microsoft.Maui.Platforms.MacOS` | Core AppKit backend — handlers, hosting, MapKit |
| `Microsoft.Maui.Platforms.MacOS.Essentials` | Essentials APIs for macOS |
| `Microsoft.Maui.Platforms.MacOS.BlazorWebView` | Blazor Hybrid via WKWebView |

### WPF Backend

A WPF-based alternative to the official WinUI backend for .NET MAUI. Run MAUI apps on Windows desktops using native WPF controls with 22+ fully implemented controls, Shell navigation, Blazor WebView, and 14 Essentials APIs.
Expand Down
8 changes: 5 additions & 3 deletions eng/Versions.props
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
<DevFlowMauiMinVersion>10.0.20</DevFlowMauiMinVersion>
<MicrosoftMauiControlsCompatibilityVersion>$(MicrosoftMauiControlsVersion)</MicrosoftMauiControlsCompatibilityVersion>
<MicrosoftMauiEssentialsVersion>$(MicrosoftMauiControlsVersion)</MicrosoftMauiEssentialsVersion>
<MicrosoftAspNetCoreComponentsWebViewVersion>10.0.3</MicrosoftAspNetCoreComponentsWebViewVersion>
<MicrosoftMauiControlsMapsVersion>$(MicrosoftMauiControlsVersion)</MicrosoftMauiControlsMapsVersion>
<MicrosoftAspNetCoreComponentsWebViewMauiVersion>$(MicrosoftMauiControlsVersion)</MicrosoftAspNetCoreComponentsWebViewMauiVersion>
</PropertyGroup>
Expand All @@ -34,6 +35,7 @@
</PropertyGroup>
<!-- Pinned dependencies (third party, not flowing via maestro) -->
<PropertyGroup Label="Third Party">
<AathifMahirMauiIconsCupertinoVersion>5.0.0</AathifMahirMauiIconsCupertinoVersion>
<FizzlerVersion>1.3.1</FizzlerVersion>
<MicrosoftCodeAnalysisCSharpVersion>4.12.0</MicrosoftCodeAnalysisCSharpVersion>
<SkiaSharpVersion>3.119.2</SkiaSharpVersion>
Expand All @@ -56,14 +58,14 @@
<XamarinAppleToolsMaciOSVersion>1.0.0-preview.1.26230.1</XamarinAppleToolsMaciOSVersion>
</PropertyGroup>
<PropertyGroup Label="Platform Extensions">
<PlatformMauiMacOSVersion>0.3.0</PlatformMauiMacOSVersion>
<PlatformMauiMacOSBlazorWebViewVersion>$(PlatformMauiMacOSVersion)</PlatformMauiMacOSBlazorWebViewVersion>
<PlatformMauiMacOSEssentialsVersion>$(PlatformMauiMacOSVersion)</PlatformMauiMacOSEssentialsVersion>
<PlatformMauiLinuxGtk4Version>0.6.0</PlatformMauiLinuxGtk4Version>
<PlatformMauiLinuxGtk4BlazorWebViewVersion>$(PlatformMauiLinuxGtk4Version)</PlatformMauiLinuxGtk4BlazorWebViewVersion>
<PlatformMauiLinuxGtk4EssentialsVersion>$(PlatformMauiLinuxGtk4Version)</PlatformMauiLinuxGtk4EssentialsVersion>
<PlatformMauiWindowsWpfVersion>0.1.0</PlatformMauiWindowsWpfVersion>
<PlatformMauiWindowsWpfEssentialsVersion>$(PlatformMauiWindowsWpfVersion)</PlatformMauiWindowsWpfEssentialsVersion>
<PlatformMauiMacOSVersion>0.3.0</PlatformMauiMacOSVersion>
<PlatformMauiMacOSBlazorWebViewVersion>$(PlatformMauiMacOSVersion)</PlatformMauiMacOSBlazorWebViewVersion>
<PlatformMauiMacOSEssentialsVersion>$(PlatformMauiMacOSVersion)</PlatformMauiMacOSEssentialsVersion>
</PropertyGroup>
<!-- EssentialsAI preview iteration (bump for each new preview drop when DotNetFinalVersionKind=release) -->
<PropertyGroup Label="EssentialsAI">
Expand Down
90 changes: 90 additions & 0 deletions eng/pipelines/devflow-official.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,12 @@ parameters:
default: false
- name: publishWpfNuget
displayName: 'Publish WPF packages to NuGet.org'
type: boolean
default: false
- name: publishMacOSNuget
displayName: 'Publish macOS AppKit packages to NuGet.org'
type: boolean
default: false
- name: publishEssentialsAINuget
displayName: 'Publish EssentialsAI packages to NuGet.org'
type: boolean
Expand Down Expand Up @@ -326,6 +332,35 @@ extends:
-projects $(Build.SourcesDirectory)\platforms\Windows.WPF\Windows.WPF.slnx
$(_OfficialBuildArgs)
displayName: Build, Test and Pack WPF

# macOS AppKit packages target net10.0-macos — must build on macOS.
# Signing runs in the Arcade post-build stage (which validates on Windows),
# so the macOS-built nupkgs flow through the standard artifact pipeline.
- job: MacOS
displayName: macOS AppKit - macOS
pool:
name: Azure Pipelines
vmImage: macos-latest
strategy:
matrix:
Release:
_BuildConfig: Release
_OfficialBuildArgs: /p:DotNetSignType=$(_SignType)
/p:TeamName=$(_TeamName)
/p:OfficialBuildId=$(BUILD.BUILDNUMBER)
steps:
- task: UseDotNet@2
displayName: Install .NET SDK
inputs:
useGlobalJson: true
- script: dotnet workload install maui macos
displayName: Install MAUI and macOS workloads
- script: ./eng/common/cibuild.sh
--configuration $(_BuildConfig)
--prepareMachine
--projects $(Build.SourcesDirectory)/platforms/MacOS/MacOS.slnx
$(_OfficialBuildArgs)
displayName: Build and Pack macOS AppKit

- template: /eng/common/templates-official/post-build/post-build.yml@self
parameters:
Expand Down Expand Up @@ -631,3 +666,58 @@ extends:
packageParentPath: '$(Pipeline.Workspace)/EssentialsAIPackages'
nuGetFeedType: external
publishFeedCredentials: 'nuget.org (dotnetframework)'

# Publish macOS AppKit packages to NuGet.org
- ${{ if eq(parameters.publishMacOSNuget, true) }}:
- stage: publish_macos_nuget
displayName: 'Publish macOS AppKit to NuGet.org'
dependsOn:
- Validate
- publish_using_darc
jobs:
- job: PrepareArtifacts
displayName: 'Prepare macOS Artifacts'
timeoutInMinutes: 15
pool:
name: NetCore1ESPool-Internal
image: windows.vs2026preview.scout.amd64
os: windows
templateContext:
outputs:
- output: pipelineArtifact
displayName: Publish macOS Packages
targetPath: '$(Pipeline.Workspace)/MacOSPackages'
artifactName: MacOSPackagesForNuGet
steps:
- download: current
artifact: PackageArtifacts
displayName: Download PackageArtifacts
- powershell: |
New-Item -ItemType Directory -Force -Path '$(Pipeline.Workspace)/MacOSPackages'
Copy-Item '$(Pipeline.Workspace)/PackageArtifacts/Microsoft.Maui.Platforms.MacOS.*.nupkg' '$(Pipeline.Workspace)/MacOSPackages/' -Verbose -ErrorAction Stop
displayName: Filter macOS packages

- job: PublishNuGet
displayName: 'Push macOS to NuGet.org'
dependsOn: PrepareArtifacts
timeoutInMinutes: 30
pool:
name: NetCore1ESPool-Internal
image: windows.vs2026preview.scout.amd64
os: windows
templateContext:
type: releaseJob
isProduction: true
inputs:
- input: pipelineArtifact
artifactName: MacOSPackagesForNuGet
targetPath: '$(Pipeline.Workspace)/MacOSPackages'
steps:
- task: 1ES.PublishNuget@1
displayName: 'Push macOS to NuGet.org'
inputs:
useDotNetTask: false
packagesToPush: '$(Pipeline.Workspace)/MacOSPackages/*.nupkg'
packageParentPath: '$(Pipeline.Workspace)/MacOSPackages'
nuGetFeedType: external
publishFeedCredentials: 'nuget.org (dotnetframework)'
30 changes: 30 additions & 0 deletions platforms/MacOS/Directory.Build.props
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<Project>
<Import Project="../../Directory.Build.props" />

<PropertyGroup>
<LangVersion>preview</LangVersion>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<MauiVersion>$(MicrosoftMauiControlsVersion)</MauiVersion>
<!-- Keep the experimental AppKit backend building under Arcade's CI-wide warnaserror while preserving local diagnostics. -->
<WarningsNotAsErrors>$(WarningsNotAsErrors);CS0067;CS0108;CS0414;CS0612;CS0618;CS8601;CS8602;CS8603;CS8604;CS8619;CS8625;CS8765;CA1416;CA1422;IL2070</WarningsNotAsErrors>
<!-- Set to false when the maui-labs DevFlow projects should not be referenced by the sample -->
<EnableMauiDevFlow Condition="'$(EnableMauiDevFlow)' == ''">false</EnableMauiDevFlow>
</PropertyGroup>

<PropertyGroup Condition="'$(EnableMauiDevFlow)' == 'true'">
<DefineConstants>$(DefineConstants);MAUIDEVFLOW</DefineConstants>
</PropertyGroup>

<!-- Common NuGet package properties for all src/ projects -->
<PropertyGroup>
<Authors>Microsoft</Authors>
<PackageLicenseExpression>MIT</PackageLicenseExpression>
<PackageProjectUrl>https://github.com/dotnet/maui-labs/tree/main/platforms/MacOS</PackageProjectUrl>
<RepositoryUrl>https://github.com/dotnet/maui-labs.git</RepositoryUrl>
<RepositoryType>git</RepositoryType>
<PackageReadmeFile>README.md</PackageReadmeFile>
<!-- Use product-specific README instead of repo-root one -->
<PackRepoRootReadme>false</PackRepoRootReadme>
</PropertyGroup>
</Project>
5 changes: 5 additions & 0 deletions platforms/MacOS/Directory.Build.targets
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<Project>

<Import Project="../../Directory.Build.targets" />

</Project>
10 changes: 10 additions & 0 deletions platforms/MacOS/MacOS.slnx
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<Solution>
<Folder Name="/samples/">
<Project Path="samples/MacOS.Sample/MacOS.Sample.csproj" />
</Folder>
<Folder Name="/src/">
<Project Path="src/MacOS.BlazorWebView/MacOS.BlazorWebView.csproj" />
<Project Path="src/MacOS.Essentials/MacOS.Essentials.csproj" />
<Project Path="src/MacOS/MacOS.csproj" />
</Folder>
</Solution>
Loading
Loading