Compare commits
11
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9e47ca801d | ||
|
|
2fc99a5c09 | ||
|
|
cabf4363f2 | ||
|
|
05652b6d1d | ||
|
|
1bb62e3da1 | ||
|
|
7c18ae44c2 | ||
|
|
3f7c30ec29 | ||
|
|
17a593b65f | ||
|
|
f0cdd65937 | ||
|
|
719b384b38 | ||
|
|
ef96db63b8 |
No files matched your search
@@ -1,21 +1,12 @@
|
||||
name: staticlink-avalonia-native
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
avalonia_version:
|
||||
type: string
|
||||
default: ''
|
||||
force_build:
|
||||
type: boolean
|
||||
default: false
|
||||
publish_to_nuget:
|
||||
type: boolean
|
||||
default: false
|
||||
schedule:
|
||||
- cron: "17 3 * * *"
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
avalonia_version:
|
||||
description: Avalonia version to build; empty checks the latest stable 11.x and 12.x versions
|
||||
description: Avalonia version to build; empty uses the latest stable NuGet version
|
||||
required: false
|
||||
type: string
|
||||
force_build:
|
||||
@@ -26,16 +17,21 @@ on:
|
||||
publish_to_nuget:
|
||||
description: Publish with NuGet Trusted Publishing after smoke tests
|
||||
required: true
|
||||
default: false
|
||||
default: true
|
||||
type: boolean
|
||||
|
||||
concurrency:
|
||||
group: staticlink-avalonia-native
|
||||
cancel-in-progress: false
|
||||
|
||||
jobs:
|
||||
detect:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: read
|
||||
outputs:
|
||||
versions: ${{ steps.version.outputs.versions }}
|
||||
avalonia_version: ${{ steps.version.outputs.avalonia_version }}
|
||||
package_version: ${{ steps.version.outputs.package_version }}
|
||||
should_build: ${{ steps.version.outputs.should_build }}
|
||||
steps:
|
||||
- name: Detect unpublished Avalonia version
|
||||
@@ -47,112 +43,74 @@ jobs:
|
||||
run: |
|
||||
set -euo pipefail
|
||||
|
||||
if [ -n "$REQUESTED_VERSION" ]; then
|
||||
candidate_versions=("$REQUESTED_VERSION")
|
||||
else
|
||||
nuget_versions="$(curl --fail --silent --show-error --location \
|
||||
https://api.nuget.org/v3-flatcontainer/avalonia/index.json)"
|
||||
candidate_versions=()
|
||||
for major in 11 12; do
|
||||
candidate_versions+=("$(jq -r --arg major "$major" \
|
||||
'[.versions[] | select(startswith($major + ".") and (contains("-") | not))] | last' \
|
||||
<<< "$nuget_versions")")
|
||||
done
|
||||
avalonia_version="$REQUESTED_VERSION"
|
||||
if [ -z "$avalonia_version" ]; then
|
||||
avalonia_version="$(curl --fail --silent --show-error --location \
|
||||
https://api.nuget.org/v3-flatcontainer/avalonia/index.json \
|
||||
| jq -r '[.versions[] | select(contains("-") | not)] | last')"
|
||||
fi
|
||||
|
||||
versions='[]'
|
||||
for avalonia_version in "${candidate_versions[@]}"; do
|
||||
if [ -z "$avalonia_version" ] || [ "$avalonia_version" = "null" ]; then
|
||||
echo "Could not determine a stable Avalonia version." >&2
|
||||
echo "Could not determine the latest stable Avalonia version." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
package_version="$avalonia_version.2"
|
||||
package_version="$avalonia_version.1"
|
||||
package_url="https://api.nuget.org/v3-flatcontainer/staticlink.avalonia.native/$package_version/staticlink.avalonia.native.$package_version.nupkg"
|
||||
status=$(curl --retry 3 --silent --show-error --location --output /dev/null --write-out '%{http_code}' "$package_url")
|
||||
if [ "$status" != 200 ] && [ "$status" != 404 ]; then
|
||||
echo "NuGet availability check failed: HTTP $status" >&2
|
||||
exit 1
|
||||
fi
|
||||
if [ "$FORCE_BUILD" != "true" ] && [ "$status" = 200 ]; then
|
||||
echo "Already published: $package_version"
|
||||
continue
|
||||
should_build=true
|
||||
if [ "$FORCE_BUILD" != "true" ] && curl --fail --silent --location --output /dev/null "$package_url"; then
|
||||
should_build=false
|
||||
fi
|
||||
|
||||
echo "Build required: $package_version"
|
||||
versions="$(jq -cn --argjson versions "$versions" \
|
||||
--arg avalonia_version "$avalonia_version" \
|
||||
--arg package_version "$package_version" \
|
||||
'$versions + [{avalonia_version: $avalonia_version, package_version: $package_version}]')"
|
||||
done
|
||||
|
||||
echo "versions=$versions" >> "$GITHUB_OUTPUT"
|
||||
if [ "$versions" = '[]' ]; then
|
||||
echo 'should_build=false' >> "$GITHUB_OUTPUT"
|
||||
else
|
||||
echo 'should_build=true' >> "$GITHUB_OUTPUT"
|
||||
fi
|
||||
|
||||
toolchain:
|
||||
needs: detect
|
||||
if: ${{ needs.detect.outputs.should_build == 'true' }}
|
||||
permissions:
|
||||
contents: read
|
||||
packages: write
|
||||
uses: ./.github/workflows/zig-toolchain-image.yml
|
||||
with:
|
||||
validation_rids: '["osx-x64","osx-arm64"]'
|
||||
echo "Avalonia version: $avalonia_version"
|
||||
echo "StaticLink.Avalonia.Native version: $package_version"
|
||||
echo "Build required: $should_build"
|
||||
echo "avalonia_version=$avalonia_version" >> "$GITHUB_OUTPUT"
|
||||
echo "package_version=$package_version" >> "$GITHUB_OUTPUT"
|
||||
echo "should_build=$should_build" >> "$GITHUB_OUTPUT"
|
||||
|
||||
build:
|
||||
needs: [detect, toolchain]
|
||||
needs: detect
|
||||
if: ${{ needs.detect.outputs.should_build == 'true' }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
version: ${{ fromJSON(needs.detect.outputs.versions) }}
|
||||
rid: [osx-x64, osx-arm64]
|
||||
include:
|
||||
- rid: osx-x64
|
||||
runner: macos-14
|
||||
- rid: osx-arm64
|
||||
runner: macos-15
|
||||
runs-on: ubuntu-24.04
|
||||
runs-on: ${{ matrix.runner }}
|
||||
permissions:
|
||||
contents: read
|
||||
packages: read
|
||||
env:
|
||||
TOOLCHAIN_IMAGE: ${{ needs.toolchain.outputs.image }}
|
||||
RID: ${{ matrix.rid }}
|
||||
AVALONIA_VERSION: ${{ matrix.version.avalonia_version }}
|
||||
AVALONIA_VERSION: ${{ needs.detect.outputs.avalonia_version }}
|
||||
WORK_DIR: ${{ github.workspace }}/External/AvaloniaNative/.work
|
||||
OUTPUT_DIR: ${{ github.workspace }}/External/AvaloniaNative/${{ matrix.rid }}/native
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Pull immutable toolchain image
|
||||
env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
ACTOR: ${{ github.actor }}
|
||||
run: |
|
||||
printf '%s' "$GH_TOKEN" | docker login ghcr.io -u "$ACTOR" --password-stdin
|
||||
docker pull "$TOOLCHAIN_IMAGE"
|
||||
- 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 and font preinit with Zig
|
||||
run: |
|
||||
mkdir -p "$WORK_DIR" "$OUTPUT_DIR"
|
||||
docker run --rm --user "$(id -u):$(id -g)" \
|
||||
-e HOME=/tmp/staticlink-home -e RID -e AVALONIA_VERSION \
|
||||
-v "$PWD:/src" -w /src --entrypoint bash "$TOOLCHAIN_IMAGE" \
|
||||
scripts/build-avalonia-native-container.sh
|
||||
- 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.version.avalonia_version }}-${{ matrix.rid }}
|
||||
name: native-avalonia-${{ matrix.rid }}
|
||||
path: |
|
||||
External/AvaloniaNative/${{ matrix.rid }}/native/libAvaloniaNative.a
|
||||
External/AvaloniaNative/${{ matrix.rid }}/native/macos_font_preinit.o
|
||||
External/AvaloniaNative/${{ matrix.rid }}/native/avalonia-native-build.json
|
||||
if-no-files-found: error
|
||||
|
||||
pack:
|
||||
@@ -160,9 +118,6 @@ jobs:
|
||||
- detect
|
||||
- build
|
||||
if: ${{ needs.detect.outputs.should_build == 'true' }}
|
||||
strategy:
|
||||
matrix:
|
||||
version: ${{ fromJSON(needs.detect.outputs.versions) }}
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: read
|
||||
@@ -177,7 +132,7 @@ jobs:
|
||||
- name: Download static AvaloniaNative archives
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
pattern: native-avalonia-${{ matrix.version.avalonia_version }}-*
|
||||
pattern: native-avalonia-*
|
||||
path: artifacts/native
|
||||
merge-multiple: false
|
||||
|
||||
@@ -187,9 +142,8 @@ jobs:
|
||||
set -euo pipefail
|
||||
for rid in osx-x64 osx-arm64; do
|
||||
mkdir -p "External/AvaloniaNative/$rid/native"
|
||||
cp "artifacts/native/native-avalonia-${{ matrix.version.avalonia_version }}-$rid/libAvaloniaNative.a" "External/AvaloniaNative/$rid/native/"
|
||||
cp "artifacts/native/native-avalonia-${{ matrix.version.avalonia_version }}-$rid/macos_font_preinit.o" "External/AvaloniaNative/$rid/native/"
|
||||
cp "artifacts/native/native-avalonia-${{ matrix.version.avalonia_version }}-$rid/avalonia-native-build.json" "External/AvaloniaNative/$rid/native/"
|
||||
cp "artifacts/native/native-avalonia-$rid/libAvaloniaNative.a" "External/AvaloniaNative/$rid/native/"
|
||||
cp "artifacts/native/native-avalonia-$rid/macos_font_preinit.o" "External/AvaloniaNative/$rid/native/"
|
||||
done
|
||||
|
||||
- name: Pack StaticLink.Avalonia.Native
|
||||
@@ -197,13 +151,13 @@ jobs:
|
||||
dotnet pack NuGet/AvaloniaNative/StaticLink.Avalonia.Native.csproj \
|
||||
-c Release \
|
||||
-o artifacts/nuget \
|
||||
/p:PackageVersion=${{ matrix.version.package_version }} \
|
||||
/p:Version=${{ matrix.version.package_version }}
|
||||
/p:PackageVersion=${{ needs.detect.outputs.package_version }} \
|
||||
/p:Version=${{ needs.detect.outputs.package_version }}
|
||||
|
||||
- name: Upload NuGet package
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: staticlink-avalonia-native-${{ matrix.version.package_version }}
|
||||
name: staticlink-avalonia-native-${{ needs.detect.outputs.package_version }}
|
||||
path: artifacts/nuget/*.nupkg
|
||||
if-no-files-found: error
|
||||
|
||||
@@ -215,8 +169,6 @@ jobs:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
version: ${{ fromJSON(needs.detect.outputs.versions) }}
|
||||
rid: [osx-x64, osx-arm64]
|
||||
include:
|
||||
- rid: osx-x64
|
||||
runner: macos-14
|
||||
@@ -236,7 +188,7 @@ jobs:
|
||||
- name: Download NuGet package
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: staticlink-avalonia-native-${{ matrix.version.package_version }}
|
||||
name: staticlink-avalonia-native-${{ needs.detect.outputs.package_version }}
|
||||
path: artifacts/nuget
|
||||
|
||||
- name: Publish Avalonia NativeAOT smoke app
|
||||
@@ -246,8 +198,8 @@ jobs:
|
||||
pwsh ./scripts/create-avalonia-smoke.ps1 `
|
||||
-ProjectDir $projectDir `
|
||||
-NuGetSource (Resolve-Path "artifacts/nuget") `
|
||||
-AvaloniaVersion "${{ matrix.version.avalonia_version }}" `
|
||||
-StaticLinkNativeVersion "${{ matrix.version.package_version }}"
|
||||
-AvaloniaVersion "${{ needs.detect.outputs.avalonia_version }}" `
|
||||
-StaticLinkNativeVersion "${{ needs.detect.outputs.package_version }}"
|
||||
dotnet publish (Join-Path $projectDir "AvaloniaStaticLinkSmoke.csproj") `
|
||||
-c Release `
|
||||
-r "${{ matrix.rid }}" `
|
||||
@@ -291,22 +243,11 @@ jobs:
|
||||
sys.exit(proc.returncode if proc.returncode > 0 else 1)
|
||||
PY
|
||||
|
||||
- name: Upload AvaloniaNative smoke app
|
||||
if: ${{ always() }}
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: avalonia-native-smoke-${{ matrix.version.avalonia_version }}-${{ matrix.rid }}
|
||||
path: artifacts/smoke-${{ matrix.rid }}/**
|
||||
if-no-files-found: warn
|
||||
|
||||
publish:
|
||||
needs:
|
||||
- detect
|
||||
- smoke
|
||||
if: ${{ needs.detect.outputs.should_build == 'true' && inputs.publish_to_nuget == true }}
|
||||
strategy:
|
||||
matrix:
|
||||
version: ${{ fromJSON(needs.detect.outputs.versions) }}
|
||||
if: ${{ needs.detect.outputs.should_build == 'true' && (github.event_name == 'schedule' || inputs.publish_to_nuget == true) }}
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: read
|
||||
@@ -315,35 +256,23 @@ jobs:
|
||||
- name: Download NuGet package
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: staticlink-avalonia-native-${{ matrix.version.package_version }}
|
||||
name: staticlink-avalonia-native-${{ needs.detect.outputs.package_version }}
|
||||
path: artifacts/nuget
|
||||
|
||||
- uses: actions/setup-dotnet@v4
|
||||
with:
|
||||
dotnet-version: "10.0.302"
|
||||
|
||||
- name: Validate Trusted Publishing configuration
|
||||
env:
|
||||
NUGET_USER: ${{ vars.NUGET_USER }}
|
||||
NUGET_API_KEY: ${{ secrets.NUGET_API_KEY }}
|
||||
run: |
|
||||
if [ -z "$NUGET_USER" ] && [ -z "$NUGET_API_KEY" ]; then
|
||||
echo 'Configure NUGET_USER with Trusted Publishing or NUGET_API_KEY.' >&2
|
||||
exit 1
|
||||
fi
|
||||
run: test -n "$NUGET_USER"
|
||||
|
||||
- name: NuGet login
|
||||
if: ${{ vars.NUGET_USER != '' }}
|
||||
id: login
|
||||
uses: NuGet/login@v1
|
||||
with:
|
||||
user: ${{ vars.NUGET_USER }}
|
||||
|
||||
- name: Publish to nuget.org
|
||||
env:
|
||||
NUGET_API_KEY: ${{ steps.login.outputs.NUGET_API_KEY || secrets.NUGET_API_KEY }}
|
||||
run: |
|
||||
dotnet nuget push artifacts/nuget/*.nupkg \
|
||||
--source https://www.nuget.org/api/v2/package \
|
||||
--api-key "$NUGET_API_KEY" \
|
||||
--api-key "${{ steps.login.outputs.NUGET_API_KEY }}" \
|
||||
--skip-duplicate
|
||||
@@ -0,0 +1,106 @@
|
||||
name: staticlink-avalonia-repack
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
source_version:
|
||||
description: Existing package version containing the static libraries
|
||||
required: true
|
||||
default: 3.119.4-7922.1
|
||||
type: string
|
||||
publish_to_nuget:
|
||||
description: Publish package to nuget.org
|
||||
required: true
|
||||
default: false
|
||||
type: boolean
|
||||
|
||||
jobs:
|
||||
repack:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Setup .NET
|
||||
uses: actions/setup-dotnet@v4
|
||||
with:
|
||||
dotnet-version: "10.0.x"
|
||||
|
||||
- name: Extract static libraries from existing package
|
||||
env:
|
||||
SOURCE_VERSION: ${{ inputs.source_version }}
|
||||
run: |
|
||||
python3 - <<'PY'
|
||||
import os
|
||||
import pathlib
|
||||
import urllib.request
|
||||
import zipfile
|
||||
|
||||
version = os.environ["SOURCE_VERSION"]
|
||||
package = pathlib.Path("artifacts/source.nupkg")
|
||||
package.parent.mkdir(parents=True, exist_ok=True)
|
||||
urllib.request.urlretrieve(
|
||||
f"https://api.nuget.org/v3-flatcontainer/staticlink.avalonia/{version}/staticlink.avalonia.{version}.nupkg",
|
||||
package,
|
||||
)
|
||||
|
||||
output = pathlib.Path("External/NativeStatic")
|
||||
with zipfile.ZipFile(package) as archive:
|
||||
for entry in archive.infolist():
|
||||
name = entry.filename.replace("\\", "/")
|
||||
if not name.startswith("static/") or name.endswith("/"):
|
||||
continue
|
||||
destination = output / name.removeprefix("static/")
|
||||
destination.parent.mkdir(parents=True, exist_ok=True)
|
||||
destination.write_bytes(archive.read(entry))
|
||||
PY
|
||||
|
||||
- name: Verify static archives
|
||||
run: |
|
||||
for rid in linux-x64 linux-arm64 linux-musl-x64 linux-musl-arm64 osx-x64 osx-arm64; do
|
||||
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 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
|
||||
test -f External/NativeStatic/$rid/native/libANGLE_static.lib
|
||||
test -f External/NativeStatic/$rid/native/libGLESv2_static.lib
|
||||
done
|
||||
test -f External/NativeStatic/win-x86/native/skia_x86_stdcall_thunks.lib
|
||||
|
||||
- name: Pack NuGet package
|
||||
run: dotnet pack NuGet/StaticGraphics/StaticLink.Avalonia.csproj -c Release -o artifacts/nuget
|
||||
|
||||
- name: Verify portable NuGet paths
|
||||
run: |
|
||||
package=$(find artifacts/nuget -name 'StaticLink.Avalonia.*.nupkg' ! -name 'StaticLink.Avalonia.Native.*.nupkg' -print -quit)
|
||||
test -n "$package"
|
||||
if unzip -Z1 "$package" | grep -F '\'; then
|
||||
echo "NuGet package contains Windows-only backslash paths."
|
||||
exit 1
|
||||
fi
|
||||
unzip -Z1 "$package" | grep -Fx 'buildTransitive/StaticLink.Avalonia.props'
|
||||
unzip -Z1 "$package" | grep -Fx 'buildTransitive/StaticLink.Avalonia.targets'
|
||||
|
||||
- name: Upload NuGet artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: staticlink-avalonia-repacked-nuget
|
||||
path: artifacts/nuget/*.nupkg
|
||||
if-no-files-found: error
|
||||
|
||||
- name: Publish to nuget.org
|
||||
if: ${{ inputs.publish_to_nuget == true }}
|
||||
env:
|
||||
NUGET_API_KEY: ${{ secrets.NUGET_API_KEY }}
|
||||
run: |
|
||||
test -n "$NUGET_API_KEY"
|
||||
dotnet nuget push artifacts/nuget/*.nupkg \
|
||||
--source "https://api.nuget.org/v3/index.json" \
|
||||
--api-key "$NUGET_API_KEY" \
|
||||
--skip-duplicate
|
||||
@@ -0,0 +1,454 @@
|
||||
name: staticlink-avalonia
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
publish_to_nuget:
|
||||
description: Publish package to nuget.org
|
||||
required: true
|
||||
default: false
|
||||
type: boolean
|
||||
publish_to_release:
|
||||
description: Publish NuGet package and smoke apps to GitHub Release
|
||||
required: true
|
||||
default: true
|
||||
type: boolean
|
||||
push:
|
||||
tags:
|
||||
- "staticlink-avalonia-v*"
|
||||
|
||||
env:
|
||||
DOTNET_ALPINE_IMAGE: mcr.microsoft.com/dotnet/sdk:10.0.302-alpine3.23
|
||||
|
||||
jobs:
|
||||
preflight:
|
||||
uses: ./.github/workflows/static-graphics-preflight.yml
|
||||
|
||||
build-linux:
|
||||
needs: preflight
|
||||
uses: ./.github/workflows/static-graphics-linux.yml
|
||||
with:
|
||||
skiasharp_version: ${{ needs.preflight.outputs.skiasharp_version }}
|
||||
angle_branch: ${{ needs.preflight.outputs.angle_branch }}
|
||||
|
||||
build-musl:
|
||||
needs: preflight
|
||||
uses: ./.github/workflows/static-graphics-musl.yml
|
||||
with:
|
||||
skiasharp_version: ${{ needs.preflight.outputs.skiasharp_version }}
|
||||
angle_branch: ${{ needs.preflight.outputs.angle_branch }}
|
||||
dotnet_alpine_image: mcr.microsoft.com/dotnet/sdk:10.0.302-alpine3.23
|
||||
|
||||
build-windows:
|
||||
needs: preflight
|
||||
uses: ./.github/workflows/static-graphics-windows.yml
|
||||
with:
|
||||
skiasharp_version: ${{ needs.preflight.outputs.skiasharp_version }}
|
||||
angle_branch: ${{ needs.preflight.outputs.angle_branch }}
|
||||
|
||||
build-macos:
|
||||
needs: preflight
|
||||
uses: ./.github/workflows/static-graphics-macos.yml
|
||||
with:
|
||||
skiasharp_version: ${{ needs.preflight.outputs.skiasharp_version }}
|
||||
angle_branch: ${{ needs.preflight.outputs.angle_branch }}
|
||||
|
||||
pack:
|
||||
runs-on: ubuntu-24.04
|
||||
needs:
|
||||
- build-linux
|
||||
- build-musl
|
||||
- build-windows
|
||||
- build-macos
|
||||
permissions:
|
||||
contents: read
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Setup .NET
|
||||
uses: actions/setup-dotnet@v4
|
||||
with:
|
||||
dotnet-version: "10.0.302"
|
||||
|
||||
- name: Download static archives
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
pattern: native-static-*
|
||||
path: External/NativeStatic
|
||||
merge-multiple: false
|
||||
|
||||
- name: Move static archives into RID directories
|
||||
run: |
|
||||
for rid in win-x64 win-x86 win-arm64 linux-x64 linux-arm64 linux-musl-x64 linux-musl-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"
|
||||
if [ ! -d "External/NativeStatic/$rid/native" ]; then
|
||||
mkdir -p "External/NativeStatic/$rid/native"
|
||||
find "External/NativeStatic/$rid" -maxdepth 1 -type f -exec mv {} "External/NativeStatic/$rid/native/" \;
|
||||
fi
|
||||
done
|
||||
|
||||
- name: Verify static archives
|
||||
run: |
|
||||
for rid in linux-x64 linux-arm64 linux-musl-x64 linux-musl-arm64 osx-x64 osx-arm64; do
|
||||
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 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
|
||||
test -f External/NativeStatic/$rid/native/libANGLE_static.lib
|
||||
test -f External/NativeStatic/$rid/native/libGLESv2_static.lib
|
||||
done
|
||||
test -f External/NativeStatic/win-x86/native/skia_x86_stdcall_thunks.lib
|
||||
|
||||
- name: Pack NuGet package
|
||||
run: dotnet pack NuGet/StaticGraphics/StaticLink.Avalonia.csproj -c Release -o artifacts/nuget
|
||||
|
||||
- name: Verify portable NuGet paths
|
||||
shell: bash
|
||||
run: |
|
||||
package=$(find artifacts/nuget -name 'StaticLink.Avalonia.*.nupkg' ! -name 'StaticLink.Avalonia.Native.*.nupkg' -print -quit)
|
||||
test -n "$package"
|
||||
if unzip -Z1 "$package" | grep -F '\'; then
|
||||
echo "NuGet package contains Windows-only backslash paths."
|
||||
exit 1
|
||||
fi
|
||||
unzip -Z1 "$package" | grep -Fx 'buildTransitive/StaticLink.Avalonia.props'
|
||||
unzip -Z1 "$package" | grep -Fx 'buildTransitive/StaticLink.Avalonia.targets'
|
||||
|
||||
- name: Upload NuGet artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: staticlink-avalonia-nuget
|
||||
path: |
|
||||
artifacts/nuget/*.nupkg
|
||||
artifacts/nuget/*.snupkg
|
||||
if-no-files-found: error
|
||||
|
||||
smoke-avalonia:
|
||||
needs: pack
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- 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
|
||||
- rid: linux-x64
|
||||
runner: ubuntu-24.04
|
||||
- rid: linux-arm64
|
||||
runner: ubuntu-24.04-arm
|
||||
- rid: linux-musl-x64
|
||||
runner: ubuntu-24.04
|
||||
- rid: linux-musl-arm64
|
||||
runner: ubuntu-24.04-arm
|
||||
- rid: osx-x64
|
||||
runner: macos-15
|
||||
avalonia_version: 11.3.14
|
||||
- rid: osx-arm64
|
||||
runner: macos-15
|
||||
avalonia_version: 11.3.14
|
||||
runs-on: ${{ matrix.runner }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Setup MSVC environment
|
||||
if: ${{ startsWith(matrix.rid, 'win-') }}
|
||||
uses: ilammy/msvc-dev-cmd@v1
|
||||
with:
|
||||
arch: ${{ matrix.msvc_arch }}
|
||||
|
||||
- name: Install Linux publish dependencies
|
||||
if: ${{ startsWith(matrix.rid, 'linux-') && !startsWith(matrix.rid, 'linux-musl-') }}
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y clang lld xvfb zlib1g-dev libfontconfig1-dev libfreetype6 libgl1 libice6 libsm6 libx11-6 libxcb1 libxcursor1 libxext6 libxfixes3 libxinerama1 libxrandr2 libxrender1 libxi6
|
||||
|
||||
- name: Setup .NET
|
||||
uses: actions/setup-dotnet@v4
|
||||
with:
|
||||
dotnet-version: "10.0.302"
|
||||
|
||||
- name: Download NuGet package
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: staticlink-avalonia-nuget
|
||||
path: artifacts/nuget
|
||||
|
||||
- name: Publish Avalonia single-file smoke app
|
||||
if: ${{ !startsWith(matrix.rid, 'linux-musl-') }}
|
||||
shell: pwsh
|
||||
run: |
|
||||
$ErrorActionPreference = "Stop"
|
||||
$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]
|
||||
$avaloniaVersion = "${{ matrix.avalonia_version }}"
|
||||
if (-not $avaloniaVersion) { $avaloniaVersion = "11.3.14" }
|
||||
$projectDir = Join-Path $PWD "artifacts/avalonia-smoke-src"
|
||||
pwsh ./scripts/create-avalonia-smoke.ps1 -ProjectDir $projectDir -NuGetSource (Resolve-Path "artifacts/nuget") -StaticLinkVersion $version -AvaloniaVersion $avaloniaVersion
|
||||
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: Publish Avalonia musl smoke app
|
||||
if: ${{ startsWith(matrix.rid, 'linux-musl-') }}
|
||||
shell: pwsh
|
||||
run: |
|
||||
$ErrorActionPreference = "Stop"
|
||||
$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]
|
||||
$projectDir = Join-Path $PWD "artifacts/avalonia-smoke-src"
|
||||
pwsh ./scripts/create-avalonia-smoke.ps1 -ProjectDir $projectDir -NuGetSource "/workspace/artifacts/nuget" -StaticLinkVersion $version -AvaloniaVersion "11.3.14"
|
||||
docker run --rm `
|
||||
-v "${{ github.workspace }}:/workspace" `
|
||||
-w /workspace `
|
||||
"${{ env.DOTNET_ALPINE_IMAGE }}" `
|
||||
sh -c "apk add --no-cache clang lld build-base zlib-dev fontconfig-dev && dotnet publish /workspace/artifacts/avalonia-smoke-src/AvaloniaStaticLinkSmoke.csproj -c Release -r ${{ matrix.rid }} --configfile /workspace/artifacts/avalonia-smoke-src/NuGet.config /p:PublishAot=true /p:SelfContained=true /p:PublishSingleFile=true /p:StripSymbols=true /p:PublishDir=/workspace/artifacts/smoke-${{ matrix.rid }}/"
|
||||
|
||||
- name: Verify no dynamic graphics libraries remain
|
||||
shell: pwsh
|
||||
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")
|
||||
}
|
||||
if ($blocked) {
|
||||
$blocked | ForEach-Object { Write-Error "Unexpected dynamic graphics library: $($_.FullName)" }
|
||||
exit 1
|
||||
}
|
||||
Get-ChildItem -Path $publishDir -Recurse -File | ForEach-Object { $_.FullName }
|
||||
|
||||
- name: Verify Windows executable architecture
|
||||
if: ${{ startsWith(matrix.rid, 'win-') }}
|
||||
shell: pwsh
|
||||
run: |
|
||||
$ErrorActionPreference = "Stop"
|
||||
$app = Join-Path $PWD "artifacts/smoke-${{ matrix.rid }}/AvaloniaStaticLinkSmoke.exe"
|
||||
$expectedMachine = @{
|
||||
"win-x64" = "8664 machine"
|
||||
"win-x86" = "14C machine"
|
||||
"win-arm64" = "AA64 machine"
|
||||
}["${{ matrix.rid }}"]
|
||||
$headers = & dumpbin /headers $app | Out-String
|
||||
if ($LASTEXITCODE -ne 0 -or $headers -notmatch [regex]::Escape($expectedMachine)) {
|
||||
throw "Expected $expectedMachine in PE headers for $app.`n$headers"
|
||||
}
|
||||
|
||||
- name: Run Windows Avalonia smoke app
|
||||
if: ${{ matrix.rid == 'win-x64' || matrix.rid == 'win-x86' }}
|
||||
shell: pwsh
|
||||
run: |
|
||||
$ErrorActionPreference = "Stop"
|
||||
$publishDir = Join-Path $PWD "artifacts/smoke-${{ matrix.rid }}"
|
||||
$app = Join-Path $publishDir "AvaloniaStaticLinkSmoke.exe"
|
||||
$process = Start-Process -FilePath $app -WorkingDirectory $publishDir -PassThru
|
||||
if ($process.WaitForExit(15000)) {
|
||||
if ($process.ExitCode -eq 0) {
|
||||
Write-Host "Avalonia Windows smoke app exited normally."
|
||||
exit 0
|
||||
}
|
||||
throw "Avalonia Windows smoke app failed with exit code $($process.ExitCode)."
|
||||
}
|
||||
|
||||
Stop-Process -Id $process.Id -Force
|
||||
Write-Host "Avalonia Windows smoke app stayed alive for 15 seconds."
|
||||
|
||||
- name: Run Linux Avalonia smoke app
|
||||
if: ${{ startsWith(matrix.rid, 'linux-') && !startsWith(matrix.rid, 'linux-musl-') }}
|
||||
shell: bash
|
||||
run: |
|
||||
set +e
|
||||
cd "artifacts/smoke-${{ matrix.rid }}"
|
||||
chmod +x ./AvaloniaStaticLinkSmoke
|
||||
timeout 15s xvfb-run -a ./AvaloniaStaticLinkSmoke
|
||||
code=$?
|
||||
if [ "$code" = 124 ] || [ "$code" = 143 ]; then
|
||||
echo "Avalonia Linux smoke app stayed alive for 15 seconds."
|
||||
exit 0
|
||||
fi
|
||||
exit "$code"
|
||||
|
||||
- name: Verify musl ELF dependencies
|
||||
if: ${{ startsWith(matrix.rid, 'linux-musl-') }}
|
||||
shell: bash
|
||||
run: |
|
||||
set -euo pipefail
|
||||
docker run --rm \
|
||||
-v "${{ github.workspace }}:/workspace" \
|
||||
-w /workspace \
|
||||
alpine:3.23 \
|
||||
sh -c 'apk add --no-cache binutils pax-utils && app="artifacts/smoke-${{ matrix.rid }}/AvaloniaStaticLinkSmoke" && readelf -l "$app" | grep "Requesting program interpreter: /lib/ld-musl-" && scanelf -n "$app" && ! scanelf -n "$app" | grep -E "ld-linux|ld64.so"'
|
||||
|
||||
- name: Run Linux musl Avalonia smoke app
|
||||
if: ${{ startsWith(matrix.rid, 'linux-musl-') }}
|
||||
shell: bash
|
||||
run: |
|
||||
set -euo pipefail
|
||||
docker run --rm \
|
||||
-v "${{ github.workspace }}:/workspace" \
|
||||
-w /workspace/artifacts/smoke-${{ matrix.rid }} \
|
||||
alpine:3.23 \
|
||||
sh -c 'apk add --no-cache xvfb-run libstdc++ libgcc fontconfig freetype ttf-dejavu libx11 libxcb libxext libxrender libxi libxrandr libxcursor libxfixes libxinerama libice libsm mesa-gl mesa-egl && fc-cache -f && fc-match sans && chmod +x ./AvaloniaStaticLinkSmoke && timeout 15s xvfb-run -a ./AvaloniaStaticLinkSmoke || code=$?; if [ "${code:-0}" = 124 ] || [ "${code:-0}" = 143 ]; then echo "Avalonia musl smoke app stayed alive for 15 seconds."; exit 0; fi; exit "${code:-0}"'
|
||||
|
||||
- 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:
|
||||
name: avalonia-smoke-${{ matrix.rid }}
|
||||
path: artifacts/smoke-${{ matrix.rid }}/**
|
||||
if-no-files-found: error
|
||||
|
||||
publish-nuget:
|
||||
runs-on: ubuntu-24.04
|
||||
needs:
|
||||
- pack
|
||||
- smoke-avalonia
|
||||
steps:
|
||||
- name: Setup .NET
|
||||
uses: actions/setup-dotnet@v4
|
||||
with:
|
||||
dotnet-version: "10.0.302"
|
||||
|
||||
- name: Download NuGet package
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: staticlink-avalonia-nuget
|
||||
path: artifacts/nuget
|
||||
|
||||
- name: Publish to nuget.org
|
||||
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: |
|
||||
if [ -z "$NUGET_API_KEY" ]; then
|
||||
echo "NUGET_API_KEY secret is not configured. Skipping publish."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
for package in artifacts/nuget/*.nupkg; do
|
||||
dotnet nuget push "$package" \
|
||||
--source "https://api.nuget.org/v3/index.json" \
|
||||
--api-key "$NUGET_API_KEY" \
|
||||
--skip-duplicate
|
||||
done
|
||||
|
||||
release:
|
||||
runs-on: ubuntu-24.04
|
||||
needs:
|
||||
- preflight
|
||||
- pack
|
||||
- smoke-avalonia
|
||||
- publish-nuget
|
||||
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 NuGet artifact
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: staticlink-avalonia-nuget
|
||||
path: release-artifacts/staticlink-avalonia-nuget
|
||||
|
||||
- name: Download smoke artifacts
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
pattern: avalonia-smoke-*
|
||||
path: release-artifacts
|
||||
merge-multiple: false
|
||||
|
||||
- name: Prepare release files
|
||||
run: |
|
||||
mkdir -p 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")"
|
||||
(cd "$dir" && zip -r "../../release-files/$name.zip" .)
|
||||
done
|
||||
ls -la release-files
|
||||
|
||||
- name: Publish GitHub Release
|
||||
env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
PACKAGE_VERSION: ${{ needs.preflight.outputs.package_version }}
|
||||
run: |
|
||||
if [ "${GITHUB_REF_TYPE}" = "tag" ]; then
|
||||
release_tag="${GITHUB_REF_NAME}"
|
||||
title="${GITHUB_REF_NAME}"
|
||||
else
|
||||
release_tag="staticlink-avalonia-v${PACKAGE_VERSION}"
|
||||
title="StaticLink.Avalonia ${PACKAGE_VERSION}"
|
||||
fi
|
||||
|
||||
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/* \
|
||||
--target "$GITHUB_SHA" \
|
||||
--title "$title" \
|
||||
--notes "NuGet package plus Avalonia 11.3.14 NativeAOT single-file smoke apps for win-x64, win-x86, win-arm64, linux-x64, linux-arm64, linux-musl-x64, linux-musl-arm64, osx-x64, and osx-arm64."
|
||||
fi
|
||||
@@ -0,0 +1,64 @@
|
||||
name: static-graphics-linux
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
skiasharp_version:
|
||||
required: true
|
||||
type: string
|
||||
angle_branch:
|
||||
required: true
|
||||
type: string
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
skiasharp_version:
|
||||
required: true
|
||||
default: "3.119.4"
|
||||
type: string
|
||||
angle_branch:
|
||||
required: true
|
||||
default: "7922"
|
||||
type: string
|
||||
|
||||
jobs:
|
||||
build:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- rid: linux-x64
|
||||
target_cpu: x64
|
||||
runner: ubuntu-24.04
|
||||
- rid: linux-arm64
|
||||
target_cpu: arm64
|
||||
runner: ubuntu-24.04-arm
|
||||
runs-on: ${{ matrix.runner }}
|
||||
env:
|
||||
SKIASHARP_VERSION: ${{ inputs.skiasharp_version }}
|
||||
ANGLE_BRANCH: ${{ inputs.angle_branch }}
|
||||
RID: ${{ matrix.rid }}
|
||||
TARGET_CPU: ${{ matrix.target_cpu }}
|
||||
LLVM_AR: llvm-ar
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Restore native build cache
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: External/NativeStatic/.work
|
||||
key: native-work-linux-${{ matrix.rid }}-${{ inputs.skiasharp_version }}-${{ inputs.angle_branch }}-${{ hashFiles('External/NativeStatic/patches/*.patch', 'scripts/build-linux-static-graphics.sh') }}
|
||||
|
||||
- name: Install native build dependencies
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y clang lld llvm g++ ninja-build pkg-config libfontconfig1-dev libglib2.0-dev libgl1-mesa-dev libpci-dev libx11-dev libxcb1-dev libxext-dev
|
||||
|
||||
- name: Build Linux static graphics libraries
|
||||
run: scripts/build-linux-static-graphics.sh all
|
||||
|
||||
- name: Upload Linux static archives
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: native-static-${{ matrix.rid }}
|
||||
path: External/NativeStatic/${{ matrix.rid }}/*
|
||||
if-no-files-found: error
|
||||
@@ -0,0 +1,74 @@
|
||||
name: static-graphics-macos
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
skiasharp_version:
|
||||
required: true
|
||||
type: string
|
||||
angle_branch:
|
||||
required: true
|
||||
type: string
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
skiasharp_version:
|
||||
required: true
|
||||
default: "3.119.4"
|
||||
type: string
|
||||
angle_branch:
|
||||
required: true
|
||||
default: "7922"
|
||||
type: string
|
||||
|
||||
jobs:
|
||||
build:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- rid: osx-x64
|
||||
target_cpu: x64
|
||||
- rid: osx-arm64
|
||||
target_cpu: arm64
|
||||
runs-on: macos-15
|
||||
env:
|
||||
SKIASHARP_VERSION: ${{ inputs.skiasharp_version }}
|
||||
ANGLE_BRANCH: ${{ inputs.angle_branch }}
|
||||
RID: ${{ matrix.rid }}
|
||||
TARGET_CPU: ${{ matrix.target_cpu }}
|
||||
WORK_DIR: ${{ github.workspace }}/External/NativeStatic/.work
|
||||
OUTPUT_DIR: ${{ github.workspace }}/External/NativeStatic/${{ matrix.rid }}/native
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Restore native build cache
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: External/NativeStatic/.work
|
||||
key: native-work-macos-${{ matrix.rid }}-${{ inputs.skiasharp_version }}-${{ inputs.angle_branch }}-${{ hashFiles('External/NativeStatic/patches/*.patch', 'scripts/build-macos-static-graphics.sh') }}
|
||||
|
||||
- name: Install native build dependencies
|
||||
run: brew install ninja
|
||||
|
||||
- name: Install Xcode Metal toolchain
|
||||
run: |
|
||||
set -euo pipefail
|
||||
cat > /tmp/staticlink-metal-check.metal <<'EOF'
|
||||
#include <metal_stdlib>
|
||||
using namespace metal;
|
||||
kernel void staticlink_metal_check(device float* values [[buffer(0)]], uint id [[thread_position_in_grid]]) { values[id] = 0; }
|
||||
EOF
|
||||
if ! xcrun metal -c /tmp/staticlink-metal-check.metal -o /tmp/staticlink-metal-check.air >/dev/null 2>&1; then
|
||||
sudo xcodebuild -downloadComponent MetalToolchain
|
||||
fi
|
||||
xcrun metal -c /tmp/staticlink-metal-check.metal -o /tmp/staticlink-metal-check.air >/dev/null
|
||||
|
||||
- name: Build macOS static graphics libraries
|
||||
run: bash ./scripts/build-macos-static-graphics.sh all
|
||||
|
||||
- name: Upload macOS static archives
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: native-static-${{ matrix.rid }}
|
||||
path: External/NativeStatic/${{ matrix.rid }}/*
|
||||
if-no-files-found: error
|
||||
@@ -0,0 +1,92 @@
|
||||
name: static-graphics-musl
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
skiasharp_version:
|
||||
required: true
|
||||
type: string
|
||||
angle_branch:
|
||||
required: true
|
||||
type: string
|
||||
dotnet_alpine_image:
|
||||
required: true
|
||||
type: string
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
skiasharp_version:
|
||||
required: true
|
||||
default: "3.119.4"
|
||||
type: string
|
||||
angle_branch:
|
||||
required: true
|
||||
default: "7922"
|
||||
type: string
|
||||
dotnet_alpine_image:
|
||||
required: true
|
||||
default: mcr.microsoft.com/dotnet/sdk:10.0.302-alpine3.23
|
||||
type: string
|
||||
|
||||
jobs:
|
||||
build:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- rid: linux-musl-x64
|
||||
target_cpu: x64
|
||||
runner: ubuntu-24.04
|
||||
- rid: linux-musl-arm64
|
||||
target_cpu: arm64
|
||||
runner: ubuntu-24.04-arm
|
||||
runs-on: ${{ matrix.runner }}
|
||||
env:
|
||||
SKIASHARP_VERSION: ${{ inputs.skiasharp_version }}
|
||||
ANGLE_BRANCH: ${{ inputs.angle_branch }}
|
||||
DOTNET_ALPINE_IMAGE: ${{ inputs.dotnet_alpine_image }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Restore native build cache
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: External/NativeStatic/.work
|
||||
key: native-work-musl-${{ matrix.rid }}-${{ inputs.skiasharp_version }}-${{ inputs.angle_branch }}-${{ hashFiles('External/NativeStatic/patches/*.patch', 'scripts/build-linux-static-graphics.sh') }}
|
||||
|
||||
- name: Build Linux musl static graphics libraries
|
||||
run: |
|
||||
docker run --rm \
|
||||
-v "$PWD:/workspace" \
|
||||
-w /workspace \
|
||||
-e RID="${{ matrix.rid }}" \
|
||||
-e TARGET_CPU="${{ matrix.target_cpu }}" \
|
||||
-e OUTPUT_DIR="/workspace/External/NativeStatic/${{ matrix.rid }}/native" \
|
||||
-e SKIASHARP_VERSION="$SKIASHARP_VERSION" \
|
||||
-e ANGLE_BRANCH="$ANGLE_BRANCH" \
|
||||
-e LLVM_AR=llvm-ar \
|
||||
-e DEPOT_TOOLS_BOOTSTRAP_PYTHON3=0 \
|
||||
-e VPYTHON_BYPASS="manually managed python not supported by chrome operations" \
|
||||
"$DOTNET_ALPINE_IMAGE" \
|
||||
sh -lc '
|
||||
set -e
|
||||
apk add --no-cache bash ca-certificates git python3 py3-httplib2 py3-pysocks py3-six clang compiler-rt lld llvm g++ ninja pkgconf fontconfig-dev glib-dev mesa-dev libx11-dev libxcb-dev libxext-dev pciutils-dev linux-headers perl curl tar xz patch gcompat libc6-compat
|
||||
python3 - <<'"'"'PY'"'"'
|
||||
import pathlib
|
||||
import httplib2
|
||||
|
||||
path = pathlib.Path(httplib2.__file__).with_name("socks.py")
|
||||
if not path.exists():
|
||||
path.write_text("from socks import *\n")
|
||||
PY
|
||||
bash scripts/build-linux-static-graphics.sh all
|
||||
'
|
||||
|
||||
- name: Normalize native build cache ownership
|
||||
run: sudo chown -R "$(id -u):$(id -g)" External/NativeStatic/.work
|
||||
|
||||
- name: Upload Linux musl static archives
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: native-static-${{ matrix.rid }}
|
||||
path: External/NativeStatic/${{ matrix.rid }}/*
|
||||
if-no-files-found: error
|
||||
@@ -0,0 +1,81 @@
|
||||
name: static-graphics-preflight
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
outputs:
|
||||
package_version:
|
||||
value: ${{ jobs.validate.outputs.package_version }}
|
||||
skiasharp_version:
|
||||
value: ${{ jobs.validate.outputs.skiasharp_version }}
|
||||
angle_branch:
|
||||
value: ${{ jobs.validate.outputs.angle_branch }}
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
validate:
|
||||
runs-on: ubuntu-24.04
|
||||
outputs:
|
||||
package_version: ${{ steps.versions.outputs.package_version }}
|
||||
skiasharp_version: ${{ steps.versions.outputs.skiasharp_version }}
|
||||
angle_branch: ${{ steps.versions.outputs.angle_branch }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Setup .NET
|
||||
uses: actions/setup-dotnet@v4
|
||||
with:
|
||||
dotnet-version: "10.0.302"
|
||||
|
||||
- name: Read and validate versions
|
||||
id: versions
|
||||
shell: bash
|
||||
run: |
|
||||
python3 - <<'PY'
|
||||
import os
|
||||
import pathlib
|
||||
import xml.etree.ElementTree as ET
|
||||
|
||||
project = pathlib.Path("NuGet/StaticGraphics/StaticLink.Avalonia.csproj")
|
||||
root = ET.parse(project).getroot()
|
||||
package_version = root.findtext(".//Version")
|
||||
skia_reference = next(
|
||||
item.attrib["Version"]
|
||||
for item in root.findall(".//PackageReference")
|
||||
if item.attrib.get("Include") == "SkiaSharp"
|
||||
)
|
||||
version_base, revision = package_version.rsplit(".", 1)
|
||||
skiasharp_version, angle_branch = version_base.split("-", 1)
|
||||
if not revision.isdigit() or skiasharp_version != skia_reference:
|
||||
raise SystemExit(f"Inconsistent package version: {package_version}, SkiaSharp: {skia_reference}")
|
||||
if os.environ.get("GITHUB_REF_TYPE") == "tag":
|
||||
expected_tag = f"staticlink-avalonia-v{package_version}"
|
||||
if os.environ.get("GITHUB_REF_NAME") != expected_tag:
|
||||
raise SystemExit(f"Release tag must be {expected_tag}")
|
||||
|
||||
with open(os.environ["GITHUB_OUTPUT"], "a", encoding="utf-8") as output:
|
||||
output.write(f"package_version={package_version}\n")
|
||||
output.write(f"skiasharp_version={skiasharp_version}\n")
|
||||
output.write(f"angle_branch={angle_branch}\n")
|
||||
PY
|
||||
|
||||
- name: Validate upstream refs and ANGLE patch
|
||||
env:
|
||||
SKIASHARP_VERSION: ${{ steps.versions.outputs.skiasharp_version }}
|
||||
ANGLE_BRANCH: ${{ steps.versions.outputs.angle_branch }}
|
||||
shell: bash
|
||||
run: |
|
||||
set -euo pipefail
|
||||
git ls-remote --exit-code --heads https://github.com/mono/SkiaSharp.git "refs/heads/release/${SKIASHARP_VERSION}"
|
||||
git clone --depth 1 --branch "chromium/${ANGLE_BRANCH}" https://github.com/google/angle.git /tmp/staticlink-angle
|
||||
git -C /tmp/staticlink-angle apply --check "$GITHUB_WORKSPACE/External/NativeStatic/patches/angle-chromium-${ANGLE_BRANCH}.patch"
|
||||
|
||||
- name: Validate scripts
|
||||
shell: bash
|
||||
run: |
|
||||
set -euo pipefail
|
||||
bash -n scripts/build-linux-static-graphics.sh
|
||||
bash -n scripts/build-macos-static-graphics.sh
|
||||
pwsh -NoProfile -Command '$files = @("scripts/build-windows-static-graphics.ps1", "scripts/create-avalonia-smoke.ps1"); foreach ($file in $files) { $errors = $null; [System.Management.Automation.Language.Parser]::ParseFile((Resolve-Path $file), [ref]$null, [ref]$errors) | Out-Null; if ($errors.Count) { $errors | Format-List | Out-String; exit 1 } }'
|
||||
|
||||
- name: Compile smoke project
|
||||
run: dotnet build Smoke/AvaloniaStaticLinkSmoke/AvaloniaStaticLinkSmoke.csproj -c Release -p:PublishAot=false
|
||||
@@ -0,0 +1,92 @@
|
||||
name: static-graphics-windows
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
skiasharp_version:
|
||||
required: true
|
||||
type: string
|
||||
angle_branch:
|
||||
required: true
|
||||
type: string
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
skiasharp_version:
|
||||
required: true
|
||||
default: "3.119.4"
|
||||
type: string
|
||||
angle_branch:
|
||||
required: true
|
||||
default: "7922"
|
||||
type: string
|
||||
|
||||
jobs:
|
||||
build:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- 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
|
||||
runs-on: windows-2022
|
||||
env:
|
||||
SKIASHARP_VERSION: ${{ inputs.skiasharp_version }}
|
||||
ANGLE_BRANCH: ${{ inputs.angle_branch }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Restore native build cache
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: External/NativeStatic/.work
|
||||
key: native-work-windows-${{ matrix.rid }}-${{ inputs.skiasharp_version }}-${{ inputs.angle_branch }}-${{ hashFiles('External/NativeStatic/patches/*.patch', 'scripts/build-windows-static-graphics.ps1') }}
|
||||
|
||||
- name: Setup MSVC environment
|
||||
uses: ilammy/msvc-dev-cmd@v1
|
||||
with:
|
||||
arch: ${{ matrix.msvc_arch }}
|
||||
|
||||
- name: Configure Chromium Visual Studio environment
|
||||
shell: pwsh
|
||||
run: |
|
||||
"DEPOT_TOOLS_WIN_TOOLCHAIN=0" >> $env:GITHUB_ENV
|
||||
"GYP_MSVS_VERSION=17.0" >> $env:GITHUB_ENV
|
||||
"GYP_MSVS_OVERRIDE_PATH=$($env:VSINSTALLDIR.TrimEnd('\', '/'))" >> $env:GITHUB_ENV
|
||||
|
||||
- name: Install native build dependencies
|
||||
shell: pwsh
|
||||
run: |
|
||||
git config --global core.longpaths true
|
||||
choco install ninja llvm -y
|
||||
|
||||
- name: Validate Windows ANGLE inputs
|
||||
shell: pwsh
|
||||
env:
|
||||
RID: ${{ matrix.rid }}
|
||||
TARGET_CPU: ${{ matrix.target_cpu }}
|
||||
DEPOT_TOOLS_WIN_TOOLCHAIN: 0
|
||||
GYP_MSVS_VERSION: 17.0
|
||||
run: .\scripts\build-windows-static-graphics.ps1 angle-preflight
|
||||
|
||||
- name: Build Windows static graphics libraries
|
||||
shell: pwsh
|
||||
env:
|
||||
RID: ${{ matrix.rid }}
|
||||
TARGET_CPU: ${{ matrix.target_cpu }}
|
||||
DEPOT_TOOLS_WIN_TOOLCHAIN: 0
|
||||
GYP_MSVS_VERSION: 17.0
|
||||
run: .\scripts\build-windows-static-graphics.ps1 all
|
||||
|
||||
- name: Upload Windows static archives
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: native-static-${{ matrix.rid }}
|
||||
path: External/NativeStatic/${{ matrix.rid }}/*
|
||||
if-no-files-found: error
|
||||
@@ -1,78 +0,0 @@
|
||||
name: pinned-zig-toolchain-image
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
validation_rids:
|
||||
type: string
|
||||
default: '[]'
|
||||
outputs:
|
||||
image:
|
||||
description: Immutable Debian 12 Zig toolchain image reference
|
||||
value: ${{ jobs.image.outputs.image }}
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
packages: write
|
||||
|
||||
jobs:
|
||||
image:
|
||||
runs-on: ubuntu-24.04
|
||||
timeout-minutes: 60
|
||||
outputs:
|
||||
image: ${{ steps.publish.outputs.image }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Publish or reuse exact toolchain image
|
||||
id: publish
|
||||
env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
ACTOR: ${{ github.actor }}
|
||||
REPOSITORY: ${{ github.repository }}
|
||||
VALIDATION_RIDS: ${{ inputs.validation_rids || '[]' }}
|
||||
BASE_HASH: ${{ hashFiles('build/linux-toolchain/Dockerfile') }}
|
||||
RECIPE_HASH: ${{ hashFiles('build/linux-toolchain/Dockerfile*', 'build/linux-toolchain/*.py', 'build/linux-toolchain/*.c', 'build/linux-toolchain/*.gn.in', 'build/linux-toolchain/*lock.json', 'build/linux-toolchain/versions/*.json', 'build/linux-toolchain/patches/**') }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
printf '%s' "$GH_TOKEN" | docker login ghcr.io -u "$ACTOR" --password-stdin
|
||||
repository="ghcr.io/${REPOSITORY,,}-zig"
|
||||
image="$repository:recipe-$RECIPE_HASH"
|
||||
base="$repository:debian12-$BASE_HASH"
|
||||
built_image=false
|
||||
if ! docker pull "$image"; then
|
||||
if ! docker pull "$base"; then
|
||||
docker build --platform linux/amd64 \
|
||||
--label "org.opencontainers.image.source=https://github.com/$REPOSITORY" \
|
||||
-t "$base" build/linux-toolchain
|
||||
docker push "$base"
|
||||
docker pull "$base"
|
||||
fi
|
||||
base_digest="$(docker image inspect --format '{{index .RepoDigests 0}}' "$base")"
|
||||
docker build --platform linux/amd64 \
|
||||
--build-arg "TOOLCHAIN_IMAGE=$base_digest" \
|
||||
--label "org.opencontainers.image.source=https://github.com/$REPOSITORY" \
|
||||
-f build/linux-toolchain/Dockerfile.cross-probe \
|
||||
-t "$image" build/linux-toolchain
|
||||
built_image=true
|
||||
fi
|
||||
mkdir -p artifacts/toolchain-environment
|
||||
docker run --rm --user "$(id -u):$(id -g)" \
|
||||
-e HOME=/tmp -e DOTNET_CLI_HOME=/tmp -e ZIG_GLOBAL_CACHE_DIR=/tmp/zig-cache \
|
||||
-v "$PWD/artifacts/toolchain-environment:/validation" \
|
||||
--entrypoint python3 "$image" /opt/staticlink/validate-toolchain.py --output /validation --rids "$VALIDATION_RIDS"
|
||||
if [ "$built_image" = true ]; then
|
||||
docker push "$image"
|
||||
docker pull "$image"
|
||||
fi
|
||||
digest="$(docker image inspect --format '{{index .RepoDigests 0}}' "$image")"
|
||||
case "$digest" in "$repository"@sha256:*) ;; *) echo 'No immutable image digest' >&2; exit 1 ;; esac
|
||||
echo "image=$digest" >> "$GITHUB_OUTPUT"
|
||||
echo "Toolchain: $digest" >> "$GITHUB_STEP_SUMMARY"
|
||||
- name: Upload environment validation report
|
||||
if: ${{ always() }}
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: toolchain-environment-validation
|
||||
path: artifacts/toolchain-environment/
|
||||
if-no-files-found: warn
|
||||
@@ -1,38 +0,0 @@
|
||||
# Manual artifact validation
|
||||
|
||||
Daily schedules are disabled during validation. No NuGet.org publication or
|
||||
GitHub Release is requested by the manual dispatcher on main.
|
||||
|
||||
Before release builds, run nuget-static-graphics.yml on skia4 with
|
||||
environment_only=true. This checks the actual container's Python/depot_tools,
|
||||
.NET 8/10, SDKs, sysroots, and C/C++ compilation plus C executable linking for
|
||||
all nine RIDs. Download toolchain-environment-validation to inspect the report.
|
||||
The same environment gate runs before every graphics and native build and
|
||||
must pass before the toolchain image is published for release compilation.
|
||||
|
||||
- skia3: nuget-static-graphics.yml; latest stable SkiaSharp 3.
|
||||
- skia4: nuget-static-graphics.yml; latest stable SkiaSharp 4.
|
||||
- avalonia-native: nuget-avalonia-native.yml; latest stable Avalonia 11 and 12.
|
||||
|
||||
Download staticlink-avalonia-nuget and avalonia-smoke-<RID> from each graphics run.
|
||||
Download staticlink-avalonia-native-<version> and
|
||||
avalonia-native-smoke-<AvaloniaVersion>-<RID> from the native run.
|
||||
Native archives and source locks are also retained as Actions artifacts.
|
||||
|
||||
Graphics macOS smoke tests use the already published AvaloniaNative revision 1
|
||||
by default, so the graphics builds do not require the experimental native
|
||||
revision 2 to be published. The native branch validates its own local revision 2
|
||||
package separately. To test both experimental packages together, put both
|
||||
downloaded packages in a local NuGet feed and reference their exact versions.
|
||||
|
||||
Smoke executables are retained even if a later runtime validation fails.
|
||||
An artifact is not evidence that all validation gates passed; check job results.
|
||||
|
||||
The daily-native-release workflow on main currently supports manual dispatch
|
||||
only. Its three matrix jobs check out their own branch and dispatch independently.
|
||||
Use force_build=true to rebuild published versions for testing.
|
||||
After validation, enable the schedule on main only; non-default branches cannot
|
||||
run their own GitHub cron schedules. Publication remains an explicit opt-in.
|
||||
While publication is disabled, an unpublished package may be rebuilt on every
|
||||
check; add successful-run tracking before enabling artifact-only daily builds
|
||||
if avoiding repeated builds is required.
|
||||
@@ -1,9 +0,0 @@
|
||||
# Daily releases (not enabled)
|
||||
|
||||
This branch currently runs manual artifact validation only. The independent
|
||||
three-branch dispatcher is on main and has no schedule yet. NuGet.org and
|
||||
GitHub Release publication are disabled for the initial runs.
|
||||
|
||||
See [ACTION-TESTING.md](ACTION-TESTING.md) for artifact names, the macOS native
|
||||
package used by graphics smoke tests, and the steps required before daily
|
||||
builds are enabled.
|
||||
@@ -19,8 +19,6 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Include="../../External/AvaloniaNative/osx-x64/native/avalonia-native-build.json" Pack="true" PackagePath="buildMetadata/osx-x64.json" />
|
||||
<None Include="../../External/AvaloniaNative/osx-arm64/native/avalonia-native-build.json" Pack="true" PackagePath="buildMetadata/osx-arm64.json" />
|
||||
<None Include="README.md" Pack="true" PackagePath="README.md" />
|
||||
<None Include="lib/net8.0/_._" Pack="true" PackagePath="lib/net8.0/_._" />
|
||||
<None Include="buildTransitive/StaticLink.Avalonia.Native.props" Pack="true" PackagePath="buildTransitive/$(PackageId).props" />
|
||||
|
||||
@@ -4,48 +4,32 @@ Static native libraries for Avalonia single-file NativeAOT publishing.
|
||||
|
||||
## Install
|
||||
|
||||
Choose the static graphics package that matches the Avalonia and SkiaSharp major versions used by your application.
|
||||
|
||||
| Avalonia version | SkiaSharp version | `StaticLink.Avalonia` version |
|
||||
| --- | --- | --- |
|
||||
| 11 | 2.88.9 | `2.88.9-7151.10` |
|
||||
| 11 | 3.119.4 | `3.119.4-7922.1` |
|
||||
| 12 | 3.119.4 | `3.119.4-7922.1` |
|
||||
| 12 | 4.150.1 | `4.150.1-7922.1` |
|
||||
|
||||
Example:
|
||||
```xml
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Avalonia" Version="12.1.0" />
|
||||
<PackageReference Include="StaticLink.Avalonia" Version="4.150.1-7922.1" />
|
||||
</ItemGroup>
|
||||
```bash
|
||||
dotnet add package StaticLink.Avalonia
|
||||
```
|
||||
|
||||
### macOS
|
||||
Or add it manually:
|
||||
|
||||
For macOS, also reference `StaticLink.Avalonia.Native`. This package contains `libAvaloniaNative.a`, so its version must match the Avalonia version used by the application.
|
||||
```xml
|
||||
<PackageReference Include="StaticLink.Avalonia" Version="3.119.4-7922.1" />
|
||||
```
|
||||
|
||||
For macOS, also reference `StaticLink.Avalonia.Native`. This package is macOS-only and must match your Avalonia version because it contains `libAvaloniaNative.a`.
|
||||
|
||||
```xml
|
||||
<!-- Avalonia 11.3.14 -->
|
||||
<PackageReference Include="StaticLink.Avalonia.Native" Version="11.3.14.1" />
|
||||
|
||||
<!-- Avalonia 12.1.0 -->
|
||||
<PackageReference Include="StaticLink.Avalonia.Native" Version="12.1.0.1" />
|
||||
```
|
||||
|
||||
Add only the `StaticLink.Avalonia.Native` reference matching your Avalonia version.
|
||||
|
||||
On macOS, only Avalonia 12 with skia3/4 supports Metal. Avalonia 11 fully static apps must use OpenGL or Software because its Metal path dynamically loads `libSkiaSharp`.
|
||||
|
||||
## Publish
|
||||
|
||||
```bash
|
||||
dotnet publish -c Release -r win-x64 -p:PublishAot=true
|
||||
dotnet publish -c Release -r win-x64 \
|
||||
-p:PublishAot=true \
|
||||
-p:SelfContained=true \
|
||||
-p:PublishSingleFile=true \
|
||||
-p:StripSymbols=true
|
||||
```
|
||||
|
||||
Use the RID you need, such as `win-x86`, `linux-x64`, `linux-arm64`, `osx-arm64`, or `osx-x64`.
|
||||
|
||||
|
||||
## Native Package Automation
|
||||
|
||||
`.github/workflows/nuget-avalonia-native.yml` runs daily and checks the latest stable `Avalonia` version on NuGet.org. If `StaticLink.Avalonia.Native.<AvaloniaVersion>.1` does not exist, it builds both macOS architectures from the matching Avalonia source tag, runs NativeAOT smoke tests, and publishes the package with NuGet Trusted Publishing.
|
||||
For macOS, avoid the Metal renderer for fully static output. Use OpenGL or Software.
|
||||
@@ -6,7 +6,7 @@
|
||||
<IncludeBuildOutput>false</IncludeBuildOutput>
|
||||
<SuppressDependenciesWhenPacking>false</SuppressDependenciesWhenPacking>
|
||||
<PackageId>StaticLink.Avalonia</PackageId>
|
||||
<Version>4.150.1-7922.2</Version>
|
||||
<Version>3.119.4-7922.1</Version>
|
||||
<Authors>greepar</Authors>
|
||||
<Company>greepar</Company>
|
||||
<Description>Static SkiaSharp, HarfBuzzSharp, and ANGLE libraries for Avalonia NativeAOT single-file publishing.</Description>
|
||||
@@ -19,12 +19,11 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="SkiaSharp" Version="4.150.1" />
|
||||
<PackageReference Include="SkiaSharp" Version="3.119.4" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Include="README.md" Pack="true" PackagePath="" />
|
||||
<None Include="../../build/linux-toolchain/release.lock.json" Condition="Exists('../../build/linux-toolchain/release.lock.json')" Pack="true" PackagePath="buildMetadata/sources.lock.json" />
|
||||
<None Include="lib/net8.0/_._" Pack="true" PackagePath="lib/net8.0/_._" />
|
||||
<None Include="buildTransitive/StaticLink.Avalonia.props" Pack="true" PackagePath="buildTransitive/$(PackageId).props" />
|
||||
<None Include="buildTransitive/StaticLink.Avalonia.targets" Pack="true" PackagePath="buildTransitive/$(PackageId).targets" />
|
||||
|
||||
@@ -163,19 +163,4 @@
|
||||
</ItemGroup>
|
||||
<Delete Files="@(_StaticLinkAvaloniaFilesToDelete)" TreatErrorsAsWarnings="true" />
|
||||
</Target>
|
||||
<Target Name="StaticLinkAvaloniaAddZigRuntime"
|
||||
BeforeTargets="LinkNative"
|
||||
Condition="'$(PublishAot)' == 'true' and Exists('$(_StaticLinkAvaloniaNativeRoot)/zig-build.json')">
|
||||
<PropertyGroup Condition="$(RuntimeIdentifier.StartsWith('win-'))">
|
||||
<CppLinker>lld-link</CppLinker>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<NativeLibrary Include="$(_StaticLinkAvaloniaNativeRoot)/zig-runtime/*.lib" Condition="$(RuntimeIdentifier.StartsWith('win-'))" />
|
||||
<NativeLibrary Include="$(_StaticLinkAvaloniaNativeRoot)/zig-runtime/*.a" Condition="!$(RuntimeIdentifier.StartsWith('win-'))" />
|
||||
<NativeLibrary Include="$(_StaticLinkAvaloniaNativeRoot)/libEGL_static.lib" Condition="Exists('$(_StaticLinkAvaloniaNativeRoot)/libEGL_static.lib')" />
|
||||
<NativeLibrary Include="$(_StaticLinkAvaloniaNativeRoot)/libEGL_static.a" Condition="Exists('$(_StaticLinkAvaloniaNativeRoot)/libEGL_static.a')" />
|
||||
<NativeSystemLibrary Include="X11;Xext;xcb;wayland-client;wayland-egl;ffi" Condition="$(RuntimeIdentifier.StartsWith('linux-'))" />
|
||||
<LinkerArg Include="/lldmingw" Condition="$(RuntimeIdentifier.StartsWith('win-'))" />
|
||||
</ItemGroup>
|
||||
</Target>
|
||||
</Project>
|
||||
@@ -1,53 +1,62 @@
|
||||
> 3/4 分支构建更新:原生图形库与 macOS AvaloniaNative 已统一为 Linux 上的 Zig 入口;Windows/macOS runner 用于消费者运行验收。配置与真实编译的验证范围见 [CROSS-COMPILE.md](build/linux-toolchain/CROSS-COMPILE.md),每日发布说明见 [DAILY-RELEASE.md](DAILY-RELEASE.md)。完整九平台回归与 Docker 镜像尚待 Action 实跑,不能视为已全部通过。
|
||||
|
||||
# StaticLink.Avalonia
|
||||
|
||||
Static native libraries for Avalonia single-file NativeAOT publishing.
|
||||
|
||||
## Install
|
||||
|
||||
Choose the static graphics package that matches the Avalonia and SkiaSharp major versions used by your application.
|
||||
|
||||
| Avalonia version | SkiaSharp version | `StaticLink.Avalonia` version |
|
||||
| --- | --- | --- |
|
||||
| 11 | 2.88.9 | `2.88.9-7151.10` |
|
||||
| 11 | 3.119.4 | `3.119.4-7922.1` |
|
||||
| 12 | 3.119.4 | `3.119.4-7922.1` |
|
||||
| 12 | 4.150.1 | `4.150.1-7922.1` |
|
||||
|
||||
Example:
|
||||
```xml
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Avalonia" Version="12.1.0" />
|
||||
<PackageReference Include="StaticLink.Avalonia" Version="4.150.1-7922.1" />
|
||||
</ItemGroup>
|
||||
```bash
|
||||
dotnet add package StaticLink.Avalonia
|
||||
```
|
||||
|
||||
### macOS
|
||||
Or add it manually:
|
||||
|
||||
For macOS, also reference `StaticLink.Avalonia.Native`. This package contains `libAvaloniaNative.a`, so its version must match the Avalonia version used by the application.
|
||||
```xml
|
||||
<PackageReference Include="StaticLink.Avalonia" Version="3.119.4-7922.1" />
|
||||
```
|
||||
|
||||
`3.119.4-7922.1` supports Avalonia 11. If you need the SkiaSharp 2 line for an Avalonia 11 project, use this optional package variant:
|
||||
|
||||
```xml
|
||||
<PackageReference Include="StaticLink.Avalonia" Version="2.88.9-7151.10" />
|
||||
```
|
||||
|
||||
`2.88.9-7151.10` is only for Avalonia 11 projects that specifically want SkiaSharp 2.
|
||||
|
||||
For macOS, also reference `StaticLink.Avalonia.Native`. This package is macOS-only and must match your Avalonia version because it contains `libAvaloniaNative.a`.
|
||||
|
||||
```xml
|
||||
<!-- Avalonia 11.3.14 -->
|
||||
<PackageReference Include="StaticLink.Avalonia.Native" Version="11.3.14.1" />
|
||||
|
||||
<!-- Avalonia 12.1.0 -->
|
||||
<PackageReference Include="StaticLink.Avalonia.Native" Version="12.1.0.1" />
|
||||
```
|
||||
|
||||
Add only the `StaticLink.Avalonia.Native` reference matching your Avalonia version.
|
||||
|
||||
On macOS, only Avalonia 12 with skia3/4 supports Metal. Avalonia 11 fully static apps must use OpenGL or Software because its Metal path dynamically loads `libSkiaSharp`.
|
||||
|
||||
## Publish
|
||||
|
||||
```bash
|
||||
dotnet publish -c Release -r win-x64 -p:PublishAot=true
|
||||
dotnet publish -c Release -r win-x64 \
|
||||
-p:PublishAot=true \
|
||||
-p:SelfContained=true \
|
||||
-p:PublishSingleFile=true \
|
||||
-p:StripSymbols=true
|
||||
```
|
||||
|
||||
Use the RID you need, such as `win-x86`, `linux-x64`, `linux-arm64`, `osx-arm64`, or `osx-x64`.
|
||||
|
||||
For macOS, avoid the Metal renderer for fully static output. Use OpenGL or Software.
|
||||
|
||||
## Native Package Automation
|
||||
|
||||
`.github/workflows/nuget-avalonia-native.yml` runs daily and checks the latest stable `Avalonia` version on NuGet.org. If `StaticLink.Avalonia.Native.<AvaloniaVersion>.1` does not exist, it builds both macOS architectures from the matching Avalonia source tag, runs NativeAOT smoke tests, and publishes the package with NuGet Trusted Publishing.
|
||||
|
||||
Configure NuGet.org Trusted Publishing for this repository and the `nuget-avalonia-native.yml` workflow, then add the NuGet.org account name as the repository variable `NUGET_USER`. No long-lived NuGet API key is used by this workflow.
|
||||
|
||||
## Static Graphics Automation
|
||||
|
||||
`.github/workflows/nuget-static-graphics.yml` runs a fast version, upstream-ref, patch, script, and smoke-project preflight before starting native builds. It then calls independent Windows, Linux, Linux musl, and macOS workflows, packs their artifacts, runs all NativeAOT smoke tests, and only then publishes NuGet and GitHub Release assets.
|
||||
|
||||
The platform workflows can also be dispatched independently when diagnosing a single platform:
|
||||
|
||||
- `static-graphics-windows.yml`
|
||||
- `static-graphics-linux.yml`
|
||||
- `static-graphics-musl.yml`
|
||||
- `static-graphics-macos.yml`
|
||||
|
||||
The release workflow derives the SkiaSharp version and ANGLE branch from `NuGet/StaticGraphics/StaticLink.Avalonia.csproj`. Native source and build directories are cached by platform, RID, version, patch, and build script.
|
||||
@@ -1,7 +1,6 @@
|
||||
using Avalonia;
|
||||
using Avalonia.Controls.ApplicationLifetimes;
|
||||
using Avalonia.Markup.Xaml;
|
||||
using Avalonia.Threading;
|
||||
|
||||
namespace AvaloniaStaticLinkSmoke;
|
||||
|
||||
@@ -16,28 +15,7 @@ public sealed partial class App : Application
|
||||
{
|
||||
if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
|
||||
{
|
||||
var renderer = Environment.GetEnvironmentVariable("STATICLINK_MAC_RENDERER") ?? "opengl";
|
||||
var autoClose = Environment.GetEnvironmentVariable("STATICLINK_SMOKE_AUTOCLOSE") == "1";
|
||||
desktop.MainWindow = new MainWindow(autoClose ? CompleteSmoke : null);
|
||||
|
||||
void CompleteSmoke(string backend)
|
||||
{
|
||||
Dispatcher.UIThread.Post(() =>
|
||||
{
|
||||
if (!renderer.Equals("metal", StringComparison.OrdinalIgnoreCase) ||
|
||||
backend.Equals("Metal", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
Console.WriteLine($"STATICLINK_SMOKE_READY={renderer}");
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.Error.WriteLine($"Expected the Metal renderer, but the active Skia backend was {backend}.");
|
||||
Environment.ExitCode = 1;
|
||||
}
|
||||
|
||||
desktop.MainWindow?.Close();
|
||||
});
|
||||
}
|
||||
desktop.MainWindow = new MainWindow();
|
||||
}
|
||||
|
||||
base.OnFrameworkInitializationCompleted();
|
||||
|
||||
@@ -1,60 +1,11 @@
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Media;
|
||||
using Avalonia.Rendering.SceneGraph;
|
||||
using Avalonia.Skia;
|
||||
|
||||
namespace AvaloniaStaticLinkSmoke;
|
||||
|
||||
public sealed partial class MainWindow : Window
|
||||
{
|
||||
private readonly Action<string>? _renderResult;
|
||||
private int _renderResultReported;
|
||||
|
||||
public MainWindow() : this(null)
|
||||
public MainWindow()
|
||||
{
|
||||
}
|
||||
|
||||
public MainWindow(Action<string>? renderResult)
|
||||
{
|
||||
_renderResult = renderResult;
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
public override void Render(DrawingContext context)
|
||||
{
|
||||
base.Render(context);
|
||||
if (_renderResult is not null)
|
||||
{
|
||||
context.Custom(new MetalBackendProbe(new Rect(Bounds.Size), ReportMetalResult));
|
||||
}
|
||||
}
|
||||
|
||||
private void ReportMetalResult(string backend)
|
||||
{
|
||||
if (Interlocked.Exchange(ref _renderResultReported, 1) == 0)
|
||||
{
|
||||
_renderResult?.Invoke(backend);
|
||||
}
|
||||
}
|
||||
|
||||
private sealed class MetalBackendProbe(Rect bounds, Action<string> report) : ICustomDrawOperation
|
||||
{
|
||||
public Rect Bounds { get; } = bounds;
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
}
|
||||
|
||||
public bool Equals(ICustomDrawOperation? other) => false;
|
||||
|
||||
public bool HitTest(Point point) => false;
|
||||
|
||||
public void Render(ImmediateDrawingContext context)
|
||||
{
|
||||
var feature = context.TryGetFeature(typeof(ISkiaSharpApiLeaseFeature)) as ISkiaSharpApiLeaseFeature;
|
||||
using var lease = feature?.Lease();
|
||||
report(lease?.GrContext?.Backend.ToString() ?? "Software");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -38,18 +38,16 @@ internal static class Program
|
||||
}
|
||||
|
||||
if (OperatingSystem.IsMacOS())
|
||||
{
|
||||
var renderer = Environment.GetEnvironmentVariable("STATICLINK_MAC_RENDERER");
|
||||
if (!string.Equals(renderer, "default", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
builder = builder.With(new AvaloniaNativePlatformOptions
|
||||
{
|
||||
RenderingMode = string.Equals(renderer, "metal", StringComparison.OrdinalIgnoreCase)
|
||||
? [AvaloniaNativeRenderingMode.Metal]
|
||||
: [AvaloniaNativeRenderingMode.OpenGl, AvaloniaNativeRenderingMode.Software]
|
||||
RenderingMode =
|
||||
[
|
||||
AvaloniaNativeRenderingMode.OpenGl,
|
||||
AvaloniaNativeRenderingMode.Software
|
||||
]
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return builder;
|
||||
}
|
||||
|
||||
@@ -1,72 +0,0 @@
|
||||
{
|
||||
"checked_at_utc": "2026-10-04",
|
||||
"live_plan": [
|
||||
{
|
||||
"ref": "4.150.1-7922.1",
|
||||
"skiasharp_version": "4.153.1",
|
||||
"package_version": "4.153.1-7922.1"
|
||||
}
|
||||
],
|
||||
"source_lock_checks": {
|
||||
"3.119.2": {
|
||||
"skiasharp_version": "3.119.2",
|
||||
"skiasharp_revision": "2888c737ad016d584c74525e2d35db5097ea8576",
|
||||
"angle_branch": "7922",
|
||||
"angle_revision": "7e08726e32026a0bbabd6ec8a1a90f5ab533ed66",
|
||||
"skia_revision": "927041a58f130e0dd0562ba86cb4170989ad39e9"
|
||||
},
|
||||
"3.119.4": {
|
||||
"skiasharp_version": "3.119.4",
|
||||
"skiasharp_revision": "f568ac94dd768ef9a2f593537cfde2dd0d348ef5",
|
||||
"angle_branch": "7922",
|
||||
"angle_revision": "7e08726e32026a0bbabd6ec8a1a90f5ab533ed66",
|
||||
"skia_revision": "7dbfc07dd33181f84e0958afb7ee805c6c769f0b"
|
||||
},
|
||||
"4.150.2": {
|
||||
"skiasharp_version": "4.150.2",
|
||||
"skiasharp_revision": "fd1fdd5239f826514651a4ada5d7bb3dcec2fb43",
|
||||
"angle_branch": "7922",
|
||||
"angle_revision": "7e08726e32026a0bbabd6ec8a1a90f5ab533ed66",
|
||||
"skia_revision": "b70519562e2d26d3cf56286d3a13ca25152cfae4"
|
||||
},
|
||||
"4.150.3": {
|
||||
"skiasharp_version": "4.150.3",
|
||||
"skiasharp_revision": "f8a404ff3375872d042404a29189ceb8e3001a41",
|
||||
"angle_branch": "7922",
|
||||
"angle_revision": "7e08726e32026a0bbabd6ec8a1a90f5ab533ed66",
|
||||
"skia_revision": "eb86e4b3ee034085b62d3980b3d94629862441e6"
|
||||
},
|
||||
"4.150.5": {
|
||||
"skiasharp_version": "4.150.5",
|
||||
"skiasharp_revision": "16f82682f756217654eb1a152cdb639e358b8976",
|
||||
"angle_branch": "7922",
|
||||
"angle_revision": "7e08726e32026a0bbabd6ec8a1a90f5ab533ed66",
|
||||
"skia_revision": "579fa81eeed6906732e27b7d95149538584dd20b"
|
||||
},
|
||||
"4.153.1": {
|
||||
"skiasharp_version": "4.153.1",
|
||||
"skiasharp_revision": "4783f51448f9b070dda4f87b83e941c9599e466e",
|
||||
"angle_branch": "7922",
|
||||
"angle_revision": "7e08726e32026a0bbabd6ec8a1a90f5ab533ed66",
|
||||
"skia_revision": "45afab4f1f0921f3feb97f58cf89b136fffa85e6"
|
||||
}
|
||||
},
|
||||
"checks_passed": [
|
||||
"actionlint",
|
||||
"python-json-yaml-bash-syntax",
|
||||
"numeric-stable-version-selection",
|
||||
"skip-published-version",
|
||||
"freeze-skia2",
|
||||
"real-nuget-discovery",
|
||||
"immutable-tag-and-skia-gitlink-resolution",
|
||||
"generated-package-version-and-exact-dependency"
|
||||
],
|
||||
"not_run": [
|
||||
"full-build-of-the-six-new-versions",
|
||||
"github-actions",
|
||||
"docker-cold-build",
|
||||
"windows-macos-runtime",
|
||||
"dotnet-pack",
|
||||
"nuget-publish"
|
||||
]
|
||||
}
|
||||
@@ -1,60 +0,0 @@
|
||||
# Zig cross compilation for SkiaSharp 3 / 4
|
||||
|
||||
All nine native targets use Zig 0.14.1 from Linux: linux-x64, linux-arm64,
|
||||
linux-musl-x64, linux-musl-arm64, win-x64, win-x86, win-arm64, osx-x64, osx-arm64.
|
||||
Windows uses the GNU ABI, without MSVC. macOS uses a checksum-pinned real SDK,
|
||||
without Xcode. AvaloniaNative 11/12 also compiles with Zig on Linux.
|
||||
|
||||
## Local evidence (2026-10-04)
|
||||
|
||||
| Check | Result |
|
||||
| --- | --- |
|
||||
| 3.119.2, 3.119.4, 4.150.3, 4.150.5, 4.153.1 × nine GN configurations | 45 passed; these are configuration checks |
|
||||
| All five versions, Windows x64 Skia/SkiaSharp/HarfBuzz compilation and executable link | Passed |
|
||||
| 3.119.4 Windows x86 Skia and stdcall thunks | Compilation and raster/EGL links passed; fixed ANGLE archives reused |
|
||||
| 3.119.4 Linux x64 | All six archives and both links passed; raster/UTF-8 execution passed |
|
||||
| 3.119.4 Linux ARM64 | Three Skia archives and raster link passed; raster/UTF-8 execution passed under QEMU |
|
||||
| 4.153.1 macOS ARM64 | Three Skia archives and raster executable link passed |
|
||||
| AvaloniaNative 11.3.14 / 12.1.0, both macOS architectures | Four full compilations and SDK libc++ executable links passed |
|
||||
|
||||
Exact scope is recorded in `recent-version-validation.json`. Earlier baseline
|
||||
results are retained separately. The raster probe checks 64 pixels and UTF-8
|
||||
buffer ingestion; it does not prove complete font shaping or GPU operation.
|
||||
|
||||
There is no local Docker daemon or Windows/macOS runtime. The complete Debian
|
||||
image, five releases × nine full builds, NativeAOT consumer applications and
|
||||
actual Actions/NuGet publication have not been verified locally. Local builds
|
||||
used the Linux host and pinned cross tools, not a running Debian container.
|
||||
|
||||
## Repeatable inputs and failure policy
|
||||
|
||||
`Dockerfile` pins Debian 12 by digest, apt by snapshot and depot_tools by commit.
|
||||
`Dockerfile.cross-probe` is the production cross image despite its historical
|
||||
name. It pins Zig, the macOS SDK, WinRT headers, availability runtime and Linux
|
||||
sysroot packages by checksum. SDK extraction supports pinned Debian Python 3.11.
|
||||
|
||||
`zig-toolchain-image.yml` builds/reuses GHCR images by recipe digest and passes
|
||||
an immutable image digest to downstream builds. Repository package write
|
||||
permission is required. Source profiles pin SkiaSharp, Skia and ANGLE commits.
|
||||
The existing exact per-target source/build cache has no fallback restores;
|
||||
ccache additionally checks compiler contents. Cold downloads remain necessary.
|
||||
|
||||
`build-cross.py` adapts declared GN capabilities, rejects unknown compiler flags,
|
||||
checks static targets, builds six archives and links raster and EGL/GLES probes.
|
||||
`package-zig.py` requires archive hashes and successful links before packaging.
|
||||
Windows x86 gets generated stdcall thunks. Captured Zig runtime libraries are
|
||||
included for consumer linking. A successful C link does not establish NativeAOT
|
||||
compatibility; the release workflow gates publication on consumer OS tests.
|
||||
|
||||
## Run
|
||||
|
||||
Use the `zig-recent-regression` manual Action for recent-version full matrices.
|
||||
Use `static-graphics-zig-cross-debian12` for one pinned release and nine RIDs.
|
||||
For already synced sources, run `build/linux-toolchain/build-cross.py --help`;
|
||||
`--configure-only` configures without compiling, while `--component skia` checks
|
||||
only the three Skia libraries and their executable link.
|
||||
|
||||
This common driver supports the tested source revisions. Future compiler,
|
||||
SDK, GN or source changes can still require deliberate updates. Daily releases
|
||||
fail closed and publish only after all required jobs pass. SkiaSharp 2 is frozen
|
||||
and excluded from the new regression/release tracks.
|
||||
@@ -1,38 +0,0 @@
|
||||
# Multi-architecture index; deliberately update together with the snapshot/cache key.
|
||||
FROM debian:bookworm-slim@sha256:3783cc01769c7b2b1b83a5c5ad96c815348e28ed7da68e2e3687004faa906251
|
||||
|
||||
ARG DEBIAN_SNAPSHOT=20260901T000000Z
|
||||
ARG DEPOT_TOOLS_REVISION=8a5434051036b32412a2ecb10c213a72e3f3ccb9
|
||||
ENV DEBIAN_FRONTEND=noninteractive \
|
||||
DEPOT_TOOLS_UPDATE=0 \
|
||||
DEPOT_TOOLS_REVISION=${DEPOT_TOOLS_REVISION} \
|
||||
LLVM_AR=llvm-ar-16 \
|
||||
BUILD_JOBS=4
|
||||
|
||||
# HTTP bootstrap uses Debian's signed Release metadata. Do not disable signature checks.
|
||||
RUN rm -f /etc/apt/sources.list.d/debian.sources \
|
||||
&& printf 'deb [check-valid-until=no] http://snapshot.debian.org/archive/debian/%s bookworm main\ndeb [check-valid-until=no] http://snapshot.debian.org/archive/debian-security/%s bookworm-security main\n' "$DEBIAN_SNAPSHOT" "$DEBIAN_SNAPSHOT" > /etc/apt/sources.list \
|
||||
&& apt-get update \
|
||||
&& printf 'Package: *\nPin: origin "snapshot.debian.org"\nPin-Priority: 1001\n' > /etc/apt/preferences.d/staticlink-snapshot \
|
||||
&& apt-get dist-upgrade -y --allow-downgrades \
|
||||
&& apt-get install -y --no-install-recommends \
|
||||
ca-certificates git curl python3 python3-six python3-requests python3-httplib2 \
|
||||
build-essential ccache clang-16 lld-16 llvm-16 libclang-rt-16-dev ninja-build \
|
||||
pkg-config cmake binutils file unzip xz-utils bzip2 patch \
|
||||
libfontconfig1-dev libglib2.0-dev libgl1-mesa-dev libpci-dev \
|
||||
libx11-dev libxcb1-dev libxext-dev libwayland-dev libexpat1-dev libicu72 libssl3 \
|
||||
&& for tool in clang clang++ llvm-ar llvm-ranlib llvm-nm lld ld.lld lld-link ld64.lld; do \
|
||||
ln -s "/usr/bin/$tool-16" "/usr/local/bin/$tool"; \
|
||||
done \
|
||||
&& mkdir -p /opt/staticlink \
|
||||
&& dpkg-query -W > /opt/staticlink/packages.lock \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# Store the pinned checkout inside the image so the runner never selects depot_tools HEAD.
|
||||
RUN git init /opt/depot_tools \
|
||||
&& git -C /opt/depot_tools remote add origin https://chromium.googlesource.com/chromium/tools/depot_tools.git \
|
||||
&& git -C /opt/depot_tools fetch --depth 1 origin "$DEPOT_TOOLS_REVISION" \
|
||||
&& git -C /opt/depot_tools checkout --detach FETCH_HEAD
|
||||
ENV DEPOT_TOOLS_DIR=/opt/depot_tools
|
||||
WORKDIR /src
|
||||
CMD ["bash"]
|
||||
@@ -1,61 +0,0 @@
|
||||
# Build this local base from Dockerfile first; it contains the pinned Debian toolchain.
|
||||
ARG TOOLCHAIN_IMAGE=staticlink-debian12:probe-base
|
||||
FROM mcr.microsoft.com/dotnet/sdk:10.0.302@sha256:72dd743782f2ae7e5476fd64f6a460045e3998dc862218b80e6944cba79a01b0 AS dotnet10
|
||||
FROM mcr.microsoft.com/dotnet/sdk:8.0.416@sha256:8b5eece40d8a8050c09332eab1e65563fd4c928c5881e9e72bca7a4b0339f881 AS dotnet8
|
||||
FROM python:3.12.12-slim-bookworm@sha256:593bd06efe90efa80dc4eee3948be7c0fde4134606dd40d8dd8dbcade98e669c AS python312
|
||||
FROM ${TOOLCHAIN_IMAGE}
|
||||
COPY --from=python312 /usr/local/ /usr/local/
|
||||
ENV PYTHONPATH=/usr/lib/python3/dist-packages
|
||||
RUN ldconfig && python3 -c 'import inspect, tarfile, six, requests, httplib2; assert "filter" in inspect.signature(tarfile.TarFile.extractall).parameters'
|
||||
|
||||
ARG TARGETARCH
|
||||
RUN case "$TARGETARCH" in \
|
||||
amd64) zig_arch=x86_64; zig_sha=24aeeec8af16c381934a6cd7d95c807a8cb2cf7df9fa40d359aa884195c4716c ;; \
|
||||
arm64) zig_arch=aarch64; zig_sha=f7a654acc967864f7a050ddacfaa778c7504a0eca8d2b678839c21eea47c992b ;; \
|
||||
*) echo "Unsupported host architecture: $TARGETARCH" >&2; exit 1 ;; \
|
||||
esac \
|
||||
&& curl --fail --location --retry 3 \
|
||||
"https://ziglang.org/download/0.14.1/zig-$zig_arch-linux-0.14.1.tar.xz" -o /tmp/zig.tar.xz \
|
||||
&& printf '%s /tmp/zig.tar.xz\n' "$zig_sha" | sha256sum --check \
|
||||
&& mkdir /opt/zig \
|
||||
&& tar -xJf /tmp/zig.tar.xz -C /opt/zig --strip-components=1 \
|
||||
&& ln -s /opt/zig/zig /usr/local/bin/zig \
|
||||
&& rm /tmp/zig.tar.xz
|
||||
|
||||
ARG MACOS_SDK_SHA256=c15cf0f3f17d714d1aa5a642da8e118db53d79429eb015771ba816aa7c6c1cbd
|
||||
# Architecture-independent MinGW WinRT headers supplement Zig's SDK. Extract
|
||||
# files only: do not install Ubuntu binaries or change Debian package resolution.
|
||||
RUN curl --fail --location --retry 3 \
|
||||
https://snapshot.ubuntu.com/ubuntu/20260828T000000Z/pool/universe/m/mingw-w64/mingw-w64-common_11.0.1-3build1_all.deb \
|
||||
-o /tmp/mingw.deb \
|
||||
&& printf '%s /tmp/mingw.deb\n' \
|
||||
4a42fd30fbc3838c58c929d8a4882682fc12408bb7a0e6cafa913c0f0a57c187 | sha256sum --check \
|
||||
&& mkdir /opt/mingw && dpkg-deb --extract /tmp/mingw.deb /opt/mingw \
|
||||
&& rm /tmp/mingw.deb
|
||||
|
||||
RUN curl --fail --location --retry 3 \
|
||||
https://github.com/joseluisq/macosx-sdks/releases/download/15.5/MacOSX15.5.sdk.tar.xz \
|
||||
-o /tmp/macos-sdk.tar.xz \
|
||||
&& printf '%s /tmp/macos-sdk.tar.xz\n' "$MACOS_SDK_SHA256" | sha256sum --check \
|
||||
&& mkdir /opt/macos-sdk \
|
||||
&& tar -xJf /tmp/macos-sdk.tar.xz -C /opt/macos-sdk \
|
||||
&& rm /tmp/macos-sdk.tar.xz
|
||||
|
||||
RUN mkdir -p /opt/staticlink \
|
||||
&& curl --fail --location --retry 3 \
|
||||
https://raw.githubusercontent.com/llvm/llvm-project/llvmorg-19.1.7/compiler-rt/lib/builtins/os_version_check.c \
|
||||
-o /opt/staticlink/os_version_check.c \
|
||||
&& printf '%s /opt/staticlink/os_version_check.c\n' \
|
||||
bc0b9f10e8d1a1ac5905d710f1c9fead23878e31233748d580393edc4e3bfc18 | sha256sum --check
|
||||
|
||||
ENTRYPOINT ["python3", "/opt/staticlink/probe-cross.py"]
|
||||
|
||||
COPY --from=dotnet8 /usr/share/dotnet /opt/dotnet
|
||||
COPY --from=dotnet10 /usr/share/dotnet /opt/dotnet
|
||||
ENV DOTNET_ROOT=/opt/dotnet PATH=/opt/dotnet:${PATH}
|
||||
COPY fetch-linux-sysroots.py linux-sysroots*.lock.json /opt/staticlink/
|
||||
RUN python3 /opt/staticlink/fetch-linux-sysroots.py --output /opt/sysroots \
|
||||
--locks /opt/staticlink/linux-sysroots.lock.json /opt/staticlink/linux-sysroots-musl.lock.json
|
||||
COPY *.py smoke-*.c sources.lock.json cross-toolchain.lock.json *.gn.in /opt/staticlink/
|
||||
COPY patches/ /opt/staticlink/patches/
|
||||
COPY versions/ /opt/staticlink/versions/
|
||||
@@ -1,20 +0,0 @@
|
||||
# Debian 12 Zig cross toolchain
|
||||
|
||||
The production native-build path is the pinned Debian 12 image plus Zig 0.14.1,
|
||||
covering all nine GNU Linux, musl Linux, Windows and macOS targets. musl uses
|
||||
checksum-locked target sysroots inside the same Debian image.
|
||||
|
||||
Read [CROSS-COMPILE.md](CROSS-COMPILE.md) for current build commands, exact local
|
||||
validation scope and remaining Docker/runtime/NativeAOT verification. Read
|
||||
[DAILY-RELEASE.md](../../DAILY-RELEASE.md) for daily 3/4 release configuration.
|
||||
|
||||
`Dockerfile` pins the base digest, apt snapshot and source-preparation tools.
|
||||
`Dockerfile.cross-probe` adds Zig, macOS SDK, Windows headers, target Linux SDKs
|
||||
and .NET SDKs. The historical filename is retained for existing references.
|
||||
`zig-toolchain-image.yml` reuses recipe-tagged GHCR images and downstream jobs
|
||||
pull their immutable digest. Source locks and archive/link manifests provide
|
||||
traceability. No complete local Docker image build has been run.
|
||||
|
||||
Legacy platform helper scripts are retained for reference; production graphics
|
||||
Actions now delegate to the common Zig cross-build workflow. SkiaSharp 2 remains
|
||||
outside the new daily tracks.
|
||||
@@ -1,23 +0,0 @@
|
||||
target_os = "linux"
|
||||
target_cpu = "@CPU@"
|
||||
is_debug = false
|
||||
is_component_build = false
|
||||
is_clang = true
|
||||
treat_warnings_as_errors = false
|
||||
use_custom_libcxx = false
|
||||
use_custom_libcxx_for_host = false
|
||||
use_sysroot = false
|
||||
use_lld = false
|
||||
use_thin_lto = false
|
||||
symbol_level = 0
|
||||
angle_build_tests = false
|
||||
build_angle_deqp_tests = false
|
||||
angle_enable_swiftshader = false
|
||||
angle_enable_vulkan = false
|
||||
angle_enable_wgpu = false
|
||||
clang_use_chrome_plugins = false
|
||||
enable_rust = false
|
||||
clang_version = "19"
|
||||
|
||||
# Chromium UI/ATK is not part of the standalone ANGLE library targets.
|
||||
use_glib = false
|
||||
@@ -1,21 +0,0 @@
|
||||
target_os = "mac"
|
||||
target_cpu = "@CPU@"
|
||||
is_debug = false
|
||||
is_component_build = false
|
||||
is_clang = true
|
||||
treat_warnings_as_errors = false
|
||||
use_custom_libcxx = false
|
||||
use_custom_libcxx_for_host = false
|
||||
use_sysroot = false
|
||||
use_lld = false
|
||||
use_thin_lto = false
|
||||
symbol_level = 0
|
||||
angle_build_tests = false
|
||||
build_angle_deqp_tests = false
|
||||
angle_enable_swiftshader = false
|
||||
angle_enable_vulkan = false
|
||||
angle_enable_wgpu = false
|
||||
clang_use_chrome_plugins = false
|
||||
enable_rust = false
|
||||
use_system_xcode = true
|
||||
clang_version = "19"
|
||||
@@ -1,25 +0,0 @@
|
||||
target_os = "win"
|
||||
target_cpu = "@CPU@"
|
||||
is_debug = false
|
||||
is_component_build = false
|
||||
is_clang = true
|
||||
treat_warnings_as_errors = false
|
||||
use_custom_libcxx = false
|
||||
use_custom_libcxx_for_host = false
|
||||
use_sysroot = false
|
||||
use_lld = false
|
||||
use_thin_lto = false
|
||||
symbol_level = 0
|
||||
angle_build_tests = false
|
||||
build_angle_deqp_tests = false
|
||||
angle_enable_swiftshader = false
|
||||
angle_enable_vulkan = false
|
||||
angle_enable_wgpu = false
|
||||
clang_use_chrome_plugins = false
|
||||
enable_rust = false
|
||||
|
||||
visual_studio_version = "2022"
|
||||
windows_sdk_version = "10.0.22621.0"
|
||||
clang_version = "19"
|
||||
use_clang_modules = false
|
||||
angle_copy_compiler_dll = false
|
||||
@@ -1,43 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Build Avalonia's pinned macOS native sources with Zig on Linux."""
|
||||
import argparse,subprocess,re,json,os,hashlib
|
||||
from pathlib import Path
|
||||
p=argparse.ArgumentParser();p.add_argument('--source',type=Path,required=True);p.add_argument('--rid',choices=['osx-x64','osx-arm64'],required=True);p.add_argument('--sdk',type=Path,required=True);p.add_argument('--zig',default='zig');p.add_argument('--output',type=Path,required=True);p.add_argument('--work',type=Path,required=True);a=p.parse_args()
|
||||
a.source=a.source.resolve();a.output=a.output.resolve();a.work=a.work.resolve();a.output.mkdir(parents=True,exist_ok=True);a.work.mkdir(parents=True,exist_ok=True)
|
||||
repo=Path(__file__).resolve().parents[2]
|
||||
tools=a.work/'tools'
|
||||
subprocess.run(['python3',str(repo/'build/linux-toolchain/zig-cross.py'),'--zig',a.zig,'--target',a.rid,'--sdk',str(a.sdk),'--output',str(tools)],check=True)
|
||||
descriptor=tools/'toolchain.json'
|
||||
config=json.loads(descriptor.read_text());config['target']=config['target'].split('-macos.')[0]+'-macos.12.0.0';descriptor.write_text(json.dumps(config,indent=2)+'\n')
|
||||
native=a.source/'native/Avalonia.Native';project=native/'src/OSX/Avalonia.Native.OSX.xcodeproj/project.pbxproj'
|
||||
headers=native/'inc'
|
||||
if not (headers/'avalonia-native.h').is_file():
|
||||
header_project=native/'Avalonia.Native.macOS.proj'
|
||||
if header_project.is_file():
|
||||
subprocess.run(['dotnet','build',str(header_project),'-t:GenerateMicroComItems'],cwd=a.source,check=True)
|
||||
else:
|
||||
subprocess.run(['bash',str(native/'generate-headers.sh')],cwd=a.source,check=True)
|
||||
# Match the authoritative Xcode Sources build phases, rather than guessing every .mm in the repo.
|
||||
project_text=project.read_text()
|
||||
names=set(re.findall(r'/\* (.+?\.(?:mm|m|cpp|cc|c)) in Sources \*/',project_text))
|
||||
file_flags={}
|
||||
for name,flags in re.findall(r'/\* (.+?\.(?:mm|m|cpp|cc|c)) in Sources \*/[^\n]*COMPILER_FLAGS = \"([^\"]+)\"',project_text):
|
||||
import shlex
|
||||
file_flags[name]=shlex.split(flags)
|
||||
if not names:raise SystemExit('No authoritative Xcode source list found')
|
||||
objects=[];source_hashes={}
|
||||
for name in sorted(names):
|
||||
matches=list(native.rglob(name))
|
||||
if len(matches)!=1:raise SystemExit('Ambiguous or missing Xcode source '+name+': '+str(matches))
|
||||
source=matches[0];obj=a.work/(hashlib.sha256(str(source.relative_to(native)).encode()).hexdigest()+'.o')
|
||||
command=[str(tools/('cc' if source.suffix in ('.c','.m') else 'cxx')),'-O2','-fPIC','-fblocks','-mmacosx-version-min=12.0','-I'+str(headers),'-I'+str(native/'src/OSX'),'-I'+str(native/'src'),'-c',str(source),'-o',str(obj)]
|
||||
if source.suffix in ('.mm','.m'):command+=['-fobjc-arc']
|
||||
if source.suffix in ('.mm','.cpp','.cc'):command+=['-std=c++17']
|
||||
command+=file_flags.get(name,[])
|
||||
subprocess.run(command,check=True);objects.append(obj);source_hashes[str(source.relative_to(native))]=hashlib.sha256(source.read_bytes()).hexdigest()
|
||||
subprocess.run([str(tools/'ar'),'rcs',str(a.output/'libAvaloniaNative.a'),*map(str,objects)],check=True)
|
||||
# The macOS font pre-initializer is compiled by the same cross compiler.
|
||||
env=dict(os.environ,RID=a.rid,OUTPUT_DIR=str(a.output),CC=str(tools/'cc'),STATICLINK_ZIG_CROSS='1')
|
||||
subprocess.run(['bash',str(repo/'scripts/build-macos-font-preinit.sh')],env=env,check=True)
|
||||
commit=subprocess.check_output(['git','-C',str(a.source),'rev-parse','HEAD'],text=True).strip()
|
||||
(a.output/'avalonia-native-build.json').write_text(json.dumps({'source_commit':commit,'rid':a.rid,'toolchain':json.loads((tools/'toolchain.json').read_text()),'sources':source_hashes,'validation':'compiled archive; macOS AOT/runtime validation runs separately'},indent=2)+'\n')
|
||||
@@ -1,242 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Build pinned, already dependency-synced SkiaSharp/ANGLE sources from Linux."""
|
||||
import argparse
|
||||
import hashlib
|
||||
import json
|
||||
import os
|
||||
from pathlib import Path
|
||||
import platform
|
||||
import shutil
|
||||
import subprocess
|
||||
import sys
|
||||
from skia_compat import archive, configure, parse_args, repair_xps, repair_skcms
|
||||
|
||||
HERE = Path(__file__).resolve().parent
|
||||
|
||||
|
||||
def run(args, cwd=None, env=None):
|
||||
print('+', ' '.join(map(str, args)), flush=True)
|
||||
subprocess.run(list(map(str, args)), cwd=cwd, env=env, check=True)
|
||||
|
||||
|
||||
def patch(source, filename):
|
||||
path = HERE / 'patches' / filename
|
||||
cmd = ['git', '-C', str(source), 'apply']
|
||||
if subprocess.run(cmd + ['--reverse', '--check', str(path)], capture_output=True).returncode == 0:
|
||||
return
|
||||
run(cmd + ['--check', path])
|
||||
run(cmd + [path])
|
||||
|
||||
|
||||
def main():
|
||||
p = argparse.ArgumentParser(description=__doc__)
|
||||
p.add_argument('--target', choices=['linux-x64', 'linux-arm64', 'linux-musl-x64', 'linux-musl-arm64', 'win-x64', 'win-x86', 'win-arm64', 'osx-x64', 'osx-arm64'], required=True)
|
||||
p.add_argument('--sources-manifest', type=Path, help='cross-sources.json from prepare-cross-sources.sh')
|
||||
p.add_argument('--source-lock', type=Path, help='Exact version profile; defaults to sources.lock.json')
|
||||
p.add_argument('--skia', type=Path, help='SkiaSharp externals/skia, with its pinned dependencies synced')
|
||||
p.add_argument('--angle', type=Path, help='ANGLE source with pinned DEPS synced, including tools/win')
|
||||
p.add_argument('--angle-gn', type=Path, help='GN from the pinned ANGLE DEPS')
|
||||
p.add_argument('--zig', default='zig')
|
||||
p.add_argument('--sdk', type=Path, default=Path('/opt/macos-sdk/MacOSX15.5.sdk'))
|
||||
p.add_argument('--mingw-headers', type=Path, default=Path('/opt/mingw/usr/share/mingw-w64/include'))
|
||||
p.add_argument('--availability-source', type=Path, default=Path('/opt/staticlink/os_version_check.c'))
|
||||
p.add_argument('--linux-sysroots', type=Path, default=Path('/opt/sysroots'))
|
||||
p.add_argument('--linux-headers', type=Path, default=Path('/opt/staticlink/linux-headers'))
|
||||
p.add_argument('--work', type=Path, required=True)
|
||||
p.add_argument('--output', type=Path, required=True)
|
||||
p.add_argument('--jobs', type=int, default=4)
|
||||
p.add_argument('--configure-only', action='store_true')
|
||||
p.add_argument('--component', choices=['all', 'skia'], default='all', help='Build Skia alone when validating a new SkiaSharp release')
|
||||
a = p.parse_args()
|
||||
if a.sources_manifest:
|
||||
sources = json.loads(a.sources_manifest.read_text())
|
||||
if a.source_lock is None and sources.get('source_lock'):
|
||||
a.source_lock = Path(sources['source_lock'])
|
||||
for name in ('skia', 'angle', 'angle_gn'):
|
||||
if getattr(a, name) is None:
|
||||
setattr(a, name, Path(sources[name]))
|
||||
if any(getattr(a, name) is None for name in ('skia', 'angle', 'angle_gn')):
|
||||
p.error('Provide --sources-manifest or all of --skia, --angle and --angle-gn')
|
||||
if platform.system() != 'Linux' or a.jobs < 1:
|
||||
p.error('Requires Linux and positive --jobs')
|
||||
for name in ('skia', 'angle', 'angle_gn', 'sdk', 'work', 'output', 'availability_source', 'mingw_headers'):
|
||||
setattr(a, name, getattr(a, name).resolve())
|
||||
lock = json.loads((a.source_lock or HERE / 'sources.lock.json').read_text())
|
||||
for src, key in ((a.skia, 'skia_revision'), (a.angle, 'angle_revision')):
|
||||
revision = subprocess.check_output(['git', '-C', str(src), 'rev-parse', 'HEAD'], text=True).strip()
|
||||
if revision != lock[key]:
|
||||
raise SystemExit(f'{src}: expected {lock[key]}, got {revision}; update the lock and revalidate first')
|
||||
if 'skiasharp_build("SkiaSharp")' not in (a.skia / 'BUILD.gn').read_text():
|
||||
raise SystemExit('--skia must be the SkiaSharp-patched Skia source, not vanilla Google Skia')
|
||||
a.work.mkdir(parents=True, exist_ok=True)
|
||||
a.output.mkdir(parents=True, exist_ok=True)
|
||||
windows = a.target.startswith('win')
|
||||
mac = a.target.startswith('osx')
|
||||
linux = a.target.startswith('linux')
|
||||
cpu = a.target.rsplit('-', 1)[1]
|
||||
os_name = 'win' if windows else ('mac' if mac else 'linux')
|
||||
if windows and not (a.mingw_headers / 'windows.ui.composition.h').is_file():
|
||||
raise SystemExit('Windows ANGLE requires --mingw-headers containing the pinned WinRT headers')
|
||||
recipe = hashlib.sha256()
|
||||
for path in sorted(HERE.rglob('*')):
|
||||
if path.is_file() and (path.suffix in ('.py', '.in', '.patch', '.c') or path.name in ('cross-toolchain.lock.json', 'linux-sysroots.lock.json', 'linux-sysroots-musl.lock.json')):
|
||||
recipe.update(str(path.relative_to(HERE)).encode())
|
||||
recipe.update(path.read_bytes())
|
||||
variant = hashlib.sha256((json.dumps(lock, sort_keys=True) + recipe.hexdigest()).encode()).hexdigest()[:16]
|
||||
shared = {'angle_revision': lock['angle_revision'], 'recipe': recipe.hexdigest(), 'toolchain': json.loads((HERE / 'cross-toolchain.lock.json').read_text())}
|
||||
angle_variant = hashlib.sha256(json.dumps(shared, sort_keys=True).encode()).hexdigest()[:16]
|
||||
tools = a.work / angle_variant / a.target
|
||||
host_cpu = 'arm64' if platform.machine() == 'aarch64' else 'x64'
|
||||
host_tools = a.work / angle_variant / ('linux-' + host_cpu)
|
||||
for target, output in ((a.target, tools), ('linux-' + host_cpu, host_tools)):
|
||||
command = [sys.executable, HERE / 'zig-cross.py', '--zig', a.zig, '--target', target,
|
||||
'--output', output, '--sdk', a.sdk, '--mingw-headers', a.mingw_headers]
|
||||
if target.startswith('linux'):
|
||||
command += ['--linux-sysroot', a.linux_sysroots / target, '--linux-headers', a.linux_headers]
|
||||
run(command)
|
||||
config = json.loads((tools / 'toolchain.json').read_text())
|
||||
zig = config['zig']
|
||||
zig_lib = Path(json.loads(subprocess.check_output([zig, 'env'], text=True))['lib_dir'])
|
||||
print('skcms Clang compatibility:', repair_skcms(a.skia), flush=True)
|
||||
if windows:
|
||||
print('XPS compatibility:', repair_xps(a.skia), flush=True)
|
||||
# First apply the project's static ANGLE target patch if necessary.
|
||||
if 'angle_static_library("libANGLE_static")' not in (a.angle / 'BUILD.gn').read_text():
|
||||
patch(a.angle, 'angle-static-targets.patch')
|
||||
for filename in ('BUILDCONFIG.gn-zig.patch', 'BUILD.gn-zig.patch',
|
||||
'sdk_info-linux.patch', 'find_sdk-linux.patch', 'gcc-toolchain-objc.patch'):
|
||||
patch(a.angle, filename)
|
||||
run([sys.executable, a.angle / 'build/util/lastchange.py', '-o', a.angle / 'build/util/LASTCHANGE'], cwd=a.angle)
|
||||
# Separate runtime paths prevent architectures from sharing an incompatible cache.
|
||||
clang = tools / 'clang'
|
||||
runtime = clang / 'lib/clang/19/lib' / ('windows' if windows else ('darwin' if mac else 'linux')) / (
|
||||
'clang_rt.builtins-' + {'x64': 'x86_64', 'x86': 'i386', 'arm64': 'aarch64'}[cpu] + '.lib'
|
||||
if windows else ('libclang_rt.osx.a' if mac else 'libclang_rt.builtins-' + ('x86_64' if cpu == 'x64' else 'aarch64') + '.a'))
|
||||
runtime.parent.mkdir(parents=True, exist_ok=True)
|
||||
run([zig, 'build-lib', zig_lib / 'compiler_rt.zig', '-target', config['target'],
|
||||
'-O', 'ReleaseFast', '-fPIC', '-femit-bin=' + str(runtime)])
|
||||
if linux:
|
||||
for runtime_cpu, runtime_target in ((cpu, config['target']), (host_cpu, json.loads((host_tools / 'toolchain.json').read_text())['target'])):
|
||||
triple = 'x86_64-unknown-linux-gnu' if runtime_cpu == 'x64' else 'aarch64-unknown-linux-gnu'
|
||||
alias = clang / 'lib/clang/19/lib' / triple / 'libclang_rt.builtins.a'
|
||||
alias.parent.mkdir(parents=True, exist_ok=True)
|
||||
run([zig, 'build-lib', zig_lib / 'compiler_rt.zig', '-target', runtime_target,
|
||||
'-O', 'ReleaseFast', '-fPIC', '-femit-bin=' + str(alias)])
|
||||
availability = None
|
||||
if mac:
|
||||
if hashlib.sha256(a.availability_source.read_bytes()).hexdigest() != 'bc0b9f10e8d1a1ac5905d710f1c9fead23878e31233748d580393edc4e3bfc18':
|
||||
raise SystemExit('LLVM availability source checksum mismatch')
|
||||
availability = tools / 'os_version_check.o'
|
||||
run([tools / 'cc', '-c', a.availability_source, '-o', availability])
|
||||
run([tools / 'ar', 'rcs', runtime, availability])
|
||||
env = os.environ.copy()
|
||||
env['PATH'] = str(tools) + os.pathsep + env['PATH']
|
||||
env['CCACHE_BASEDIR'] = str(a.skia)
|
||||
env['CCACHE_NOHASHDIR'] = 'true'
|
||||
env['CCACHE_COMPILERCHECK'] = 'content'
|
||||
env['STATICLINK_MACOS_SDK'] = str(a.sdk)
|
||||
env['STATICLINK_DARWIN_TOOLS'] = str(tools)
|
||||
skia_out = a.skia / 'out' / ('staticlink-zig-' + a.target + '-' + variant)
|
||||
angle_out = a.angle / 'out' / ('staticlink-zig-' + a.target + '-' + angle_variant)
|
||||
for out in (skia_out, angle_out):
|
||||
out.mkdir(parents=True, exist_ok=True)
|
||||
skia_args = (HERE / ('skia-' + os_name + '.gn.in')).read_text().replace('@CPU@', cpu)
|
||||
if mac:
|
||||
skia_args += f'min_macos_version = "{"11.0" if cpu == "arm64" else "10.13"}"\n'
|
||||
skia_args += f'xcode_sysroot = {json.dumps(str(a.sdk))}\n'
|
||||
for name in ('cc', 'cxx', 'ar'):
|
||||
skia_args += name + ' = ' + json.dumps(str(tools / name)) + '\n'
|
||||
if linux:
|
||||
for key in ('cc', 'cxx', 'ar'):
|
||||
skia_args = skia_args.replace('@' + key.upper() + '@', str(tools / key))
|
||||
capabilities = configure(a.skia, skia_out, parse_args(skia_args), a.skia / 'bin/gn', env)
|
||||
for target in ('skia', 'SkiaSharp', 'HarfBuzzSharp'):
|
||||
description = json.loads(subprocess.check_output([str(a.skia / 'bin/gn'), 'desc', str(skia_out.relative_to(a.skia)),
|
||||
'//:' + target, '--format=json'], cwd=a.skia, env=env, text=True))
|
||||
kind = next(iter(description.values()))['type']
|
||||
if kind != 'static_library':
|
||||
raise SystemExit(f'{target} is {kind}; expected static_library')
|
||||
if windows:
|
||||
# Upstream Skia fixes Windows to the MSVC rules; retain its graph and
|
||||
# replace compiler/archive commands explicitly with the GNU adapters.
|
||||
path = skia_out / 'toolchain.ninja'
|
||||
body = path.read_text()
|
||||
index = body.index('subninja ')
|
||||
rules = ''
|
||||
for name, flags in (('cc', 'cflags_c'), ('cxx', 'cflags_cc')):
|
||||
rules += f'rule {name}\n command = {tools / name} -MD -MF ${{out}}.d ${{defines}} ${{include_dirs}} ${{cflags}} ${{{flags}}} -c ${{in}} -o ${{out}}\n depfile = ${{out}}.d\n deps = gcc\n'
|
||||
rules += f'rule alink\n command = {tools / "ar"} rcs ${{out}} @${{out}}.rsp\n rspfile = ${{out}}.rsp\n rspfile_content = ${{in_newline}}\n'
|
||||
rules += 'rule stamp\n command = touch ${out}\nrule copy\n command = cp ${in} ${out}\nrule asm\n command = false\n'
|
||||
path.write_text(rules + '\n' + body[index:])
|
||||
sdk_link = angle_out / 'sdk/xcode_links/MacOSX15.5.sdk'
|
||||
if mac:
|
||||
sdk_link.parent.mkdir(parents=True, exist_ok=True)
|
||||
if sdk_link.is_symlink():
|
||||
sdk_link.unlink()
|
||||
sdk_link.symlink_to(a.sdk)
|
||||
# Each architecture gets an independent toolchain file; concurrent builds
|
||||
# do not rewrite another target's generated GN toolchain.
|
||||
toolchain_dir = a.angle / ('staticlink_zig_' + a.target.replace('-', '_') + '_' + angle_variant)
|
||||
toolchain_dir.mkdir(exist_ok=True)
|
||||
text = 'import("//build/toolchain/gcc_toolchain.gni")\n'
|
||||
for name, folder, target_os, target_cpu in (('target', tools, os_name, cpu), ('host', host_tools, 'linux', host_cpu)):
|
||||
text += f'gcc_toolchain("{name}") {{\n'
|
||||
for var in ('cc', 'cxx', 'ar'):
|
||||
text += ' ' + var + ' = ' + json.dumps(str(folder / var)) + '\n'
|
||||
text += f' ld = cxx\n nm = "nm"\n readelf = "readelf"\n toolchain_args = {{ current_os = "{target_os}" current_cpu = "{target_cpu}" is_clang = true use_remoteexec = false }}\n}}\n'
|
||||
(toolchain_dir / 'BUILD.gn').write_text(text)
|
||||
angle_args = (HERE / ('angle-' + os_name + '.gn.in')).read_text().replace('@CPU@', cpu)
|
||||
angle_args += f'custom_toolchain = "//{toolchain_dir.name}:target"\nhost_toolchain = "//{toolchain_dir.name}:host"\n'
|
||||
angle_args += 'clang_base_path = ' + json.dumps(str(clang)) + '\n'
|
||||
if linux:
|
||||
angle_args += 'pkg_config = ' + json.dumps(str(tools / 'pkg-config')) + '\n'
|
||||
angle_args += 'host_pkg_config = ' + json.dumps(str(host_tools / 'pkg-config')) + '\n'
|
||||
if windows:
|
||||
# These mandatory GN metadata paths refer to the real MinGW headers.
|
||||
# The SDK/version strings satisfy GN; MSVC/Windows SDK are not used.
|
||||
for name, path in (('visual_studio_path', Path(zig).parent), ('wdk_path', Path(zig).parent),
|
||||
('windows_sdk_path', zig_lib / 'libc/include/any-windows-any')):
|
||||
angle_args += name + ' = ' + json.dumps(str(path)) + '\n'
|
||||
(angle_out / 'args.gn').write_text(angle_args)
|
||||
run([a.angle_gn, 'gen', angle_out.relative_to(a.angle)], cwd=a.angle, env=env)
|
||||
if a.configure_only:
|
||||
print(f'Configured {lock["skiasharp_version"]} {a.target}: all three Skia targets are static libraries')
|
||||
return
|
||||
run(['ninja', '-C', skia_out, '-j', a.jobs, 'skia', 'SkiaSharp', 'HarfBuzzSharp'], env=env)
|
||||
if a.component == 'all':
|
||||
run(['ninja', '-C', angle_out, '-j', a.jobs, 'libANGLE_static', 'libGLESv2_static', 'libEGL_static'], env=env)
|
||||
if availability:
|
||||
run([tools / 'ar', 'rcs', archive(skia_out, 'skia'), availability])
|
||||
files = [(archive(skia_out, name), name)
|
||||
for name in ('skia', 'SkiaSharp', 'HarfBuzzSharp')]
|
||||
if a.component == 'all':
|
||||
files += [(angle_out / ('obj/lib' + name + '_static.a'), name) for name in ('ANGLE', 'GLESv2', 'EGL')]
|
||||
manifest = dict(target=a.target, sources=lock, toolchain=config, archives={})
|
||||
manifest['build_variant'] = variant
|
||||
manifest['skia_capabilities'] = capabilities
|
||||
if linux:
|
||||
manifest['linux_sdk_packages'] = json.loads((HERE / ('linux-sysroots-musl.lock.json' if 'musl' in a.target else 'linux-sysroots.lock.json')).read_text())[a.target]
|
||||
manifest['toolchain_inputs'] = json.loads((HERE / 'cross-toolchain.lock.json').read_text())
|
||||
manifest['gn_sha256'] = {str(path): hashlib.sha256(path.read_bytes()).hexdigest()
|
||||
for path in (a.skia / 'bin/gn', a.angle_gn)}
|
||||
manifest['recipe_sha256'] = {str(path.relative_to(HERE)): hashlib.sha256(path.read_bytes()).hexdigest()
|
||||
for path in sorted(HERE.rglob('*')) if path.is_file() and (path.suffix in ('.py', '.in', '.patch', '.c') or path.name in ('cross-toolchain.lock.json', 'linux-sysroots.lock.json', 'linux-sysroots-musl.lock.json'))}
|
||||
packages = Path('/opt/staticlink/packages.lock')
|
||||
if packages.is_file():
|
||||
shutil.copy2(packages, a.output / 'toolchain-packages.lock')
|
||||
manifest['packages_sha256'] = hashlib.sha256(packages.read_bytes()).hexdigest()
|
||||
for source, name in files:
|
||||
dest = a.output / ('lib' + name + '.a')
|
||||
shutil.copy2(source, dest)
|
||||
manifest['archives'][dest.name] = hashlib.sha256(dest.read_bytes()).hexdigest()
|
||||
run([sys.executable, HERE / 'link-cross.py', '--toolchain', tools, '--skia', a.skia,
|
||||
'--angle', a.angle, '--libraries', a.output, '--output', a.output / 'link-tests', '--component', a.component])
|
||||
if a.target == 'win-x86':
|
||||
run([sys.executable, HERE / 'x86-thunks.py', '--source', a.skia.parent.parent,
|
||||
'--toolchain', tools, '--libraries', a.output])
|
||||
manifest['link_tests'] = 'passed; target runtime tests still required'
|
||||
(a.output / 'cross-build.json').write_text(json.dumps(manifest, indent=2) + '\n')
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@@ -1,10 +0,0 @@
|
||||
{
|
||||
"zig_version": "0.14.1",
|
||||
"macos_sdk_version": "15.5",
|
||||
"macos_sdk_sha256": "c15cf0f3f17d714d1aa5a642da8e118db53d79429eb015771ba816aa7c6c1cbd",
|
||||
"mingw_headers_version": "11.0.1-3build1",
|
||||
"mingw_package_sha256": "4a42fd30fbc3838c58c929d8a4882682fc12408bb7a0e6cafa913c0f0a57c187",
|
||||
"llvm_availability_revision": "llvmorg-19.1.7",
|
||||
"llvm_availability_sha256": "bc0b9f10e8d1a1ac5905d710f1c9fead23878e31233748d580393edc4e3bfc18",
|
||||
"angle_gn_revision": "e331ddb6e93389abfc75c611690bb82f5274029e"
|
||||
}
|
||||
@@ -1,39 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Materialize target SDK libraries from immutable, checksum-locked packages."""
|
||||
import argparse,json,hashlib,urllib.request,tarfile,subprocess
|
||||
from pathlib import Path
|
||||
p=argparse.ArgumentParser();p.add_argument('--output',type=Path,required=True);p.add_argument('--locks',type=Path,nargs='+',required=True);a=p.parse_args()
|
||||
for lock in a.locks:
|
||||
for rid,packages in json.loads(lock.read_text()).items():
|
||||
dest=a.output/rid;dest.mkdir(parents=True,exist_ok=True)
|
||||
for package in packages:
|
||||
with urllib.request.urlopen(package['url'],timeout=90) as response:data=response.read()
|
||||
if hashlib.sha256(data).hexdigest()!=package['sha256']:raise SystemExit('SDK checksum mismatch: '+package['name'])
|
||||
path=a.output/(rid+'-'+Path(package['url']).name);path.write_bytes(data)
|
||||
if path.suffix=='.deb':subprocess.run(['dpkg-deb','--extract',str(path),str(dest)],check=True)
|
||||
else:
|
||||
with tarfile.open(path,mode='r:gz',ignore_zeros=True) as tar:
|
||||
members=[m for m in tar.getmembers() if m.name.startswith(('lib/','usr/lib/','usr/include/','etc/fonts/'))]
|
||||
for m in members:
|
||||
if m.issym() and m.linkname.startswith('/'):
|
||||
import posixpath
|
||||
m.linkname=posixpath.relpath(m.linkname.lstrip('/'),posixpath.dirname(m.name))
|
||||
# Debian 12's pinned Python 3.11 has no extraction-filter API.
|
||||
# Validate paths and links explicitly before extracting locked APK files.
|
||||
root=dest.resolve()
|
||||
for m in members:
|
||||
target=(root/m.name).resolve()
|
||||
if not target.is_relative_to(root):raise SystemExit('Unsafe SDK archive path: '+m.name)
|
||||
if not (m.isfile() or m.isdir() or m.issym() or m.islnk()):raise SystemExit('Unsupported SDK archive entry: '+m.name)
|
||||
if m.issym() or m.islnk():
|
||||
link=(target.parent/m.linkname if m.issym() else root/m.linkname).resolve()
|
||||
if not link.is_relative_to(root):raise SystemExit('Unsafe SDK archive link: '+m.name)
|
||||
tar.extractall(dest,members=members)
|
||||
path.unlink()
|
||||
print(rid,package['name'],package['version'],flush=True)
|
||||
# Copy only platform headers; never replace Zig's target libc headers with the host's.
|
||||
import shutil
|
||||
headers=a.output.parent/'staticlink/linux-headers';headers.mkdir(parents=True,exist_ok=True)
|
||||
for name in ('fontconfig','X11','xcb','GL','KHR','EGL','freetype2','libdrm'):
|
||||
src=a.output/'linux-x64/usr/include'/name
|
||||
if src.is_dir():shutil.copytree(src,headers/name,dirs_exist_ok=True,symlinks=True)
|
||||
@@ -1,100 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Link raster/HarfBuzz and EGL/GLES executables against cross-built archives."""
|
||||
import argparse
|
||||
import json
|
||||
from pathlib import Path
|
||||
import subprocess
|
||||
import re
|
||||
|
||||
HERE = Path(__file__).resolve().parent
|
||||
|
||||
|
||||
def main():
|
||||
p = argparse.ArgumentParser(description=__doc__)
|
||||
p.add_argument('--toolchain', type=Path, required=True)
|
||||
p.add_argument('--skia', type=Path, required=True)
|
||||
p.add_argument('--angle', type=Path, required=True)
|
||||
p.add_argument('--libraries', type=Path, required=True)
|
||||
p.add_argument('--output', type=Path, required=True)
|
||||
p.add_argument('--component', choices=['all', 'skia'], default='all')
|
||||
a = p.parse_args()
|
||||
config = json.loads((a.toolchain / 'toolchain.json').read_text())
|
||||
windows = 'windows' in config['target']
|
||||
a.output.mkdir(parents=True, exist_ok=True)
|
||||
target = config['target']
|
||||
flags = []
|
||||
mac = 'macos' in target
|
||||
linux = 'linux' in target
|
||||
if mac:
|
||||
# ANGLE's pinned Chromium build has a macOS 13 deployment minimum.
|
||||
target = target.split('-macos.')[0] + '-macos.13.0'
|
||||
sdk = config['sdk']
|
||||
flags = ['-isysroot', sdk, '-L' + sdk + '/usr/lib', '-F' + sdk + '/System/Library/Frameworks']
|
||||
for name in (('raster', 'angle') if a.component == 'all' else ('raster',)):
|
||||
obj = a.output / ('smoke-' + name + '.o')
|
||||
includes = [a.skia, a.skia / 'third_party/externals/harfbuzz/src', a.angle / 'include']
|
||||
command = [str(a.toolchain / 'cc')]
|
||||
if name == 'angle':
|
||||
command.extend(('-DANGLE_STATIC=1', '-DKHRONOS_STATIC'))
|
||||
else:
|
||||
header = (a.skia / 'include/core/SkMilestone.h').read_text()
|
||||
match = re.search(r'^\s*#define\s+SK_MILESTONE\s+(\d+)', header, re.MULTILINE)
|
||||
if not match:
|
||||
raise SystemExit('Cannot discover the Skia milestone; inspect the new source layout')
|
||||
command.append('-DSTATICLINK_EXPECTED_MILESTONE=' + match[1])
|
||||
command += ['-I' + str(path) for path in includes]
|
||||
command += ['-c', str(HERE / ('smoke-' + name + '.c')), '-o', str(obj)]
|
||||
subprocess.run(command, check=True)
|
||||
libs = ('SkiaSharp', 'skia', 'HarfBuzzSharp') if name == 'raster' else ('EGL', 'GLESv2', 'ANGLE')
|
||||
command = [config['zig'], 'c++', '-target', target, '-O2', *flags, str(obj)]
|
||||
command += [str(a.libraries / ('lib' + library + '.a')) for library in libs]
|
||||
if windows:
|
||||
command += ['-l' + lib for lib in ('dwrite', 'gdi32', 'ole32', 'oleaut32', 'user32', 'uuid',
|
||||
'windowscodecs', 'dxguid', 'dxgi', 'd3d11', 'd3d9', 'dwmapi', 'shlwapi', 'setupapi', 'version', 'advapi32', 'api-ms-win-core-synch-l1-2-0')]
|
||||
elif mac:
|
||||
for framework in ('CoreFoundation', 'CoreGraphics', 'CoreText', 'Foundation', 'AppKit',
|
||||
'Metal', 'QuartzCore', 'OpenGL', 'IOKit', 'IOSurface'):
|
||||
command += ['-framework', framework]
|
||||
command += ['-lobjc']
|
||||
availability = a.toolchain / 'os_version_check.o'
|
||||
if availability.is_file():
|
||||
command.append(str(availability))
|
||||
elif linux:
|
||||
sysroot = Path(config.get('linux_sysroot') or '/')
|
||||
for path in (sysroot / 'usr/lib', sysroot / 'lib', sysroot / 'usr/lib' / ('x86_64-linux-gnu' if target.startswith('x86_64') else 'aarch64-linux-gnu')):
|
||||
if path.is_dir():
|
||||
command += ['-L' + str(path)]
|
||||
command += ['-lfontconfig', '-ldl', '-lm', '-lpthread'] if name == 'raster' else ['-lX11', '-lXext', '-lxcb', '-lwayland-client', '-lwayland-egl', '-lffi', '-ldl', '-lm', '-lpthread']
|
||||
command += ['-v']
|
||||
command += ['-o', str(a.output / ('smoke-' + name + ('.exe' if windows else '')))]
|
||||
result = subprocess.run(command, capture_output=True, text=True)
|
||||
print(result.stdout, end='')
|
||||
print(result.stderr, end='')
|
||||
result.check_returncode()
|
||||
# Keep the exact runtime archives chosen by this Zig target. AOT consumes
|
||||
# these without substituting the consumer machine's C++ toolchain.
|
||||
import shlex, shutil
|
||||
runtimes = {}
|
||||
project_archives = {path.resolve() for path in a.libraries.glob('lib*.a')}
|
||||
for line in (result.stdout + '\n' + result.stderr).splitlines():
|
||||
try:
|
||||
tokens = shlex.split(line)
|
||||
except ValueError:
|
||||
continue
|
||||
for token in tokens:
|
||||
path = Path(token)
|
||||
if path.suffix in ('.a', '.lib') and path.is_file() and path.resolve() not in project_archives and not path.resolve().is_relative_to(a.libraries.resolve()):
|
||||
dest = a.libraries / 'zig-runtime' / path.name
|
||||
dest.parent.mkdir(exist_ok=True)
|
||||
shutil.copy2(path, dest)
|
||||
runtimes[path.name] = str(path)
|
||||
descriptor = a.libraries / 'zig-runtime' / 'inputs.json'
|
||||
if descriptor.exists():
|
||||
runtimes = dict(json.loads(descriptor.read_text()), **runtimes)
|
||||
descriptor.parent.mkdir(exist_ok=True)
|
||||
descriptor.write_text(json.dumps(runtimes, indent=2) + '\n')
|
||||
print('Executable link tests passed. Run them on the target OS to validate behavior.')
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@@ -1,474 +0,0 @@
|
||||
{
|
||||
"linux-musl-x64": [
|
||||
{
|
||||
"name": "brotli-dev",
|
||||
"version": "1.2.0-r0",
|
||||
"url": "https://dl-cdn.alpinelinux.org/alpine/v3.23/main/x86_64/brotli-dev-1.2.0-r0.apk",
|
||||
"sha256": "f61bd37140c76a22e97ad9d7461becda5d41526bbee1a8bc2523edad5ae6f35e"
|
||||
},
|
||||
{
|
||||
"name": "brotli-libs",
|
||||
"version": "1.2.0-r0",
|
||||
"url": "https://dl-cdn.alpinelinux.org/alpine/v3.23/main/x86_64/brotli-libs-1.2.0-r0.apk",
|
||||
"sha256": "09fbf1ddf0c71c6c4ab7bc12aef3452d8ace5adeab10c4c30214fc70f5e0e087"
|
||||
},
|
||||
{
|
||||
"name": "bzip2-dev",
|
||||
"version": "1.0.8-r6",
|
||||
"url": "https://dl-cdn.alpinelinux.org/alpine/v3.23/main/x86_64/bzip2-dev-1.0.8-r6.apk",
|
||||
"sha256": "59a73f8712a9c0c16553a759149ee5ecf87a6160ef021aeb922ddb0c0b3a695b"
|
||||
},
|
||||
{
|
||||
"name": "expat",
|
||||
"version": "2.8.5-r0",
|
||||
"url": "https://dl-cdn.alpinelinux.org/alpine/v3.23/main/x86_64/expat-2.8.5-r0.apk",
|
||||
"sha256": "19f3d19d7deb82e357a70cb30b38dd81fa1cbecdb7e0a834071e993d5df18246"
|
||||
},
|
||||
{
|
||||
"name": "expat-dev",
|
||||
"version": "2.8.5-r0",
|
||||
"url": "https://dl-cdn.alpinelinux.org/alpine/v3.23/main/x86_64/expat-dev-2.8.5-r0.apk",
|
||||
"sha256": "5a31977673fbdacf195d372114501c06b18eb1f24553c99b92e47e0e24478f9e"
|
||||
},
|
||||
{
|
||||
"name": "fontconfig",
|
||||
"version": "2.17.1-r0",
|
||||
"url": "https://dl-cdn.alpinelinux.org/alpine/v3.23/main/x86_64/fontconfig-2.17.1-r0.apk",
|
||||
"sha256": "f44cea53076f18428dad0c27c75ca717ebfc3d2f0f4c8d4428ce70b62e25adf1"
|
||||
},
|
||||
{
|
||||
"name": "fontconfig-dev",
|
||||
"version": "2.17.1-r0",
|
||||
"url": "https://dl-cdn.alpinelinux.org/alpine/v3.23/main/x86_64/fontconfig-dev-2.17.1-r0.apk",
|
||||
"sha256": "e819dd0eb3f2a2a4f802a16911959e1232b323c4e2db9ce020c3d52e9bfd5053"
|
||||
},
|
||||
{
|
||||
"name": "freetype",
|
||||
"version": "2.14.3-r0",
|
||||
"url": "https://dl-cdn.alpinelinux.org/alpine/v3.23/main/x86_64/freetype-2.14.3-r0.apk",
|
||||
"sha256": "670c9922ab4eb9df65c0e4ad7839bbe3f486016fc1fb637c46d657b74d99a24f"
|
||||
},
|
||||
{
|
||||
"name": "freetype-dev",
|
||||
"version": "2.14.3-r0",
|
||||
"url": "https://dl-cdn.alpinelinux.org/alpine/v3.23/main/x86_64/freetype-dev-2.14.3-r0.apk",
|
||||
"sha256": "85a90244c039722c409996e5e5e65d4751664984ed1843a00c5d751577627972"
|
||||
},
|
||||
{
|
||||
"name": "libbsd",
|
||||
"version": "0.12.2-r0",
|
||||
"url": "https://dl-cdn.alpinelinux.org/alpine/v3.23/main/x86_64/libbsd-0.12.2-r0.apk",
|
||||
"sha256": "1252092dea853063252bbdaf9fa604819055b004ba3114b88b842fbfe44659e9"
|
||||
},
|
||||
{
|
||||
"name": "libbz2",
|
||||
"version": "1.0.8-r6",
|
||||
"url": "https://dl-cdn.alpinelinux.org/alpine/v3.23/main/x86_64/libbz2-1.0.8-r6.apk",
|
||||
"sha256": "9995840a76ac97ec006259391b7a81b73b73c5cf2f462bf12bb2250afbf665b9"
|
||||
},
|
||||
{
|
||||
"name": "libexpat",
|
||||
"version": "2.8.5-r0",
|
||||
"url": "https://dl-cdn.alpinelinux.org/alpine/v3.23/main/x86_64/libexpat-2.8.5-r0.apk",
|
||||
"sha256": "5216046085b92da88a6b107dbbb558f69d49c347a6335291fcf199ebd1670a8f"
|
||||
},
|
||||
{
|
||||
"name": "libffi",
|
||||
"version": "3.5.2-r0",
|
||||
"url": "https://dl-cdn.alpinelinux.org/alpine/v3.23/main/x86_64/libffi-3.5.2-r0.apk",
|
||||
"sha256": "0b3473a1468bed5fbb913a1ffa121e253080b21b013fe47e0300bd7e85224e76"
|
||||
},
|
||||
{
|
||||
"name": "libffi-dev",
|
||||
"version": "3.5.2-r0",
|
||||
"url": "https://dl-cdn.alpinelinux.org/alpine/v3.23/main/x86_64/libffi-dev-3.5.2-r0.apk",
|
||||
"sha256": "737a9109fc4a763465cc117ca20edd18d4ea3fe9ed6f717251aa744b8ebbaba6"
|
||||
},
|
||||
{
|
||||
"name": "libmd",
|
||||
"version": "1.1.0-r0",
|
||||
"url": "https://dl-cdn.alpinelinux.org/alpine/v3.23/main/x86_64/libmd-1.1.0-r0.apk",
|
||||
"sha256": "704446100fb39f2699d848d97f09463dd6fdd35f3a1acb038483712e1e37f766"
|
||||
},
|
||||
{
|
||||
"name": "libpng",
|
||||
"version": "1.6.59-r0",
|
||||
"url": "https://dl-cdn.alpinelinux.org/alpine/v3.23/main/x86_64/libpng-1.6.59-r0.apk",
|
||||
"sha256": "148a10e3d6419f787b16edbc2d0bb19d12a2a078225baaa416c895c14f47fc1e"
|
||||
},
|
||||
{
|
||||
"name": "libpng-dev",
|
||||
"version": "1.6.59-r0",
|
||||
"url": "https://dl-cdn.alpinelinux.org/alpine/v3.23/main/x86_64/libpng-dev-1.6.59-r0.apk",
|
||||
"sha256": "01b89d3cea124fed78359b71f77e4d545de6e3163077167947e6adf84bdcb595"
|
||||
},
|
||||
{
|
||||
"name": "libx11",
|
||||
"version": "1.8.12-r1",
|
||||
"url": "https://dl-cdn.alpinelinux.org/alpine/v3.23/main/x86_64/libx11-1.8.12-r1.apk",
|
||||
"sha256": "cbc478a642226812ab13688bfe9ec69c86cf0e8e037dba7cfd055e8d7741f30c"
|
||||
},
|
||||
{
|
||||
"name": "libx11-dev",
|
||||
"version": "1.8.12-r1",
|
||||
"url": "https://dl-cdn.alpinelinux.org/alpine/v3.23/main/x86_64/libx11-dev-1.8.12-r1.apk",
|
||||
"sha256": "91eac12015dffbeb06b2755eae52722b1740018d775db33fbe68abc353b951df"
|
||||
},
|
||||
{
|
||||
"name": "libxau",
|
||||
"version": "1.0.12-r0",
|
||||
"url": "https://dl-cdn.alpinelinux.org/alpine/v3.23/main/x86_64/libxau-1.0.12-r0.apk",
|
||||
"sha256": "61ee983ec9d47821cae9b3e1c8245a5b0b228361839be9b596a42c817b691a9f"
|
||||
},
|
||||
{
|
||||
"name": "libxau-dev",
|
||||
"version": "1.0.12-r0",
|
||||
"url": "https://dl-cdn.alpinelinux.org/alpine/v3.23/main/x86_64/libxau-dev-1.0.12-r0.apk",
|
||||
"sha256": "2af8a78f1deaf398e96964f17d5640e3448fc5e935392e3550283e8d7c54a6cc"
|
||||
},
|
||||
{
|
||||
"name": "libxcb",
|
||||
"version": "1.17.0-r1",
|
||||
"url": "https://dl-cdn.alpinelinux.org/alpine/v3.23/main/x86_64/libxcb-1.17.0-r1.apk",
|
||||
"sha256": "f73934506edfdcb6895f04e313481ca48592ac4cec59cdb8fc073a7681bfbd31"
|
||||
},
|
||||
{
|
||||
"name": "libxcb-dev",
|
||||
"version": "1.17.0-r1",
|
||||
"url": "https://dl-cdn.alpinelinux.org/alpine/v3.23/main/x86_64/libxcb-dev-1.17.0-r1.apk",
|
||||
"sha256": "8735d97a346eae3999a599e49eb533481478d0ef9466e6e5a5453dd1e3ae8f3d"
|
||||
},
|
||||
{
|
||||
"name": "libxdmcp",
|
||||
"version": "1.1.5-r1",
|
||||
"url": "https://dl-cdn.alpinelinux.org/alpine/v3.23/main/x86_64/libxdmcp-1.1.5-r1.apk",
|
||||
"sha256": "f134d28babb070834066aa716c303768ed0ede32ac086f3dfbd8cbbac62380ee"
|
||||
},
|
||||
{
|
||||
"name": "libxdmcp-dev",
|
||||
"version": "1.1.5-r1",
|
||||
"url": "https://dl-cdn.alpinelinux.org/alpine/v3.23/main/x86_64/libxdmcp-dev-1.1.5-r1.apk",
|
||||
"sha256": "d8a304762ea4295287ef1adf9d93d64f04bdfc4e845b453698b3276b12e8fc10"
|
||||
},
|
||||
{
|
||||
"name": "libxext",
|
||||
"version": "1.3.6-r2",
|
||||
"url": "https://dl-cdn.alpinelinux.org/alpine/v3.23/main/x86_64/libxext-1.3.6-r2.apk",
|
||||
"sha256": "404beb855daf09fdb8d15f177a3608da62825a44497a805675a186171c04eb6c"
|
||||
},
|
||||
{
|
||||
"name": "libxext-dev",
|
||||
"version": "1.3.6-r2",
|
||||
"url": "https://dl-cdn.alpinelinux.org/alpine/v3.23/main/x86_64/libxext-dev-1.3.6-r2.apk",
|
||||
"sha256": "ebb6262372a918a6bee4ff2137dacdb1fa13be78d0e3544a082d6530ce8e05b6"
|
||||
},
|
||||
{
|
||||
"name": "libxml2",
|
||||
"version": "2.13.9-r1",
|
||||
"url": "https://dl-cdn.alpinelinux.org/alpine/v3.23/main/x86_64/libxml2-2.13.9-r1.apk",
|
||||
"sha256": "1af363248efb54914993bbd516c89878c2b5b0c53be0c78bb43d5a3e9a8ceda6"
|
||||
},
|
||||
{
|
||||
"name": "mesa-dev",
|
||||
"version": "25.2.7-r1",
|
||||
"url": "https://dl-cdn.alpinelinux.org/alpine/v3.23/main/x86_64/mesa-dev-25.2.7-r1.apk",
|
||||
"sha256": "da17f767ae27fc8ff9a958ff82d217ee3a890d888b43e6a62171a402b48156a1"
|
||||
},
|
||||
{
|
||||
"name": "musl",
|
||||
"version": "1.2.5-r23",
|
||||
"url": "https://dl-cdn.alpinelinux.org/alpine/v3.23/main/x86_64/musl-1.2.5-r23.apk",
|
||||
"sha256": "4f3c4a7bf9f51d2c91007e333b17459362ffd881b4a343e8da07b6c50c4f4a0d"
|
||||
},
|
||||
{
|
||||
"name": "wayland-dev",
|
||||
"version": "1.24.0-r0",
|
||||
"url": "https://dl-cdn.alpinelinux.org/alpine/v3.23/main/x86_64/wayland-dev-1.24.0-r0.apk",
|
||||
"sha256": "5afcb3e3c414d2c0e602bc9ef1b4868fd7df9e53aec55f3f722ce4897019f014"
|
||||
},
|
||||
{
|
||||
"name": "wayland-libs-client",
|
||||
"version": "1.24.0-r0",
|
||||
"url": "https://dl-cdn.alpinelinux.org/alpine/v3.23/main/x86_64/wayland-libs-client-1.24.0-r0.apk",
|
||||
"sha256": "020313c601f85a9e91d1ae0d01e9f1e9905d1127b78dce9c278a75cfd52416d2"
|
||||
},
|
||||
{
|
||||
"name": "wayland-libs-cursor",
|
||||
"version": "1.24.0-r0",
|
||||
"url": "https://dl-cdn.alpinelinux.org/alpine/v3.23/main/x86_64/wayland-libs-cursor-1.24.0-r0.apk",
|
||||
"sha256": "e87fb03656132b550182b019b7f3218f336ff9637dc574ef0f22a0ad148f8577"
|
||||
},
|
||||
{
|
||||
"name": "wayland-libs-egl",
|
||||
"version": "1.24.0-r0",
|
||||
"url": "https://dl-cdn.alpinelinux.org/alpine/v3.23/main/x86_64/wayland-libs-egl-1.24.0-r0.apk",
|
||||
"sha256": "2d9165a79e7e779b52dd203959f64eb8f7caad460f3e6d76097efc432e115936"
|
||||
},
|
||||
{
|
||||
"name": "wayland-libs-server",
|
||||
"version": "1.24.0-r0",
|
||||
"url": "https://dl-cdn.alpinelinux.org/alpine/v3.23/main/x86_64/wayland-libs-server-1.24.0-r0.apk",
|
||||
"sha256": "c30fd5c6f081732670e7dd69316df73cb3939b8c53237314ca1ec3f991b2a1f7"
|
||||
},
|
||||
{
|
||||
"name": "xorgproto",
|
||||
"version": "2024.1-r0",
|
||||
"url": "https://dl-cdn.alpinelinux.org/alpine/v3.23/main/x86_64/xorgproto-2024.1-r0.apk",
|
||||
"sha256": "96e2b99a0227d301170ae840c37693d65c767dd0a15a1243ced45325850ad424"
|
||||
},
|
||||
{
|
||||
"name": "xz-libs",
|
||||
"version": "5.8.4-r0",
|
||||
"url": "https://dl-cdn.alpinelinux.org/alpine/v3.23/main/x86_64/xz-libs-5.8.4-r0.apk",
|
||||
"sha256": "3c8cc415e88c2a097543d9ee828081ec1905e7d0f57a319c8896269b0e00a672"
|
||||
},
|
||||
{
|
||||
"name": "zlib",
|
||||
"version": "1.3.2-r0",
|
||||
"url": "https://dl-cdn.alpinelinux.org/alpine/v3.23/main/x86_64/zlib-1.3.2-r0.apk",
|
||||
"sha256": "f56dea63692059bd65854bb179b7551971a441000b0d98c5b031291ca0450b56"
|
||||
},
|
||||
{
|
||||
"name": "zlib-dev",
|
||||
"version": "1.3.2-r0",
|
||||
"url": "https://dl-cdn.alpinelinux.org/alpine/v3.23/main/x86_64/zlib-dev-1.3.2-r0.apk",
|
||||
"sha256": "c811e48ea401e05479a74d93f8ac820bbb6af44b2adf0335769316e5cc2b72c4"
|
||||
}
|
||||
],
|
||||
"linux-musl-arm64": [
|
||||
{
|
||||
"name": "brotli-dev",
|
||||
"version": "1.2.0-r0",
|
||||
"url": "https://dl-cdn.alpinelinux.org/alpine/v3.23/main/aarch64/brotli-dev-1.2.0-r0.apk",
|
||||
"sha256": "012c9917e3a3f37efbb255fdff240d4fe0ee83a2e4e5d7511eddcce57a2daa30"
|
||||
},
|
||||
{
|
||||
"name": "brotli-libs",
|
||||
"version": "1.2.0-r0",
|
||||
"url": "https://dl-cdn.alpinelinux.org/alpine/v3.23/main/aarch64/brotli-libs-1.2.0-r0.apk",
|
||||
"sha256": "c8a9113b0007d40291e55cfc196744b64004253707e37b3c07e188166fb2d0a0"
|
||||
},
|
||||
{
|
||||
"name": "bzip2-dev",
|
||||
"version": "1.0.8-r6",
|
||||
"url": "https://dl-cdn.alpinelinux.org/alpine/v3.23/main/aarch64/bzip2-dev-1.0.8-r6.apk",
|
||||
"sha256": "69d79bb497c25e81fce8695653f448666c08bc8b28fa51506b74b38946a0a03a"
|
||||
},
|
||||
{
|
||||
"name": "expat",
|
||||
"version": "2.8.5-r0",
|
||||
"url": "https://dl-cdn.alpinelinux.org/alpine/v3.23/main/aarch64/expat-2.8.5-r0.apk",
|
||||
"sha256": "b5b520d2bd7a89e8fbad6a59667f70d4656326dd8a4df84c3e5ef4b5c0056243"
|
||||
},
|
||||
{
|
||||
"name": "expat-dev",
|
||||
"version": "2.8.5-r0",
|
||||
"url": "https://dl-cdn.alpinelinux.org/alpine/v3.23/main/aarch64/expat-dev-2.8.5-r0.apk",
|
||||
"sha256": "2aad86f9f50aeb5b3c7a0e4022693dd810f51ec9c7a28037f3d2e71dbd9ecb1e"
|
||||
},
|
||||
{
|
||||
"name": "fontconfig",
|
||||
"version": "2.17.1-r0",
|
||||
"url": "https://dl-cdn.alpinelinux.org/alpine/v3.23/main/aarch64/fontconfig-2.17.1-r0.apk",
|
||||
"sha256": "38e815b8f898482e3c8111ac158208ba0a6a9aa13dbef49ccc36b36df77c793e"
|
||||
},
|
||||
{
|
||||
"name": "fontconfig-dev",
|
||||
"version": "2.17.1-r0",
|
||||
"url": "https://dl-cdn.alpinelinux.org/alpine/v3.23/main/aarch64/fontconfig-dev-2.17.1-r0.apk",
|
||||
"sha256": "5661ba91c9da743151b333a69b05f467f5c4145395f3d54567e7e9999aa8d842"
|
||||
},
|
||||
{
|
||||
"name": "freetype",
|
||||
"version": "2.14.3-r0",
|
||||
"url": "https://dl-cdn.alpinelinux.org/alpine/v3.23/main/aarch64/freetype-2.14.3-r0.apk",
|
||||
"sha256": "b1012afa50bdebe872fab255b1c6db8c2c05b0dc4fc274c48d714e1887401b4e"
|
||||
},
|
||||
{
|
||||
"name": "freetype-dev",
|
||||
"version": "2.14.3-r0",
|
||||
"url": "https://dl-cdn.alpinelinux.org/alpine/v3.23/main/aarch64/freetype-dev-2.14.3-r0.apk",
|
||||
"sha256": "cd8d91f81c9477f0f76fd8db8158237fa99b1e0f73f6ec6e929bfc46b076b51d"
|
||||
},
|
||||
{
|
||||
"name": "libbsd",
|
||||
"version": "0.12.2-r0",
|
||||
"url": "https://dl-cdn.alpinelinux.org/alpine/v3.23/main/aarch64/libbsd-0.12.2-r0.apk",
|
||||
"sha256": "358715f27bfe492dcb11f3589c8f106c37071780f55adafc52b2c5cfd3771e4d"
|
||||
},
|
||||
{
|
||||
"name": "libbz2",
|
||||
"version": "1.0.8-r6",
|
||||
"url": "https://dl-cdn.alpinelinux.org/alpine/v3.23/main/aarch64/libbz2-1.0.8-r6.apk",
|
||||
"sha256": "ccd478f4d5346a25911d4ee977690e2695e0ca3acf3e6b1a8c1300b2f4311e2f"
|
||||
},
|
||||
{
|
||||
"name": "libexpat",
|
||||
"version": "2.8.5-r0",
|
||||
"url": "https://dl-cdn.alpinelinux.org/alpine/v3.23/main/aarch64/libexpat-2.8.5-r0.apk",
|
||||
"sha256": "18e5a4f1715dd9fee420d250d14be9e59936352929085939f33da01c3fbde28d"
|
||||
},
|
||||
{
|
||||
"name": "libffi",
|
||||
"version": "3.5.2-r0",
|
||||
"url": "https://dl-cdn.alpinelinux.org/alpine/v3.23/main/aarch64/libffi-3.5.2-r0.apk",
|
||||
"sha256": "ebf430b246a6b1167350431e2af59a09f4edbc42dc3e03f3b9d74800ba5f9e7f"
|
||||
},
|
||||
{
|
||||
"name": "libffi-dev",
|
||||
"version": "3.5.2-r0",
|
||||
"url": "https://dl-cdn.alpinelinux.org/alpine/v3.23/main/aarch64/libffi-dev-3.5.2-r0.apk",
|
||||
"sha256": "96830dcf534e196258838122fcaae6582ea02c957413a31e53a86ae403db0478"
|
||||
},
|
||||
{
|
||||
"name": "libmd",
|
||||
"version": "1.1.0-r0",
|
||||
"url": "https://dl-cdn.alpinelinux.org/alpine/v3.23/main/aarch64/libmd-1.1.0-r0.apk",
|
||||
"sha256": "8818536cdc38dd3c252d6c6915f65ddd49390aa209cc7f70b87c446adedf820c"
|
||||
},
|
||||
{
|
||||
"name": "libpng",
|
||||
"version": "1.6.59-r0",
|
||||
"url": "https://dl-cdn.alpinelinux.org/alpine/v3.23/main/aarch64/libpng-1.6.59-r0.apk",
|
||||
"sha256": "087102199da459dd8985c118a67d6d6c463de6798f243424feb239d1087b1064"
|
||||
},
|
||||
{
|
||||
"name": "libpng-dev",
|
||||
"version": "1.6.59-r0",
|
||||
"url": "https://dl-cdn.alpinelinux.org/alpine/v3.23/main/aarch64/libpng-dev-1.6.59-r0.apk",
|
||||
"sha256": "9f7a8ceb60638786dd675ccc526668516a8ca4df4b54daa05f526df12f76c7bd"
|
||||
},
|
||||
{
|
||||
"name": "libx11",
|
||||
"version": "1.8.12-r1",
|
||||
"url": "https://dl-cdn.alpinelinux.org/alpine/v3.23/main/aarch64/libx11-1.8.12-r1.apk",
|
||||
"sha256": "7f53f6f26293abac468b9563f2a90bc9a34306ec8a677af23d01d7455e3db943"
|
||||
},
|
||||
{
|
||||
"name": "libx11-dev",
|
||||
"version": "1.8.12-r1",
|
||||
"url": "https://dl-cdn.alpinelinux.org/alpine/v3.23/main/aarch64/libx11-dev-1.8.12-r1.apk",
|
||||
"sha256": "114785b13b6df10d7997e9e8e12bf95fd5f0e6644fd420fa84dcfc0956cdecb9"
|
||||
},
|
||||
{
|
||||
"name": "libxau",
|
||||
"version": "1.0.12-r0",
|
||||
"url": "https://dl-cdn.alpinelinux.org/alpine/v3.23/main/aarch64/libxau-1.0.12-r0.apk",
|
||||
"sha256": "ddfad479041b53e5f57a2fdfac12454993ae3937f6f893d67cd98cbd63abfcf0"
|
||||
},
|
||||
{
|
||||
"name": "libxau-dev",
|
||||
"version": "1.0.12-r0",
|
||||
"url": "https://dl-cdn.alpinelinux.org/alpine/v3.23/main/aarch64/libxau-dev-1.0.12-r0.apk",
|
||||
"sha256": "bed89cb8971efccf37f0a77d6cddcd31f122a322d04fc75117cddb48804c2290"
|
||||
},
|
||||
{
|
||||
"name": "libxcb",
|
||||
"version": "1.17.0-r1",
|
||||
"url": "https://dl-cdn.alpinelinux.org/alpine/v3.23/main/aarch64/libxcb-1.17.0-r1.apk",
|
||||
"sha256": "8609cadcd7af03c1aade3663fdf3bbe27e4180fe0edbe98d3f12f0ae6e95aedc"
|
||||
},
|
||||
{
|
||||
"name": "libxcb-dev",
|
||||
"version": "1.17.0-r1",
|
||||
"url": "https://dl-cdn.alpinelinux.org/alpine/v3.23/main/aarch64/libxcb-dev-1.17.0-r1.apk",
|
||||
"sha256": "f6d1488df536002017c10a435caa32f9527ec9ad5aa86cbab639cde4258a2b67"
|
||||
},
|
||||
{
|
||||
"name": "libxdmcp",
|
||||
"version": "1.1.5-r1",
|
||||
"url": "https://dl-cdn.alpinelinux.org/alpine/v3.23/main/aarch64/libxdmcp-1.1.5-r1.apk",
|
||||
"sha256": "f95a668a5b8888aadbee24e8ffb30f60e4d40cdf8ef61b35383e7ecf49182c66"
|
||||
},
|
||||
{
|
||||
"name": "libxdmcp-dev",
|
||||
"version": "1.1.5-r1",
|
||||
"url": "https://dl-cdn.alpinelinux.org/alpine/v3.23/main/aarch64/libxdmcp-dev-1.1.5-r1.apk",
|
||||
"sha256": "fa1dd28326caf9e3299bf36a94fa5d62c6f448588044fcf95ddcf2bcaabd9aff"
|
||||
},
|
||||
{
|
||||
"name": "libxext",
|
||||
"version": "1.3.6-r2",
|
||||
"url": "https://dl-cdn.alpinelinux.org/alpine/v3.23/main/aarch64/libxext-1.3.6-r2.apk",
|
||||
"sha256": "bb7e84c1d38e5dcdfdb56e543394469f9c884cb13e09f5e07986863a9bea62e7"
|
||||
},
|
||||
{
|
||||
"name": "libxext-dev",
|
||||
"version": "1.3.6-r2",
|
||||
"url": "https://dl-cdn.alpinelinux.org/alpine/v3.23/main/aarch64/libxext-dev-1.3.6-r2.apk",
|
||||
"sha256": "9b70dc8e575dbc28feed289a4336bc181cc7327886364aefe4bb3bb81a98c49b"
|
||||
},
|
||||
{
|
||||
"name": "libxml2",
|
||||
"version": "2.13.9-r1",
|
||||
"url": "https://dl-cdn.alpinelinux.org/alpine/v3.23/main/aarch64/libxml2-2.13.9-r1.apk",
|
||||
"sha256": "91d3e730edbd5214c501696725e7af9a93e12a9dd6a296e719dca2f3de0697d5"
|
||||
},
|
||||
{
|
||||
"name": "mesa-dev",
|
||||
"version": "25.2.7-r1",
|
||||
"url": "https://dl-cdn.alpinelinux.org/alpine/v3.23/main/aarch64/mesa-dev-25.2.7-r1.apk",
|
||||
"sha256": "a9759357562a1365b35b01a2be05cc33ec3ab0f3a1c1bd079a0b68e4c29ef129"
|
||||
},
|
||||
{
|
||||
"name": "musl",
|
||||
"version": "1.2.5-r23",
|
||||
"url": "https://dl-cdn.alpinelinux.org/alpine/v3.23/main/aarch64/musl-1.2.5-r23.apk",
|
||||
"sha256": "6a3edd924ead1fad88a69e28c5775809af3026b322f58428001cd02fedc5299e"
|
||||
},
|
||||
{
|
||||
"name": "wayland-dev",
|
||||
"version": "1.24.0-r0",
|
||||
"url": "https://dl-cdn.alpinelinux.org/alpine/v3.23/main/aarch64/wayland-dev-1.24.0-r0.apk",
|
||||
"sha256": "681397cc91e05bb6cc63af4b37a59aa510aaab37539c9e6629d7fbfbcb1f0e57"
|
||||
},
|
||||
{
|
||||
"name": "wayland-libs-client",
|
||||
"version": "1.24.0-r0",
|
||||
"url": "https://dl-cdn.alpinelinux.org/alpine/v3.23/main/aarch64/wayland-libs-client-1.24.0-r0.apk",
|
||||
"sha256": "47634dcc2befcae378f9f60681d2af1864db85e57f65e11a3557a43f77911073"
|
||||
},
|
||||
{
|
||||
"name": "wayland-libs-cursor",
|
||||
"version": "1.24.0-r0",
|
||||
"url": "https://dl-cdn.alpinelinux.org/alpine/v3.23/main/aarch64/wayland-libs-cursor-1.24.0-r0.apk",
|
||||
"sha256": "a6f8e01ec409b183693169af006d1edc8b673af801bd540820fdb7808cb5e27b"
|
||||
},
|
||||
{
|
||||
"name": "wayland-libs-egl",
|
||||
"version": "1.24.0-r0",
|
||||
"url": "https://dl-cdn.alpinelinux.org/alpine/v3.23/main/aarch64/wayland-libs-egl-1.24.0-r0.apk",
|
||||
"sha256": "4f2ae7b94f0b6c95dae885c0c24ac59eea5fd2b7a4680cec43dd8366c86564d2"
|
||||
},
|
||||
{
|
||||
"name": "wayland-libs-server",
|
||||
"version": "1.24.0-r0",
|
||||
"url": "https://dl-cdn.alpinelinux.org/alpine/v3.23/main/aarch64/wayland-libs-server-1.24.0-r0.apk",
|
||||
"sha256": "c6bc1243dd337ba638834cd1e7a5ccfd10b6e2315e63af02f441bff581c35c66"
|
||||
},
|
||||
{
|
||||
"name": "xorgproto",
|
||||
"version": "2024.1-r0",
|
||||
"url": "https://dl-cdn.alpinelinux.org/alpine/v3.23/main/aarch64/xorgproto-2024.1-r0.apk",
|
||||
"sha256": "8d53e4b89f3067a4d24f7645127b100a4d46a567eccb82428fe5256c17316b0d"
|
||||
},
|
||||
{
|
||||
"name": "xz-libs",
|
||||
"version": "5.8.4-r0",
|
||||
"url": "https://dl-cdn.alpinelinux.org/alpine/v3.23/main/aarch64/xz-libs-5.8.4-r0.apk",
|
||||
"sha256": "55cec0880e1d06049147cd295a7c8a2909a668fc58a00c187741f3a16c25c55d"
|
||||
},
|
||||
{
|
||||
"name": "zlib",
|
||||
"version": "1.3.2-r0",
|
||||
"url": "https://dl-cdn.alpinelinux.org/alpine/v3.23/main/aarch64/zlib-1.3.2-r0.apk",
|
||||
"sha256": "ecda4cc94fd18f90182f1d3a615889df5e0db9cf78926d11627dd23e06d2e6e8"
|
||||
},
|
||||
{
|
||||
"name": "zlib-dev",
|
||||
"version": "1.3.2-r0",
|
||||
"url": "https://dl-cdn.alpinelinux.org/alpine/v3.23/main/aarch64/zlib-dev-1.3.2-r0.apk",
|
||||
"sha256": "18a7f594ad7439629cb5889e4f0ad71075dd9f0cd4729a0461ba1501e21bc583"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1,594 +0,0 @@
|
||||
{
|
||||
"linux-x64": [
|
||||
{
|
||||
"name": "libbrotli-dev",
|
||||
"version": "1.0.9-2+b6",
|
||||
"url": "https://snapshot.debian.org/archive/debian/20260901T000000Z/pool/main/b/brotli/libbrotli-dev_1.0.9-2+b6_amd64.deb",
|
||||
"sha256": "932de11d4d9caee3300319b2fdf6ca505ca739706be48737df5e40ee90ccb6ca"
|
||||
},
|
||||
{
|
||||
"name": "libbrotli1",
|
||||
"version": "1.0.9-2+b6",
|
||||
"url": "https://snapshot.debian.org/archive/debian/20260901T000000Z/pool/main/b/brotli/libbrotli1_1.0.9-2+b6_amd64.deb",
|
||||
"sha256": "563b4caec1aa5e876bd3355b36e7a38e1484baf5a293b48d1e8bd22db786e4d7"
|
||||
},
|
||||
{
|
||||
"name": "libbsd0",
|
||||
"version": "0.11.7-2",
|
||||
"url": "https://snapshot.debian.org/archive/debian/20260901T000000Z/pool/main/libb/libbsd/libbsd0_0.11.7-2_amd64.deb",
|
||||
"sha256": "bb31cc8b40f962a85b2cec970f7f79cc704a1ae4bad24257a822055404b2c60b"
|
||||
},
|
||||
{
|
||||
"name": "libbz2-1.0",
|
||||
"version": "1.0.8-5+b1",
|
||||
"url": "https://snapshot.debian.org/archive/debian/20260901T000000Z/pool/main/b/bzip2/libbz2-1.0_1.0.8-5+b1_amd64.deb",
|
||||
"sha256": "54149da3f44b22d523b26b692033b84503d822cc5122fed606ea69cc83ca5aeb"
|
||||
},
|
||||
{
|
||||
"name": "libbz2-dev",
|
||||
"version": "1.0.8-5+b1",
|
||||
"url": "https://snapshot.debian.org/archive/debian/20260901T000000Z/pool/main/b/bzip2/libbz2-dev_1.0.8-5+b1_amd64.deb",
|
||||
"sha256": "df7204e188f7514ceae9c6f57c6c8b25ce8a642746fe284c6e89122ef26b7e57"
|
||||
},
|
||||
{
|
||||
"name": "libc6",
|
||||
"version": "2.36-9+deb12u14",
|
||||
"url": "https://snapshot.debian.org/archive/debian/20260901T000000Z/pool/main/g/glibc/libc6_2.36-9+deb12u14_amd64.deb",
|
||||
"sha256": "ba4f88f73dbc3ae9055f3c20f4523bfdbaf1ad13ff95e258924f77d20b4fbedf"
|
||||
},
|
||||
{
|
||||
"name": "libegl-dev",
|
||||
"version": "1.6.0-1",
|
||||
"url": "https://snapshot.debian.org/archive/debian/20260901T000000Z/pool/main/libg/libglvnd/libegl-dev_1.6.0-1_amd64.deb",
|
||||
"sha256": "0ec9bffb024527dfb61eaeae44966e2b5b3114b3dc315b4117b0df95b1c96ef8"
|
||||
},
|
||||
{
|
||||
"name": "libegl1",
|
||||
"version": "1.6.0-1",
|
||||
"url": "https://snapshot.debian.org/archive/debian/20260901T000000Z/pool/main/libg/libglvnd/libegl1_1.6.0-1_amd64.deb",
|
||||
"sha256": "fe4d8b39f6e6fe1a32ab1efd85893553eaa9cf3866aa668ccf355f585b37d523"
|
||||
},
|
||||
{
|
||||
"name": "libexpat1",
|
||||
"version": "2.5.0-1+deb12u2",
|
||||
"url": "https://snapshot.debian.org/archive/debian/20260901T000000Z/pool/main/e/expat/libexpat1_2.5.0-1+deb12u2_amd64.deb",
|
||||
"sha256": "2255e62fc22a86d2c544b8a3f516da9aee19383ad5742722ab4ce7f66a30dbc8"
|
||||
},
|
||||
{
|
||||
"name": "libexpat1-dev",
|
||||
"version": "2.5.0-1+deb12u2",
|
||||
"url": "https://snapshot.debian.org/archive/debian/20260901T000000Z/pool/main/e/expat/libexpat1-dev_2.5.0-1+deb12u2_amd64.deb",
|
||||
"sha256": "757279c1ce56ca88ca519e4c01cffd94e8480ce936f53fe9b0d61dc1bab20394"
|
||||
},
|
||||
{
|
||||
"name": "libffi-dev",
|
||||
"version": "3.4.4-1",
|
||||
"url": "https://snapshot.debian.org/archive/debian/20260901T000000Z/pool/main/libf/libffi/libffi-dev_3.4.4-1_amd64.deb",
|
||||
"sha256": "89fb890aee5148f4d308a46cd8980a54fd44135f068f05b38a6ad06800bf6df3"
|
||||
},
|
||||
{
|
||||
"name": "libffi8",
|
||||
"version": "3.4.4-1",
|
||||
"url": "https://snapshot.debian.org/archive/debian/20260901T000000Z/pool/main/libf/libffi/libffi8_3.4.4-1_amd64.deb",
|
||||
"sha256": "6d9f6c25c30efccce6d4bceaa48ea86c329a3432abb360a141f76ac223a4c34a"
|
||||
},
|
||||
{
|
||||
"name": "libfontconfig-dev",
|
||||
"version": "2.14.1-4",
|
||||
"url": "https://snapshot.debian.org/archive/debian/20260901T000000Z/pool/main/f/fontconfig/libfontconfig-dev_2.14.1-4_amd64.deb",
|
||||
"sha256": "74f4bbde5795e4fb4c453308bd0eb8ef45d7ade3cf11b3c18394f9e2c15d28df"
|
||||
},
|
||||
{
|
||||
"name": "libfontconfig1",
|
||||
"version": "2.14.1-4",
|
||||
"url": "https://snapshot.debian.org/archive/debian/20260901T000000Z/pool/main/f/fontconfig/libfontconfig1_2.14.1-4_amd64.deb",
|
||||
"sha256": "16ee38d374e064f534116dc442b086ef26f9831f1c0af7e5fb4fe4512e700649"
|
||||
},
|
||||
{
|
||||
"name": "libfreetype-dev",
|
||||
"version": "2.12.1+dfsg-5+deb12u4",
|
||||
"url": "https://snapshot.debian.org/archive/debian/20260901T000000Z/pool/main/f/freetype/libfreetype-dev_2.12.1+dfsg-5+deb12u4_amd64.deb",
|
||||
"sha256": "5fa327ae78e645cff5a2aadad92ca3640abc5cee7ad5368d7551bea8930202af"
|
||||
},
|
||||
{
|
||||
"name": "libfreetype6",
|
||||
"version": "2.12.1+dfsg-5+deb12u4",
|
||||
"url": "https://snapshot.debian.org/archive/debian/20260901T000000Z/pool/main/f/freetype/libfreetype6_2.12.1+dfsg-5+deb12u4_amd64.deb",
|
||||
"sha256": "8043e479f73f29992d652e3f9dfe8b17f9780c7ea6330afe379ec5f9f188ac44"
|
||||
},
|
||||
{
|
||||
"name": "libgl-dev",
|
||||
"version": "1.6.0-1",
|
||||
"url": "https://snapshot.debian.org/archive/debian/20260901T000000Z/pool/main/libg/libglvnd/libgl-dev_1.6.0-1_amd64.deb",
|
||||
"sha256": "ebc12df48ae53924e114d9358ef3da4306d7ef8f7179300af52f1faef8b5db3e"
|
||||
},
|
||||
{
|
||||
"name": "libgl1",
|
||||
"version": "1.6.0-1",
|
||||
"url": "https://snapshot.debian.org/archive/debian/20260901T000000Z/pool/main/libg/libglvnd/libgl1_1.6.0-1_amd64.deb",
|
||||
"sha256": "6f89b1702c48e9a2437bb3c1ffac8e1ab2d828fc28b3d14b2eecd4cc19b2c790"
|
||||
},
|
||||
{
|
||||
"name": "libglvnd0",
|
||||
"version": "1.6.0-1",
|
||||
"url": "https://snapshot.debian.org/archive/debian/20260901T000000Z/pool/main/libg/libglvnd/libglvnd0_1.6.0-1_amd64.deb",
|
||||
"sha256": "b6da5b153dd62d8b5e5fbe25242db1fc05c068707c365db49abda8c2427c75f8"
|
||||
},
|
||||
{
|
||||
"name": "libglx0",
|
||||
"version": "1.6.0-1",
|
||||
"url": "https://snapshot.debian.org/archive/debian/20260901T000000Z/pool/main/libg/libglvnd/libglx0_1.6.0-1_amd64.deb",
|
||||
"sha256": "95f568df73dedf43ae66834a75502112e0d4f3ad7124f3dbfa790b739383b896"
|
||||
},
|
||||
{
|
||||
"name": "libmd0",
|
||||
"version": "1.0.4-2",
|
||||
"url": "https://snapshot.debian.org/archive/debian/20260901T000000Z/pool/main/libm/libmd/libmd0_1.0.4-2_amd64.deb",
|
||||
"sha256": "03539fd30c509e27101d13a56e52eda9062bdf1aefe337c07ab56def25a13eab"
|
||||
},
|
||||
{
|
||||
"name": "libpng-dev",
|
||||
"version": "1.6.39-2+deb12u5",
|
||||
"url": "https://snapshot.debian.org/archive/debian/20260901T000000Z/pool/main/libp/libpng1.6/libpng-dev_1.6.39-2+deb12u5_amd64.deb",
|
||||
"sha256": "25649c413d02092ae7b1093a3c3ee54cbd2d4fdb0a0494787e434ccf0905903f"
|
||||
},
|
||||
{
|
||||
"name": "libpng16-16",
|
||||
"version": "1.6.39-2+deb12u5",
|
||||
"url": "https://snapshot.debian.org/archive/debian/20260901T000000Z/pool/main/libp/libpng1.6/libpng16-16_1.6.39-2+deb12u5_amd64.deb",
|
||||
"sha256": "a56d64bfaa9da12aafb83347909e62e6fd5fd251e6b34c194065911a30359978"
|
||||
},
|
||||
{
|
||||
"name": "libpthread-stubs0-dev",
|
||||
"version": "0.4-1",
|
||||
"url": "https://snapshot.debian.org/archive/debian/20260901T000000Z/pool/main/libp/libpthread-stubs/libpthread-stubs0-dev_0.4-1_amd64.deb",
|
||||
"sha256": "54632f160e1e8a43656a87195a547391038c4ca0f53291b849cd4457ba5dfde9"
|
||||
},
|
||||
{
|
||||
"name": "libuuid1",
|
||||
"version": "2.38.1-5+deb12u3",
|
||||
"url": "https://snapshot.debian.org/archive/debian/20260901T000000Z/pool/main/u/util-linux/libuuid1_2.38.1-5+deb12u3_amd64.deb",
|
||||
"sha256": "5fff398321da62d28a842bcbabd193d72ae21724962c029dc32b1dc6b2deaeaf"
|
||||
},
|
||||
{
|
||||
"name": "libwayland-client0",
|
||||
"version": "1.21.0-1",
|
||||
"url": "https://snapshot.debian.org/archive/debian/20260901T000000Z/pool/main/w/wayland/libwayland-client0_1.21.0-1_amd64.deb",
|
||||
"sha256": "1f002d028b8b79eec9847c636d8886d10dfe8c884cc2bebe18086b1391c5a28d"
|
||||
},
|
||||
{
|
||||
"name": "libwayland-cursor0",
|
||||
"version": "1.21.0-1",
|
||||
"url": "https://snapshot.debian.org/archive/debian/20260901T000000Z/pool/main/w/wayland/libwayland-cursor0_1.21.0-1_amd64.deb",
|
||||
"sha256": "0b684467ec795024fcaae99ea4384959cc4052b2da5adec38c9b76dfed9bcf41"
|
||||
},
|
||||
{
|
||||
"name": "libwayland-dev",
|
||||
"version": "1.21.0-1",
|
||||
"url": "https://snapshot.debian.org/archive/debian/20260901T000000Z/pool/main/w/wayland/libwayland-dev_1.21.0-1_amd64.deb",
|
||||
"sha256": "063ac40e71069a1a92c2be32799f4a2d234f3d361ba98cea2e3137a7ab6804d1"
|
||||
},
|
||||
{
|
||||
"name": "libwayland-egl1",
|
||||
"version": "1.21.0-1",
|
||||
"url": "https://snapshot.debian.org/archive/debian/20260901T000000Z/pool/main/w/wayland/libwayland-egl1_1.21.0-1_amd64.deb",
|
||||
"sha256": "cb4225f0e15e00a3570d4cbc288c87ff477d73e741c3f1c5a6d47cf350d45378"
|
||||
},
|
||||
{
|
||||
"name": "libwayland-server0",
|
||||
"version": "1.21.0-1",
|
||||
"url": "https://snapshot.debian.org/archive/debian/20260901T000000Z/pool/main/w/wayland/libwayland-server0_1.21.0-1_amd64.deb",
|
||||
"sha256": "df0396221d7b794496a687ec61fae82b6465648bc0ab6501ba0a5ed7f56eb8d6"
|
||||
},
|
||||
{
|
||||
"name": "libx11-6",
|
||||
"version": "2:1.8.4-2+deb12u2",
|
||||
"url": "https://snapshot.debian.org/archive/debian/20260901T000000Z/pool/main/libx/libx11/libx11-6_1.8.4-2+deb12u2_amd64.deb",
|
||||
"sha256": "d88c973e79fd9b65838d77624142952757e47a6eb1a58602acf0911cf35989f4"
|
||||
},
|
||||
{
|
||||
"name": "libx11-dev",
|
||||
"version": "2:1.8.4-2+deb12u2",
|
||||
"url": "https://snapshot.debian.org/archive/debian/20260901T000000Z/pool/main/libx/libx11/libx11-dev_1.8.4-2+deb12u2_amd64.deb",
|
||||
"sha256": "8493220d4309af1907a1f2f6eeb204c8103dafcc368394fbc4a0858c28612ff9"
|
||||
},
|
||||
{
|
||||
"name": "libx11-xcb1",
|
||||
"version": "2:1.8.4-2+deb12u2",
|
||||
"url": "https://snapshot.debian.org/archive/debian/20260901T000000Z/pool/main/libx/libx11/libx11-xcb1_1.8.4-2+deb12u2_amd64.deb",
|
||||
"sha256": "f5da45e1d881a793250a96613f28c471a248877f1a0f18a5c90e2a620a76c898"
|
||||
},
|
||||
{
|
||||
"name": "libxau-dev",
|
||||
"version": "1:1.0.9-1",
|
||||
"url": "https://snapshot.debian.org/archive/debian/20260901T000000Z/pool/main/libx/libxau/libxau-dev_1.0.9-1_amd64.deb",
|
||||
"sha256": "d1a7f5d484e0879b3b2e8d512894744505e53d078712ce65903fef2ecfd824bb"
|
||||
},
|
||||
{
|
||||
"name": "libxau6",
|
||||
"version": "1:1.0.9-1",
|
||||
"url": "https://snapshot.debian.org/archive/debian/20260901T000000Z/pool/main/libx/libxau/libxau6_1.0.9-1_amd64.deb",
|
||||
"sha256": "679db1c4579ec7c61079adeaae8528adeb2e4bf5465baa6c56233b995d714750"
|
||||
},
|
||||
{
|
||||
"name": "libxcb1",
|
||||
"version": "1.15-1",
|
||||
"url": "https://snapshot.debian.org/archive/debian/20260901T000000Z/pool/main/libx/libxcb/libxcb1_1.15-1_amd64.deb",
|
||||
"sha256": "fdc61332a3892168f3cc9cfa1fe9cf11a91dc3e0acacbc47cbc50ebaa234cc71"
|
||||
},
|
||||
{
|
||||
"name": "libxcb1-dev",
|
||||
"version": "1.15-1",
|
||||
"url": "https://snapshot.debian.org/archive/debian/20260901T000000Z/pool/main/libx/libxcb/libxcb1-dev_1.15-1_amd64.deb",
|
||||
"sha256": "c078c024114fdada06d3158af1771d7ed8763ab434cfbcbe6a334aa8a9cae358"
|
||||
},
|
||||
{
|
||||
"name": "libxdmcp-dev",
|
||||
"version": "1:1.1.2-3",
|
||||
"url": "https://snapshot.debian.org/archive/debian/20260901T000000Z/pool/main/libx/libxdmcp/libxdmcp-dev_1.1.2-3_amd64.deb",
|
||||
"sha256": "c6733e5f6463afd261998e408be6eb37f24ce0a64b63bed50a87ddb18ebc1699"
|
||||
},
|
||||
{
|
||||
"name": "libxdmcp6",
|
||||
"version": "1:1.1.2-3",
|
||||
"url": "https://snapshot.debian.org/archive/debian/20260901T000000Z/pool/main/libx/libxdmcp/libxdmcp6_1.1.2-3_amd64.deb",
|
||||
"sha256": "ecb8536f5fb34543b55bb9dc5f5b14c9dbb4150a7bddb3f2287b7cab6e9d25ef"
|
||||
},
|
||||
{
|
||||
"name": "libxext-dev",
|
||||
"version": "2:1.3.4-1+b1",
|
||||
"url": "https://snapshot.debian.org/archive/debian/20260901T000000Z/pool/main/libx/libxext/libxext-dev_1.3.4-1+b1_amd64.deb",
|
||||
"sha256": "591456aba90eeed7a1c1b044d469fd7704bf7d83af9dc574bbe2efc4a2fd1dba"
|
||||
},
|
||||
{
|
||||
"name": "libxext6",
|
||||
"version": "2:1.3.4-1+b1",
|
||||
"url": "https://snapshot.debian.org/archive/debian/20260901T000000Z/pool/main/libx/libxext/libxext6_1.3.4-1+b1_amd64.deb",
|
||||
"sha256": "504b7be9d7df4f6f4519e8dd4d6f9d03a9fb911a78530fa23a692fba3058cba6"
|
||||
},
|
||||
{
|
||||
"name": "libxfixes3",
|
||||
"version": "1:6.0.0-2",
|
||||
"url": "https://snapshot.debian.org/archive/debian/20260901T000000Z/pool/main/libx/libxfixes/libxfixes3_6.0.0-2_amd64.deb",
|
||||
"sha256": "1cd616396ff2ecae77e6e8b5b7695d414f0146de2d147837a2a02165f99e1a2c"
|
||||
},
|
||||
{
|
||||
"name": "libxi6",
|
||||
"version": "2:1.8-1+b1",
|
||||
"url": "https://snapshot.debian.org/archive/debian/20260901T000000Z/pool/main/libx/libxi/libxi6_1.8-1+b1_amd64.deb",
|
||||
"sha256": "6c2fb5f241b311788990122c6e693915867cd8ed9d6da2e3524aec7ed3cdb4c0"
|
||||
},
|
||||
{
|
||||
"name": "libxrandr2",
|
||||
"version": "2:1.5.2-2+b1",
|
||||
"url": "https://snapshot.debian.org/archive/debian/20260901T000000Z/pool/main/libx/libxrandr/libxrandr2_1.5.2-2+b1_amd64.deb",
|
||||
"sha256": "e2e10b672085ddf1d294cd689ed21bde5899325fd13626c2614b7d7b2d49a808"
|
||||
},
|
||||
{
|
||||
"name": "libxrender1",
|
||||
"version": "1:0.9.10-1.1",
|
||||
"url": "https://snapshot.debian.org/archive/debian/20260901T000000Z/pool/main/libx/libxrender/libxrender1_0.9.10-1.1_amd64.deb",
|
||||
"sha256": "b2a6d160578f359220101947c8d67059b44704a251e688de1d0b744fefedfd1a"
|
||||
},
|
||||
{
|
||||
"name": "x11proto-dev",
|
||||
"version": "2022.1-1",
|
||||
"url": "https://snapshot.debian.org/archive/debian/20260901T000000Z/pool/main/x/xorgproto/x11proto-dev_2022.1-1_all.deb",
|
||||
"sha256": "3cab66a6591774188a568f9b54c4e7956f18da76e0e0fc4a779db5f6bcc3f148"
|
||||
},
|
||||
{
|
||||
"name": "xtrans-dev",
|
||||
"version": "1.4.0-1",
|
||||
"url": "https://snapshot.debian.org/archive/debian/20260901T000000Z/pool/main/x/xtrans/xtrans-dev_1.4.0-1_all.deb",
|
||||
"sha256": "9ce1af9464faee0c679348dd11cdf63934c12e734a64e0903692b0cb5af38e06"
|
||||
},
|
||||
{
|
||||
"name": "zlib1g",
|
||||
"version": "1:1.2.13.dfsg-1",
|
||||
"url": "https://snapshot.debian.org/archive/debian/20260901T000000Z/pool/main/z/zlib/zlib1g_1.2.13.dfsg-1_amd64.deb",
|
||||
"sha256": "d7dd1d1411fedf27f5e27650a6eff20ef294077b568f4c8c5e51466dc7c08ce4"
|
||||
},
|
||||
{
|
||||
"name": "zlib1g-dev",
|
||||
"version": "1:1.2.13.dfsg-1",
|
||||
"url": "https://snapshot.debian.org/archive/debian/20260901T000000Z/pool/main/z/zlib/zlib1g-dev_1.2.13.dfsg-1_amd64.deb",
|
||||
"sha256": "f9ce531f60cbd5df37996af9370e0171be96902a17ec2bdbd8d62038c354094f"
|
||||
}
|
||||
],
|
||||
"linux-arm64": [
|
||||
{
|
||||
"name": "libbrotli-dev",
|
||||
"version": "1.0.9-2+b6",
|
||||
"url": "https://snapshot.debian.org/archive/debian/20260901T000000Z/pool/main/b/brotli/libbrotli-dev_1.0.9-2+b6_arm64.deb",
|
||||
"sha256": "68f334eb61694c2e5ca756174d111109f72193d1e3c14a25a65833c6dfcd98b7"
|
||||
},
|
||||
{
|
||||
"name": "libbrotli1",
|
||||
"version": "1.0.9-2+b6",
|
||||
"url": "https://snapshot.debian.org/archive/debian/20260901T000000Z/pool/main/b/brotli/libbrotli1_1.0.9-2+b6_arm64.deb",
|
||||
"sha256": "3137de7f71952e710ee9f0df05026b3c6f463be9369a502d57c7696732f1ed22"
|
||||
},
|
||||
{
|
||||
"name": "libbsd0",
|
||||
"version": "0.11.7-2",
|
||||
"url": "https://snapshot.debian.org/archive/debian/20260901T000000Z/pool/main/libb/libbsd/libbsd0_0.11.7-2_arm64.deb",
|
||||
"sha256": "ef00f132ddd268ee67d756998723ee18543db27ab34930c0a9f1cff75cf55382"
|
||||
},
|
||||
{
|
||||
"name": "libbz2-1.0",
|
||||
"version": "1.0.8-5+b1",
|
||||
"url": "https://snapshot.debian.org/archive/debian/20260901T000000Z/pool/main/b/bzip2/libbz2-1.0_1.0.8-5+b1_arm64.deb",
|
||||
"sha256": "d3a96ece03326498b39ff093a76800dfcbcb1d4049d6ae6e9f6fa1aa7a590ad6"
|
||||
},
|
||||
{
|
||||
"name": "libbz2-dev",
|
||||
"version": "1.0.8-5+b1",
|
||||
"url": "https://snapshot.debian.org/archive/debian/20260901T000000Z/pool/main/b/bzip2/libbz2-dev_1.0.8-5+b1_arm64.deb",
|
||||
"sha256": "c9827ab40420f1259b1a10983978ec8de87c11fc1a6b3c192adea1c4c490754f"
|
||||
},
|
||||
{
|
||||
"name": "libc6",
|
||||
"version": "2.36-9+deb12u14",
|
||||
"url": "https://snapshot.debian.org/archive/debian/20260901T000000Z/pool/main/g/glibc/libc6_2.36-9+deb12u14_arm64.deb",
|
||||
"sha256": "01f4330719fd4f65580e16ea5a0527f372fca750e8f588d26deaf09f2d3b1cf4"
|
||||
},
|
||||
{
|
||||
"name": "libegl-dev",
|
||||
"version": "1.6.0-1",
|
||||
"url": "https://snapshot.debian.org/archive/debian/20260901T000000Z/pool/main/libg/libglvnd/libegl-dev_1.6.0-1_arm64.deb",
|
||||
"sha256": "8a3004f892785a5fa4c9f969c116f567a36d1c8e9b3d5fd0403055151e36c7d3"
|
||||
},
|
||||
{
|
||||
"name": "libegl1",
|
||||
"version": "1.6.0-1",
|
||||
"url": "https://snapshot.debian.org/archive/debian/20260901T000000Z/pool/main/libg/libglvnd/libegl1_1.6.0-1_arm64.deb",
|
||||
"sha256": "707097a275155c600e2e9251c4ee7cdfdb2d8f50a678a850a2526a7bc9664166"
|
||||
},
|
||||
{
|
||||
"name": "libexpat1",
|
||||
"version": "2.5.0-1+deb12u2",
|
||||
"url": "https://snapshot.debian.org/archive/debian/20260901T000000Z/pool/main/e/expat/libexpat1_2.5.0-1+deb12u2_arm64.deb",
|
||||
"sha256": "8dc1976735acf825e3a922d82f171e20feec7394da2b8c616091983e38706275"
|
||||
},
|
||||
{
|
||||
"name": "libexpat1-dev",
|
||||
"version": "2.5.0-1+deb12u2",
|
||||
"url": "https://snapshot.debian.org/archive/debian/20260901T000000Z/pool/main/e/expat/libexpat1-dev_2.5.0-1+deb12u2_arm64.deb",
|
||||
"sha256": "9987e4aa214b0ec23fc2ba6a99b8f10d2dc68f2de347722215ae3f960802e3d3"
|
||||
},
|
||||
{
|
||||
"name": "libffi-dev",
|
||||
"version": "3.4.4-1",
|
||||
"url": "https://snapshot.debian.org/archive/debian/20260901T000000Z/pool/main/libf/libffi/libffi-dev_3.4.4-1_arm64.deb",
|
||||
"sha256": "8ff6335f76752ef8659762435d0d88129ef0090a587520853238809bd10ef392"
|
||||
},
|
||||
{
|
||||
"name": "libffi8",
|
||||
"version": "3.4.4-1",
|
||||
"url": "https://snapshot.debian.org/archive/debian/20260901T000000Z/pool/main/libf/libffi/libffi8_3.4.4-1_arm64.deb",
|
||||
"sha256": "80b5c36177dc0e29d531c7eddbed3cc7355cb490e49f8cfa5959572d161f27b3"
|
||||
},
|
||||
{
|
||||
"name": "libfontconfig-dev",
|
||||
"version": "2.14.1-4",
|
||||
"url": "https://snapshot.debian.org/archive/debian/20260901T000000Z/pool/main/f/fontconfig/libfontconfig-dev_2.14.1-4_arm64.deb",
|
||||
"sha256": "7da35e69d4f43b337aa9508da8e9089de80e75285141be3d7bec1055a0501aa4"
|
||||
},
|
||||
{
|
||||
"name": "libfontconfig1",
|
||||
"version": "2.14.1-4",
|
||||
"url": "https://snapshot.debian.org/archive/debian/20260901T000000Z/pool/main/f/fontconfig/libfontconfig1_2.14.1-4_arm64.deb",
|
||||
"sha256": "4836d9deca824883f0de33d4f8f3718ba776c6e7c80cd7c418b5a0f86c009b9e"
|
||||
},
|
||||
{
|
||||
"name": "libfreetype-dev",
|
||||
"version": "2.12.1+dfsg-5+deb12u4",
|
||||
"url": "https://snapshot.debian.org/archive/debian/20260901T000000Z/pool/main/f/freetype/libfreetype-dev_2.12.1+dfsg-5+deb12u4_arm64.deb",
|
||||
"sha256": "4e5057ac9107c69c0f49f4a8989056a7c37184c94c73ee48ba7023c5fb118db7"
|
||||
},
|
||||
{
|
||||
"name": "libfreetype6",
|
||||
"version": "2.12.1+dfsg-5+deb12u4",
|
||||
"url": "https://snapshot.debian.org/archive/debian/20260901T000000Z/pool/main/f/freetype/libfreetype6_2.12.1+dfsg-5+deb12u4_arm64.deb",
|
||||
"sha256": "b8d32e54ebc9020637f8fa16b6afa64a5731e40845a6e01880d38d6f632237c9"
|
||||
},
|
||||
{
|
||||
"name": "libgl-dev",
|
||||
"version": "1.6.0-1",
|
||||
"url": "https://snapshot.debian.org/archive/debian/20260901T000000Z/pool/main/libg/libglvnd/libgl-dev_1.6.0-1_arm64.deb",
|
||||
"sha256": "56add9e710c072cf56504beed50a639f9f7c64f4e31e66958fa65a566084888c"
|
||||
},
|
||||
{
|
||||
"name": "libgl1",
|
||||
"version": "1.6.0-1",
|
||||
"url": "https://snapshot.debian.org/archive/debian/20260901T000000Z/pool/main/libg/libglvnd/libgl1_1.6.0-1_arm64.deb",
|
||||
"sha256": "f4043ab47f52325973d2b608514b3469b055b65c744861c7f378755a32e799d6"
|
||||
},
|
||||
{
|
||||
"name": "libglvnd0",
|
||||
"version": "1.6.0-1",
|
||||
"url": "https://snapshot.debian.org/archive/debian/20260901T000000Z/pool/main/libg/libglvnd/libglvnd0_1.6.0-1_arm64.deb",
|
||||
"sha256": "d5063205fab5322ee686f33f87c6315b3fcd1335ea4e7bc8202b48ed4f9c9e83"
|
||||
},
|
||||
{
|
||||
"name": "libglx0",
|
||||
"version": "1.6.0-1",
|
||||
"url": "https://snapshot.debian.org/archive/debian/20260901T000000Z/pool/main/libg/libglvnd/libglx0_1.6.0-1_arm64.deb",
|
||||
"sha256": "523f9b71f75e48ae605d8ef298a4b03ade26ade9a808a85329a3bd82a54b9b0d"
|
||||
},
|
||||
{
|
||||
"name": "libmd0",
|
||||
"version": "1.0.4-2",
|
||||
"url": "https://snapshot.debian.org/archive/debian/20260901T000000Z/pool/main/libm/libmd/libmd0_1.0.4-2_arm64.deb",
|
||||
"sha256": "99a8c7dd591fae9fb37d8bf8dfdffa850e207fa405b3198c5b24711a5f972381"
|
||||
},
|
||||
{
|
||||
"name": "libpng-dev",
|
||||
"version": "1.6.39-2+deb12u5",
|
||||
"url": "https://snapshot.debian.org/archive/debian/20260901T000000Z/pool/main/libp/libpng1.6/libpng-dev_1.6.39-2+deb12u5_arm64.deb",
|
||||
"sha256": "f02dc017801713dfd11aaa7e72d705f747570e029fd242c29af072d64474ddfc"
|
||||
},
|
||||
{
|
||||
"name": "libpng16-16",
|
||||
"version": "1.6.39-2+deb12u5",
|
||||
"url": "https://snapshot.debian.org/archive/debian/20260901T000000Z/pool/main/libp/libpng1.6/libpng16-16_1.6.39-2+deb12u5_arm64.deb",
|
||||
"sha256": "69aba3963ddfb11b98e5bf4b0d022f76b797436568884b10f2da32e0f4b8c2dd"
|
||||
},
|
||||
{
|
||||
"name": "libpthread-stubs0-dev",
|
||||
"version": "0.4-1",
|
||||
"url": "https://snapshot.debian.org/archive/debian/20260901T000000Z/pool/main/libp/libpthread-stubs/libpthread-stubs0-dev_0.4-1_arm64.deb",
|
||||
"sha256": "acd58ed5d26d3f4d4b0856ebec6bc43f9c4357601a532eee0d2de839a8b8952e"
|
||||
},
|
||||
{
|
||||
"name": "libuuid1",
|
||||
"version": "2.38.1-5+deb12u3",
|
||||
"url": "https://snapshot.debian.org/archive/debian/20260901T000000Z/pool/main/u/util-linux/libuuid1_2.38.1-5+deb12u3_arm64.deb",
|
||||
"sha256": "3b2d19df0f3190108cf54228c4cfc822226c06d8f3615a5ab16a7dffb1f58aed"
|
||||
},
|
||||
{
|
||||
"name": "libwayland-client0",
|
||||
"version": "1.21.0-1",
|
||||
"url": "https://snapshot.debian.org/archive/debian/20260901T000000Z/pool/main/w/wayland/libwayland-client0_1.21.0-1_arm64.deb",
|
||||
"sha256": "ae390cc04c2eb1de90b9a6373505b22c730ada5e72daa50c507b7f99c12faf06"
|
||||
},
|
||||
{
|
||||
"name": "libwayland-cursor0",
|
||||
"version": "1.21.0-1",
|
||||
"url": "https://snapshot.debian.org/archive/debian/20260901T000000Z/pool/main/w/wayland/libwayland-cursor0_1.21.0-1_arm64.deb",
|
||||
"sha256": "8c8d1a3942bc3fc9dd3ea7c679c1a314e59cdaaa700883d54d1bb3ec89db256b"
|
||||
},
|
||||
{
|
||||
"name": "libwayland-dev",
|
||||
"version": "1.21.0-1",
|
||||
"url": "https://snapshot.debian.org/archive/debian/20260901T000000Z/pool/main/w/wayland/libwayland-dev_1.21.0-1_arm64.deb",
|
||||
"sha256": "932405c58195d299495230792e374ad304adadf3d3ffdc07eda3466b756adc33"
|
||||
},
|
||||
{
|
||||
"name": "libwayland-egl1",
|
||||
"version": "1.21.0-1",
|
||||
"url": "https://snapshot.debian.org/archive/debian/20260901T000000Z/pool/main/w/wayland/libwayland-egl1_1.21.0-1_arm64.deb",
|
||||
"sha256": "c08124a4d9af24f058b45c88867a84697882e755ea94965795d152fe26fe57c9"
|
||||
},
|
||||
{
|
||||
"name": "libwayland-server0",
|
||||
"version": "1.21.0-1",
|
||||
"url": "https://snapshot.debian.org/archive/debian/20260901T000000Z/pool/main/w/wayland/libwayland-server0_1.21.0-1_arm64.deb",
|
||||
"sha256": "4d99e7e0503fdaa999e67d47d8612c0465e775eafa47819573da50bdb09064f2"
|
||||
},
|
||||
{
|
||||
"name": "libx11-6",
|
||||
"version": "2:1.8.4-2+deb12u2",
|
||||
"url": "https://snapshot.debian.org/archive/debian/20260901T000000Z/pool/main/libx/libx11/libx11-6_1.8.4-2+deb12u2_arm64.deb",
|
||||
"sha256": "d1d533e983582282a9ea82c87ac5ce715a9b67bd6d1acbd2439a11c63c36549b"
|
||||
},
|
||||
{
|
||||
"name": "libx11-dev",
|
||||
"version": "2:1.8.4-2+deb12u2",
|
||||
"url": "https://snapshot.debian.org/archive/debian/20260901T000000Z/pool/main/libx/libx11/libx11-dev_1.8.4-2+deb12u2_arm64.deb",
|
||||
"sha256": "34bfc833561de983cfb4475523fedc13abb4faee14a876300de659591779add8"
|
||||
},
|
||||
{
|
||||
"name": "libx11-xcb1",
|
||||
"version": "2:1.8.4-2+deb12u2",
|
||||
"url": "https://snapshot.debian.org/archive/debian/20260901T000000Z/pool/main/libx/libx11/libx11-xcb1_1.8.4-2+deb12u2_arm64.deb",
|
||||
"sha256": "21c7e6f19909bb1e02bb3c2089789791858c54d37e86cef9d7872782c1cb711e"
|
||||
},
|
||||
{
|
||||
"name": "libxau-dev",
|
||||
"version": "1:1.0.9-1",
|
||||
"url": "https://snapshot.debian.org/archive/debian/20260901T000000Z/pool/main/libx/libxau/libxau-dev_1.0.9-1_arm64.deb",
|
||||
"sha256": "21db3761a8f388fc83707c00fac645d4332737a859dd727571e1e6ede003b048"
|
||||
},
|
||||
{
|
||||
"name": "libxau6",
|
||||
"version": "1:1.0.9-1",
|
||||
"url": "https://snapshot.debian.org/archive/debian/20260901T000000Z/pool/main/libx/libxau/libxau6_1.0.9-1_arm64.deb",
|
||||
"sha256": "36c2bf400641a80521093771dc2562c903df4065f9eb03add50d90564337ea6c"
|
||||
},
|
||||
{
|
||||
"name": "libxcb1",
|
||||
"version": "1.15-1",
|
||||
"url": "https://snapshot.debian.org/archive/debian/20260901T000000Z/pool/main/libx/libxcb/libxcb1_1.15-1_arm64.deb",
|
||||
"sha256": "041d9a68415c3ccf3ce8f4f8b88e4bbfb5dc1f0d97013c6ef8423e620ea50f84"
|
||||
},
|
||||
{
|
||||
"name": "libxcb1-dev",
|
||||
"version": "1.15-1",
|
||||
"url": "https://snapshot.debian.org/archive/debian/20260901T000000Z/pool/main/libx/libxcb/libxcb1-dev_1.15-1_arm64.deb",
|
||||
"sha256": "87b5c3f1bb130727df68295ecfaadc305ee10c150afeb1a183e95b9150e18db5"
|
||||
},
|
||||
{
|
||||
"name": "libxdmcp-dev",
|
||||
"version": "1:1.1.2-3",
|
||||
"url": "https://snapshot.debian.org/archive/debian/20260901T000000Z/pool/main/libx/libxdmcp/libxdmcp-dev_1.1.2-3_arm64.deb",
|
||||
"sha256": "6fd0bc51f3a4e6b7f944f24f15524a4c4ba68a4b0aa136c18bdb96a2d36988f2"
|
||||
},
|
||||
{
|
||||
"name": "libxdmcp6",
|
||||
"version": "1:1.1.2-3",
|
||||
"url": "https://snapshot.debian.org/archive/debian/20260901T000000Z/pool/main/libx/libxdmcp/libxdmcp6_1.1.2-3_arm64.deb",
|
||||
"sha256": "e92569ac33247261aa09adfadc34ced3994ac301cf8b58de415a2d5dbf15ccfc"
|
||||
},
|
||||
{
|
||||
"name": "libxext-dev",
|
||||
"version": "2:1.3.4-1+b1",
|
||||
"url": "https://snapshot.debian.org/archive/debian/20260901T000000Z/pool/main/libx/libxext/libxext-dev_1.3.4-1+b1_arm64.deb",
|
||||
"sha256": "07f5e3efeba9564071885b2d0d2ba277692fa309a9f05ef862688af0022b1fcf"
|
||||
},
|
||||
{
|
||||
"name": "libxext6",
|
||||
"version": "2:1.3.4-1+b1",
|
||||
"url": "https://snapshot.debian.org/archive/debian/20260901T000000Z/pool/main/libx/libxext/libxext6_1.3.4-1+b1_arm64.deb",
|
||||
"sha256": "5e9c0ad606eb4674c645fe8e0e64330c47d2729f7a59ed569848610efd5d5b62"
|
||||
},
|
||||
{
|
||||
"name": "libxfixes3",
|
||||
"version": "1:6.0.0-2",
|
||||
"url": "https://snapshot.debian.org/archive/debian/20260901T000000Z/pool/main/libx/libxfixes/libxfixes3_6.0.0-2_arm64.deb",
|
||||
"sha256": "d47bda8fed01b19b41d503e2df05d9166c58e30e2376f2f8784ceb7a834befe6"
|
||||
},
|
||||
{
|
||||
"name": "libxi6",
|
||||
"version": "2:1.8-1+b1",
|
||||
"url": "https://snapshot.debian.org/archive/debian/20260901T000000Z/pool/main/libx/libxi/libxi6_1.8-1+b1_arm64.deb",
|
||||
"sha256": "b26383c9929d8bfba051eee22301e064d17039ed022bbf31990feb0d7a03b36c"
|
||||
},
|
||||
{
|
||||
"name": "libxrandr2",
|
||||
"version": "2:1.5.2-2+b1",
|
||||
"url": "https://snapshot.debian.org/archive/debian/20260901T000000Z/pool/main/libx/libxrandr/libxrandr2_1.5.2-2+b1_arm64.deb",
|
||||
"sha256": "f0bc7f79fee182caae176652fdb1bf349d13b9591b10ad4dc1c896521da8e49f"
|
||||
},
|
||||
{
|
||||
"name": "libxrender1",
|
||||
"version": "1:0.9.10-1.1",
|
||||
"url": "https://snapshot.debian.org/archive/debian/20260901T000000Z/pool/main/libx/libxrender/libxrender1_0.9.10-1.1_arm64.deb",
|
||||
"sha256": "f260193deb4eaf0b410a1c61e1f84804366ee3372b8bad9f38005f7dbcd89aae"
|
||||
},
|
||||
{
|
||||
"name": "x11proto-dev",
|
||||
"version": "2022.1-1",
|
||||
"url": "https://snapshot.debian.org/archive/debian/20260901T000000Z/pool/main/x/xorgproto/x11proto-dev_2022.1-1_all.deb",
|
||||
"sha256": "3cab66a6591774188a568f9b54c4e7956f18da76e0e0fc4a779db5f6bcc3f148"
|
||||
},
|
||||
{
|
||||
"name": "xtrans-dev",
|
||||
"version": "1.4.0-1",
|
||||
"url": "https://snapshot.debian.org/archive/debian/20260901T000000Z/pool/main/x/xtrans/xtrans-dev_1.4.0-1_all.deb",
|
||||
"sha256": "9ce1af9464faee0c679348dd11cdf63934c12e734a64e0903692b0cb5af38e06"
|
||||
},
|
||||
{
|
||||
"name": "zlib1g",
|
||||
"version": "1:1.2.13.dfsg-1",
|
||||
"url": "https://snapshot.debian.org/archive/debian/20260901T000000Z/pool/main/z/zlib/zlib1g_1.2.13.dfsg-1_arm64.deb",
|
||||
"sha256": "52b8b8a145bbe1956bba82034f77022cbef0c3d0885c9e32d9817a7932fe1913"
|
||||
},
|
||||
{
|
||||
"name": "zlib1g-dev",
|
||||
"version": "1:1.2.13.dfsg-1",
|
||||
"url": "https://snapshot.debian.org/archive/debian/20260901T000000Z/pool/main/z/zlib/zlib1g-dev_1.2.13.dfsg-1_arm64.deb",
|
||||
"sha256": "afb60f0bae432f2f0edfe2d674e99c1a13a147c9aa2b52f2f23e3df19ece76f5"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1,103 +0,0 @@
|
||||
{
|
||||
"tested_date_utc": "2026-10-04",
|
||||
"host": "Ubuntu 24.04 Linux x64",
|
||||
"zig_version": "0.14.1",
|
||||
"sources": {
|
||||
"skiasharp_version": "4.150.1",
|
||||
"skiasharp_revision": "c3e4f4c20e1f23ab74d31a8838a5bd6dc55365f2",
|
||||
"angle_branch": "7922",
|
||||
"angle_revision": "7e08726e32026a0bbabd6ec8a1a90f5ab533ed66",
|
||||
"skia_revision": "0aa2d542e833ffd1d4d1b68a5152375e7f65ce11"
|
||||
},
|
||||
"target_runtime_tested": false,
|
||||
"docker_build_tested": false,
|
||||
"cold_source_preparation_tested": false,
|
||||
"avalonia_nativeaot_tested": false,
|
||||
"targets": {
|
||||
"win-x64": {
|
||||
"six_archives_compiled": true,
|
||||
"raster_harfbuzz_link": "passed",
|
||||
"egl_gles_link": "passed",
|
||||
"archives_sha256": {
|
||||
"libANGLE.a": "9b4af0208fef7773dc91f684cdf676b156f48eb40821c99eb55b531f4b262214",
|
||||
"libEGL.a": "dc1d8568d8d3bab0d5e6956f97db88a1d3c5887a5f2437dfd29fa5abb2a48c97",
|
||||
"libGLESv2.a": "a78c019c732a356691b849d8f632dab9f1c3254452ef98fc3ed963fd33e7049c",
|
||||
"libHarfBuzzSharp.a": "71602aa223348bc34f754438bd2f9b90ba025547c8305b0ad45e23fbd4d0a882",
|
||||
"libSkiaSharp.a": "3aa2b79953dfcd3b8dde7996701c3a29878e61fb589a6398f0cccacd1c33f4f2",
|
||||
"libskia.a": "40418692d55d26e55f1882f8386ce341410a0712ae1691d47a26b3033bd7e9a8"
|
||||
},
|
||||
"executables_sha256": {
|
||||
"smoke-angle.exe": "bc54570c5f9cdca0a28e2f9ceb2bdb1a118cabfdf6516557d1d31fd777a7d4c5",
|
||||
"smoke-raster.exe": "289f963e2180bd12cdca298b931451ebc7698bef71930318899adc4505fbccef"
|
||||
}
|
||||
},
|
||||
"win-x86": {
|
||||
"six_archives_compiled": true,
|
||||
"raster_harfbuzz_link": "passed",
|
||||
"egl_gles_link": "passed",
|
||||
"archives_sha256": {
|
||||
"libANGLE.a": "27f715956b9625ffca27ebb10e4135d173ed03970745c257fe6437fd8db23daf",
|
||||
"libEGL.a": "ddab449877aa244333f43c4a79705d3c1347c5cfae778c46ca707cd78e9ed8ed",
|
||||
"libGLESv2.a": "adf90968b2a8984c9bceefbbce1edacb1a06038fdc9b2bfc962e9227a9c947bd",
|
||||
"libHarfBuzzSharp.a": "8483f2e5cc92561884163f317f496a2e4b6b61242774176fe8b6370bbc54c695",
|
||||
"libSkiaSharp.a": "565c25b03b4f574a7db5dca98327b5f7b8eea07c1f0dab5e09d6c731ad71fd29",
|
||||
"libskia.a": "97e086493216fef2d372f555c62c2fbaf28e4d6a61398ec37334164408bcc31f"
|
||||
},
|
||||
"executables_sha256": {
|
||||
"smoke-angle.exe": "5e3a6a7951f038fa1e1a9889e8f3212de285a9464b4b722700da259b1bb9e7bb",
|
||||
"smoke-raster.exe": "9b1b4dbc3686caa89ae03cb19c5d29b3cde16ab8c0381f7c1c8b339a8f5169e5"
|
||||
}
|
||||
},
|
||||
"win-arm64": {
|
||||
"six_archives_compiled": true,
|
||||
"raster_harfbuzz_link": "passed",
|
||||
"egl_gles_link": "passed",
|
||||
"archives_sha256": {
|
||||
"libANGLE.a": "d496f595573d62e64ad1fad9339f64249ddd3904d37146ad3d1e1c58b032d797",
|
||||
"libEGL.a": "8f87692e53a3843eb8131e51f0cbc03c7eef02039d22cc25348ecacbc12028d7",
|
||||
"libGLESv2.a": "cea510c2d0bbed66bd67d0070953408da23a39a0e5a3be959ed4cec6069973cb",
|
||||
"libHarfBuzzSharp.a": "662f4174d0bc0ee0760fdeacebb7ce8f187118b524239a745058547d4c25ca10",
|
||||
"libSkiaSharp.a": "17d4ed43351f0b97b6c816de41a3e2469dd42d4df42acc6201fd30a75b8e25df",
|
||||
"libskia.a": "52d4b8ec673881d4beb729580eac867696ca5fda4ad4c2a498f33cd8b915c76b"
|
||||
},
|
||||
"executables_sha256": {
|
||||
"smoke-angle.exe": "68367ceba8053f75b841d0e2b7ab6bc8f613836b91ebd13e463fe6d261b245a9",
|
||||
"smoke-raster.exe": "ce758159e371ae94504ae1502dbe26034ea1c3789f33f71a0f65640991578dfb"
|
||||
}
|
||||
},
|
||||
"osx-x64": {
|
||||
"six_archives_compiled": true,
|
||||
"raster_harfbuzz_link": "passed",
|
||||
"egl_gles_link": "passed",
|
||||
"archives_sha256": {
|
||||
"libANGLE.a": "353b6ad07961f94cdbde8f7901fc924fbb50600156da8194ec7dd5d9c9d96115",
|
||||
"libEGL.a": "6ea3c6d73e1f6a3785fdd941c37e50c7d00f3f5c136edf648f27243e5698d517",
|
||||
"libGLESv2.a": "e3bbb289e2be771c498eae0c4037e3d9058a0a52e100dd5b6622de42f00ecb7c",
|
||||
"libHarfBuzzSharp.a": "c80b4156937b0a63ff649d7ef9ee520e342ee6f6d556a65a42e37095e91e1157",
|
||||
"libSkiaSharp.a": "2a1e5d7d7737921cdb6a9679630fb3068ce1d2eecd7300ec7747898bb8132d39",
|
||||
"libskia.a": "8062a85f7f5ded8f67c19db06b42c6792a526d5856c4bae467fb46d182992315"
|
||||
},
|
||||
"executables_sha256": {
|
||||
"smoke-angle": "1930720daf83d6a63268427b5c1a700a46fa6cf8edd93821133224fb1d456522",
|
||||
"smoke-raster": "6cb98cb854b52f94339eb225422d511b6e11abc9e5299658b455352f332139c4"
|
||||
}
|
||||
},
|
||||
"osx-arm64": {
|
||||
"six_archives_compiled": true,
|
||||
"raster_harfbuzz_link": "passed",
|
||||
"egl_gles_link": "passed",
|
||||
"archives_sha256": {
|
||||
"libANGLE.a": "3459ece2b66c8cbb096bf20016a40d4d463224ff7a0b4e29cab44c578daf1665",
|
||||
"libEGL.a": "6011625f7ac8bf467e3135588a9a30e472f55fec6de3834b1b472deed4627d15",
|
||||
"libGLESv2.a": "2c4e990ddc67f98abcc09401fa5541386cbe80458581c6fd621fd379a8541835",
|
||||
"libHarfBuzzSharp.a": "3802662600cca36985997d24187c3bc06e1a20c258fc260778eecd34a5d791f9",
|
||||
"libSkiaSharp.a": "e5bf6468713228ab9386d6f31f6556aed98a9cbc307b4be1fbbd61644f97658b",
|
||||
"libskia.a": "44e3515fdf0f09c8621b35c37c23d4441d34a831d42b88391811ad8fdff710da"
|
||||
},
|
||||
"executables_sha256": {
|
||||
"smoke-angle": "f19386a0d04af9a89f8ec70df6f3a1205747cfc2761efd86c4e781bcf0818018",
|
||||
"smoke-raster": "954dde21bf79234fa0abc30b6e5307c88558996b7777f0d459693a3588b1cc43"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,56 +0,0 @@
|
||||
{
|
||||
"date_utc": "2026-10-04",
|
||||
"compiler": "Zig 0.14.1 / Clang 19",
|
||||
"cross_configuration_checks": {
|
||||
"2.88.9/win-x64": 0,
|
||||
"2.88.9/win-x86": 0,
|
||||
"2.88.9/win-arm64": 0,
|
||||
"2.88.9/osx-x64": 0,
|
||||
"2.88.9/osx-arm64": 0,
|
||||
"3.119.1/win-x64": 0,
|
||||
"3.119.1/win-x86": 0,
|
||||
"3.119.1/win-arm64": 0,
|
||||
"3.119.1/osx-x64": 0,
|
||||
"3.119.1/osx-arm64": 0,
|
||||
"4.150.1/win-x64": 0,
|
||||
"4.150.1/win-x86": 0,
|
||||
"4.150.1/win-arm64": 0,
|
||||
"4.150.1/osx-x64": 0,
|
||||
"4.150.1/osx-arm64": 0
|
||||
},
|
||||
"native_linux_configuration_checks": {
|
||||
"2.88.9/x64": "passed",
|
||||
"2.88.9/arm64": "passed",
|
||||
"3.119.1/x64": "passed",
|
||||
"3.119.1/arm64": "passed",
|
||||
"4.150.1/x64": "passed",
|
||||
"4.150.1/arm64": "passed"
|
||||
},
|
||||
"new_full_build_checks": {
|
||||
"2.88.9": {
|
||||
"target": "win-x64",
|
||||
"three_archives": "passed",
|
||||
"raster_harfbuzz_executable_link": "passed",
|
||||
"sha256": {
|
||||
"libskia.a": "d972f868e4910cee774d592b09e3e52f65657ec3b10a1c38c26e6625e998196e",
|
||||
"libSkiaSharp.a": "e7f22c39ce570fa74988e13a288e00646cf1b08e0be82e60a6b589bab149a8fd",
|
||||
"libHarfBuzzSharp.a": "e7e117c25a16f9770f0953a260441d920b5a1e27b8c52457429f03ddacbe8855",
|
||||
"smoke-raster.exe": "6a8ab77adc1444933757f702aa4dab10716a60a284ffa4777745493443909f9d"
|
||||
}
|
||||
},
|
||||
"3.119.1": {
|
||||
"target": "win-x64",
|
||||
"three_archives": "passed",
|
||||
"raster_harfbuzz_executable_link": "passed",
|
||||
"sha256": {
|
||||
"libskia.a": "d895266910b2fc8a6a72d56715ddd0b50e1e9752b184d3b99a31b8ca6614451a",
|
||||
"libSkiaSharp.a": "544685511adf5b29eac2df771ef5088ba271fb570614671d0bde68e841ac3b32",
|
||||
"libHarfBuzzSharp.a": "6ac05af0bb31b42af86f003e4eb70db4c4eeb021b5a438282bbd182db0dba100",
|
||||
"smoke-raster.exe": "80cfda94712bd1df0671ce96fb27a174053451557d99ab542f148ac45a951532"
|
||||
}
|
||||
}
|
||||
},
|
||||
"runtime_tests": false,
|
||||
"docker_cold_build_tested": false,
|
||||
"4.150.1": "Previous five-target full archive/link checks are in local-cross-validation.json; updated win-x64 link test also passed."
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Export verified Zig archives in the layout consumed by the NuGet package."""
|
||||
import argparse,json,shutil,hashlib
|
||||
from pathlib import Path
|
||||
p=argparse.ArgumentParser();p.add_argument('--input',type=Path,required=True);p.add_argument('--output',type=Path,required=True);p.add_argument('--rid',required=True)
|
||||
a=p.parse_args();manifest=json.loads((a.input/'cross-build.json').read_text())
|
||||
if manifest['target']!=a.rid or not manifest.get('link_tests','').startswith('passed'):
|
||||
raise SystemExit('Only successfully linked target archives may be packaged')
|
||||
names={'libskia.a':'skia.lib','libSkiaSharp.a':'SkiaSharp.lib','libHarfBuzzSharp.a':'libHarfBuzzSharp.lib','libANGLE.a':'libANGLE_static.lib','libGLESv2.a':'libGLESv2_static.lib','libEGL.a':'libEGL_static.lib'} if a.rid.startswith('win') else {'libskia.a':'libskia.a','libSkiaSharp.a':'libSkiaSharp.a','libHarfBuzzSharp.a':'libHarfBuzzSharp.a','libANGLE.a':'libANGLE_static.a','libGLESv2.a':'libGLESv2_static.a','libEGL.a':'libEGL_static.a'}
|
||||
a.output.mkdir(parents=True,exist_ok=True)
|
||||
for source,destination in names.items():
|
||||
path=a.input/source
|
||||
if hashlib.sha256(path.read_bytes()).hexdigest()!=manifest['archives'][source]:raise SystemExit('Archive checksum mismatch: '+source)
|
||||
shutil.copy2(path,a.output/destination)
|
||||
runtime=a.input/'zig-runtime'
|
||||
if not runtime.is_dir() or not [p for p in runtime.iterdir() if p.suffix in ('.a','.lib')]:raise SystemExit('Zig C++/compiler runtime archives were not captured')
|
||||
(a.output/'zig-runtime').mkdir(exist_ok=True)
|
||||
for path in runtime.iterdir():
|
||||
if path.suffix not in ('.a','.lib'):continue
|
||||
dest=path.stem+'.lib' if a.rid.startswith('win') else path.name
|
||||
shutil.copy2(path,a.output/'zig-runtime'/dest)
|
||||
if a.rid=='win-x86':
|
||||
path=a.input/'skia_x86_stdcall_thunks.lib'
|
||||
if not path.is_file():raise SystemExit('x86 stdcall thunks are required')
|
||||
shutil.copy2(path,a.output/path.name)
|
||||
shutil.copy2(a.input/'cross-build.json',a.output/'zig-build.json')
|
||||
print('Packaged',a.rid)
|
||||
@@ -1,2 +0,0 @@
|
||||
# Unified diffs contain space-prefixed empty context lines.
|
||||
*.patch -whitespace
|
||||
@@ -1,28 +0,0 @@
|
||||
--- a/BUILD.gn
|
||||
+++ b/BUILD.gn
|
||||
@@ -427,7 +427,8 @@
|
||||
ldflags = [ "-Wl,--build-id" ]
|
||||
}
|
||||
|
||||
-_use_copy_compiler_dll = angle_has_build && is_win
|
||||
+declare_args() { angle_copy_compiler_dll = true }
|
||||
+_use_copy_compiler_dll = angle_has_build && is_win && angle_copy_compiler_dll
|
||||
|
||||
if (_use_copy_compiler_dll) {
|
||||
copy("copy_compiler_dll") {
|
||||
@@ -1534,6 +1535,7 @@
|
||||
}
|
||||
|
||||
angle_static_library("libGLESv2_static") {
|
||||
+ complete_static_lib = true
|
||||
|
||||
sources = libglesv2_sources
|
||||
public_deps = [ ":libGLESv2_thin_static" ]
|
||||
@@ -1652,6 +1654,7 @@
|
||||
}
|
||||
|
||||
libEGL_template("libEGL_static") {
|
||||
+ complete_static_lib = true
|
||||
target_type = "angle_static_library"
|
||||
public_configs = [ ":angle_static_config" ]
|
||||
deps = [ ":libGLESv2_static" ]
|
||||
@@ -1,20 +0,0 @@
|
||||
--- a/build/config/BUILDCONFIG.gn
|
||||
+++ b/build/config/BUILDCONFIG.gn
|
||||
@@ -584,7 +584,7 @@
|
||||
}
|
||||
|
||||
if (!defined(use_libcxx_modules)) {
|
||||
- use_libcxx_modules = is_clang
|
||||
+ use_libcxx_modules = is_clang && !(is_win && host_os == "linux")
|
||||
}
|
||||
|
||||
if (filter_include(
|
||||
@@ -715,7 +715,7 @@
|
||||
}
|
||||
|
||||
if (!defined(use_libcxx_modules)) {
|
||||
- use_libcxx_modules = is_clang
|
||||
+ use_libcxx_modules = is_clang && !(is_win && host_os == "linux")
|
||||
}
|
||||
|
||||
if (filter_include(
|
||||
@@ -1,64 +0,0 @@
|
||||
diff --git a/DEPS b/DEPS
|
||||
index 8ba99a6..1a5e1a5 100644
|
||||
--- a/DEPS
|
||||
+++ b/DEPS
|
||||
@@ -768,9 +768,4 @@ deps = {
|
||||
},
|
||||
|
||||
- 'third_party/catapult': {
|
||||
- 'url': Var('chromium_git') + '/catapult.git' + '@' + Var('catapult_revision'),
|
||||
- 'condition': 'not build_with_chromium',
|
||||
- },
|
||||
-
|
||||
# Cherry is a dEQP/VK-GL-CTS management GUI written in Go. We use it for viewing test results.
|
||||
'third_party/cherry': {
|
||||
@@ -795,9 +790,4 @@ deps = {
|
||||
|
||||
|
||||
- 'third_party/dawn': {
|
||||
- 'url': Var('dawn_git') + '/dawn.git' + '@' + Var('dawn_revision'),
|
||||
- 'condition': 'checkout_angle_dawn_deps and not build_with_chromium'
|
||||
- },
|
||||
-
|
||||
'third_party/depot_tools': {
|
||||
'url': Var('chromium_git') + '/chromium/tools/depot_tools.git@94e89b10b92cc9d6e58fc8d1b6474b7d29e8a114',
|
||||
@@ -875,9 +865,4 @@ deps = {
|
||||
},
|
||||
|
||||
- 'third_party/llvm/src': {
|
||||
- 'url': Var('chromium_git') + '/external/github.com/llvm/llvm-project@67790d3fb06b184b7be9c4d3e36ab01f0ac4198e',
|
||||
- 'condition': 'checkout_angle_cl_deps and not build_with_chromium',
|
||||
- },
|
||||
-
|
||||
'third_party/llvm-build/Release+Asserts': {
|
||||
'dep_type': 'gcs',
|
||||
@@ -1217,9 +1202,4 @@ deps = {
|
||||
},
|
||||
|
||||
- 'third_party/SwiftShader': {
|
||||
- 'url': Var('swiftshader_git') + '/SwiftShader@f3e464b1e56795940f826a972b39e19bd9f6ac6c',
|
||||
- 'condition': 'not build_with_chromium',
|
||||
- },
|
||||
-
|
||||
'third_party/turbine/cipd': {
|
||||
'packages': [
|
||||
@@ -1233,8 +1213,4 @@ deps = {
|
||||
},
|
||||
|
||||
- 'third_party/VK-GL-CTS/src': {
|
||||
- 'url': Var('chromium_git') + '/external/github.com/KhronosGroup/VK-GL-CTS' + '@' + Var('vk_gl_cts_revision'),
|
||||
- },
|
||||
-
|
||||
'third_party/vulkan-deps': {
|
||||
'url': Var('chromium_git') + '/vulkan-deps@f2b9fece7c6772c09379b3a6938dbcd2573f2a3e',
|
||||
diff --git a/src/compiler/translator/IntermNode.cpp b/src/compiler/translator/IntermNode.cpp
|
||||
index 710bba9..33d4a64 100644
|
||||
--- a/src/compiler/translator/IntermNode.cpp
|
||||
+++ b/src/compiler/translator/IntermNode.cpp
|
||||
@@ -881,5 +881,5 @@ const TConstantUnion *TIntermAggregate::getConstantValue() const
|
||||
angle::base::CheckedNumeric<size_t> checkedArraySize = elementSize;
|
||||
checkedArraySize *= getOutermostArraySize();
|
||||
- constArray = new TConstantUnion[checkedArraySize.ValueOrDie()];
|
||||
+ constArray = new TConstantUnion[static_cast<size_t>(checkedArraySize.ValueOrDie())];
|
||||
|
||||
size_t elementOffset = 0u;
|
||||
@@ -1,21 +0,0 @@
|
||||
--- a/BUILD.gn
|
||||
+++ b/BUILD.gn
|
||||
@@ -1523,7 +1523,18 @@
|
||||
public_deps = [ ":libANGLE" ]
|
||||
}
|
||||
|
||||
+angle_static_library("libANGLE_static") {
|
||||
+ complete_static_lib = true
|
||||
+ public_deps = [ ":libANGLE" ]
|
||||
+}
|
||||
+
|
||||
+angle_static_library("libANGLE_with_capture_static") {
|
||||
+ complete_static_lib = true
|
||||
+ public_deps = [ ":libANGLE_with_capture" ]
|
||||
+}
|
||||
+
|
||||
angle_static_library("libGLESv2_static") {
|
||||
+
|
||||
sources = libglesv2_sources
|
||||
public_deps = [ ":libGLESv2_thin_static" ]
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
--- a/build/mac/find_sdk.py
|
||||
+++ b/build/mac/find_sdk.py
|
||||
@@ -1,3 +1,12 @@
|
||||
+import os,sys,json
|
||||
+if sys.platform == 'linux' and os.environ.get('STATICLINK_MACOS_SDK'):
|
||||
+ sdk=os.environ['STATICLINK_MACOS_SDK']
|
||||
+ if '--print_sdk_path' in sys.argv:print('//'+str(__import__('pathlib').Path.cwd().relative_to(__import__('pathlib').Path(__file__).resolve().parents[2]))+'/sdk/xcode_links/MacOSX15.5.sdk')
|
||||
+ if '--print_bin_path' in sys.argv:print(os.environ['STATICLINK_DARWIN_TOOLS'])
|
||||
+ if '--print_sdk_build' in sys.argv:print('24F74')
|
||||
+ print('15.5')
|
||||
+ sys.exit(0)
|
||||
+
|
||||
#!/usr/bin/env python3
|
||||
# Copyright 2012 The Chromium Authors
|
||||
# Use of this source code is governed by a BSD-style license that can be
|
||||
@@ -1,38 +0,0 @@
|
||||
--- a/build/toolchain/gcc_toolchain.gni
|
||||
+++ b/build/toolchain/gcc_toolchain.gni
|
||||
@@ -369,6 +369,35 @@
|
||||
outputs = [ output ]
|
||||
}
|
||||
|
||||
+ if (current_os == "mac") {
|
||||
+ tool("objc") {
|
||||
+ output = "$object_subdir/{{source_name_part}}.o"
|
||||
+ depfile = "$output.d"
|
||||
+ precompiled_header_type = "gcc"
|
||||
+
|
||||
+ # {{output}} may contain .dwo file, so use $output instead of {{output}}
|
||||
+ # in command.
|
||||
+ command = "$coverage_wrapper$cc $md -MF $depfile {{defines}} {{include_dirs}} {{cflags}} {{cflags_objc}}${extra_cppflags}${extra_cflags}${module_name_flag} -c {{source}} -o $output"
|
||||
+ depsformat = "gcc"
|
||||
+ description = "OBJC {{output}}"
|
||||
+ outputs = [ output ]
|
||||
+ }
|
||||
+
|
||||
+ tool("objcxx") {
|
||||
+ output = "$object_subdir/{{source_name_part}}.o"
|
||||
+ depfile = "$output.d"
|
||||
+ precompiled_header_type = "gcc"
|
||||
+
|
||||
+ # {{output}} may contain .dwo file, so use $output instead of {{output}}
|
||||
+ # in command.
|
||||
+ command = "$coverage_wrapper$cxx $md -MF $depfile {{defines}} {{include_dirs}} {{cflags}} {{cflags_objcc}}${extra_cppflags}${extra_cxxflags} {{module_deps}}${module_name_flag} -c {{source}} -o $output"
|
||||
+ depsformat = "gcc"
|
||||
+ description = "OBJCXX {{output}}"
|
||||
+ outputs = [ output ]
|
||||
+ }
|
||||
+
|
||||
+ }
|
||||
+
|
||||
tool("cxx_module") {
|
||||
depfile = "{{output}}.d"
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
--- a/build/config/apple/sdk_info.py
|
||||
+++ b/build/config/apple/sdk_info.py
|
||||
@@ -1,3 +1,11 @@
|
||||
+import os,sys,json
|
||||
+if sys.platform == 'linux' and os.environ.get('STATICLINK_MACOS_SDK'):
|
||||
+ sdk=os.environ['STATICLINK_MACOS_SDK']
|
||||
+ sdk='//'+str(__import__('pathlib').Path.cwd().relative_to(__import__('pathlib').Path(__file__).resolve().parents[3]))+'/sdk/xcode_links/MacOSX15.5.sdk'
|
||||
+ values={'xcode_version':'1640','xcode_version_int':1640,'xcode_build':'16F6','sdk_path':sdk,'sdk_version':'15.5','sdk_build':'24F74','sdk_platform_path':sdk,'toolchains_path':os.environ['STATICLINK_DARWIN_TOOLS']}
|
||||
+ for k,v in values.items():print(k+'='+json.dumps(v))
|
||||
+ sys.exit(0)
|
||||
+
|
||||
#!/usr/bin/env python3
|
||||
# Copyright 2014 The Chromium Authors
|
||||
# Use of this source code is governed by a BSD-style license that can be
|
||||
@@ -1,11 +0,0 @@
|
||||
--- a/src/xps/SkXPSDevice.cpp
|
||||
+++ b/src/xps/SkXPSDevice.cpp
|
||||
@@ -337,7 +337,7 @@
|
||||
return true;
|
||||
}
|
||||
|
||||
-static HRESULT subset_typeface(const SkXPSDevice::TypefaceUse& current) {
|
||||
+HRESULT subset_typeface(const SkXPSDevice::TypefaceUse& current) {
|
||||
//The CreateFontPackage API is only supported on desktop, not in UWP
|
||||
#if defined(SK_WINUWP) || defined(SK_BUILD_FOR_WINRT) || defined(SK_BUILD_FOR_NANOSERVER)
|
||||
return E_NOTIMPL;
|
||||
@@ -1,81 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Compile target objects and SDK API probes; this does not build release libraries."""
|
||||
import argparse
|
||||
import json
|
||||
import pathlib
|
||||
import subprocess
|
||||
import tempfile
|
||||
|
||||
TARGETS = (
|
||||
"x86-windows-gnu", "x86_64-windows-gnu", "aarch64-windows-gnu",
|
||||
"x86-windows-msvc", "x86_64-windows-msvc", "aarch64-windows-msvc",
|
||||
"x86_64-macos", "aarch64-macos",
|
||||
)
|
||||
SOURCES = {
|
||||
"plain": "int answer(void) { return 42; }\n",
|
||||
"cpp": '#include <string>\nextern "C" int answer(void) { std::string s="test"; return int(s.size()); }\n',
|
||||
"windows": '''#include <windows.h>
|
||||
#include <dwrite_3.h>
|
||||
#include <xpsobjectmodel.h>
|
||||
// These call shapes are required by Skia 4.150.1's DirectWrite paint backend.
|
||||
HRESULT paint_child(IDWritePaintReader* reader, DWRITE_PAINT_ELEMENT* element) {
|
||||
return reader->MoveToFirstChild(element);
|
||||
}
|
||||
void paint_color(IDWritePaintReader* reader, DWRITE_COLOR_F color) {
|
||||
reader->SetTextColor(color);
|
||||
}
|
||||
''',
|
||||
"macos": '''#include <ApplicationServices/ApplicationServices.h>
|
||||
#import <Metal/Metal.h>
|
||||
int answer(void) { return sizeof(CFIndex); }
|
||||
''',
|
||||
}
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description=__doc__)
|
||||
parser.add_argument("--zig", default="zig")
|
||||
parser.add_argument("--output", type=pathlib.Path, required=True)
|
||||
parser.add_argument("--target", choices=TARGETS, action="append")
|
||||
parser.add_argument("--macos-sdk", type=pathlib.Path)
|
||||
parser.add_argument("--windows-sdk", type=pathlib.Path,
|
||||
help="An xwin splat containing crt/include and sdk/include")
|
||||
args = parser.parse_args()
|
||||
output = args.output.resolve()
|
||||
output.mkdir(parents=True, exist_ok=True)
|
||||
version = subprocess.check_output([args.zig, "version"], text=True).strip()
|
||||
results = {"zig_version": version, "targets": {}}
|
||||
with tempfile.TemporaryDirectory(prefix="staticlink-probe-") as temporary:
|
||||
source_dir = pathlib.Path(temporary)
|
||||
for name, source in SOURCES.items():
|
||||
suffix = ".mm" if name == "macos" else ".cpp"
|
||||
(source_dir / (name + suffix)).write_text(source)
|
||||
for target in args.target or TARGETS:
|
||||
destination = output / target
|
||||
destination.mkdir(exist_ok=True)
|
||||
flags = []
|
||||
if "macos" in target and args.macos_sdk:
|
||||
sdk = args.macos_sdk.resolve()
|
||||
flags += ["-isysroot", str(sdk), "-F", str(sdk / "System/Library/Frameworks")]
|
||||
if target.endswith("windows-msvc") and args.windows_sdk:
|
||||
sdk = args.windows_sdk.resolve()
|
||||
for include in ("crt/include", "sdk/include/ucrt", "sdk/include/shared", "sdk/include/um"):
|
||||
flags += ["-isystem", str(sdk / include)]
|
||||
target_results = {}
|
||||
for name in ("plain", "cpp", "windows" if "windows" in target else "macos"):
|
||||
suffix = ".mm" if name == "macos" else ".cpp"
|
||||
command = [args.zig, "c++", "-target", target, "-std=c++20", *flags,
|
||||
"-c", str(source_dir / (name + suffix)),
|
||||
"-o", str(destination / (name + ".o"))]
|
||||
result = subprocess.run(command, stdout=subprocess.PIPE,
|
||||
stderr=subprocess.STDOUT, text=True)
|
||||
(destination / (name + ".log")).write_text(result.stdout)
|
||||
target_results[name] = {"exit_code": result.returncode, "command": command}
|
||||
print(target, name, "PASS" if result.returncode == 0 else "FAIL", flush=True)
|
||||
results["targets"][target] = target_results
|
||||
(output / "results.json").write_text(json.dumps(results, indent=2) + "\n")
|
||||
return int(any(test["exit_code"] for tests in results["targets"].values() for test in tests.values()))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
raise SystemExit(main())
|
||||
@@ -1,68 +0,0 @@
|
||||
{
|
||||
"date": "2026-10-04",
|
||||
"zig": "0.14.1",
|
||||
"versions": [
|
||||
"3.119.2",
|
||||
"3.119.4",
|
||||
"4.150.3",
|
||||
"4.150.5",
|
||||
"4.153.1"
|
||||
],
|
||||
"configuration": {
|
||||
"passed": 45,
|
||||
"targets_per_version": 9,
|
||||
"full_build": false
|
||||
},
|
||||
"full_skia_build_and_executable_link": {
|
||||
"win-x64": [
|
||||
"3.119.2",
|
||||
"3.119.4",
|
||||
"4.150.3",
|
||||
"4.150.5",
|
||||
"4.153.1"
|
||||
],
|
||||
"win-x86": [
|
||||
"3.119.4"
|
||||
],
|
||||
"linux-x64": [
|
||||
"3.119.4"
|
||||
],
|
||||
"linux-arm64": [
|
||||
"3.119.4"
|
||||
],
|
||||
"osx-arm64": [
|
||||
"4.153.1"
|
||||
]
|
||||
},
|
||||
"angle": {
|
||||
"linux-x64": "3.119.4: six archives compiled and both executable links passed",
|
||||
"win-x86": "3.119.4: fixed ANGLE archives reused; both executable links passed"
|
||||
},
|
||||
"execution": {
|
||||
"linux-x64": "64 raster pixels and 2 UTF-8 codepoints passed",
|
||||
"linux-arm64": "same raster/UTF-8 test passed under QEMU",
|
||||
"gpu": "not validated; Linux ANGLE probe lacked a display"
|
||||
},
|
||||
"avalonia_native": {
|
||||
"versions": [
|
||||
"11.3.14",
|
||||
"12.1.0"
|
||||
],
|
||||
"targets": [
|
||||
"osx-x64",
|
||||
"osx-arm64"
|
||||
],
|
||||
"compilation": "all four passed",
|
||||
"executable_link": "all four passed against macOS SDK system libc++",
|
||||
"execution": "not run"
|
||||
},
|
||||
"not_validated": [
|
||||
"complete Debian Docker image build",
|
||||
"all five releases full nine-RID build",
|
||||
"Windows/macOS runtime",
|
||||
"full NativeAOT application",
|
||||
"GitHub Actions execution",
|
||||
"NuGet publication"
|
||||
],
|
||||
"environment_note": "Local builds ran on the Linux host with pinned cross tools, not inside Docker. Disk exhaustion required resumptions; it is not recorded as source incompatibility."
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
target_os = "linux"
|
||||
target_cpu = "@CPU@"
|
||||
is_official_build = true
|
||||
is_static_skiasharp = true
|
||||
skia_enable_tools = false
|
||||
skia_enable_ganesh = true
|
||||
skia_enable_pdf = false
|
||||
skia_enable_skottie = false
|
||||
skia_use_dng_sdk = false
|
||||
skia_use_fontconfig = true
|
||||
skia_use_freetype = true
|
||||
skia_use_harfbuzz = false
|
||||
skia_use_icu = false
|
||||
skia_use_piex = false
|
||||
skia_use_sfntly = false
|
||||
skia_use_system_expat = false
|
||||
skia_use_system_freetype2 = false
|
||||
skia_use_system_libjpeg_turbo = false
|
||||
skia_use_system_libpng = false
|
||||
skia_use_system_libwebp = false
|
||||
skia_use_system_zlib = false
|
||||
skia_use_vulkan = false
|
||||
skia_use_xps = false
|
||||
extra_cflags_cc = [ "-frtti", "-pthread" ]
|
||||
cc = "@CC@"
|
||||
cxx = "@CXX@"
|
||||
ar = "@AR@"
|
||||
extra_cflags = [ "-DSKIA_C_DLL", "-DHAVE_SYSCALL_GETRANDOM", "-DXML_DEV_URANDOM" ]
|
||||
# Standalone SkiaSharp excludes the Chromium PartitionAlloc dependency.
|
||||
skia_use_partition_alloc = false
|
||||
@@ -1,27 +0,0 @@
|
||||
target_os = "mac"
|
||||
target_cpu = "@CPU@"
|
||||
is_official_build = true
|
||||
is_static_skiasharp = true
|
||||
skia_enable_tools = false
|
||||
skia_enable_ganesh = true
|
||||
skia_use_metal = true
|
||||
skia_enable_pdf = false
|
||||
skia_enable_skottie = false
|
||||
skia_use_dng_sdk = false
|
||||
skia_use_fontconfig = false
|
||||
skia_use_freetype = false
|
||||
skia_use_harfbuzz = false
|
||||
skia_use_icu = false
|
||||
skia_use_piex = false
|
||||
skia_use_sfntly = false
|
||||
skia_use_system_expat = false
|
||||
skia_use_system_libjpeg_turbo = false
|
||||
skia_use_system_libpng = false
|
||||
skia_use_system_libwebp = false
|
||||
skia_use_system_zlib = false
|
||||
skia_use_vulkan = false
|
||||
skia_use_xps = false
|
||||
extra_cflags = [ "-DSKIA_C_DLL" ]
|
||||
extra_cflags_cc = [ "-frtti" ]
|
||||
# Standalone SkiaSharp excludes the Chromium PartitionAlloc dependency.
|
||||
skia_use_partition_alloc = false
|
||||
@@ -1,28 +0,0 @@
|
||||
target_os = "win"
|
||||
target_cpu = "@CPU@"
|
||||
is_official_build = true
|
||||
is_static_skiasharp = true
|
||||
is_clang = true
|
||||
skia_enable_tools = false
|
||||
skia_enable_ganesh = true
|
||||
skia_enable_pdf = false
|
||||
skia_enable_skottie = false
|
||||
skia_use_dng_sdk = false
|
||||
skia_use_fontconfig = false
|
||||
skia_use_freetype = false
|
||||
skia_use_harfbuzz = false
|
||||
skia_use_icu = false
|
||||
skia_use_piex = false
|
||||
skia_use_sfntly = false
|
||||
skia_use_system_expat = false
|
||||
skia_use_system_freetype2 = false
|
||||
skia_use_system_libjpeg_turbo = false
|
||||
skia_use_system_libpng = false
|
||||
skia_use_system_libwebp = false
|
||||
skia_use_system_zlib = false
|
||||
skia_use_vulkan = false
|
||||
skia_use_xps = true
|
||||
extra_cflags = [ "-DSKIA_C_DLL" ]
|
||||
extra_cflags_cc = [ "/GR" ]
|
||||
# Standalone SkiaSharp excludes the Chromium PartitionAlloc dependency.
|
||||
skia_use_partition_alloc = false
|
||||
@@ -1,123 +0,0 @@
|
||||
"""Discover Skia GN capabilities; keep version policy out of the build driver."""
|
||||
import json
|
||||
from pathlib import Path
|
||||
import re
|
||||
import subprocess
|
||||
|
||||
|
||||
def repair_xps(source):
|
||||
path = source / 'src/xps/SkXPSDevice.cpp'
|
||||
header = source / 'src/xps/SkXPSDevice.h'
|
||||
if not path.exists() or not header.exists():
|
||||
return 'absent'
|
||||
text = path.read_text()
|
||||
if not re.search(r'friend\s+HRESULT\s+subset_typeface\s*\(', header.read_text()):
|
||||
return 'not-needed'
|
||||
text, count = re.subn(r'(?m)^static HRESULT (subset_typeface\s*\()', r'HRESULT \1', text)
|
||||
if count > 1:
|
||||
raise RuntimeError('Ambiguous XPS helper declarations; inspect the new source layout')
|
||||
if count:
|
||||
path.write_text(text)
|
||||
return 'repaired' if count else 'already-compatible'
|
||||
|
||||
|
||||
def repair_skcms(source):
|
||||
repaired = []
|
||||
for relative in ('third_party/skcms/skcms.cc', 'modules/skcms/skcms.cc'):
|
||||
path = source / relative
|
||||
if not path.is_file():
|
||||
continue
|
||||
text = path.read_text()
|
||||
def replace(match):
|
||||
features = match[2]
|
||||
if 'avx512f' in features.split(',') and 'evex512' not in features.split(','):
|
||||
return match[1] + features + ',evex512' + match[3]
|
||||
return match[0]
|
||||
updated = re.sub(r'(#pragma clang attribute push\(__attribute__\(\(target\(")([^"]+)("\)\)\))', replace, text)
|
||||
if updated != text:
|
||||
path.write_text(updated)
|
||||
repaired.append(relative)
|
||||
# This changes only the AVX512-dispatched functions' Clang target attribute;
|
||||
# the baseline CPU path and runtime dispatch remain unchanged.
|
||||
return repaired
|
||||
|
||||
|
||||
def configure(source, out, desired, gn, env):
|
||||
# GN itself resolves imports, defaults and conditional declarations. Text
|
||||
# searches alone can incorrectly report an option from an inactive branch.
|
||||
# Apply the feature policy during discovery too: Skia's default tools build
|
||||
# can otherwise demand test-only dependencies before we can list options.
|
||||
bootstrap = dict(desired)
|
||||
out.mkdir(parents=True, exist_ok=True)
|
||||
def write(values):
|
||||
(out / 'args.gn').write_text(''.join(f'{key} = {value}\n' for key, value in values.items()))
|
||||
write(bootstrap)
|
||||
subprocess.run([str(gn), 'gen', str(out.relative_to(source))],
|
||||
cwd=source, env=env, check=True)
|
||||
command = [str(gn), 'args', str(out.relative_to(source)), '--list', '--json']
|
||||
result = subprocess.run(command, cwd=source, env=env, capture_output=True, text=True)
|
||||
if result.returncode:
|
||||
raise RuntimeError('Cannot discover Skia build arguments:\n' + result.stdout + result.stderr)
|
||||
# Older GN emits warnings before the JSON array for unsupported bootstrap args.
|
||||
match = re.search(r'(?m)^\[\s*\{', result.stdout)
|
||||
if not match:
|
||||
raise RuntimeError('GN did not return an argument list:\n' + result.stdout)
|
||||
arguments = json.loads(result.stdout[match.start():])
|
||||
available = {entry['name'] for entry in arguments}
|
||||
values = {key: value for key, value in desired.items() if key in available}
|
||||
if 'skia_enable_ganesh' in available:
|
||||
values['skia_enable_ganesh'] = 'true'
|
||||
elif 'skia_enable_gpu' in available:
|
||||
values['skia_enable_gpu'] = 'true'
|
||||
else:
|
||||
raise RuntimeError('No known Skia GPU switch; refusing to silently change the graphics feature set')
|
||||
required = {'target_os', 'target_cpu', 'is_static_skiasharp', 'extra_cflags', 'extra_cflags_cc'}
|
||||
required |= {key for key in ('skia_use_metal', 'skia_use_xps') if desired.get(key) == 'true'}
|
||||
missing = required - available
|
||||
if missing:
|
||||
raise RuntimeError('Skia source lacks required build capabilities: ' + ', '.join(sorted(missing)))
|
||||
write(values)
|
||||
subprocess.run([str(gn), 'gen', str(out.relative_to(source)), '--fail-on-unused-args'],
|
||||
cwd=source, env=env, check=True)
|
||||
report = {'available_arguments': sorted(available), 'selected_arguments': values,
|
||||
'omitted_obsolete_arguments': sorted(set(desired) - available)}
|
||||
(out / 'skia-capabilities.json').write_text(json.dumps(report, indent=2) + '\n')
|
||||
return report
|
||||
|
||||
|
||||
def parse_args(text):
|
||||
# Values can include multiline lists, as used by the native Linux recipe.
|
||||
assignments = list(re.finditer(r'(?m)^[ \t]*([A-Za-z_]\w*)[ \t]*=', text))
|
||||
if not assignments:
|
||||
raise ValueError('No GN assignments in build recipe')
|
||||
return {match[1]: text[match.end():assignments[index + 1].start()
|
||||
if index + 1 < len(assignments) else len(text)].strip()
|
||||
for index, match in enumerate(assignments)}
|
||||
|
||||
|
||||
def archive(source, name):
|
||||
candidates = [source / (name + '.lib'), source / ('lib' + name + '.a'),
|
||||
source / 'obj' / (name + '.lib'), source / 'obj' / ('lib' + name + '.a')]
|
||||
matches = [path for path in candidates if path.is_file()]
|
||||
if len(matches) != 1:
|
||||
raise RuntimeError(f'Expected one archive for {name}; found {matches}')
|
||||
return matches[0]
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
import argparse
|
||||
import os
|
||||
p = argparse.ArgumentParser(description='Configure native or cross Skia using its actual GN capabilities')
|
||||
p.add_argument('--source', type=Path, required=True)
|
||||
p.add_argument('--out', type=Path, required=True)
|
||||
a = p.parse_args()
|
||||
source, out = a.source.resolve(), a.out.resolve()
|
||||
gn = source / ('bin/gn.exe' if os.name == 'nt' else 'bin/gn')
|
||||
repair_xps(source)
|
||||
desired = parse_args((out / 'args.gn').read_text())
|
||||
compiler = desired.get('cc', 'clang-cl' if os.name == 'nt' else 'clang').strip('"')
|
||||
version = subprocess.run([compiler, '--version'], capture_output=True, text=True, check=True)
|
||||
match = re.search(r'clang version (\d+)', version.stdout)
|
||||
if match and int(match[1]) >= 19:
|
||||
repair_skcms(source)
|
||||
configure(source, out, desired, gn, os.environ.copy())
|
||||
@@ -1,3 +0,0 @@
|
||||
#include <EGL/egl.h>
|
||||
#include <GLES2/gl2.h>
|
||||
int main(void) { EGLDisplay d = eglGetDisplay(EGL_DEFAULT_DISPLAY); EGLint a,b; if (!eglInitialize(d,&a,&b)) return 1; glClear(GL_COLOR_BUFFER_BIT); return eglTerminate(d) ? 0 : 2; }
|
||||
@@ -1,31 +0,0 @@
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include "include/c/sk_general.h"
|
||||
#include "include/c/sk_surface.h"
|
||||
#include "include/c/sk_canvas.h"
|
||||
#include "hb.h"
|
||||
#ifndef STATICLINK_EXPECTED_MILESTONE
|
||||
#error "Pass the milestone detected from this source tree"
|
||||
#endif
|
||||
int main(void) {
|
||||
if (sk_version_get_milestone() != STATICLINK_EXPECTED_MILESTONE) return 1;
|
||||
sk_imageinfo_t info = {NULL, 8, 8, RGBA_8888_SK_COLORTYPE, PREMUL_SK_ALPHATYPE};
|
||||
sk_surface_t *surface = sk_surface_new_raster(&info, 0, NULL);
|
||||
if (!surface) return 2;
|
||||
sk_canvas_clear(sk_surface_get_canvas(surface), 0xff336699u);
|
||||
uint8_t pixels[8*8*4];
|
||||
if (!sk_surface_read_pixels(surface, &info, pixels, 8*4, 0, 0)) return 3;
|
||||
for (int i=0; i<8*8; i++) {
|
||||
if (pixels[i*4] != 0x33 || pixels[i*4+1] != 0x66 || pixels[i*4+2] != 0x99 || pixels[i*4+3] != 0xff) return 4;
|
||||
}
|
||||
sk_surface_unref(surface);
|
||||
hb_buffer_t *buffer = hb_buffer_create();
|
||||
hb_buffer_add_utf8(buffer, "A\xe4\xb8\xad", 4, 0, -1);
|
||||
hb_buffer_guess_segment_properties(buffer);
|
||||
unsigned length = 0;
|
||||
hb_glyph_info_t *glyphs = hb_buffer_get_glyph_infos(buffer, &length);
|
||||
if (length != 2 || glyphs[0].codepoint != 65 || glyphs[1].codepoint != 0x4e2d) return 5;
|
||||
hb_buffer_destroy(buffer);
|
||||
printf("PASS Skia=%s HarfBuzz=%s raster=64 pixels UTF8=2 codepoints\n", sk_version_get_string(), hb_version_string());
|
||||
return 0;
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
{
|
||||
"skiasharp_version": "4.150.1",
|
||||
"skiasharp_revision": "c3e4f4c20e1f23ab74d31a8838a5bd6dc55365f2",
|
||||
"angle_branch": "7922",
|
||||
"angle_revision": "7e08726e32026a0bbabd6ec8a1a90f5ab533ed66",
|
||||
"skia_revision": "0aa2d542e833ffd1d4d1b68a5152375e7f65ce11"
|
||||
}
|
||||
@@ -1,89 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Fetch pinned native cross-build dependencies without cloning Git history."""
|
||||
import argparse
|
||||
import ast
|
||||
import json
|
||||
import hashlib
|
||||
from pathlib import Path
|
||||
import re
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
# These dependencies correspond to features explicitly disabled by this recipe.
|
||||
# Unknown/new dependencies stay enabled; do not infer a skip from their names.
|
||||
DISABLED = {'dng_sdk', 'icu', 'dawn', 'angle2', 'swiftshader', 'emsdk'}
|
||||
|
||||
|
||||
def evaluate(node, variables):
|
||||
if isinstance(node, ast.Constant):
|
||||
return node.value
|
||||
if isinstance(node, ast.Dict):
|
||||
return {evaluate(k, variables): evaluate(v, variables) for k, v in zip(node.keys, node.values)}
|
||||
if isinstance(node, (ast.List, ast.Tuple)):
|
||||
return [evaluate(n, variables) for n in node.elts]
|
||||
if isinstance(node, ast.BinOp) and isinstance(node.op, ast.Add):
|
||||
return evaluate(node.left, variables) + evaluate(node.right, variables)
|
||||
if isinstance(node, ast.Call) and isinstance(node.func, ast.Name) and node.func.id == 'Var' and len(node.args) == 1:
|
||||
return variables[evaluate(node.args[0], variables)]
|
||||
raise ValueError('Unsupported DEPS expression: ' + ast.dump(node))
|
||||
|
||||
|
||||
def dependencies(source):
|
||||
values = {}
|
||||
for node in ast.parse((source / 'DEPS').read_text()).body:
|
||||
if isinstance(node, ast.Assign):
|
||||
for name in node.targets:
|
||||
if isinstance(name, ast.Name) and name.id in ('vars', 'deps'):
|
||||
values[name.id] = evaluate(node.value, values.get('vars', {}))
|
||||
if not values.get('deps'):
|
||||
raise ValueError('No dependency map in DEPS')
|
||||
return values['deps']
|
||||
|
||||
|
||||
def main():
|
||||
p = argparse.ArgumentParser(description=__doc__)
|
||||
p.add_argument('--source', type=Path, required=True)
|
||||
p.add_argument('--cache', type=Path, help='Immutable dependency checkouts shared across version profiles')
|
||||
p.add_argument('--no-fetch-gn', action='store_true', help='Use an existing verified GN for a local test')
|
||||
a = p.parse_args()
|
||||
source = a.source.resolve()
|
||||
records = {}
|
||||
for relative, value in dependencies(source).items():
|
||||
if not isinstance(value, str):
|
||||
continue # GN/Ninja CIPD packages are handled by upstream fetch-gn.
|
||||
if Path(relative).name in DISABLED:
|
||||
continue
|
||||
if '..' in Path(relative).parts:
|
||||
raise ValueError('Dependency path escapes source: ' + relative)
|
||||
link = source / relative
|
||||
path = link.absolute()
|
||||
if not path.is_relative_to(source):
|
||||
raise ValueError('Dependency path escapes source: ' + relative)
|
||||
url, revision = value.rsplit('@', 1)
|
||||
if not re.fullmatch(r'[0-9a-f]{40}', revision):
|
||||
raise ValueError('Dependency is not commit-pinned: ' + value)
|
||||
if a.cache:
|
||||
key = hashlib.sha256((url + '@' + revision).encode()).hexdigest()
|
||||
cached = a.cache.resolve() / key
|
||||
if link.is_symlink():
|
||||
link.unlink()
|
||||
if not link.exists():
|
||||
link.parent.mkdir(parents=True, exist_ok=True)
|
||||
link.symlink_to(cached, target_is_directory=True)
|
||||
path = cached
|
||||
if not (path / '.git').exists():
|
||||
subprocess.run(['git', 'init', '-q', str(path)], check=True)
|
||||
subprocess.run(['git', '-C', str(path), 'remote', 'add', 'origin', url], check=True)
|
||||
current = subprocess.run(['git', '-C', str(path), 'rev-parse', 'HEAD'], capture_output=True, text=True)
|
||||
if current.stdout.strip() != revision:
|
||||
subprocess.run(['git', '-C', str(path), 'remote', 'set-url', 'origin', url], check=True)
|
||||
subprocess.run(['git', '-C', str(path), 'fetch', '--depth=1', 'origin', revision], check=True)
|
||||
subprocess.run(['git', '-C', str(path), 'checkout', '--detach', revision], check=True)
|
||||
records[relative] = revision
|
||||
if not a.no_fetch_gn:
|
||||
subprocess.run([sys.executable, str(source / 'bin/fetch-gn')], cwd=source, check=True)
|
||||
(source / 'native-cross-deps.json').write_text(json.dumps(records, indent=2) + '\n')
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@@ -1,102 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Validate the actual release container before compiling native libraries."""
|
||||
import argparse
|
||||
import inspect
|
||||
import json
|
||||
from pathlib import Path
|
||||
import runpy
|
||||
import shutil
|
||||
import subprocess
|
||||
import sys
|
||||
import tarfile
|
||||
import tempfile
|
||||
|
||||
|
||||
def run(command):
|
||||
print("+", " ".join(map(str, command)), flush=True)
|
||||
return subprocess.check_output(list(map(str, command)), text=True, stderr=subprocess.STDOUT)
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description=__doc__)
|
||||
parser.add_argument("--output", type=Path, required=True)
|
||||
parser.add_argument("--rids", default="[]")
|
||||
args = parser.parse_args()
|
||||
args.output.mkdir(parents=True, exist_ok=True)
|
||||
report = {"python": sys.version, "targets": {}, "passed": False}
|
||||
try:
|
||||
if "filter" not in inspect.signature(tarfile.TarFile.extractall).parameters:
|
||||
raise RuntimeError("depot_tools requires tarfile extraction filters")
|
||||
for module in ("six", "requests", "httplib2"):
|
||||
__import__(module)
|
||||
run([sys.executable, "/opt/depot_tools/gclient.py", "help"])
|
||||
for tool in ("git", "ninja", "clang", "llvm-ar", "lld", "pkg-config", "cmake", "patch", "file", "dotnet", "zig"):
|
||||
if not shutil.which(tool):
|
||||
raise RuntimeError("Missing tool: " + tool)
|
||||
report["zig"] = run(["zig", "version"]).strip()
|
||||
if report["zig"] != "0.14.1":
|
||||
raise RuntimeError("Unexpected Zig version")
|
||||
report["dotnet_sdks"] = run(["dotnet", "--list-sdks"]).splitlines()
|
||||
for major in ("8.", "10."):
|
||||
if not any(version.startswith(major) for version in report["dotnet_sdks"]):
|
||||
raise RuntimeError("Missing .NET SDK " + major)
|
||||
adapter = Path(__file__).with_name("zig-cross.py")
|
||||
targets = runpy.run_path(str(adapter))["TARGETS"]
|
||||
requested = json.loads(args.rids)
|
||||
if not isinstance(requested, list) or any(rid not in targets for rid in requested):
|
||||
raise ValueError("Expected a JSON array of supported RIDs")
|
||||
if requested:
|
||||
targets = {rid: targets[rid] for rid in requested}
|
||||
sdk = Path("/opt/macos-sdk/MacOSX15.5.sdk")
|
||||
if json.loads((sdk / "SDKSettings.json").read_text())["Version"] != "15.5":
|
||||
raise RuntimeError("Unexpected macOS SDK version")
|
||||
with tempfile.TemporaryDirectory(prefix="staticlink-environment-") as temporary:
|
||||
work = Path(temporary)
|
||||
plain = work / "main.c"
|
||||
plain.write_text("int main(void) { return 0; }\n")
|
||||
cpp = work / "probe.cpp"
|
||||
for rid in targets:
|
||||
target_work = work / rid
|
||||
command = [sys.executable, adapter, "--target", rid, "--output", target_work,
|
||||
"--sdk", sdk, "--mingw-headers", "/opt/mingw/usr/share/mingw-w64/include"]
|
||||
source = "#include <string>\nint value() { return int(std::string(\\\"ok\\\").size()); }\n".replace('\\\"', '"')
|
||||
if rid.startswith("linux"):
|
||||
sysroot = Path("/opt/sysroots") / rid
|
||||
if not (sysroot / "usr/include").is_dir():
|
||||
raise RuntimeError("Missing sysroot: " + rid)
|
||||
if not (sysroot / "usr/include/wayland-client.h").is_file():
|
||||
raise RuntimeError("Missing Wayland headers: " + rid)
|
||||
command += ["--linux-sysroot", sysroot, "--linux-headers", "/opt/staticlink/linux-headers"]
|
||||
source += "#include <fontconfig/fontconfig.h>\n#include <ffi.h>\n#include <ft2build.h>\n#include FT_FREETYPE_H\n"
|
||||
elif rid.startswith("win"):
|
||||
source += "#include <windows.h>\n#include <dwrite_3.h>\n#include <XpsObjectModel.h>\n#include <windows.ui.composition.h>\n"
|
||||
cpp.write_text(source)
|
||||
run(command)
|
||||
run([target_work / "cxx", "-std=c++17", "-c", cpp, "-o", target_work / "cpp.o"])
|
||||
run([target_work / "cc", "-c", plain, "-o", target_work / "main.o"])
|
||||
run([target_work / "ar", "rcs", target_work / "probe.a", target_work / "main.o"])
|
||||
executable = target_work / ("probe.exe" if rid.startswith("win") else "probe")
|
||||
run([target_work / "cc", plain, "-o", executable])
|
||||
if rid.startswith("osx"):
|
||||
objc = work / "probe.mm"
|
||||
objc.write_text("#import <Cocoa/Cocoa.h>\n#import <Metal/Metal.h>\nint value() { return sizeof(CFIndex); }\n")
|
||||
run([target_work / "cxx", "-fobjc-arc", "-fblocks", "-c", objc, "-o", target_work / "objc.o"])
|
||||
report["targets"][rid] = {
|
||||
"passed": True,
|
||||
"object": run(["file", target_work / "main.o"]).strip(),
|
||||
"executable": run(["file", executable]).strip(),
|
||||
}
|
||||
print(rid + ": C/C++ compile, archive and executable link PASS", flush=True)
|
||||
report["passed"] = True
|
||||
except Exception as error:
|
||||
report["error"] = str(error)
|
||||
if isinstance(error, subprocess.CalledProcessError):
|
||||
report["error_output"] = error.output
|
||||
print(error.output, flush=True)
|
||||
raise
|
||||
finally:
|
||||
(args.output / "environment-validation.json").write_text(json.dumps(report, indent=2) + "\n")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -1,7 +0,0 @@
|
||||
{
|
||||
"skiasharp_version": "2.88.9",
|
||||
"skiasharp_revision": "9699cdf046a989423a5e5eca68e7fd813486d81c",
|
||||
"angle_branch": "7922",
|
||||
"angle_revision": "7e08726e32026a0bbabd6ec8a1a90f5ab533ed66",
|
||||
"skia_revision": "4bed689c9c9eb77a120c6a9d54af6a572c85d1c2"
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
{
|
||||
"skiasharp_version": "3.119.1",
|
||||
"skiasharp_revision": "cc78b5933d23e6383db5d246e70db915770d55d6",
|
||||
"angle_branch": "7922",
|
||||
"angle_revision": "7e08726e32026a0bbabd6ec8a1a90f5ab533ed66",
|
||||
"skia_revision": "40f75dc0051d141913c07c20d4c19590c7da0cb7"
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
{
|
||||
"skiasharp_version": "3.119.2",
|
||||
"skiasharp_revision": "2888c737ad016d584c74525e2d35db5097ea8576",
|
||||
"angle_branch": "7922",
|
||||
"angle_revision": "7e08726e32026a0bbabd6ec8a1a90f5ab533ed66",
|
||||
"skia_revision": "927041a58f130e0dd0562ba86cb4170989ad39e9"
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
{
|
||||
"skiasharp_version": "3.119.4",
|
||||
"skiasharp_revision": "f568ac94dd768ef9a2f593537cfde2dd0d348ef5",
|
||||
"angle_branch": "7922",
|
||||
"angle_revision": "7e08726e32026a0bbabd6ec8a1a90f5ab533ed66",
|
||||
"skia_revision": "7dbfc07dd33181f84e0958afb7ee805c6c769f0b"
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
{
|
||||
"skiasharp_version": "4.150.1",
|
||||
"skiasharp_revision": "c3e4f4c20e1f23ab74d31a8838a5bd6dc55365f2",
|
||||
"angle_branch": "7922",
|
||||
"angle_revision": "7e08726e32026a0bbabd6ec8a1a90f5ab533ed66",
|
||||
"skia_revision": "0aa2d542e833ffd1d4d1b68a5152375e7f65ce11"
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
{
|
||||
"skiasharp_version": "4.150.2",
|
||||
"skiasharp_revision": "fd1fdd5239f826514651a4ada5d7bb3dcec2fb43",
|
||||
"angle_branch": "7922",
|
||||
"angle_revision": "7e08726e32026a0bbabd6ec8a1a90f5ab533ed66",
|
||||
"skia_revision": "b70519562e2d26d3cf56286d3a13ca25152cfae4"
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
{
|
||||
"skiasharp_version": "4.150.3",
|
||||
"skiasharp_revision": "f8a404ff3375872d042404a29189ceb8e3001a41",
|
||||
"angle_branch": "7922",
|
||||
"angle_revision": "7e08726e32026a0bbabd6ec8a1a90f5ab533ed66",
|
||||
"skia_revision": "eb86e4b3ee034085b62d3980b3d94629862441e6"
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
{
|
||||
"skiasharp_version": "4.150.5",
|
||||
"skiasharp_revision": "16f82682f756217654eb1a152cdb639e358b8976",
|
||||
"angle_branch": "7922",
|
||||
"angle_revision": "7e08726e32026a0bbabd6ec8a1a90f5ab533ed66",
|
||||
"skia_revision": "579fa81eeed6906732e27b7d95149538584dd20b"
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
{
|
||||
"skiasharp_version": "4.153.1",
|
||||
"skiasharp_revision": "4783f51448f9b070dda4f87b83e941c9599e466e",
|
||||
"angle_branch": "7922",
|
||||
"angle_revision": "7e08726e32026a0bbabd6ec8a1a90f5ab533ed66",
|
||||
"skia_revision": "45afab4f1f0921f3feb97f58cf89b136fffa85e6"
|
||||
}
|
||||
@@ -1,69 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Generate cdecl -> stdcall adapters using the pinned managed P/Invoke ABI."""
|
||||
import argparse,re,subprocess,json
|
||||
from pathlib import Path
|
||||
p=argparse.ArgumentParser();p.add_argument('--source',type=Path,required=True);p.add_argument('--toolchain',type=Path,required=True);p.add_argument('--libraries',type=Path,required=True);a=p.parse_args()
|
||||
files=[a.source/'binding/SkiaSharp/SkiaApi.generated.cs',a.source/'binding/HarfBuzzSharp/HarfBuzzApi.generated.cs']
|
||||
text='\n'.join(x.read_text() if x.is_file() else subprocess.check_output(['git','-C',str(a.source),'show','HEAD:'+str(x.relative_to(a.source))],text=True) for x in files)
|
||||
structs={}
|
||||
# Generated structs use public fields; omit properties and methods.
|
||||
for match in re.finditer(r'\bstruct\s+(\w+)\s*\{',text):
|
||||
pos=match.end();depth=1;end=pos
|
||||
while depth:
|
||||
if text[end]=='{':depth+=1
|
||||
if text[end]=='}':depth-=1
|
||||
end+=1
|
||||
block=text[pos:end-1]
|
||||
structs[match[1]]=[m[1].strip() for m in re.finditer(r'^\s*public\s+(.+?)\s+\w+;\s*$',block,re.M)]
|
||||
sizes={}
|
||||
def layout(t):
|
||||
t=re.sub(r'\b(?:ref|out|in|readonly)\b','',t).strip()
|
||||
if '*' in t or t.endswith(('[]','Delegate')):return 4,4
|
||||
if t in sizes:return sizes[t],4
|
||||
if t in structs:raise KeyError(t)
|
||||
if t in ['Int64','UInt64','long','ulong','Double','double']:return 8,4
|
||||
if t in ['Int16','UInt16','short','ushort']:return 2,2
|
||||
if t in ['Byte','SByte','byte','sbyte','Boolean','bool']:return 1,1
|
||||
return 4,4 # enums and generated opaque pointer aliases
|
||||
pending=set(structs)
|
||||
while pending:
|
||||
done=set()
|
||||
for name in sorted(pending):
|
||||
offset=0;align=1
|
||||
try:
|
||||
for t in structs[name]:
|
||||
n,k=layout(t);offset=(offset+k-1)//k*k+n;align=max(align,k)
|
||||
except KeyError:continue
|
||||
sizes[name]=(offset+align-1)//align*align;done.add(name)
|
||||
if not done:raise SystemExit('Unresolved managed struct layout: '+str(pending))
|
||||
pending-=done
|
||||
symbols=set()
|
||||
for path in a.libraries.glob('lib*.a'):
|
||||
result=subprocess.run(['nm','--defined-only',str(path)],capture_output=True,text=True,check=True)
|
||||
symbols.update(re.findall(r'\bT\s+(_(?:sk|gr|hb)_\w+)\s*$',result.stdout,re.M))
|
||||
thunks={}
|
||||
def parameters(s):
|
||||
result=[];depth=0;start=0
|
||||
for i,c in enumerate(s):
|
||||
if c in '[<(':depth+=1
|
||||
elif c in ']> )'.replace(' ',''):depth-=1
|
||||
elif c==',' and depth==0:result.append(s[start:i]);start=i+1
|
||||
result.append(s[start:]);return [v.strip() for v in result if v.strip()]
|
||||
for m in re.finditer(r'internal static (?:extern|partial)\s+.+?\s+((?:sk|gr|hb)_\w+)\s*\((.*?)\);',text,re.S):
|
||||
symbol='_'+m[1]
|
||||
if symbol not in symbols:continue
|
||||
count=0
|
||||
for param in parameters(m[2]):
|
||||
param=re.sub(r'/\*.*?\*/|\[[^\]]+\]','',param).strip();typ=param.rsplit(' ',1)[0]
|
||||
n,_=layout(typ);count+=(n+3)//4*4
|
||||
thunks[symbol+'@'+str(count)]=(symbol,count)
|
||||
if not thunks:raise SystemExit('No x86 exported APIs matched pinned managed bindings')
|
||||
assembly=['.text','.set "@feat.00", 1']
|
||||
for name,(symbol,count) in sorted(thunks.items()):
|
||||
assembly+=['.globl "'+name+'"','"'+name+'":']+['pushl '+str(count)+'(%esp)']*(count//4)
|
||||
assembly+=['calll '+symbol,'addl $'+str(count)+', %esp','retl $'+str(count)]
|
||||
path=a.libraries/'skia_x86_stdcall_thunks.s';path.write_text('\n'.join(assembly)+'\n');obj=path.with_suffix('.o')
|
||||
subprocess.run([str(a.toolchain/'cc'),'-c',str(path),'-o',str(obj)],check=True)
|
||||
subprocess.run([str(a.toolchain/'ar'),'rcs',str(a.libraries/'skia_x86_stdcall_thunks.lib'),str(obj)],check=True)
|
||||
(a.libraries/'x86-thunks.json').write_text(json.dumps({'count':len(thunks),'layouts':sizes,'thunks':thunks},indent=2)+'\n')
|
||||
print('Generated',len(thunks),'x86 stdcall thunks')
|
||||
@@ -1,293 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Pinned Zig compiler adapters for static-library cross-builds on Linux."""
|
||||
import argparse
|
||||
import hashlib
|
||||
import json
|
||||
import os
|
||||
from pathlib import Path
|
||||
import shlex
|
||||
import shutil
|
||||
import subprocess
|
||||
import sys
|
||||
import re
|
||||
|
||||
TARGETS = {
|
||||
"linux-x64": "x86_64-linux-gnu.2.36.0", "linux-arm64": "aarch64-linux-gnu.2.36.0",
|
||||
"linux-musl-x64": "x86_64-linux-musl", "linux-musl-arm64": "aarch64-linux-musl",
|
||||
"win-x64": "x86_64-windows-gnu", "win-x86": "x86-windows-gnu",
|
||||
"win-arm64": "aarch64-windows-gnu", "osx-x64": "x86_64-macos.10.13.0",
|
||||
"osx-arm64": "aarch64-macos.11.0.0",
|
||||
}
|
||||
|
||||
|
||||
def mingw_overlay(zig_lib, output):
|
||||
source = zig_lib / "libc/include/any-windows-any/dwrite_3.h"
|
||||
text = source.read_text()
|
||||
# Add only non-virtual overloads/default arguments. Keep IID, virtual order,
|
||||
# virtual parameter types and C vtables exactly as supplied by MinGW.
|
||||
for name in ("IDWritePaintReader", "IDWriteFontFace4"):
|
||||
start = text.index(name + " : public")
|
||||
end = text.index("#ifdef __CRT_UUID_DECL", start)
|
||||
block = text[start:end]
|
||||
if name == "IDWritePaintReader":
|
||||
block = block.replace("UINT32 struct_size) = 0;",
|
||||
"UINT32 struct_size = sizeof(DWRITE_PAINT_ELEMENT)) = 0;")
|
||||
extra = """ HRESULT SetCurrentGlyph(UINT32 glyph, DWRITE_PAINT_ELEMENT *element,
|
||||
D2D_RECT_F *clip, DWRITE_PAINT_ATTRIBUTES *attributes = 0) {
|
||||
return SetCurrentGlyph(glyph, element, sizeof(DWRITE_PAINT_ELEMENT), clip, attributes);
|
||||
}
|
||||
HRESULT SetTextColor(const DWRITE_COLOR_F &color) { return SetTextColor(&color); }
|
||||
"""
|
||||
else:
|
||||
extra = """ HRESULT GetGlyphImageFormats(UINT16 glyph, UINT32 first, UINT32 last,
|
||||
DWRITE_GLYPH_IMAGE_FORMATS *formats) {
|
||||
return GetGlyphImageFormats_(glyph, first, last, formats);
|
||||
}
|
||||
"""
|
||||
index = block.rindex("};")
|
||||
block = block[:index] + extra + block[index:]
|
||||
text = text[:start] + block + text[end:]
|
||||
output.mkdir(parents=True, exist_ok=True)
|
||||
(output / "dwrite_3.h").write_text(text)
|
||||
for name in ("XpsObjectModel.h", "ObjBase.h", "DispatcherQueue.h", "VersionHelpers.h", "T2EmbApi.h", "FontSub.h"):
|
||||
alias = output / name
|
||||
if alias.is_symlink():
|
||||
alias.unlink()
|
||||
alias.symlink_to(source.parent / name.lower())
|
||||
return hashlib.sha256(source.read_bytes()).hexdigest()
|
||||
|
||||
|
||||
def compiler(config, tool, incoming):
|
||||
target = config["target"]
|
||||
if "--version" in incoming and "linux-gnu." in target:
|
||||
target = target.split("linux-gnu.")[0] + "linux-gnu"
|
||||
windows = "windows" in target
|
||||
args = ["-I" + config["include"]] if windows else [
|
||||
"-isysroot", config["sdk"], "-idirafter", config["sdk"] + "/usr/include",
|
||||
"-F", config["sdk"] + "/System/Library/Frameworks", "-Wno-elaborated-enum-base",
|
||||
] if "macos" in target else []
|
||||
if config.get('linux_abi_headers'):
|
||||
args += ['-I' + config['linux_abi_headers']]
|
||||
if config.get('linux_headers'):
|
||||
args += ['-I' + config['linux_headers'], '-I' + config['linux_headers'] + '/freetype2']
|
||||
if config.get('linux_sysroot') and '-c' not in incoming and '-o' in incoming:
|
||||
root = Path(config['linux_sysroot'])
|
||||
cpu = 'x86_64' if target.startswith('x86_64') else 'aarch64'
|
||||
for path in (root / 'usr/lib' / (cpu + '-linux-gnu'), root / 'lib' / (cpu + '-linux-gnu'), root / 'usr/lib', root / 'lib'):
|
||||
args += ['-L' + str(path)]
|
||||
if 'linux' in target and '-c' not in incoming and '-o' in incoming:
|
||||
args.append('-fuse-ld=lld')
|
||||
if windows:
|
||||
# Accept Windows header/Skia spellings such as __forceinline while
|
||||
# retaining the GNU target ABI and leaving _MSC_VER undefined.
|
||||
args.append("-fms-extensions")
|
||||
if windows and config.get("mingw_headers"):
|
||||
args.extend(("-idirafter", config["mingw_headers"]))
|
||||
mapping = {
|
||||
"/O2": "-O2", "/fp:precise": "-ffp-model=precise", "/std:c++20": "-std=c++20",
|
||||
"/std:c11": "-std=c11", "/GR": "-frtti", "/GR-": "-fno-rtti", "/w": "-w",
|
||||
"/Ob2": "-finline-functions", "/arch:AVX2": "-mcpu=x86_64_v3",
|
||||
"/arch:AVX512": "-mcpu=x86_64_v4+evex512", "/TC": "-xc", "/TP": "-xc++",
|
||||
"/Gy": "-ffunction-sections", "/Gw": "-fdata-sections",
|
||||
"/Oy-": "-fno-omit-frame-pointer", "/guard:cf": "-mguard=cf",
|
||||
"/W3": "-Wall",
|
||||
"-march=x86-64-v3": "-mcpu=x86_64_v3", "-march=x86-64-v4": "-mcpu=x86_64_v4+evex512",
|
||||
"-march=armv8-a+crc+crypto": "-mcpu=generic+crc+aes+sha2",
|
||||
}
|
||||
iterator = iter(incoming)
|
||||
for flag in iterator:
|
||||
if flag in ("-Wl,--fatal-warnings", "-Wl,--disable-new-dtags"):
|
||||
continue
|
||||
if flag in ("-o", "-MF", "-MT", "-MQ", "-I", "-isystem", "-isysroot", "-F", "-idirafter", "-include"):
|
||||
args.extend((flag, next(iterator)))
|
||||
continue
|
||||
if flag in ("-target", "--target"):
|
||||
next(iterator)
|
||||
continue
|
||||
if flag.startswith("--target="):
|
||||
continue
|
||||
if flag.startswith("/clang:"):
|
||||
flag = flag[7:]
|
||||
if flag.startswith(("-fdiagnostics-show-inlining-chain", "-fno-lifetime-dse",
|
||||
"-fsanitize-ignore-for-ubsan-feature=", "-fmsc-version=")):
|
||||
continue
|
||||
if flag.startswith("/D"):
|
||||
flag = "-D" + flag[2:]
|
||||
if re.fullmatch(r"/std:(c\+\+\d+|c\d+)", flag):
|
||||
flag = "-std=" + flag[5:]
|
||||
if flag in ("/arch:SSE", "/arch:SSE2", "/arch:AVX"):
|
||||
flag = {"/arch:SSE": "-msse", "/arch:SSE2": "-msse2", "/arch:AVX": "-mavx"}[flag]
|
||||
if flag == "/W4":
|
||||
args.extend(("-Wall", "-Wextra"))
|
||||
continue
|
||||
if flag in ("/bigobj", "/utf-8", "/Zc:inline", "/Zc:lambda", "/Zc:twoPhase", "/FS", "/MT"):
|
||||
continue
|
||||
if flag.startswith(("/wd", "/we")):
|
||||
continue # MSVC diagnostic numbers have no GNU Clang equivalent.
|
||||
if windows and flag.startswith("/") and flag not in mapping and not Path(flag).exists():
|
||||
raise SystemExit("Unsupported MSVC option: " + flag)
|
||||
if flag == '-stdlib=libstdc++':
|
||||
flag = '-stdlib=libc++'
|
||||
args.append(mapping.get(flag, flag))
|
||||
if any(flag.startswith("-mavx512") for flag in args):
|
||||
args.append("-mevex512")
|
||||
if windows:
|
||||
if "-DCRC32_SIMD_SSE42_PCLMUL" in args:
|
||||
args.extend(("-msse4.2", "-mpclmul"))
|
||||
if "-DADLER32_SIMD_SSSE3" in args:
|
||||
args.append("-mssse3")
|
||||
# Older MSVC GN rules express SSE dispatch through a macro: Clang needs
|
||||
# matching CPU features on those units, never on ordinary baseline units.
|
||||
if target.startswith(("x86", "i386")):
|
||||
levels = {"SSE2": ["-msse2"], "SSE3": ["-msse3"], "SSSE3": ["-mssse3"],
|
||||
"SSE41": ["-msse4.1"], "SSE42": ["-msse4.2", "-mcrc32"]}
|
||||
for level, features in levels.items():
|
||||
if "-DSK_CPU_SSE_LEVEL=SK_CPU_SSE_LEVEL_" + level in args:
|
||||
args.extend(features)
|
||||
return [config["zig"], "cc" if tool == "cc" else "c++", "-target", target, *args]
|
||||
|
||||
|
||||
def execute(config, tool, incoming):
|
||||
if tool in ("cc", "cxx"):
|
||||
command = compiler(config, tool, incoming)
|
||||
elif tool == "ar":
|
||||
flags = [x.replace("rcsT", "rcs") for x in incoming if x not in ("/WX", "/ignore:4221", "-T", "--thin")]
|
||||
command = [config["zig"], "ar"]
|
||||
if "macos" in config["target"]:
|
||||
command.append("--format=darwin")
|
||||
command += flags
|
||||
else:
|
||||
output = None
|
||||
inputs = []
|
||||
iterator = iter(incoming)
|
||||
for flag in iterator:
|
||||
if flag in ("-static", "-no_warning_for_no_symbols"):
|
||||
continue
|
||||
if flag == "-o":
|
||||
output = next(iterator)
|
||||
elif flag == "-filelist":
|
||||
inputs.extend(Path(next(iterator)).read_text().splitlines())
|
||||
elif flag.startswith("@"):
|
||||
inputs.extend(shlex.split(Path(flag[1:]).read_text()))
|
||||
else:
|
||||
inputs.append(flag)
|
||||
if not output:
|
||||
raise SystemExit("Darwin libtool adapter needs -o")
|
||||
command = [config["zig"], "ar", "--format=darwin", "rcs", output, *inputs]
|
||||
if tool in ('ar', 'libtool'):
|
||||
# Never leave a truncated archive behind when disk/network/job failures
|
||||
# interrupt archiving. GN response files contain a complete member list.
|
||||
index = next((i for i, arg in enumerate(command[2:], 2)
|
||||
if not arg.startswith('@') and Path(arg).suffix in ('.a', '.lib')), None)
|
||||
if index is None:
|
||||
raise SystemExit('Cannot identify archive output: ' + str(command))
|
||||
dest = Path(command[index])
|
||||
temporary = dest.with_name(dest.name + '.tmp-' + str(os.getpid()))
|
||||
temporary.unlink(missing_ok=True)
|
||||
objects = [x for x in command[index + 1:] if not x.startswith('-')]
|
||||
if tool == 'ar' and dest.exists() and len(objects) == 1 and not objects[0].startswith('@'):
|
||||
shutil.copy2(dest, temporary) # Explicit runtime/availability append.
|
||||
command[index] = str(temporary)
|
||||
try:
|
||||
subprocess.run(command, check=True)
|
||||
os.replace(temporary, dest)
|
||||
finally:
|
||||
temporary.unlink(missing_ok=True)
|
||||
return
|
||||
cache = shutil.which('ccache')
|
||||
if tool in ('cc', 'cxx') and cache and os.environ.get('CCACHE_DIR') and '-c' in incoming:
|
||||
os.environ['CCACHE_COMPILERTYPE'] = 'clang'
|
||||
raw = str(Path(config['output']) / ('_cached-' + tool))
|
||||
os.execv(cache, [cache, raw, *command[4:]])
|
||||
os.execv(config["zig"], command)
|
||||
|
||||
|
||||
def prepare(args):
|
||||
zig = str(Path(shutil.which(args.zig) or args.zig).resolve())
|
||||
version = subprocess.check_output([zig, "version"], text=True).strip()
|
||||
if version != "0.14.1":
|
||||
raise SystemExit("This adapter is verified with Zig 0.14.1; got " + version)
|
||||
lib = Path(json.loads(subprocess.check_output([zig, "env"], text=True))["lib_dir"])
|
||||
output = args.output.resolve()
|
||||
output.mkdir(parents=True, exist_ok=True)
|
||||
config = {"zig": zig, "target": TARGETS[args.target], "version": version}
|
||||
if args.target.startswith("win"):
|
||||
include = output / "include"
|
||||
# Regeneration is idempotent; remove only the generated SDK case alias.
|
||||
alias = include / "XpsObjectModel.h"
|
||||
if alias.is_symlink():
|
||||
alias.unlink()
|
||||
config["mingw_header_sha256"] = mingw_overlay(lib, include)
|
||||
config["include"] = str(include)
|
||||
if args.mingw_headers:
|
||||
config["mingw_headers"] = str(args.mingw_headers.resolve())
|
||||
header = args.mingw_headers / "windows.ui.composition.h"
|
||||
if header.is_file():
|
||||
original = header.read_text()
|
||||
text = original
|
||||
# WIDL 11 omitted namespace qualification on these imported
|
||||
# types. Use the real declarations already imported by the
|
||||
# header; preserve interface UUIDs and method/vtable order.
|
||||
for name in ("DirectXAlphaMode", "DirectXPixelFormat"):
|
||||
text = text.replace("enum " + name, "enum ABI::Windows::Graphics::DirectX::" + name)
|
||||
text = text.replace("struct Size", "struct ABI::Windows::Foundation::Size")
|
||||
for name in ("Vector2", "Vector3", "Vector4", "Matrix3x2", "Matrix4x4", "Quaternion"):
|
||||
text = text.replace("struct " + name, "struct ABI::Windows::Foundation::Numerics::" + name)
|
||||
(include / header.name).write_text(text)
|
||||
config["composition_header_sha256"] = hashlib.sha256(header.read_bytes()).hexdigest()
|
||||
elif args.target.startswith("osx"):
|
||||
if not args.sdk or not (args.sdk / "SDKSettings.json").is_file():
|
||||
raise SystemExit("macOS target requires --sdk pointing to a macOS SDK")
|
||||
config["sdk"] = str(args.sdk.resolve())
|
||||
settings = args.sdk / "SDKSettings.json"
|
||||
if json.loads(settings.read_text()).get("Version") != "15.5":
|
||||
raise SystemExit("ANGLE metadata adapter is pinned to macOS SDK 15.5")
|
||||
config["sdk_settings_sha256"] = hashlib.sha256(settings.read_bytes()).hexdigest()
|
||||
if args.target.startswith('linux'):
|
||||
config['linux_sysroot'] = str(args.linux_sysroot.resolve()) if args.linux_sysroot else ''
|
||||
config['linux_headers'] = str(args.linux_headers.resolve()) if args.linux_headers else ''
|
||||
config['output'] = str(output)
|
||||
if args.target.startswith('linux'):
|
||||
root = Path(config['linux_sysroot'])
|
||||
abi = output / 'include-linux'
|
||||
abi.mkdir(exist_ok=True)
|
||||
cpu = 'x86_64' if config['target'].startswith('x86_64') else 'aarch64'
|
||||
for name in ('ffi.h', 'ffitarget.h'):
|
||||
for prefix in (root / 'usr/include' / (cpu + '-linux-gnu'), root / 'usr/include'):
|
||||
src = prefix / name
|
||||
if src.is_file():
|
||||
(abi / name).write_bytes(src.read_bytes())
|
||||
break
|
||||
config['linux_abi_headers'] = str(abi)
|
||||
pc = output / 'pkg-config'
|
||||
dirs = [root / 'usr/lib' / (cpu + '-linux-gnu') / 'pkgconfig', root / 'usr/lib/pkgconfig', root / 'usr/share/pkgconfig']
|
||||
pc.write_text('#!/bin/sh\nexport PKG_CONFIG_SYSROOT_DIR=' + shlex.quote(str(root)) + '\nexport PKG_CONFIG_LIBDIR=' + shlex.quote(':'.join(map(str, dirs))) + '\nexec /usr/bin/pkg-config "$@"\n')
|
||||
pc.chmod(0o755)
|
||||
for kind in ('cc', 'cxx'):
|
||||
raw = output / ('_cached-' + kind)
|
||||
mode = 'cc' if kind == 'cc' else 'c++'
|
||||
raw.write_text('#!/bin/sh\nexec ' + shlex.quote(zig) + ' ' + mode + ' -target ' + shlex.quote(config['target']) + ' "$@"\n')
|
||||
raw.chmod(0o755)
|
||||
descriptor = output / "toolchain.json"
|
||||
descriptor.write_text(json.dumps(config, indent=2) + "\n")
|
||||
for tool in ("cc", "cxx", "ar", "libtool"):
|
||||
executable = output / tool
|
||||
executable.write_text("#!/bin/sh\nexec python3 " + shlex.quote(str(Path(__file__).resolve())) +
|
||||
" run " + shlex.quote(str(descriptor)) + " " + tool + ' "$@"\n')
|
||||
executable.chmod(0o755)
|
||||
print(descriptor)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
if len(sys.argv) > 1 and sys.argv[1] == "run":
|
||||
execute(json.loads(Path(sys.argv[2]).read_text()), sys.argv[3], sys.argv[4:])
|
||||
else:
|
||||
parser = argparse.ArgumentParser(description=__doc__)
|
||||
parser.add_argument("--zig", default="zig")
|
||||
parser.add_argument("--target", choices=TARGETS, required=True)
|
||||
parser.add_argument("--sdk", type=Path)
|
||||
parser.add_argument("--mingw-headers", type=Path, help="Pinned extra WinRT headers, after Zig's headers")
|
||||
parser.add_argument("--linux-sysroot", type=Path)
|
||||
parser.add_argument("--linux-headers", type=Path)
|
||||
parser.add_argument("--output", type=Path, required=True)
|
||||
prepare(parser.parse_args())
|
||||
@@ -1,5 +0,0 @@
|
||||
{
|
||||
"branches": [
|
||||
{"major": 4, "ref": "skia4", "angle_branch": "7922", "revision": "2"}
|
||||
]
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
import json, os
|
||||
from pathlib import Path
|
||||
import xml.etree.ElementTree as ET
|
||||
lock = json.loads(os.environ["SOURCE_LOCK_JSON"])
|
||||
path = Path("build/linux-toolchain/release.lock.json")
|
||||
path.write_text(json.dumps(lock, indent=2) + "\n")
|
||||
project = Path("NuGet/StaticGraphics/StaticLink.Avalonia.csproj")
|
||||
root = ET.parse(project)
|
||||
root.find(".//Version").text = os.environ["PACKAGE_VERSION"]
|
||||
for item in root.findall(".//PackageReference"):
|
||||
if item.attrib.get("Include") == "SkiaSharp":
|
||||
item.set("Version", "[" + lock["skiasharp_version"] + "]")
|
||||
root.write(project, encoding="unicode")
|
||||
@@ -1,15 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
: "${RID:?RID is required}"
|
||||
: "${AVALONIA_VERSION:?AVALONIA_VERSION is required}"
|
||||
mkdir -p "$HOME"
|
||||
source_dir="/src/External/AvaloniaNative/.work/Avalonia-$AVALONIA_VERSION"
|
||||
git clone --depth 1 --branch "$AVALONIA_VERSION" https://github.com/AvaloniaUI/Avalonia.git "$source_dir"
|
||||
if git -C "$source_dir" config -f .gitmodules --get-regexp path | grep -q "[[:space:]]external/Numerge$"; then
|
||||
git -C "$source_dir" submodule update --init --depth 1 external/Numerge
|
||||
fi
|
||||
python3 build/linux-toolchain/build-avalonia-native-cross.py \
|
||||
--source "$source_dir" --rid "$RID" --sdk /opt/macos-sdk/MacOSX15.5.sdk \
|
||||
--work "/src/External/AvaloniaNative/.work/zig-$AVALONIA_VERSION-$RID" \
|
||||
--output "/src/External/AvaloniaNative/$RID/native"
|
||||
|
||||
@@ -1,46 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
root="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||
rid="${RID:-linux-x64}"
|
||||
case "$rid" in
|
||||
linux-x64) cpu=x64; platform=linux/amd64 ;;
|
||||
linux-arm64) cpu=arm64; platform=linux/arm64 ;;
|
||||
*) echo "Debian container currently supports linux-x64 and linux-arm64: $rid" >&2; exit 2 ;;
|
||||
esac
|
||||
source_lock="$(realpath "${SOURCE_LOCK:-$root/build/linux-toolchain/sources.lock.json}")"
|
||||
case "$source_lock" in
|
||||
"$root/"*) container_lock="/src/${source_lock#"$root/"}" ;;
|
||||
*) echo "SOURCE_LOCK must be inside the mounted repository" >&2; exit 2 ;;
|
||||
esac
|
||||
lock_key="$(sha256sum "$source_lock" | cut -c1-16)"
|
||||
eval "$(python3 - "$source_lock" <<'PY'
|
||||
import json, shlex, sys
|
||||
lock = json.load(open(sys.argv[1]))
|
||||
for key, value in lock.items():
|
||||
print(f'{key.upper()}={shlex.quote(value)}')
|
||||
PY
|
||||
)"
|
||||
image="staticlink-debian12:$(sha256sum "$root/build/linux-toolchain/Dockerfile" | cut -c1-16)"
|
||||
docker build --platform "$platform" -t "$image" "$root/build/linux-toolchain"
|
||||
docker run --rm --platform "$platform" \
|
||||
--user "$(id -u):$(id -g)" \
|
||||
-v "$root:/src" -w /src \
|
||||
-e HOME=/tmp/staticlink-home \
|
||||
-e RID="$rid" -e TARGET_CPU="$cpu" \
|
||||
-e BUILD_JOBS="${BUILD_JOBS:-4}" \
|
||||
-e WORK_DIR="/src/External/NativeStatic/.work/native-$lock_key" \
|
||||
-e SOURCE_LOCK="$container_lock" \
|
||||
-e SKIASHARP_VERSION="$SKIASHARP_VERSION" -e SKIASHARP_REVISION="$SKIASHARP_REVISION" \
|
||||
-e ANGLE_BRANCH="$ANGLE_BRANCH" -e ANGLE_REVISION="$ANGLE_REVISION" \
|
||||
-e DEPOT_TOOLS_DIR=/src/External/NativeStatic/.work/depot_tools \
|
||||
"$image" bash -c '
|
||||
set -euo pipefail
|
||||
mkdir -p "$HOME" "$(dirname "$DEPOT_TOOLS_DIR")"
|
||||
# The image checkout is read-only for a non-root user; gclient needs a writable copy.
|
||||
if [[ ! -d "$DEPOT_TOOLS_DIR/.git" ]]; then
|
||||
cp -a /opt/depot_tools "$DEPOT_TOOLS_DIR"
|
||||
fi
|
||||
scripts/build-linux-static-graphics.sh "${1:-all}"
|
||||
cp /opt/staticlink/packages.lock "External/NativeStatic/$RID/toolchain-packages.lock"
|
||||
cp "$SOURCE_LOCK" "External/NativeStatic/$RID/sources.lock.json"
|
||||
' bash "${1:-all}"
|
||||
@@ -6,7 +6,7 @@ WORK_DIR="${WORK_DIR:-$ROOT_DIR/External/NativeStatic/.work}"
|
||||
TARGET_CPU="${TARGET_CPU:-x64}"
|
||||
RID="${RID:-linux-$TARGET_CPU}"
|
||||
OUTPUT_DIR="${OUTPUT_DIR:-$ROOT_DIR/External/NativeStatic/$RID}"
|
||||
SKIASHARP_VERSION="${SKIASHARP_VERSION:-4.150.1}"
|
||||
SKIASHARP_VERSION="${SKIASHARP_VERSION:-3.119.4}"
|
||||
ANGLE_BRANCH="${ANGLE_BRANCH:-7922}"
|
||||
BUILD_JOBS="${BUILD_JOBS:-$(nproc)}"
|
||||
ANGLE_PATCH_DIR="${ANGLE_PATCH_DIR:-$ROOT_DIR/External/NativeStatic/patches}"
|
||||
@@ -20,7 +20,7 @@ Usage: scripts/build-linux-static-graphics.sh [skia|angle|all]
|
||||
Environment:
|
||||
WORK_DIR Source/build cache directory. Default: External/NativeStatic/.work
|
||||
OUTPUT_DIR Final static library directory. Default: External/NativeStatic/linux-$TARGET_CPU
|
||||
SKIASHARP_VERSION SkiaSharp release branch version. Default: 4.150.1
|
||||
SKIASHARP_VERSION SkiaSharp release branch version. Default: 3.119.4
|
||||
ANGLE_BRANCH ANGLE chromium branch. Default: 7922
|
||||
TARGET_CPU GN target_cpu. Default: x64. Supported: x64, arm64
|
||||
RID Output RID. Default: linux-$TARGET_CPU
|
||||
@@ -53,20 +53,10 @@ ensure_tools() {
|
||||
}
|
||||
|
||||
ensure_depot_tools() {
|
||||
local depot_dir="${DEPOT_TOOLS_DIR:-$WORK_DIR/depot_tools}"
|
||||
local depot_dir="$WORK_DIR/depot_tools"
|
||||
local python_bin_dir
|
||||
python_bin_dir="$(dirname "$(command -v python3)")"
|
||||
if [[ -n "${DEPOT_TOOLS_REVISION:-}" ]]; then
|
||||
if [[ ! -d "$depot_dir/.git" ]]; then
|
||||
git init "$depot_dir"
|
||||
git -C "$depot_dir" remote add origin https://chromium.googlesource.com/chromium/tools/depot_tools.git
|
||||
fi
|
||||
if [[ "$(git -C "$depot_dir" rev-parse HEAD 2>/dev/null || true)" != "$DEPOT_TOOLS_REVISION" ]]; then
|
||||
git -C "$depot_dir" fetch --depth 1 origin "$DEPOT_TOOLS_REVISION"
|
||||
git -C "$depot_dir" checkout --detach FETCH_HEAD
|
||||
fi
|
||||
export DEPOT_TOOLS_UPDATE=0
|
||||
elif [[ ! -d "$depot_dir/.git" ]]; then
|
||||
git clone --depth 1 https://chromium.googlesource.com/chromium/tools/depot_tools.git "$depot_dir"
|
||||
else
|
||||
git -C "$depot_dir" pull --ff-only
|
||||
@@ -146,14 +136,7 @@ PY
|
||||
|
||||
sync_skiasharp() {
|
||||
local src="$WORK_DIR/SkiaSharp-$SKIASHARP_VERSION"
|
||||
if [[ -n "${SKIASHARP_REVISION:-}" ]]; then
|
||||
if [[ ! -d "$src/.git" ]]; then
|
||||
git init "$src" >&2
|
||||
git -C "$src" remote add origin https://github.com/mono/SkiaSharp.git
|
||||
fi
|
||||
git -C "$src" fetch --depth 1 origin "$SKIASHARP_REVISION"
|
||||
git -C "$src" checkout --detach FETCH_HEAD >&2
|
||||
elif [[ ! -d "$src/.git" ]]; then
|
||||
git clone --depth 1 --branch "release/$SKIASHARP_VERSION" https://github.com/mono/SkiaSharp.git "$src"
|
||||
else
|
||||
git -C "$src" fetch --depth 1 origin "release/$SKIASHARP_VERSION"
|
||||
@@ -172,7 +155,7 @@ import sys
|
||||
|
||||
path = pathlib.Path(sys.argv[1])
|
||||
text = path.read_text()
|
||||
deps_path = path.parent.parent / "DEPS"
|
||||
deps_path = path.with_name("DEPS")
|
||||
if deps_path.exists():
|
||||
deps = deps_path.read_text()
|
||||
deps = re.sub(r'^\s*"third_party/externals/dng_sdk"\s*:\s*"[^"]+",\s*\n', '', deps, flags=re.MULTILINE)
|
||||
@@ -186,13 +169,12 @@ PY
|
||||
|
||||
sync_skia_deps() {
|
||||
local skia_dir="$1/externals/skia"
|
||||
# GN can exist after a partial/failed sync; it is not a completion marker.
|
||||
# git-sync-deps reuses already-correct checkouts and repairs missing dependencies.
|
||||
if [[ ! -x "$skia_dir/bin/gn" ]]; then
|
||||
prepare_skia_git_sync_deps "$skia_dir"
|
||||
|
||||
local attempt
|
||||
for attempt in $(seq 1 "$SKIA_DEPS_RETRIES"); do
|
||||
if GIT_SYNC_DEPS_SKIP_EMSDK=1 python3 "$skia_dir/tools/git-sync-deps"; then
|
||||
if python3 "$skia_dir/tools/git-sync-deps"; then
|
||||
return 0
|
||||
fi
|
||||
if [[ "$attempt" == "$SKIA_DEPS_RETRIES" ]]; then
|
||||
@@ -201,6 +183,7 @@ sync_skia_deps() {
|
||||
echo "git-sync-deps failed; retrying ($attempt/$SKIA_DEPS_RETRIES)..." >&2
|
||||
sleep 10
|
||||
done
|
||||
fi
|
||||
}
|
||||
|
||||
build_skia() {
|
||||
@@ -250,7 +233,7 @@ extra_cflags_cc = [ "-frtti" ]
|
||||
extra_ldflags = [ "-static-libstdc++", "-static-libgcc" ]
|
||||
EOF_ARGS
|
||||
|
||||
python3 "$ROOT_DIR/build/linux-toolchain/skia_compat.py" --source "$skia_dir" --out "$out_dir"
|
||||
(cd "$skia_dir" && "$skia_dir/bin/gn" gen "$out_dir")
|
||||
ninja -C "$out_dir" -j "$BUILD_JOBS" skia SkiaSharp HarfBuzzSharp
|
||||
|
||||
copy_first_existing "$OUTPUT_DIR/libskia.a" \
|
||||
@@ -266,14 +249,7 @@ EOF_ARGS
|
||||
|
||||
sync_angle() {
|
||||
local src="$WORK_DIR/ANGLE-$ANGLE_BRANCH"
|
||||
if [[ -n "${ANGLE_REVISION:-}" ]]; then
|
||||
if [[ ! -d "$src/.git" ]]; then
|
||||
git init "$src" >&2
|
||||
git -C "$src" remote add origin https://github.com/google/angle.git
|
||||
fi
|
||||
git -C "$src" fetch --depth 1 origin "$ANGLE_REVISION"
|
||||
git -C "$src" checkout --detach FETCH_HEAD >&2
|
||||
elif [[ ! -d "$src/.git" ]]; then
|
||||
git clone --depth 1 --branch "chromium/$ANGLE_BRANCH" https://github.com/google/angle.git "$src"
|
||||
else
|
||||
git -C "$src" fetch --depth 1 origin "chromium/$ANGLE_BRANCH"
|
||||
@@ -568,6 +544,4 @@ main() {
|
||||
esac
|
||||
}
|
||||
|
||||
if [[ "${BASH_SOURCE[0]}" == "$0" ]]; then
|
||||
main "$@"
|
||||
fi
|
||||
@@ -26,13 +26,8 @@ if git -C "$src" config -f .gitmodules --get-regexp path | grep -q 'external/Num
|
||||
fi
|
||||
|
||||
if [[ ! -f "$src/native/Avalonia.Native/inc/avalonia-native.h" ]]; then
|
||||
header_project="$src/native/Avalonia.Native/Avalonia.Native.macOS.proj"
|
||||
if [[ -f "$header_project" ]]; then
|
||||
dotnet build "$header_project" -t:GenerateMicroComItems
|
||||
else
|
||||
bash "$src/native/Avalonia.Native/generate-headers.sh"
|
||||
fi
|
||||
fi
|
||||
|
||||
project="$src/native/Avalonia.Native/src/OSX/Avalonia.Native.OSX.xcodeproj"
|
||||
include_dir="$src/native/Avalonia.Native/inc"
|
||||
|
||||
@@ -30,9 +30,7 @@ static void StaticLinkAvaloniaPreinitializeAppKitFonts(void)
|
||||
}
|
||||
OBJC
|
||||
|
||||
compiler=("${CC:-clang}")
|
||||
if [[ "${STATICLINK_ZIG_CROSS:-0}" != 1 ]]; then compiler+=(-arch "$ARCH"); fi
|
||||
"${compiler[@]}" \
|
||||
clang -arch "$ARCH" \
|
||||
-mmacosx-version-min=12.0 \
|
||||
-fobjc-arc \
|
||||
-c "$src" \
|
||||
|
||||
@@ -6,7 +6,7 @@ WORK_DIR="${WORK_DIR:-$ROOT_DIR/External/NativeStatic/.work}"
|
||||
TARGET_CPU="${TARGET_CPU:-arm64}"
|
||||
RID="${RID:-osx-$TARGET_CPU}"
|
||||
OUTPUT_DIR="${OUTPUT_DIR:-$ROOT_DIR/External/NativeStatic/$RID}"
|
||||
SKIASHARP_VERSION="${SKIASHARP_VERSION:-4.150.1}"
|
||||
SKIASHARP_VERSION="${SKIASHARP_VERSION:-3.119.4}"
|
||||
ANGLE_BRANCH="${ANGLE_BRANCH:-7922}"
|
||||
BUILD_JOBS="${BUILD_JOBS:-$(sysctl -n hw.ncpu)}"
|
||||
ANGLE_PATCH_DIR="${ANGLE_PATCH_DIR:-$ROOT_DIR/External/NativeStatic/patches}"
|
||||
@@ -33,11 +33,8 @@ ensure_depot_tools() {
|
||||
if [[ ! -d "$depot_dir/.git" ]]; then
|
||||
git clone --depth 1 https://chromium.googlesource.com/chromium/tools/depot_tools.git "$depot_dir"
|
||||
else
|
||||
: # The pinned checkout is refreshed below
|
||||
git -C "$depot_dir" pull --ff-only
|
||||
fi
|
||||
git -C "$depot_dir" fetch --depth 1 origin 8a5434051036b32412a2ecb10c213a72e3f3ccb9
|
||||
git -C "$depot_dir" checkout -q --force FETCH_HEAD
|
||||
export DEPOT_TOOLS_UPDATE=0
|
||||
export PATH="$depot_dir:$PATH"
|
||||
}
|
||||
|
||||
@@ -59,15 +56,11 @@ copy_first_existing() {
|
||||
sync_skiasharp() {
|
||||
local src="$WORK_DIR/SkiaSharp-$SKIASHARP_VERSION"
|
||||
if [[ ! -d "$src/.git" ]]; then
|
||||
git clone --depth 1 --branch "v$SKIASHARP_VERSION" https://github.com/mono/SkiaSharp.git "$src"
|
||||
git clone --depth 1 --branch "release/$SKIASHARP_VERSION" https://github.com/mono/SkiaSharp.git "$src"
|
||||
else
|
||||
git -C "$src" fetch --depth 1 origin "${SKIASHARP_REVISION:-refs/tags/v$SKIASHARP_VERSION}"
|
||||
git -C "$src" fetch --depth 1 origin "release/$SKIASHARP_VERSION"
|
||||
git -C "$src" checkout -q FETCH_HEAD
|
||||
fi
|
||||
if [[ -n "${SKIASHARP_REVISION:-}" ]]; then
|
||||
git -C "$src" fetch --depth 1 origin "$SKIASHARP_REVISION"
|
||||
git -C "$src" checkout -q --force FETCH_HEAD
|
||||
fi
|
||||
git -C "$src" submodule update --init --depth 1 externals/skia >&2
|
||||
echo "$src"
|
||||
}
|
||||
@@ -81,7 +74,7 @@ import sys
|
||||
|
||||
path = pathlib.Path(sys.argv[1])
|
||||
text = path.read_text()
|
||||
deps_path = path.parent.parent / "DEPS"
|
||||
deps_path = path.with_name("DEPS")
|
||||
if deps_path.exists():
|
||||
deps = deps_path.read_text()
|
||||
deps = re.sub(r'^\s*"third_party/externals/dng_sdk"\s*:\s*"[^"]+",\s*\n', '', deps, flags=re.MULTILINE)
|
||||
@@ -154,7 +147,7 @@ extra_cflags = [ "-DSKIA_C_DLL" ]
|
||||
extra_cflags_cc = [ "-frtti" ]
|
||||
EOF_ARGS
|
||||
|
||||
python3 "$ROOT_DIR/build/linux-toolchain/skia_compat.py" --source "$skia_dir" --out "$out_dir"
|
||||
(cd "$skia_dir" && "$skia_dir/bin/gn" gen "$out_dir")
|
||||
ninja -C "$out_dir" -j "$BUILD_JOBS" skia SkiaSharp HarfBuzzSharp
|
||||
copy_first_existing "$OUTPUT_DIR/libskia.a" "$out_dir/libskia.a" "$out_dir/obj/libskia.a"
|
||||
copy_first_existing "$OUTPUT_DIR/libSkiaSharp.a" "$out_dir/libSkiaSharp.a" "$out_dir/obj/libSkiaSharp.a"
|
||||
@@ -169,10 +162,6 @@ sync_angle() {
|
||||
git -C "$src" fetch --depth 1 origin "chromium/$ANGLE_BRANCH"
|
||||
git -C "$src" checkout -q FETCH_HEAD
|
||||
fi
|
||||
if [[ -n "${ANGLE_REVISION:-}" ]]; then
|
||||
git -C "$src" fetch --depth 1 origin "$ANGLE_REVISION"
|
||||
git -C "$src" checkout -q --force FETCH_HEAD
|
||||
fi
|
||||
echo "$src"
|
||||
}
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ $ErrorActionPreference = "Stop"
|
||||
|
||||
$RootDir = Split-Path -Parent $PSScriptRoot
|
||||
$WorkDir = if ($env:WORK_DIR) { $env:WORK_DIR } else { Join-Path $RootDir "External\NativeStatic\.work" }
|
||||
$SkiaSharpVersion = if ($env:SKIASHARP_VERSION) { $env:SKIASHARP_VERSION } else { "4.150.1" }
|
||||
$SkiaSharpVersion = if ($env:SKIASHARP_VERSION) { $env:SKIASHARP_VERSION } else { "3.119.4" }
|
||||
$AngleBranch = if ($env:ANGLE_BRANCH) { $env:ANGLE_BRANCH } else { "7922" }
|
||||
$TargetCpu = if ($env:TARGET_CPU) { $env:TARGET_CPU } else { "x64" }
|
||||
$Rid = if ($env:RID) { $env:RID } else { "win-$TargetCpu" }
|
||||
@@ -56,13 +56,8 @@ function Ensure-DepotTools {
|
||||
if (-not (Test-Path (Join-Path $depotDir ".git"))) {
|
||||
$null = git clone --depth 1 https://chromium.googlesource.com/chromium/tools/depot_tools.git $depotDir
|
||||
} else {
|
||||
# Refresh the pinned checkout below.
|
||||
$null = git -C $depotDir pull --ff-only
|
||||
}
|
||||
$null = git -C $depotDir fetch --depth 1 origin 8a5434051036b32412a2ecb10c213a72e3f3ccb9
|
||||
if ($LASTEXITCODE -ne 0) { throw "Cannot fetch pinned depot_tools" }
|
||||
$null = git -C $depotDir checkout -q --force FETCH_HEAD
|
||||
if ($LASTEXITCODE -ne 0) { throw "Cannot checkout pinned depot_tools" }
|
||||
$env:DEPOT_TOOLS_UPDATE = "0"
|
||||
$env:PATH = "$depotDir;$env:PATH"
|
||||
}
|
||||
|
||||
@@ -349,41 +344,15 @@ function New-WinX86SkiaStdcallThunks([string[]]$InputLibraries, [string[]]$Bindi
|
||||
function Sync-SkiaSharp {
|
||||
$src = Join-Path $WorkDir "SkiaSharp-$SkiaSharpVersion"
|
||||
if (-not (Test-Path (Join-Path $src ".git"))) {
|
||||
$null = git -c core.longpaths=true clone --depth 1 --branch "v$SkiaSharpVersion" https://github.com/mono/SkiaSharp.git $src
|
||||
$null = git -c core.longpaths=true clone --depth 1 --branch "release/$SkiaSharpVersion" https://github.com/mono/SkiaSharp.git $src
|
||||
} else {
|
||||
$null = git -C $src fetch --depth 1 origin "refs/tags/v$SkiaSharpVersion"
|
||||
$null = git -C $src fetch --depth 1 origin "release/$SkiaSharpVersion"
|
||||
$null = git -C $src checkout -q FETCH_HEAD
|
||||
}
|
||||
if ($env:SKIASHARP_REVISION) {
|
||||
$null = git -C $src fetch --depth 1 origin $env:SKIASHARP_REVISION
|
||||
if ($LASTEXITCODE -ne 0) { throw "Cannot fetch locked SkiaSharp commit" }
|
||||
$null = git -C $src checkout -q --force FETCH_HEAD
|
||||
if ($LASTEXITCODE -ne 0) { throw "Cannot checkout locked SkiaSharp commit" }
|
||||
}
|
||||
$null = git -C $src submodule update --init --depth 1 externals/skia
|
||||
return $src
|
||||
}
|
||||
|
||||
function Patch-WinX86SkiaLinker($SkiaDir) {
|
||||
if ($TargetCpu -ne "x86") {
|
||||
return
|
||||
}
|
||||
|
||||
$linkerPath = Join-Path $SkiaDir "src\c\sk_linker.cpp"
|
||||
if (-not (Test-Path $linkerPath)) { return }
|
||||
$text = Get-Content -Path $linkerPath -Raw
|
||||
if ($text -notmatch 'skjson::ObjectValue') { return }
|
||||
$pattern = '(?m)^ skjson::ObjectValue\* a = nullptr;\r?\n auto r = \(\*a\)\["tmp"\]\.getType\(\);\r?$'
|
||||
$patched = [regex]::Replace($text, $pattern, ' int r = 0;')
|
||||
if ($patched -eq $text) {
|
||||
if ($text -match '(?m)^ int r = 0;\r?$') {
|
||||
return
|
||||
}
|
||||
throw "Unable to patch win-x86 sk_linker JSON keep-alive references."
|
||||
}
|
||||
Set-Content -Path $linkerPath -Value $patched -NoNewline -Encoding UTF8
|
||||
}
|
||||
|
||||
function Prepare-SkiaGitSyncDeps($SkiaDir) {
|
||||
$syncDeps = Join-Path $SkiaDir "tools\git-sync-deps"
|
||||
$text = Get-Content -Path $syncDeps -Raw
|
||||
@@ -421,7 +390,6 @@ function Build-Skia {
|
||||
Ensure-DepotTools
|
||||
$src = Sync-SkiaSharp
|
||||
$skiaDir = Join-Path $src "externals\skia"
|
||||
Patch-WinX86SkiaLinker $skiaDir
|
||||
if (-not (Test-Path (Join-Path $skiaDir "bin\gn.exe"))) {
|
||||
Invoke-SkiaGitSyncDeps $skiaDir
|
||||
}
|
||||
@@ -460,8 +428,7 @@ extra_cflags_cc = [ "/GR" ]
|
||||
|
||||
Push-Location $skiaDir
|
||||
try {
|
||||
python (Join-Path $RootDir "build\linux-toolchain\skia_compat.py") --source $skiaDir --out $outDir
|
||||
if ($LASTEXITCODE -ne 0) { throw "Skia capability configuration failed" }
|
||||
& (Join-Path $skiaDir "bin\gn.exe") gen $outDir
|
||||
ninja -C $outDir -j $BuildJobs skia SkiaSharp HarfBuzzSharp
|
||||
} finally {
|
||||
Pop-Location
|
||||
@@ -494,12 +461,6 @@ function Sync-Angle {
|
||||
$null = git -C $src fetch --depth 1 origin "chromium/$AngleBranch"
|
||||
$null = git -C $src checkout -q FETCH_HEAD
|
||||
}
|
||||
if ($env:ANGLE_REVISION) {
|
||||
$null = git -C $src fetch --depth 1 origin $env:ANGLE_REVISION
|
||||
if ($LASTEXITCODE -ne 0) { throw "Cannot fetch locked ANGLE commit" }
|
||||
$null = git -C $src checkout -q --force FETCH_HEAD
|
||||
if ($LASTEXITCODE -ne 0) { throw "Cannot checkout locked ANGLE commit" }
|
||||
}
|
||||
return $src
|
||||
}
|
||||
|
||||
|
||||
@@ -1,47 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Plan stable releases. HTTP/network errors fail closed; only 404 means absent."""
|
||||
import argparse, json, re, urllib.request, urllib.error
|
||||
from pathlib import Path
|
||||
|
||||
def get(url):
|
||||
for attempt in range(3):
|
||||
try:
|
||||
with urllib.request.urlopen(url, timeout=45) as response:
|
||||
return json.load(response)
|
||||
except urllib.error.HTTPError as error:
|
||||
if error.code == 404:
|
||||
return None
|
||||
if error.code < 500 and error.code != 429:
|
||||
raise
|
||||
if attempt == 2:
|
||||
raise
|
||||
except (OSError, TimeoutError):
|
||||
if attempt == 2:
|
||||
raise
|
||||
raise RuntimeError("Unreachable")
|
||||
|
||||
def plan(config, upstream, published, force=False):
|
||||
result = []
|
||||
for entry in config["branches"]:
|
||||
major = entry["major"]
|
||||
candidates = [v for v in upstream if re.fullmatch(r"\d+\.\d+\.\d+", v)
|
||||
and int(v.split(".")[0]) == major]
|
||||
version = entry.get("fixed_version") or max(candidates, key=lambda v: tuple(map(int, v.split("."))))
|
||||
package = f"{version}-{entry['angle_branch']}.{entry['revision']}"
|
||||
if entry.get("daily", True) and (force or package.lower() not in {v.lower() for v in published}):
|
||||
result.append({"ref": entry["ref"], "skiasharp_version": version, "package_version": package})
|
||||
return result
|
||||
|
||||
if __name__ == "__main__":
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument("--config", default="build/release-tracks.json")
|
||||
parser.add_argument("--output", default="release-plan.json")
|
||||
parser.add_argument("--force", action="store_true")
|
||||
args = parser.parse_args()
|
||||
upstream = get("https://api.nuget.org/v3-flatcontainer/skiasharp/index.json")
|
||||
published = get("https://api.nuget.org/v3-flatcontainer/staticlink.avalonia/index.json")
|
||||
if upstream is None:
|
||||
raise SystemExit("SkiaSharp package index is missing")
|
||||
result = plan(json.loads(Path(args.config).read_text()), upstream["versions"], (published or {}).get("versions", []), force=args.force)
|
||||
Path(args.output).write_text(json.dumps(result, indent=2) + "\n")
|
||||
print(json.dumps(result))
|
||||
@@ -1,60 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
SCRIPT_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||
SOURCE_LOCK="${SOURCE_LOCK:-$SCRIPT_ROOT/build/linux-toolchain/sources.lock.json}"
|
||||
SOURCE_LOCK="$(realpath "$SOURCE_LOCK")"
|
||||
export WORK_DIR="${WORK_DIR:-$SCRIPT_ROOT/External/NativeStatic/.work/zig-sources}"
|
||||
export LLVM_AR="${LLVM_AR:-llvm-ar}"
|
||||
mkdir -p "$WORK_DIR"
|
||||
read -r SKIASHARP_VERSION SKIASHARP_REVISION ANGLE_BRANCH ANGLE_REVISION < <(
|
||||
python3 - "$SOURCE_LOCK" <<'PY'
|
||||
import json, sys
|
||||
lock = json.load(open(sys.argv[1]))
|
||||
print(lock['skiasharp_version'], lock['skiasharp_revision'], lock['angle_branch'], lock['angle_revision'])
|
||||
PY
|
||||
)
|
||||
export SKIASHARP_VERSION SKIASHARP_REVISION ANGLE_BRANCH ANGLE_REVISION
|
||||
export WORK_DIR="$WORK_DIR/$SKIASHARP_VERSION-$(sha256sum "$SOURCE_LOCK" | cut -c1-16)"
|
||||
mkdir -p "$WORK_DIR"
|
||||
source "$SCRIPT_ROOT/scripts/build-linux-static-graphics.sh"
|
||||
if [[ ! -d "$WORK_DIR/depot_tools/.git" ]]; then
|
||||
cp -a /opt/depot_tools "$WORK_DIR/depot_tools"
|
||||
fi
|
||||
export DEPOT_TOOLS_DIR="$WORK_DIR/depot_tools"
|
||||
ensure_tools
|
||||
ensure_depot_tools
|
||||
initialize_depot_tools_system_python "$DEPOT_TOOLS_DIR"
|
||||
patch_depot_tools_python_deps "$DEPOT_TOOLS_DIR"
|
||||
export VPYTHON_BYPASS="manually managed python not supported by chrome operations"
|
||||
skia_sharp="$(sync_skiasharp)"
|
||||
python3 "$SCRIPT_ROOT/build/linux-toolchain/sync-skia-deps.py" --source "$skia_sharp/externals/skia" --cache "$SCRIPT_ROOT/External/NativeStatic/.work/skia-deps"
|
||||
angle="$(sync_angle)"
|
||||
project_patch="$SCRIPT_ROOT/External/NativeStatic/patches/angle-chromium-$ANGLE_BRANCH.patch"
|
||||
if git -C "$angle" apply --reverse --check "$project_patch" >/dev/null 2>&1; then
|
||||
:
|
||||
else
|
||||
git -C "$angle" apply --check "$project_patch"
|
||||
git -C "$angle" apply "$project_patch"
|
||||
fi
|
||||
python3 - "$angle/.gclient" <<'PY'
|
||||
from pathlib import Path
|
||||
import sys
|
||||
Path(sys.argv[1]).write_text('''solutions = [{
|
||||
"name": ".", "url": "https://chromium.googlesource.com/angle/angle.git",
|
||||
"deps_file": "DEPS", "managed": False,
|
||||
"custom_deps": {"third_party/llvm-build/Release+Asserts": None},
|
||||
"custom_vars": {"checkout_angle_cl_deps": False, "checkout_angle_dawn_deps": False},
|
||||
}]
|
||||
target_os = ["linux", "win", "mac"]
|
||||
''')
|
||||
PY
|
||||
# Zig and the image's SDKs supply the compiler/runtime; skip native Xcode/MSVC
|
||||
# setup hooks while retaining the pinned source dependencies for every target.
|
||||
(cd "$angle" && gclient sync --nohooks --force)
|
||||
python3 - "$WORK_DIR/cross-sources.json" "$skia_sharp/externals/skia" "$angle" "$SOURCE_LOCK" <<'PY'
|
||||
import json, sys
|
||||
from pathlib import Path
|
||||
Path(sys.argv[1]).write_text(json.dumps({'skia': sys.argv[2], 'angle': sys.argv[3],
|
||||
'angle_gn': sys.argv[3] + '/buildtools/linux64/gn', 'source_lock': sys.argv[4]}, indent=2) + '\n')
|
||||
PY
|
||||
echo "Prepared $WORK_DIR/cross-sources.json"
|
||||
@@ -1,43 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Resolve a published SkiaSharp tag and its Skia gitlink to immutable commits."""
|
||||
import argparse, json, re, subprocess, tempfile
|
||||
from pathlib import Path
|
||||
import xml.etree.ElementTree as ET
|
||||
|
||||
def git(*args):
|
||||
return subprocess.check_output(["git", *args], text=True).strip()
|
||||
|
||||
p = argparse.ArgumentParser()
|
||||
p.add_argument("--version", default="")
|
||||
p.add_argument("--output", default="build/linux-toolchain/release.lock.json")
|
||||
a = p.parse_args()
|
||||
root = ET.parse("NuGet/StaticGraphics/StaticLink.Avalonia.csproj").getroot()
|
||||
current = next(x.attrib["Version"] for x in root.findall(".//PackageReference") if x.attrib.get("Include") == "SkiaSharp")
|
||||
version = a.version or current
|
||||
if not re.fullmatch(r"\d+\.\d+\.\d+", version) or version.split(".")[0] != current.split(".")[0]:
|
||||
raise SystemExit("Only stable versions from this branch's SkiaSharp major are allowed")
|
||||
if current.startswith("2.") and version != "2.88.9":
|
||||
raise SystemExit("SkiaSharp 2 is frozen at 2.88.9")
|
||||
base, revision = root.findtext(".//Version").rsplit(".", 1)
|
||||
angle = base.split("-", 1)[1]
|
||||
# ANGLE remains fixed: changing SkiaSharp must not silently change its toolchain.
|
||||
profile = json.loads(Path("build/linux-toolchain/sources.lock.json").read_text())
|
||||
if profile["angle_branch"] != angle:
|
||||
raise SystemExit("ANGLE branch does not match the source lock")
|
||||
remote = "https://github.com/mono/SkiaSharp.git"
|
||||
refs = git("ls-remote", "--tags", remote, f"refs/tags/v{version}", f"refs/tags/v{version}^{{}}")
|
||||
if not refs:
|
||||
raise SystemExit(f"No immutable upstream release tag for {version}; refusing a moving branch")
|
||||
lines = refs.splitlines()
|
||||
commit = next((x.split()[0] for x in lines if x.endswith("^{}")), lines[0].split()[0])
|
||||
with tempfile.TemporaryDirectory() as tmp:
|
||||
git("init", "-q", tmp)
|
||||
git("-C", tmp, "fetch", "-q", "--depth=1", remote, commit)
|
||||
tree = git("-C", tmp, "ls-tree", "FETCH_HEAD", "externals/skia")
|
||||
mode, kind, skia, name = tree.split()
|
||||
if mode != "160000" or kind != "commit":
|
||||
raise SystemExit("Skia source is not a pinned git submodule")
|
||||
profile.update(skiasharp_version=version, skiasharp_revision=commit, skia_revision=skia)
|
||||
Path(a.output).write_text(json.dumps(profile, indent=2) + "\n")
|
||||
package = f"{version}-{angle}.{revision}"
|
||||
print(json.dumps({"skiasharp_version": version, "package_version": package, "lock": profile}))
|
||||
Reference in new issue
Block a user