diff --git a/.github/workflows/macos-static-avalonia-native.yml b/.github/workflows/macos-static-avalonia-native.yml
index 3a06d02..10abc25 100644
--- a/.github/workflows/macos-static-avalonia-native.yml
+++ b/.github/workflows/macos-static-avalonia-native.yml
@@ -98,6 +98,11 @@ jobs:
-o artifacts/nuget \
/p:PackageVersion=${{ steps.version.outputs.package_version }} \
/p:Version=${{ steps.version.outputs.package_version }}
+ dotnet pack NuGet/AvaloniaNative/StaticLink.Avalonia.Native.csproj \
+ -c Release \
+ -o artifacts/nuget \
+ /p:PackageVersion=11.3.14-macavn.${{ github.run_number }} \
+ /p:Version=11.3.14-macavn.${{ github.run_number }}
- name: Upload experimental NuGet package
uses: actions/upload-artifact@v4
@@ -136,10 +141,15 @@ jobs:
run: |
$ErrorActionPreference = "Stop"
$projectDir = Join-Path $PWD "artifacts/avalonia-smoke-src"
+ $nativePackage = Get-ChildItem -Path "artifacts/nuget" -Filter "StaticLink.Avalonia.Native.*.nupkg" | Select-Object -First 1
+ if (-not $nativePackage) { throw "StaticLink AvaloniaNative NuGet package was not downloaded." }
+ if ($nativePackage.BaseName -notmatch '^StaticLink\.Avalonia\.Native\.(.+)$') { throw "Unexpected native package name: $($nativePackage.Name)" }
+ $nativeVersion = $Matches[1]
pwsh ./scripts/create-avalonia-smoke.ps1 `
-ProjectDir $projectDir `
-NuGetSource (Resolve-Path "artifacts/nuget") `
- -StaticLinkVersion "${{ needs.pack-experimental.outputs.package_version }}"
+ -StaticLinkVersion "${{ needs.pack-experimental.outputs.package_version }}" `
+ -StaticLinkNativeVersion $nativeVersion
dotnet publish (Join-Path $projectDir "AvaloniaStaticLinkSmoke.csproj") `
-c Release `
-r "${{ matrix.rid }}" `
diff --git a/.github/workflows/nuget-static-graphics.yml b/.github/workflows/nuget-static-graphics.yml
index c332ab5..352540a 100644
--- a/.github/workflows/nuget-static-graphics.yml
+++ b/.github/workflows/nuget-static-graphics.yml
@@ -131,21 +131,12 @@ jobs:
TARGET_CPU: ${{ matrix.target_cpu }}
WORK_DIR: ${{ github.workspace }}/External/NativeStatic/.work
OUTPUT_DIR: ${{ github.workspace }}/External/NativeStatic/${{ matrix.rid }}/native
- AVALONIA_VERSION: 11.3.14
steps:
- uses: actions/checkout@v4
- - name: Setup .NET for Avalonia header generation
- uses: actions/setup-dotnet@v4
- with:
- dotnet-version: "8.0.x"
-
- name: Install native build dependencies
run: brew install ninja
- - name: Build static AvaloniaNative
- run: bash ./scripts/build-macos-avalonia-native-static.sh
-
- name: Build macOS static graphics libraries
run: bash ./scripts/build-macos-static-graphics.sh all
@@ -159,12 +150,61 @@ jobs:
path: External/NativeStatic/${{ matrix.rid }}/*
if-no-files-found: error
+ build-macos-avalonia-native:
+ strategy:
+ fail-fast: false
+ matrix:
+ include:
+ - rid: osx-x64
+ runner: macos-14
+ avalonia_version: 11.3.14
+ - rid: osx-arm64
+ runner: macos-latest
+ avalonia_version: 11.3.14
+ - rid: osx-x64
+ runner: macos-14
+ avalonia_version: 12.0.3
+ - rid: osx-arm64
+ runner: macos-latest
+ avalonia_version: 12.0.3
+ runs-on: ${{ matrix.runner }}
+ env:
+ RID: ${{ matrix.rid }}
+ WORK_DIR: ${{ github.workspace }}/External/NativeStatic/.work
+ OUTPUT_DIR: ${{ github.workspace }}/External/NativeStatic/${{ matrix.rid }}/native
+ AVALONIA_VERSION: ${{ matrix.avalonia_version }}
+ steps:
+ - uses: actions/checkout@v4
+
+ - name: Setup .NET for Avalonia header generation
+ uses: actions/setup-dotnet@v4
+ with:
+ dotnet-version: |
+ 8.0.x
+ 10.0.x
+
+ - name: Build static AvaloniaNative
+ run: bash ./scripts/build-macos-avalonia-native-static.sh
+
+ - name: Build macOS font preinit object
+ run: bash scripts/build-macos-font-preinit.sh
+
+ - name: Upload static AvaloniaNative
+ uses: actions/upload-artifact@v4
+ with:
+ name: native-avalonia-${{ matrix.avalonia_version }}-${{ matrix.rid }}
+ path: |
+ External/NativeStatic/${{ matrix.rid }}/native/libAvaloniaNative.a
+ External/NativeStatic/${{ matrix.rid }}/native/macos_font_preinit.o
+ if-no-files-found: error
+
pack:
runs-on: ubuntu-latest
needs:
- build-linux
- build-windows
- build-macos
+ - build-macos-avalonia-native
permissions:
contents: read
steps:
@@ -182,6 +222,13 @@ jobs:
path: External/NativeStatic
merge-multiple: false
+ - name: Download static AvaloniaNative archives
+ uses: actions/download-artifact@v4
+ with:
+ pattern: native-avalonia-*
+ path: External/AvaloniaNative
+ merge-multiple: false
+
- name: Move static archives into RID directories
run: |
for rid in win-x64 win-arm64 linux-x64 linux-arm64 osx-x64 osx-arm64; do
@@ -200,11 +247,6 @@ jobs:
test -f External/NativeStatic/$rid/native/libGLESv2_static.a
done
- for rid in osx-x64 osx-arm64; do
- test -f External/NativeStatic/$rid/native/libAvaloniaNative.a
- test -f External/NativeStatic/$rid/native/macos_font_preinit.o
- done
-
for rid in win-x64 win-arm64; do
test -f External/NativeStatic/$rid/native/skia.lib
test -f External/NativeStatic/$rid/native/SkiaSharp.lib
@@ -214,7 +256,18 @@ jobs:
done
- name: Pack NuGet package
- run: dotnet pack NuGet/StaticGraphics/StaticLink.Avalonia.csproj -c Release -o artifacts/nuget
+ run: |
+ dotnet pack NuGet/StaticGraphics/StaticLink.Avalonia.csproj -c Release -o artifacts/nuget
+ for version in 11.3.14 12.0.3; do
+ mkdir -p External/NativeStatic/osx-x64/native External/NativeStatic/osx-arm64/native
+ cp External/AvaloniaNative/native-avalonia-$version-osx-x64/* External/NativeStatic/osx-x64/native/
+ cp External/AvaloniaNative/native-avalonia-$version-osx-arm64/* External/NativeStatic/osx-arm64/native/
+ dotnet pack NuGet/AvaloniaNative/StaticLink.Avalonia.Native.csproj \
+ -c Release \
+ -o artifacts/nuget \
+ /p:PackageVersion=$version.1 \
+ /p:Version=$version.1
+ done
- name: Upload NuGet artifact
uses: actions/upload-artifact@v4
@@ -260,8 +313,20 @@ jobs:
runner: ubuntu-24.04-arm
- rid: osx-x64
runner: macos-14
+ avalonia_version: 11.3.14
+ native_version: 11.3.14.1
- rid: osx-arm64
runner: macos-latest
+ avalonia_version: 11.3.14
+ native_version: 11.3.14.1
+ - rid: osx-x64
+ runner: macos-14
+ avalonia_version: 12.0.3
+ native_version: 12.0.3.1
+ - rid: osx-arm64
+ runner: macos-latest
+ avalonia_version: 12.0.3
+ native_version: 12.0.3.1
runs-on: ${{ matrix.runner }}
steps:
- uses: actions/checkout@v4
@@ -293,12 +358,19 @@ jobs:
shell: pwsh
run: |
$ErrorActionPreference = "Stop"
- $package = Get-ChildItem -Path "artifacts/nuget" -Filter "StaticLink.Avalonia.*.nupkg" | Select-Object -First 1
+ $package = Get-ChildItem -Path "artifacts/nuget" -Filter "StaticLink.Avalonia.*.nupkg" | Where-Object { $_.Name -notlike "StaticLink.Avalonia.Native.*" } | Select-Object -First 1
if (-not $package) { throw "StaticLink NuGet package was not downloaded." }
if ($package.BaseName -notmatch '^StaticLink\.Avalonia\.(.+)$') { throw "Unexpected package name: $($package.Name)" }
$version = $Matches[1]
+ $nativeVersion = "${{ matrix.native_version }}"
+ $avaloniaVersion = "${{ matrix.avalonia_version }}"
+ if (-not $avaloniaVersion) { $avaloniaVersion = "11.3.14" }
+ if ($nativeVersion) {
+ $nativePackage = Get-ChildItem -Path "artifacts/nuget" -Filter "StaticLink.Avalonia.Native.$nativeVersion.nupkg" | Select-Object -First 1
+ if (-not $nativePackage) { throw "StaticLink AvaloniaNative NuGet package $nativeVersion was not downloaded." }
+ }
$projectDir = Join-Path $PWD "artifacts/avalonia-smoke-src"
- pwsh ./scripts/create-avalonia-smoke.ps1 -ProjectDir $projectDir -NuGetSource (Resolve-Path "artifacts/nuget") -StaticLinkVersion $version
+ pwsh ./scripts/create-avalonia-smoke.ps1 -ProjectDir $projectDir -NuGetSource (Resolve-Path "artifacts/nuget") -StaticLinkVersion $version -AvaloniaVersion $avaloniaVersion -StaticLinkNativeVersion $nativeVersion
dotnet publish (Join-Path $projectDir "AvaloniaStaticLinkSmoke.csproj") `
-c Release `
-r "${{ matrix.rid }}" `
diff --git a/NuGet/AvaloniaNative/StaticLink.Avalonia.Native.csproj b/NuGet/AvaloniaNative/StaticLink.Avalonia.Native.csproj
new file mode 100644
index 0000000..06aef8c
--- /dev/null
+++ b/NuGet/AvaloniaNative/StaticLink.Avalonia.Native.csproj
@@ -0,0 +1,32 @@
+
+
+ net10.0
+ true
+ true
+ false
+ false
+ StaticLink.Avalonia.Native
+ 11.3.14.1
+ greepar
+ greepar
+ Static AvaloniaNative library for macOS Avalonia NativeAOT publishing.
+ Avalonia;AvaloniaNative;NativeAOT;macOS;Static
+ MIT
+ README.md
+ git
+ https://github.com/greepar/StaticLink.Avalonia
+ https://github.com/greepar/StaticLink.Avalonia
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/NuGet/StaticGraphics/buildTransitive/StaticLink.Avalonia.MacOSFontWarmup.cs b/NuGet/AvaloniaNative/buildTransitive/StaticLink.Avalonia.Native.MacOSFontWarmup.cs
similarity index 93%
rename from NuGet/StaticGraphics/buildTransitive/StaticLink.Avalonia.MacOSFontWarmup.cs
rename to NuGet/AvaloniaNative/buildTransitive/StaticLink.Avalonia.Native.MacOSFontWarmup.cs
index 28ed6b7..1b6b382 100644
--- a/NuGet/StaticGraphics/buildTransitive/StaticLink.Avalonia.MacOSFontWarmup.cs
+++ b/NuGet/AvaloniaNative/buildTransitive/StaticLink.Avalonia.Native.MacOSFontWarmup.cs
@@ -2,7 +2,7 @@ using System;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
-namespace StaticLink.Avalonia;
+namespace StaticLink.Avalonia.Native;
internal static class MacOSFontWarmup
{
@@ -29,7 +29,7 @@ internal static class MacOSFontWarmup
}
catch
{
- // Never fail application startup from the defensive macOS font-cache warmup.
+ // Defensive AppKit font-cache warmup must never fail application startup.
}
}
diff --git a/NuGet/AvaloniaNative/buildTransitive/StaticLink.Avalonia.Native.props b/NuGet/AvaloniaNative/buildTransitive/StaticLink.Avalonia.Native.props
new file mode 100644
index 0000000..6026106
--- /dev/null
+++ b/NuGet/AvaloniaNative/buildTransitive/StaticLink.Avalonia.Native.props
@@ -0,0 +1,5 @@
+
+
+ $(MSBuildThisFileDirectory)../static/
+
+
diff --git a/NuGet/AvaloniaNative/buildTransitive/StaticLink.Avalonia.Native.targets b/NuGet/AvaloniaNative/buildTransitive/StaticLink.Avalonia.Native.targets
new file mode 100644
index 0000000..6d8cd17
--- /dev/null
+++ b/NuGet/AvaloniaNative/buildTransitive/StaticLink.Avalonia.Native.targets
@@ -0,0 +1,41 @@
+
+
+ <_StaticLinkAvaloniaNativeRid Condition="'$(RuntimeIdentifier)' == 'osx-x64'">osx-x64
+ <_StaticLinkAvaloniaNativeRid Condition="'$(RuntimeIdentifier)' == 'osx-arm64'">osx-arm64
+ <_StaticLinkAvaloniaNativeRoot Condition="'$(_StaticLinkAvaloniaNativeRid)' != ''">$(StaticLinkAvaloniaNativeRoot)$(_StaticLinkAvaloniaNativeRid)/native
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ <_StaticLinkAvaloniaNativeFilesToDelete Include="$(PublishDir)libAvaloniaNative.dylib" />
+
+
+
+
diff --git a/NuGet/AvaloniaNative/lib/net10.0/_._ b/NuGet/AvaloniaNative/lib/net10.0/_._
new file mode 100644
index 0000000..e69de29
diff --git a/NuGet/StaticGraphics/README.md b/NuGet/StaticGraphics/README.md
index e4e5da2..17b9e40 100644
--- a/NuGet/StaticGraphics/README.md
+++ b/NuGet/StaticGraphics/README.md
@@ -21,6 +21,12 @@ Repository:
dotnet add package StaticLink.Avalonia
```
+For fully static macOS output, also reference the AvaloniaNative package that matches your Avalonia version:
+
+```bash
+dotnet add package StaticLink.Avalonia.Native --version 11.3.14.1
+```
+
## Publish
```bash
@@ -56,6 +62,7 @@ For macOS, avoid the Metal renderer for fully static output. Use OpenGL or Softw
## Notes
- The package is intended for Avalonia `11.3.x` NativeAOT apps.
+- `StaticLink.Avalonia.Native` is version-specific because `libAvaloniaNative.a` must match Avalonia's native ABI.
- The CI builds and smoke-publishes all six supported RIDs.
- macOS smoke tests run the published app on GitHub Actions and require it to stay alive for 15 seconds.
- Other native dependencies used by your app, such as SQLite or audio libraries, are outside this package's scope.
diff --git a/NuGet/StaticGraphics/StaticLink.Avalonia.csproj b/NuGet/StaticGraphics/StaticLink.Avalonia.csproj
index f389e75..3edc064 100644
--- a/NuGet/StaticGraphics/StaticLink.Avalonia.csproj
+++ b/NuGet/StaticGraphics/StaticLink.Avalonia.csproj
@@ -27,12 +27,11 @@
-
-
-
+
+
diff --git a/NuGet/StaticGraphics/buildTransitive/StaticLink.Avalonia.targets b/NuGet/StaticGraphics/buildTransitive/StaticLink.Avalonia.targets
index 85cb909..5024f27 100644
--- a/NuGet/StaticGraphics/buildTransitive/StaticLink.Avalonia.targets
+++ b/NuGet/StaticGraphics/buildTransitive/StaticLink.Avalonia.targets
@@ -49,12 +49,8 @@
-
-
-
-
@@ -96,8 +92,6 @@
BeforeTargets="WriteIlcRspFileForCompilation"
Condition="'$(PublishAot)' == 'true' and ('$(RuntimeIdentifier)' == 'osx-x64' or '$(RuntimeIdentifier)' == 'osx-arm64') and '$(_StaticLinkAvaloniaNativeRoot)' != ''">
-
-
@@ -118,7 +112,6 @@
<_StaticLinkAvaloniaFilesToDelete Include="$(PublishDir)libSkiaSharp.so" />
<_StaticLinkAvaloniaFilesToDelete Include="$(PublishDir)libHarfBuzzSharp.dylib" />
<_StaticLinkAvaloniaFilesToDelete Include="$(PublishDir)libSkiaSharp.dylib" />
- <_StaticLinkAvaloniaFilesToDelete Include="$(PublishDir)libAvaloniaNative.dylib" />
diff --git a/README.md b/README.md
index e4e5da2..17b9e40 100644
--- a/README.md
+++ b/README.md
@@ -21,6 +21,12 @@ Repository:
dotnet add package StaticLink.Avalonia
```
+For fully static macOS output, also reference the AvaloniaNative package that matches your Avalonia version:
+
+```bash
+dotnet add package StaticLink.Avalonia.Native --version 11.3.14.1
+```
+
## Publish
```bash
@@ -56,6 +62,7 @@ For macOS, avoid the Metal renderer for fully static output. Use OpenGL or Softw
## Notes
- The package is intended for Avalonia `11.3.x` NativeAOT apps.
+- `StaticLink.Avalonia.Native` is version-specific because `libAvaloniaNative.a` must match Avalonia's native ABI.
- The CI builds and smoke-publishes all six supported RIDs.
- macOS smoke tests run the published app on GitHub Actions and require it to stay alive for 15 seconds.
- Other native dependencies used by your app, such as SQLite or audio libraries, are outside this package's scope.
diff --git a/scripts/create-avalonia-smoke.ps1 b/scripts/create-avalonia-smoke.ps1
index 3d2fff6..e9eb5f8 100644
--- a/scripts/create-avalonia-smoke.ps1
+++ b/scripts/create-avalonia-smoke.ps1
@@ -6,13 +6,22 @@ param(
[string]$NuGetSource,
[Parameter(Mandatory = $true)]
- [string]$StaticLinkVersion
+ [string]$StaticLinkVersion,
+
+ [string]$AvaloniaVersion = "11.3.14",
+
+ [string]$StaticLinkNativeVersion = ""
)
$ErrorActionPreference = "Stop"
New-Item -ItemType Directory -Path $ProjectDir -Force | Out-Null
+$nativeReference = ""
+if ($StaticLinkNativeVersion) {
+ $nativeReference = "`n "
+}
+
@"
@@ -41,10 +50,10 @@ New-Item -ItemType Directory -Path $ProjectDir -Force | Out-Null
-
-
-
-
+
+
+
+ $nativeReference
"@ | Set-Content -Path (Join-Path $ProjectDir "AvaloniaStaticLinkSmoke.csproj") -Encoding UTF8
@@ -137,7 +146,7 @@ public sealed partial class MainWindow : Window
Title="Avalonia StaticLink Smoke">
-
+