diff --git a/.github/workflows/macos-static-avalonia-native.yml b/.github/workflows/macos-static-avalonia-native.yml deleted file mode 100644 index 10abc25..0000000 --- a/.github/workflows/macos-static-avalonia-native.yml +++ /dev/null @@ -1,256 +0,0 @@ -name: macOS static AvaloniaNative experiment - -on: - workflow_dispatch: - inputs: - publish_to_release: - description: Publish experimental artifacts to GitHub Release - required: true - default: true - type: boolean - -permissions: - contents: write - -jobs: - build-macos-native: - strategy: - fail-fast: false - matrix: - include: - - rid: osx-x64 - runner: macos-14 - target_cpu: x64 - - rid: osx-arm64 - runner: macos-latest - target_cpu: arm64 - runs-on: ${{ matrix.runner }} - env: - RID: ${{ matrix.rid }} - 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: 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 - - - name: Build macOS font preinit object - run: bash ./scripts/build-macos-font-preinit.sh - - - name: List native outputs - run: find "External/NativeStatic/${{ matrix.rid }}/native" -maxdepth 1 -type f -print - - - name: Upload macOS native libraries - uses: actions/upload-artifact@v4 - with: - name: macos-static-native-${{ matrix.rid }} - path: External/NativeStatic/${{ matrix.rid }}/native/* - if-no-files-found: error - - pack-experimental: - runs-on: ubuntu-latest - needs: build-macos-native - outputs: - package_version: ${{ steps.version.outputs.package_version }} - steps: - - uses: actions/checkout@v4 - - - name: Download macOS native libraries - uses: actions/download-artifact@v4 - with: - pattern: macos-static-native-* - path: artifacts/native - - - name: Stage native libraries - run: | - mkdir -p External/NativeStatic/osx-x64/native External/NativeStatic/osx-arm64/native - cp artifacts/native/macos-static-native-osx-x64/* External/NativeStatic/osx-x64/native/ - cp artifacts/native/macos-static-native-osx-arm64/* External/NativeStatic/osx-arm64/native/ - find External/NativeStatic/osx-x64/native External/NativeStatic/osx-arm64/native -maxdepth 1 -type f -print - - - name: Setup .NET - uses: actions/setup-dotnet@v4 - with: - dotnet-version: "10.0.x" - - - name: Compute experimental package version - id: version - run: | - version="3.119.2-7151.8-macavn.${GITHUB_RUN_NUMBER}" - echo "package_version=$version" >> "$GITHUB_OUTPUT" - echo "$version" - - - name: Pack experimental NuGet package - run: | - dotnet pack NuGet/StaticGraphics/StaticLink.Avalonia.csproj \ - -c Release \ - -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 - with: - name: macos-static-avalonia-native-nuget - path: artifacts/nuget/*.nupkg - if-no-files-found: error - - smoke-macos: - strategy: - fail-fast: false - matrix: - include: - - rid: osx-x64 - runner: macos-14 - - rid: osx-arm64 - runner: macos-latest - runs-on: ${{ matrix.runner }} - needs: pack-experimental - steps: - - uses: actions/checkout@v4 - - - name: Setup .NET - uses: actions/setup-dotnet@v4 - with: - dotnet-version: "10.0.x" - - - name: Download experimental NuGet package - uses: actions/download-artifact@v4 - with: - name: macos-static-avalonia-native-nuget - path: artifacts/nuget - - - name: Publish Avalonia smoke app - shell: pwsh - 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 }}" ` - -StaticLinkNativeVersion $nativeVersion - dotnet publish (Join-Path $projectDir "AvaloniaStaticLinkSmoke.csproj") ` - -c Release ` - -r "${{ matrix.rid }}" ` - --configfile (Join-Path $projectDir "NuGet.config") ` - /p:PublishAot=true ` - /p:SelfContained=true ` - /p:PublishSingleFile=true ` - /p:StripSymbols=true ` - /p:PublishDir="$PWD/artifacts/smoke-${{ matrix.rid }}/" - - - name: Verify static macOS output - shell: pwsh - run: | - $publishDir = "artifacts/smoke-${{ matrix.rid }}" - $blocked = Get-ChildItem -Path $publishDir -Recurse -File | Where-Object { - $_.Name -in @("libAvaloniaNative.dylib", "libHarfBuzzSharp.dylib", "libSkiaSharp.dylib") - } - if ($blocked) { - $blocked | ForEach-Object { Write-Error "Unexpected dynamic library: $($_.FullName)" } - exit 1 - } - Get-ChildItem -Path $publishDir -Recurse -File | ForEach-Object { $_.FullName } - - - name: Run Avalonia smoke app - shell: bash - run: | - set -euo pipefail - cd "artifacts/smoke-${{ matrix.rid }}" - chmod +x ./AvaloniaStaticLinkSmoke - python3 - <<'PY' - import pathlib - import subprocess - import sys - - log = pathlib.Path("avalonia-smoke-run.log") - proc = subprocess.Popen( - ["./AvaloniaStaticLinkSmoke"], - stdout=subprocess.PIPE, - stderr=subprocess.STDOUT, - text=True, - ) - - try: - output, _ = proc.communicate(timeout=15) - except subprocess.TimeoutExpired: - proc.kill() - output, _ = proc.communicate() - log.write_text(output or "") - print(output or "") - print("Avalonia smoke app stayed alive for 15 seconds.") - sys.exit(0) - - log.write_text(output or "") - print(output or "") - if proc.returncode == 0: - print("Avalonia smoke app exited normally.") - sys.exit(0) - - print(f"Avalonia smoke app failed with exit code {proc.returncode}.", file=sys.stderr) - sys.exit(proc.returncode if proc.returncode > 0 else 1) - PY - - - name: Upload macOS smoke app - uses: actions/upload-artifact@v4 - with: - name: macos-static-avalonia-native-smoke-${{ matrix.rid }} - path: artifacts/smoke-${{ matrix.rid }}/** - if-no-files-found: error - - release: - runs-on: ubuntu-latest - needs: - - pack-experimental - - smoke-macos - if: ${{ github.event_name == 'workflow_dispatch' && inputs.publish_to_release == true }} - steps: - - name: Download artifacts - uses: actions/download-artifact@v4 - with: - path: release-artifacts - - - name: Prepare release files - run: | - mkdir -p release-files - find release-artifacts/macos-static-avalonia-native-nuget -type f -name '*.nupkg' -exec cp {} release-files/ \; - for dir in release-artifacts/macos-static-avalonia-native-smoke-*; do - [ -d "$dir" ] || continue - name="$(basename "$dir")" - (cd "$dir" && zip -r "../../release-files/$name.zip" .) - done - ls -la release-files - - - name: Publish experimental GitHub Release - env: - GH_TOKEN: ${{ github.token }} - run: | - release_tag="macos-static-avalonia-native-${GITHUB_RUN_NUMBER}" - if gh release view "$release_tag" >/dev/null 2>&1; then - gh release upload "$release_tag" release-files/* --clobber - else - gh release create "$release_tag" release-files/* \ - --title "macOS static AvaloniaNative ${GITHUB_RUN_NUMBER}" \ - --notes "Experimental macOS NativeAOT package with SkiaSharp, HarfBuzzSharp, and AvaloniaNative statically linked." - fi diff --git a/.github/workflows/nuget-static-graphics.yml b/.github/workflows/nuget-static-graphics.yml index 404c8eb..c2d1e33 100644 --- a/.github/workflows/nuget-static-graphics.yml +++ b/.github/workflows/nuget-static-graphics.yml @@ -64,6 +64,9 @@ jobs: - rid: win-x64 target_cpu: x64 msvc_arch: x64 + - rid: win-x86 + target_cpu: x86 + msvc_arch: x86 - rid: win-arm64 target_cpu: arm64 msvc_arch: amd64_arm64 @@ -231,7 +234,7 @@ jobs: - name: Move static archives into RID directories run: | - for rid in win-x64 win-arm64 linux-x64 linux-arm64 osx-x64 osx-arm64; do + for rid in win-x64 win-x86 win-arm64 linux-x64 linux-arm64 osx-x64 osx-arm64; do mkdir -p "External/NativeStatic/$rid" mv "External/NativeStatic/native-static-$rid"/* "External/NativeStatic/$rid/" rmdir "External/NativeStatic/native-static-$rid" @@ -251,7 +254,7 @@ jobs: test -f External/NativeStatic/$rid/native/libGLESv2_static.a done - for rid in win-x64 win-arm64; do + for rid in win-x64 win-x86 win-arm64; do test -f External/NativeStatic/$rid/native/skia.lib test -f External/NativeStatic/$rid/native/SkiaSharp.lib test -f External/NativeStatic/$rid/native/libHarfBuzzSharp.lib @@ -308,6 +311,9 @@ jobs: - rid: win-x64 runner: windows-2022 msvc_arch: x64 + - rid: win-x86 + runner: windows-2022 + msvc_arch: x86 - rid: win-arm64 runner: windows-2022 msvc_arch: amd64_arm64 diff --git a/NuGet/StaticGraphics/README.md b/NuGet/StaticGraphics/README.md index 17b9e40..ac21f9c 100644 --- a/NuGet/StaticGraphics/README.md +++ b/NuGet/StaticGraphics/README.md @@ -1,19 +1,6 @@ # StaticLink.Avalonia -Static native libraries for Avalonia NativeAOT publishing. - -This package links Avalonia's graphics/native dependencies from static archives so NativeAOT publish output does not need the usual SkiaSharp, HarfBuzzSharp, ANGLE, or AvaloniaNative runtime files next to the executable. - -Repository: - -## Supported RIDs - -- `win-x64` -- `win-arm64` -- `linux-x64` -- `linux-arm64` -- `osx-x64` -- `osx-arm64` +Static native libraries for Avalonia single-file NativeAOT publishing. ## Install @@ -21,10 +8,16 @@ Repository: dotnet add package StaticLink.Avalonia ``` -For fully static macOS output, also reference the AvaloniaNative package that matches your Avalonia version: +Or add it manually: -```bash -dotnet add package StaticLink.Avalonia.Native --version 11.3.14.1 +```xml + +``` + +For macOS, also reference `StaticLink.Avalonia.Native`. This package is macOS-only and must match your Avalonia version because it contains `libAvaloniaNative.a`. + +```xml + ``` ## Publish @@ -37,32 +30,6 @@ dotnet publish -c Release -r win-x64 \ -p:StripSymbols=true ``` -Use the RID you need, for example `linux-x64`, `linux-arm64`, `osx-arm64`, or `osx-x64`. +Use the RID you need, such as `win-x86`, `linux-x64`, `linux-arm64`, `osx-arm64`, or `osx-x64`. -For Linux, `lld` is recommended: - -```bash -dotnet publish -c Release -r linux-x64 \ - -p:PublishAot=true \ - -p:SelfContained=true \ - -p:PublishSingleFile=true \ - -p:StripSymbols=true \ - -p:LinkerFlavor=lld -``` - -For macOS, avoid the Metal renderer for fully static output. Use OpenGL or Software: - -```csharp -.With(new AvaloniaNativePlatformOptions -{ - RenderingMode = [AvaloniaNativeRenderingMode.OpenGl, AvaloniaNativeRenderingMode.Software] -}) -``` - -## 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. +For macOS, avoid the Metal renderer for fully static output. Use OpenGL or Software. diff --git a/NuGet/StaticGraphics/StaticLink.Avalonia.csproj b/NuGet/StaticGraphics/StaticLink.Avalonia.csproj index 1c55e70..bfc2dd4 100644 --- a/NuGet/StaticGraphics/StaticLink.Avalonia.csproj +++ b/NuGet/StaticGraphics/StaticLink.Avalonia.csproj @@ -28,6 +28,7 @@ + diff --git a/NuGet/StaticGraphics/buildTransitive/StaticLink.Avalonia.targets b/NuGet/StaticGraphics/buildTransitive/StaticLink.Avalonia.targets index 5024f27..ed03adc 100644 --- a/NuGet/StaticGraphics/buildTransitive/StaticLink.Avalonia.targets +++ b/NuGet/StaticGraphics/buildTransitive/StaticLink.Avalonia.targets @@ -1,6 +1,7 @@ <_StaticLinkAvaloniaRid Condition="'$(RuntimeIdentifier)' == 'win-x64'">win-x64 + <_StaticLinkAvaloniaRid Condition="'$(RuntimeIdentifier)' == 'win-x86'">win-x86 <_StaticLinkAvaloniaRid Condition="'$(RuntimeIdentifier)' == 'win-arm64'">win-arm64 <_StaticLinkAvaloniaRid Condition="'$(RuntimeIdentifier)' == 'linux-x64'">linux-x64 <_StaticLinkAvaloniaRid Condition="'$(RuntimeIdentifier)' == 'linux-arm64'">linux-arm64 @@ -10,7 +11,7 @@ lld - + diff --git a/README.md b/README.md index 17b9e40..ac21f9c 100644 --- a/README.md +++ b/README.md @@ -1,19 +1,6 @@ # StaticLink.Avalonia -Static native libraries for Avalonia NativeAOT publishing. - -This package links Avalonia's graphics/native dependencies from static archives so NativeAOT publish output does not need the usual SkiaSharp, HarfBuzzSharp, ANGLE, or AvaloniaNative runtime files next to the executable. - -Repository: - -## Supported RIDs - -- `win-x64` -- `win-arm64` -- `linux-x64` -- `linux-arm64` -- `osx-x64` -- `osx-arm64` +Static native libraries for Avalonia single-file NativeAOT publishing. ## Install @@ -21,10 +8,16 @@ Repository: dotnet add package StaticLink.Avalonia ``` -For fully static macOS output, also reference the AvaloniaNative package that matches your Avalonia version: +Or add it manually: -```bash -dotnet add package StaticLink.Avalonia.Native --version 11.3.14.1 +```xml + +``` + +For macOS, also reference `StaticLink.Avalonia.Native`. This package is macOS-only and must match your Avalonia version because it contains `libAvaloniaNative.a`. + +```xml + ``` ## Publish @@ -37,32 +30,6 @@ dotnet publish -c Release -r win-x64 \ -p:StripSymbols=true ``` -Use the RID you need, for example `linux-x64`, `linux-arm64`, `osx-arm64`, or `osx-x64`. +Use the RID you need, such as `win-x86`, `linux-x64`, `linux-arm64`, `osx-arm64`, or `osx-x64`. -For Linux, `lld` is recommended: - -```bash -dotnet publish -c Release -r linux-x64 \ - -p:PublishAot=true \ - -p:SelfContained=true \ - -p:PublishSingleFile=true \ - -p:StripSymbols=true \ - -p:LinkerFlavor=lld -``` - -For macOS, avoid the Metal renderer for fully static output. Use OpenGL or Software: - -```csharp -.With(new AvaloniaNativePlatformOptions -{ - RenderingMode = [AvaloniaNativeRenderingMode.OpenGl, AvaloniaNativeRenderingMode.Software] -}) -``` - -## 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. +For macOS, avoid the Metal renderer for fully static output. Use OpenGL or Software.