diff --git a/.github/workflows/macos-static-avalonia-native.yml b/.github/workflows/macos-static-avalonia-native.yml index d486279..3a06d02 100644 --- a/.github/workflows/macos-static-avalonia-native.yml +++ b/.github/workflows/macos-static-avalonia-native.yml @@ -93,7 +93,7 @@ jobs: - name: Pack experimental NuGet package run: | - dotnet pack NuGet/StaticGraphics/Shiroka.Avalonia.StaticLink.csproj \ + dotnet pack NuGet/StaticGraphics/StaticLink.Avalonia.csproj \ -c Release \ -o artifacts/nuget \ /p:PackageVersion=${{ steps.version.outputs.package_version }} \ diff --git a/.github/workflows/nuget-static-graphics.yml b/.github/workflows/nuget-static-graphics.yml index bd26cf9..c332ab5 100644 --- a/.github/workflows/nuget-static-graphics.yml +++ b/.github/workflows/nuget-static-graphics.yml @@ -1,4 +1,4 @@ -name: nuget-static-graphics +name: staticlink-avalonia on: workflow_dispatch: @@ -15,7 +15,7 @@ on: type: boolean push: tags: - - "static-graphics-v*" + - "staticlink-avalonia-v*" env: SKIASHARP_VERSION: "3.119.2" @@ -121,24 +121,35 @@ jobs: include: - rid: osx-x64 target_cpu: x64 + runner: macos-14 - rid: osx-arm64 target_cpu: arm64 - runs-on: macos-latest + runner: macos-latest + 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: 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 - env: - RID: ${{ matrix.rid }} - TARGET_CPU: ${{ matrix.target_cpu }} - run: scripts/build-macos-static-graphics.sh all + run: bash ./scripts/build-macos-static-graphics.sh all - name: Build macOS font preinit object - env: - RID: ${{ matrix.rid }} run: bash scripts/build-macos-font-preinit.sh - name: Upload macOS static archives @@ -182,35 +193,40 @@ jobs: - name: Verify static archives run: | for rid in linux-x64 linux-arm64 osx-x64 osx-arm64; do - test -f External/NativeStatic/$rid/libskia.a - test -f External/NativeStatic/$rid/libSkiaSharp.a - test -f External/NativeStatic/$rid/libHarfBuzzSharp.a - test -f External/NativeStatic/$rid/libANGLE_static.a - test -f External/NativeStatic/$rid/libGLESv2_static.a + test -f External/NativeStatic/$rid/native/libskia.a + test -f External/NativeStatic/$rid/native/libSkiaSharp.a + test -f External/NativeStatic/$rid/native/libHarfBuzzSharp.a + test -f External/NativeStatic/$rid/native/libANGLE_static.a + 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/skia.lib - test -f External/NativeStatic/$rid/SkiaSharp.lib - test -f External/NativeStatic/$rid/libHarfBuzzSharp.lib - test -f External/NativeStatic/$rid/libANGLE_static.lib - test -f External/NativeStatic/$rid/libGLESv2_static.lib + test -f External/NativeStatic/$rid/native/skia.lib + test -f External/NativeStatic/$rid/native/SkiaSharp.lib + test -f External/NativeStatic/$rid/native/libHarfBuzzSharp.lib + test -f External/NativeStatic/$rid/native/libANGLE_static.lib + test -f External/NativeStatic/$rid/native/libGLESv2_static.lib done - name: Pack NuGet package - run: dotnet pack NuGet/StaticGraphics/Shiroka.Avalonia.StaticLink.csproj -c Release -o artifacts/nuget + run: dotnet pack NuGet/StaticGraphics/StaticLink.Avalonia.csproj -c Release -o artifacts/nuget - name: Upload NuGet artifact uses: actions/upload-artifact@v4 with: - name: nuget-static-graphics + name: staticlink-avalonia-nuget path: | artifacts/nuget/*.nupkg artifacts/nuget/*.snupkg if-no-files-found: error - name: Publish to nuget.org - if: ${{ startsWith(github.ref, 'refs/tags/static-graphics-v') || (github.event_name == 'workflow_dispatch' && inputs.publish_to_nuget == true) }} + if: ${{ startsWith(github.ref, 'refs/tags/staticlink-avalonia-v') || (github.event_name == 'workflow_dispatch' && inputs.publish_to_nuget == true) }} env: NUGET_API_KEY: ${{ secrets.NUGET_API_KEY }} run: | @@ -270,16 +286,16 @@ jobs: - name: Download NuGet package uses: actions/download-artifact@v4 with: - name: nuget-static-graphics + name: staticlink-avalonia-nuget path: artifacts/nuget - name: Publish Avalonia single-file smoke app shell: pwsh run: | $ErrorActionPreference = "Stop" - $package = Get-ChildItem -Path "artifacts/nuget" -Filter "Shiroka.Avalonia.StaticLink.*.nupkg" | Select-Object -First 1 + $package = Get-ChildItem -Path "artifacts/nuget" -Filter "StaticLink.Avalonia.*.nupkg" | Select-Object -First 1 if (-not $package) { throw "StaticLink NuGet package was not downloaded." } - if ($package.BaseName -notmatch '^Shiroka\.Avalonia\.StaticLink\.(.+)$') { throw "Unexpected package name: $($package.Name)" } + if ($package.BaseName -notmatch '^StaticLink\.Avalonia\.(.+)$') { throw "Unexpected package name: $($package.Name)" } $version = $Matches[1] $projectDir = Join-Path $PWD "artifacts/avalonia-smoke-src" pwsh ./scripts/create-avalonia-smoke.ps1 -ProjectDir $projectDir -NuGetSource (Resolve-Path "artifacts/nuget") -StaticLinkVersion $version @@ -298,7 +314,7 @@ jobs: run: | $publishDir = "artifacts/smoke-${{ matrix.rid }}" $blocked = Get-ChildItem -Path $publishDir -Recurse -File | Where-Object { - $_.Name -in @("libSkiaSharp.dll", "libHarfBuzzSharp.dll", "av_libglesv2.dll", "libSkiaSharp.so", "libHarfBuzzSharp.so", "libSkiaSharp.dylib", "libHarfBuzzSharp.dylib") + $_.Name -in @("libSkiaSharp.dll", "libHarfBuzzSharp.dll", "av_libglesv2.dll", "libSkiaSharp.so", "libHarfBuzzSharp.so", "libAvaloniaNative.dylib", "libSkiaSharp.dylib", "libHarfBuzzSharp.dylib") } if ($blocked) { $blocked | ForEach-Object { Write-Error "Unexpected dynamic graphics library: $($_.FullName)" } @@ -306,6 +322,46 @@ jobs: } Get-ChildItem -Path $publishDir -Recurse -File | ForEach-Object { $_.FullName } + - name: Run macOS Avalonia smoke app + if: ${{ startsWith(matrix.rid, 'osx-') }} + 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 Avalonia smoke app uses: actions/upload-artifact@v4 with: @@ -318,10 +374,12 @@ jobs: needs: - pack - smoke-avalonia - if: ${{ startsWith(github.ref, 'refs/tags/static-graphics-v') || (github.event_name == 'workflow_dispatch' && inputs.publish_to_release == true) }} + if: ${{ startsWith(github.ref, 'refs/tags/staticlink-avalonia-v') || (github.event_name == 'workflow_dispatch' && inputs.publish_to_release == true) }} permissions: contents: write steps: + - uses: actions/checkout@v4 + - name: Download release artifacts uses: actions/download-artifact@v4 with: @@ -330,7 +388,7 @@ jobs: - name: Prepare release files run: | mkdir -p release-files - find release-artifacts/nuget-static-graphics -type f \( -name '*.nupkg' -o -name '*.snupkg' \) -exec cp {} release-files/ \; + find release-artifacts/staticlink-avalonia-nuget -type f \( -name '*.nupkg' -o -name '*.snupkg' \) -exec cp {} release-files/ \; for dir in release-artifacts/avalonia-smoke-*; do [ -d "$dir" ] || continue name="$(basename "$dir")" @@ -346,8 +404,8 @@ jobs: release_tag="${GITHUB_REF_NAME}" title="${GITHUB_REF_NAME}" else - release_tag="static-graphics-smoke-${GITHUB_RUN_NUMBER}" - title="Static graphics smoke ${GITHUB_RUN_NUMBER}" + release_tag="staticlink-avalonia-smoke-${GITHUB_RUN_NUMBER}" + title="StaticLink.Avalonia smoke ${GITHUB_RUN_NUMBER}" fi if gh release view "$release_tag" >/dev/null 2>&1; then diff --git a/NuGet/StaticGraphics/README.md b/NuGet/StaticGraphics/README.md index eed8a3e..e4e5da2 100644 --- a/NuGet/StaticGraphics/README.md +++ b/NuGet/StaticGraphics/README.md @@ -1,10 +1,10 @@ -# Shiroka.Avalonia.StaticLink +# StaticLink.Avalonia -Static graphics libraries for Avalonia NativeAOT single-file publishing. +Static native libraries for Avalonia NativeAOT publishing. -This package provides static archives for SkiaSharp, HarfBuzzSharp, and ANGLE, then wires them into MSBuild through `buildTransitive` targets. It is intended for Avalonia applications that want NativeAOT single-file publish outputs without shipping Avalonia graphics native libraries next to the executable. +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: +Repository: ## Supported RIDs @@ -15,34 +15,14 @@ Repository: - `osx-x64` - `osx-arm64` -## Included Libraries - -Windows: - -- `skia.lib` -- `SkiaSharp.lib` -- `libHarfBuzzSharp.lib` -- `libANGLE_static.lib` -- `libGLESv2_static.lib` - -Linux and macOS: - -- `libskia.a` -- `libSkiaSharp.a` -- `libHarfBuzzSharp.a` -- `libANGLE_static.a` -- `libGLESv2_static.a` - ## Install ```bash -dotnet add package Shiroka.Avalonia.StaticLink +dotnet add package StaticLink.Avalonia ``` ## Publish -Windows x64 or arm64: - ```bash dotnet publish -c Release -r win-x64 \ -p:PublishAot=true \ @@ -51,7 +31,9 @@ dotnet publish -c Release -r win-x64 \ -p:StripSymbols=true ``` -Linux x64 or arm64: +Use the RID you need, for example `linux-x64`, `linux-arm64`, `osx-arm64`, or `osx-x64`. + +For Linux, `lld` is recommended: ```bash dotnet publish -c Release -r linux-x64 \ @@ -62,102 +44,18 @@ dotnet publish -c Release -r linux-x64 \ -p:LinkerFlavor=lld ``` -macOS x64 or arm64: +For macOS, avoid the Metal renderer for fully static output. Use OpenGL or Software: -```bash -dotnet publish -c Release -r osx-arm64 \ - -p:PublishAot=true \ - -p:SelfContained=true \ - -p:PublishSingleFile=true \ - -p:StripSymbols=true +```csharp +.With(new AvaloniaNativePlatformOptions +{ + RenderingMode = [AvaloniaNativeRenderingMode.OpenGl, AvaloniaNativeRenderingMode.Software] +}) ``` -The package automatically contributes the static archives as `NativeLibrary` items when `PublishAot=true` and the `RuntimeIdentifier` is supported. +## Notes -## Verify Output - -After publishing, the publish directory should not contain Avalonia graphics runtime files such as: - -- `libSkiaSharp.so` -- `libHarfBuzzSharp.so` -- `libSkiaSharp.dylib` -- `libHarfBuzzSharp.dylib` -- `libSkiaSharp.dll` -- `libHarfBuzzSharp.dll` -- `av_libglesv2.dll` - -The package stores static archives under `static//native/` inside the NuGet package, so `.a` and `.lib` files are used for linking and are not normal runtime assets. - -## Build From Source - -This repository does not depend on 2ndLAB static packages. The GitHub Actions workflow builds the native libraries from upstream source repositories: - -- SkiaSharp: -- ANGLE: - -Build scripts: - -- `scripts/build-linux-static-graphics.sh` -- `scripts/build-windows-static-graphics.ps1` -- `scripts/build-macos-static-graphics.sh` - -Build locally after the static archives exist: - -```bash -dotnet pack NuGet/StaticGraphics/Shiroka.Avalonia.StaticLink.csproj -c Release -o artifacts/nuget -``` - -The package will be written to: - -```text -artifacts/nuget/Shiroka.Avalonia.StaticLink.*.nupkg -``` - -## GitHub Actions - -The workflow `.github/workflows/nuget-static-graphics.yml` builds all native archives and packs a single NuGet package for all supported RIDs. - -It will: - -- build Linux x64 static archives on `ubuntu-latest` -- build Linux arm64 static archives on `ubuntu-24.04-arm` -- build Windows x64 and arm64 static archives on `windows-latest` -- build macOS x64 and arm64 static archives on `macos-latest` -- download all native artifacts into `External/NativeStatic//` -- run `dotnet pack` -- upload the generated `.nupkg` as a workflow artifact - -To publish automatically to nuget.org, add a repository secret named `NUGET_API_KEY`, then either: - -- run the workflow manually with `publish_to_nuget=true` -- push a tag matching `static-graphics-v*` - -Example tag: - -```bash -git tag static-graphics-v3.119.2-7151.4 -git push origin static-graphics-v3.119.2-7151.4 -``` - -## Known Runtime Dependencies - -Single-file does not always mean dependency-free. Depending on platform and publish settings, the final executable may still depend on operating system libraries and frameworks. - -Linux examples: - -- `libc.so.6` -- `libm.so.6` -- `libstdc++.so.6` -- `libgcc_s.so.1` -- `libfontconfig.so.1` -- `libfreetype.so.6` - -Linux systems also need usable fonts for text rendering and font fallback. - -## Scope - -This package only covers Avalonia graphics-related native libraries. If your application uses other native dependencies, such as SQLite, audio backends, OpenSSL, or custom native libraries, those dependencies may require separate handling. - -## License - -The NuGet package metadata uses the MIT license. The bundled third-party native libraries are built from their upstream projects and remain subject to their respective upstream licenses. +- The package is intended for Avalonia `11.3.x` NativeAOT apps. +- 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/Shiroka.Avalonia.StaticLink.csproj b/NuGet/StaticGraphics/StaticLink.Avalonia.csproj similarity index 75% rename from NuGet/StaticGraphics/Shiroka.Avalonia.StaticLink.csproj rename to NuGet/StaticGraphics/StaticLink.Avalonia.csproj index de36024..f389e75 100644 --- a/NuGet/StaticGraphics/Shiroka.Avalonia.StaticLink.csproj +++ b/NuGet/StaticGraphics/StaticLink.Avalonia.csproj @@ -5,7 +5,7 @@ true false false - Shiroka.Avalonia.StaticLink + StaticLink.Avalonia 3.119.2-7151.9 greepar greepar @@ -14,8 +14,8 @@ MIT README.md git - https://github.com/greepar/Avalonia.StaticGraphics - https://github.com/greepar/Avalonia.StaticGraphics + https://github.com/greepar/StaticLink.Avalonia + https://github.com/greepar/StaticLink.Avalonia @@ -25,9 +25,9 @@ - - - + + + diff --git a/NuGet/StaticGraphics/buildTransitive/Shiroka.Avalonia.StaticLink.props b/NuGet/StaticGraphics/buildTransitive/Shiroka.Avalonia.StaticLink.props deleted file mode 100644 index 374394b..0000000 --- a/NuGet/StaticGraphics/buildTransitive/Shiroka.Avalonia.StaticLink.props +++ /dev/null @@ -1,5 +0,0 @@ - - - $(MSBuildThisFileDirectory)../static/ - - diff --git a/NuGet/StaticGraphics/buildTransitive/Shiroka.Avalonia.StaticLink.targets b/NuGet/StaticGraphics/buildTransitive/Shiroka.Avalonia.StaticLink.targets deleted file mode 100644 index 57bcafa..0000000 --- a/NuGet/StaticGraphics/buildTransitive/Shiroka.Avalonia.StaticLink.targets +++ /dev/null @@ -1,125 +0,0 @@ - - - <_ShirokaAvaloniaStaticLinkRid Condition="'$(RuntimeIdentifier)' == 'win-x64'">win-x64 - <_ShirokaAvaloniaStaticLinkRid Condition="'$(RuntimeIdentifier)' == 'win-arm64'">win-arm64 - <_ShirokaAvaloniaStaticLinkRid Condition="'$(RuntimeIdentifier)' == 'linux-x64'">linux-x64 - <_ShirokaAvaloniaStaticLinkRid Condition="'$(RuntimeIdentifier)' == 'linux-arm64'">linux-arm64 - <_ShirokaAvaloniaStaticLinkRid Condition="'$(RuntimeIdentifier)' == 'osx-x64'">osx-x64 - <_ShirokaAvaloniaStaticLinkRid Condition="'$(RuntimeIdentifier)' == 'osx-arm64'">osx-arm64 - <_ShirokaAvaloniaStaticLinkNativeRoot Condition="'$(_ShirokaAvaloniaStaticLinkRid)' != ''">$(ShirokaAvaloniaStaticLinkRoot)$(_ShirokaAvaloniaStaticLinkRid)/native - lld - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - false - - - - - - - - - - - - - - - - - - - - - - - - - - - - - <_ShirokaAvaloniaStaticLinkFilesToDelete Include="$(PublishDir)av_libglesv2.dll" /> - <_ShirokaAvaloniaStaticLinkFilesToDelete Include="$(PublishDir)libHarfBuzzSharp.dll" /> - <_ShirokaAvaloniaStaticLinkFilesToDelete Include="$(PublishDir)libSkiaSharp.dll" /> - <_ShirokaAvaloniaStaticLinkFilesToDelete Include="$(PublishDir)libHarfBuzzSharp.so" /> - <_ShirokaAvaloniaStaticLinkFilesToDelete Include="$(PublishDir)libSkiaSharp.so" /> - <_ShirokaAvaloniaStaticLinkFilesToDelete Include="$(PublishDir)libHarfBuzzSharp.dylib" /> - <_ShirokaAvaloniaStaticLinkFilesToDelete Include="$(PublishDir)libSkiaSharp.dylib" /> - <_ShirokaAvaloniaStaticLinkFilesToDelete Include="$(PublishDir)libAvaloniaNative.dylib" /> - - - - diff --git a/NuGet/StaticGraphics/buildTransitive/Shiroka.Avalonia.StaticLink.MacOSFontWarmup.cs b/NuGet/StaticGraphics/buildTransitive/StaticLink.Avalonia.MacOSFontWarmup.cs similarity index 97% rename from NuGet/StaticGraphics/buildTransitive/Shiroka.Avalonia.StaticLink.MacOSFontWarmup.cs rename to NuGet/StaticGraphics/buildTransitive/StaticLink.Avalonia.MacOSFontWarmup.cs index fa4c29e..28ed6b7 100644 --- a/NuGet/StaticGraphics/buildTransitive/Shiroka.Avalonia.StaticLink.MacOSFontWarmup.cs +++ b/NuGet/StaticGraphics/buildTransitive/StaticLink.Avalonia.MacOSFontWarmup.cs @@ -2,7 +2,7 @@ using System; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; -namespace Shiroka.Avalonia.StaticLink; +namespace StaticLink.Avalonia; internal static class MacOSFontWarmup { diff --git a/NuGet/StaticGraphics/buildTransitive/StaticLink.Avalonia.props b/NuGet/StaticGraphics/buildTransitive/StaticLink.Avalonia.props new file mode 100644 index 0000000..61a7c36 --- /dev/null +++ b/NuGet/StaticGraphics/buildTransitive/StaticLink.Avalonia.props @@ -0,0 +1,5 @@ + + + $(MSBuildThisFileDirectory)../static/ + + diff --git a/NuGet/StaticGraphics/buildTransitive/StaticLink.Avalonia.targets b/NuGet/StaticGraphics/buildTransitive/StaticLink.Avalonia.targets new file mode 100644 index 0000000..85cb909 --- /dev/null +++ b/NuGet/StaticGraphics/buildTransitive/StaticLink.Avalonia.targets @@ -0,0 +1,125 @@ + + + <_StaticLinkAvaloniaRid Condition="'$(RuntimeIdentifier)' == 'win-x64'">win-x64 + <_StaticLinkAvaloniaRid Condition="'$(RuntimeIdentifier)' == 'win-arm64'">win-arm64 + <_StaticLinkAvaloniaRid Condition="'$(RuntimeIdentifier)' == 'linux-x64'">linux-x64 + <_StaticLinkAvaloniaRid Condition="'$(RuntimeIdentifier)' == 'linux-arm64'">linux-arm64 + <_StaticLinkAvaloniaRid Condition="'$(RuntimeIdentifier)' == 'osx-x64'">osx-x64 + <_StaticLinkAvaloniaRid Condition="'$(RuntimeIdentifier)' == 'osx-arm64'">osx-arm64 + <_StaticLinkAvaloniaNativeRoot Condition="'$(_StaticLinkAvaloniaRid)' != ''">$(StaticLinkAvaloniaRoot)$(_StaticLinkAvaloniaRid)/native + lld + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + false + + + + + + + + + + + + + + + + + + + + + + + + + + + + + <_StaticLinkAvaloniaFilesToDelete Include="$(PublishDir)av_libglesv2.dll" /> + <_StaticLinkAvaloniaFilesToDelete Include="$(PublishDir)libHarfBuzzSharp.dll" /> + <_StaticLinkAvaloniaFilesToDelete Include="$(PublishDir)libSkiaSharp.dll" /> + <_StaticLinkAvaloniaFilesToDelete Include="$(PublishDir)libHarfBuzzSharp.so" /> + <_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 eed8a3e..e4e5da2 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,10 @@ -# Shiroka.Avalonia.StaticLink +# StaticLink.Avalonia -Static graphics libraries for Avalonia NativeAOT single-file publishing. +Static native libraries for Avalonia NativeAOT publishing. -This package provides static archives for SkiaSharp, HarfBuzzSharp, and ANGLE, then wires them into MSBuild through `buildTransitive` targets. It is intended for Avalonia applications that want NativeAOT single-file publish outputs without shipping Avalonia graphics native libraries next to the executable. +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: +Repository: ## Supported RIDs @@ -15,34 +15,14 @@ Repository: - `osx-x64` - `osx-arm64` -## Included Libraries - -Windows: - -- `skia.lib` -- `SkiaSharp.lib` -- `libHarfBuzzSharp.lib` -- `libANGLE_static.lib` -- `libGLESv2_static.lib` - -Linux and macOS: - -- `libskia.a` -- `libSkiaSharp.a` -- `libHarfBuzzSharp.a` -- `libANGLE_static.a` -- `libGLESv2_static.a` - ## Install ```bash -dotnet add package Shiroka.Avalonia.StaticLink +dotnet add package StaticLink.Avalonia ``` ## Publish -Windows x64 or arm64: - ```bash dotnet publish -c Release -r win-x64 \ -p:PublishAot=true \ @@ -51,7 +31,9 @@ dotnet publish -c Release -r win-x64 \ -p:StripSymbols=true ``` -Linux x64 or arm64: +Use the RID you need, for example `linux-x64`, `linux-arm64`, `osx-arm64`, or `osx-x64`. + +For Linux, `lld` is recommended: ```bash dotnet publish -c Release -r linux-x64 \ @@ -62,102 +44,18 @@ dotnet publish -c Release -r linux-x64 \ -p:LinkerFlavor=lld ``` -macOS x64 or arm64: +For macOS, avoid the Metal renderer for fully static output. Use OpenGL or Software: -```bash -dotnet publish -c Release -r osx-arm64 \ - -p:PublishAot=true \ - -p:SelfContained=true \ - -p:PublishSingleFile=true \ - -p:StripSymbols=true +```csharp +.With(new AvaloniaNativePlatformOptions +{ + RenderingMode = [AvaloniaNativeRenderingMode.OpenGl, AvaloniaNativeRenderingMode.Software] +}) ``` -The package automatically contributes the static archives as `NativeLibrary` items when `PublishAot=true` and the `RuntimeIdentifier` is supported. +## Notes -## Verify Output - -After publishing, the publish directory should not contain Avalonia graphics runtime files such as: - -- `libSkiaSharp.so` -- `libHarfBuzzSharp.so` -- `libSkiaSharp.dylib` -- `libHarfBuzzSharp.dylib` -- `libSkiaSharp.dll` -- `libHarfBuzzSharp.dll` -- `av_libglesv2.dll` - -The package stores static archives under `static//native/` inside the NuGet package, so `.a` and `.lib` files are used for linking and are not normal runtime assets. - -## Build From Source - -This repository does not depend on 2ndLAB static packages. The GitHub Actions workflow builds the native libraries from upstream source repositories: - -- SkiaSharp: -- ANGLE: - -Build scripts: - -- `scripts/build-linux-static-graphics.sh` -- `scripts/build-windows-static-graphics.ps1` -- `scripts/build-macos-static-graphics.sh` - -Build locally after the static archives exist: - -```bash -dotnet pack NuGet/StaticGraphics/Shiroka.Avalonia.StaticLink.csproj -c Release -o artifacts/nuget -``` - -The package will be written to: - -```text -artifacts/nuget/Shiroka.Avalonia.StaticLink.*.nupkg -``` - -## GitHub Actions - -The workflow `.github/workflows/nuget-static-graphics.yml` builds all native archives and packs a single NuGet package for all supported RIDs. - -It will: - -- build Linux x64 static archives on `ubuntu-latest` -- build Linux arm64 static archives on `ubuntu-24.04-arm` -- build Windows x64 and arm64 static archives on `windows-latest` -- build macOS x64 and arm64 static archives on `macos-latest` -- download all native artifacts into `External/NativeStatic//` -- run `dotnet pack` -- upload the generated `.nupkg` as a workflow artifact - -To publish automatically to nuget.org, add a repository secret named `NUGET_API_KEY`, then either: - -- run the workflow manually with `publish_to_nuget=true` -- push a tag matching `static-graphics-v*` - -Example tag: - -```bash -git tag static-graphics-v3.119.2-7151.4 -git push origin static-graphics-v3.119.2-7151.4 -``` - -## Known Runtime Dependencies - -Single-file does not always mean dependency-free. Depending on platform and publish settings, the final executable may still depend on operating system libraries and frameworks. - -Linux examples: - -- `libc.so.6` -- `libm.so.6` -- `libstdc++.so.6` -- `libgcc_s.so.1` -- `libfontconfig.so.1` -- `libfreetype.so.6` - -Linux systems also need usable fonts for text rendering and font fallback. - -## Scope - -This package only covers Avalonia graphics-related native libraries. If your application uses other native dependencies, such as SQLite, audio backends, OpenSSL, or custom native libraries, those dependencies may require separate handling. - -## License - -The NuGet package metadata uses the MIT license. The bundled third-party native libraries are built from their upstream projects and remain subject to their respective upstream licenses. +- The package is intended for Avalonia `11.3.x` NativeAOT apps. +- 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/build-macos-font-preinit.sh b/scripts/build-macos-font-preinit.sh index 5c59d5e..36abbd3 100644 --- a/scripts/build-macos-font-preinit.sh +++ b/scripts/build-macos-font-preinit.sh @@ -19,7 +19,7 @@ cat > "$src" <<'OBJC' #import __attribute__((constructor(101))) -static void ShirokaAvaloniaStaticLinkPreinitializeAppKitFonts(void) +static void StaticLinkAvaloniaPreinitializeAppKitFonts(void) { @autoreleasepool { diff --git a/scripts/create-avalonia-smoke.ps1 b/scripts/create-avalonia-smoke.ps1 index 038e770..3d2fff6 100644 --- a/scripts/create-avalonia-smoke.ps1 +++ b/scripts/create-avalonia-smoke.ps1 @@ -44,7 +44,7 @@ New-Item -ItemType Directory -Path $ProjectDir -Force | Out-Null - + "@ | Set-Content -Path (Join-Path $ProjectDir "AvaloniaStaticLinkSmoke.csproj") -Encoding UTF8