Skip to content

Port: stop blending from motion sets whose memory was released #205

Port: stop blending from motion sets whose memory was released

Port: stop blending from motion sets whose memory was released #205

Workflow file for this run

name: PC builds
on:
push:
branches: [master]
pull_request:
workflow_dispatch:
permissions:
contents: read
jobs:
build:
name: Build and test
runs-on: ubuntu-26.04
steps:
- uses: actions/checkout@v7
with:
submodules: true
fetch-depth: 0
- name: Select the PAL_TIMING baseline
env:
PR_BASE: ${{ github.event.pull_request.base.sha }}
BEFORE: ${{ github.event.before }}
EVENT: ${{ github.event_name }}
DEFAULT_BRANCH: ${{ github.event.repository.default_branch }}
run: |
base="$PR_BASE"
if [ "$EVENT" = push ] && [ -n "$BEFORE" ] && ! [[ "$BEFORE" =~ ^0+$ ]]; then
base="$BEFORE"
elif [ "$EVENT" != pull_request ]; then
[ -n "$DEFAULT_BRANCH" ] || { echo "No default branch for the PAL_TIMING baseline" >&2; exit 1; }
git fetch --no-tags origin "refs/heads/$DEFAULT_BRANCH" || { echo "Cannot fetch the default branch for the PAL_TIMING baseline" >&2; exit 1; }
base=$(git merge-base HEAD FETCH_HEAD) || { echo "No merge-base with the default branch for the PAL_TIMING baseline" >&2; exit 1; }
fi
git cat-file -e "$base^{commit}" || { echo "Missing PAL_TIMING baseline: $base" >&2; exit 1; }
echo "CT_PAL_TIMING_BASE=$base" >> "$GITHUB_ENV"
# FFmpeg uses Kazarov's pinned build configuration; cxxbridge-cmd is a prebuilt release asset.
- name: Install the toolchain and libraries
run: |
sudo apt-get update
sudo apt-get install -y build-essential clang-22 lld-22 llvm-22 libclang1-22 python3-clang-22 cmake ninja-build glslang-tools \
mesa-vulkan-drivers vulkan-validationlayers libsdl3-dev libvulkan-dev libgtest-dev nlohmann-json3-dev
# clang++, ld.lld and llvm-readobj under their plain names.
echo "/usr/lib/llvm-22/bin" >> "$GITHUB_PATH"
rustup toolchain install 1.99.0 --profile minimal
rustup default 1.99.0
tools/ci/prebuilt-deps.sh linux-x64
# Lavapipe renders on the CPU, so the unit tests' per-case limit is widened from its 5 second default.
# CT_SYMBOLS=split also writes darkchronicle.debug with objcopy, which the symboliser check reads.
# Debug keeps the Vulkan validation layer and assertions on; the Flatpak is the shipped, Release Linux build.
- name: Configure
run: cmake --preset linux-x64 -DCT_TEST_TIMEOUT=60 -DCT_PAL_TIMING_BASE="$CT_PAL_TIMING_BASE" -DCT_SYMBOLS=split
- name: Build
run: cmake --build --preset linux-x64
# Truncations.Check and Records.Check exit 77 (SKIPPED) without the clang bindings, and a skip passes CI silently.
- name: Check that the pointer checks can run
run: python3 -c "import clang.cindex"
- name: Test
run: ctest --test-dir port/build/pc --output-on-failure -j4
- name: Test Rust data publisher
run: cargo test --locked --manifest-path tools/kazarov/Cargo.toml
# docs/SYMBOLS.md: the report symboliser, end to end against a small clang-built probe.
- name: Test the crash report symboliser
run: python3 -m unittest discover -s tools/crash -p "test_*.py" -v
# A raw frame at main resolves to main.cpp through the build id'd binary's split debug file.
- name: Check the build id and the split symbols
run: |
llvm-readelf --notes port/build/pc/darkchronicle | grep -q 'Build ID'
llvm-readelf --sections port/build/pc/darkchronicle | grep -q '.gnu_debuglink'
offset=$(llvm-nm port/build/pc/darkchronicle | awk '$3 == "main" { print $1 }')
printf '#0 darkchronicle+0x%s\n' "$offset" > report.txt
python3 tools/crash/symbolize.py report.txt --binary port/build/pc/darkchronicle.debug | tee symbolized.txt
grep -q 'main.cpp:' symbolized.txt
# The VU1 programs are native: their packed CPU halves live only in the test oracles.
- name: Check that no PS2 packing or VU1 layout helper is in the runtime
run: python3 scripts/port/native_gate.py --binary port/build/pc/darkchronicle
# A non-PIE link places the game below 4 GiB, where a pointer truncated to 32 bits still works and hides the bug.
- name: Check that darkchronicle is position-independent
run: |
llvm-readobj --file-headers port/build/pc/darkchronicle | grep -q 'Type: SharedObject'
macos:
name: Build and test (macOS arm64)
runs-on: macos-26
env:
HOMEBREW_NO_AUTO_UPDATE: 1
HOMEBREW_NO_INSTALL_CLEANUP: 1
# These 14 rendering tests read back black frames or wrong pixels only on the hosted runner's virtual
# GPU (Apple Paravirtual device under MoltenVK). The same test binary passes all 14 on Apple Silicon
# hardware (M3, macOS 27.0.1, MoltenVK 1.4.2), and Linux CI gates them on lavapipe. They are reported
# here without failing the job; remove this once the runner's GPU renders them correctly.
MACOS_GPU_REPORT_ONLY: >-
^(MgDrawPrimRender\.LinearAtlasCellsKeepTopOutlinesWithoutSamplingTheNextCell|MgShadow\.OverlappingCastersShadeTheirUnionNotTheirSum|MgVisual\.DrawManagerPathMatchesDirect|MgVisual\.DirectMaterialUsesItsOwnTextureWrap|MgVisual\.QueuedMaterialRetainsItsOwnTextureWrap|MglibAspect\.MenuFormsHideParkedStatsWithoutClippingEnteringPanel|MglibPresent\.BackBufferCapturePreservesWidePixelsAndHoldsUntilRecaptured|MglibSeam\.ReusedTextureKeyDoesNotSampleRetiredRenderTarget|MenuIconGpu\.ItemDrawSamplesSelectedAtlasCellsInCanonicalAndDisplayFrames|MenuIconGpu\.EffectUsesSelectedBakedRgbaAtlasAndRestoresNormally|MgTextureGpu\.HighResolutionKeepsLogicalCpuStrideAndSpriteBounds|GfxGpuMeshDc2\.RefSphere|GfxGpuMeshDc2\.Prog0CullModeFollowsFlagAndMirror|GfxGpuDisplayList\.PresentationCompositeDoesNotWriteTransparentDepth)$
steps:
- uses: actions/checkout@v7
with:
submodules: true
- name: Install the toolchain and libraries
run: |
brew install llvm lld cmake ninja python glslang sdl3 vulkan-headers vulkan-loader vulkan-tools molten-vk \
googletest nlohmann-json
rustup toolchain install 1.99.0 --profile minimal --component clippy,rustfmt
rustup default 1.99.0
tools/ci/prebuilt-deps.sh macos-arm64
# SDL loads the Vulkan loader by name, and dyld does not search Homebrew's prefix.
echo "SDL_VULKAN_LIBRARY=$(brew --prefix vulkan-loader)/lib/libvulkan.1.dylib" >> "$GITHUB_ENV"
echo "VK_DRIVER_FILES=$(brew --prefix)/etc/vulkan/icd.d/MoltenVK_icd.json" >> "$GITHUB_ENV"
- name: Describe the Vulkan driver
run: |
mkdir -p artifacts
vulkaninfo --summary > artifacts/vulkaninfo.txt 2>&1 || true
cat artifacts/vulkaninfo.txt
# CT_SYMBOLS=split runs dsymutil after the link, for the symbol artifact.
- name: Configure
run: cmake --preset macos-arm64-release -DCT_TEST_TIMEOUT=60 -DCT_SYMBOLS=split
- name: Build
run: cmake --build --preset macos-arm64-release
- name: Test
run: ctest --preset macos-arm64-release -E "$MACOS_GPU_REPORT_ONLY"
- name: Test cases the hosted runner's virtual GPU renders wrongly (report only)
continue-on-error: true
run: ctest --preset macos-arm64-release -R "$MACOS_GPU_REPORT_ONLY"
- name: Test Rust data publisher
run: cargo test --locked --manifest-path tools/kazarov/Cargo.toml
- name: Package the macOS build
run: tar -czf artifacts/chronicletwo-macos-arm64.tar.gz -C port/build/macos-arm64-release darkchronicle scripts Luau-LICENSE.txt -C assets data.zip
- name: Upload the macOS build
uses: actions/upload-artifact@v7
with:
name: chronicletwo-macos-arm64
path: artifacts/chronicletwo-macos-arm64.tar.gz
if-no-files-found: error
# Without Homebrew's llvm on PATH the symboliser falls back to atos, against the dSYM.
- name: Check the dSYM resolves a frame
run: |
address=$(nm port/build/macos-arm64-release/darkchronicle | awk '$3 == "_main" { print $1 }')
printf '#0 darkchronicle+0x%x\n' $((0x$address - 0x100000000)) > report.txt
python3 tools/crash/symbolize.py report.txt --binary port/build/macos-arm64-release/darkchronicle.dSYM | tee symbolized.txt
grep -q 'main.cpp:' symbolized.txt
# docs/SYMBOLS.md: tools/crash/symbolize.py resolves a report from this build with the dSYM.
- name: Package the macOS symbols
run: tar -czf artifacts/chronicletwo-macos-arm64-symbols.tar.gz -C port/build/macos-arm64-release darkchronicle darkchronicle.dSYM
- name: Upload the macOS symbols
uses: actions/upload-artifact@v7
with:
name: chronicletwo-macos-arm64-symbols-${{ github.sha }}
path: artifacts/chronicletwo-macos-arm64-symbols.tar.gz
if-no-files-found: error
- name: Upload the Vulkan description
if: always()
uses: actions/upload-artifact@v7
with:
name: macos
path: artifacts/vulkaninfo.txt
if-no-files-found: warn
windows:
name: Build and test (Windows x64)
runs-on: windows-2025
defaults:
run:
shell: pwsh
steps:
- uses: actions/checkout@v7
with:
submodules: true
# Runtime DLLs, including the Vulkan loader, are acquired and bundled by default.
- name: Install the toolchain and libraries
run: |
./tools/windows/acquire.ps1 -Root $env:RUNNER_TEMP
- name: Configure
run: |
./tools/windows/configure.ps1 -Root $env:RUNNER_TEMP -BuildDirectory $env:GITHUB_WORKSPACE/port/build/windows-x64-release-tests -Tests -BuildType Release -TestTimeout 60
- name: Build
run: |
./tools/windows/build.ps1 -Root $env:RUNNER_TEMP -BuildDirectory $env:GITHUB_WORKSPACE/port/build/windows-x64-release-tests -Tests
if ($LASTEXITCODE) { exit $LASTEXITCODE }
# The runner has no Vulkan device, so cases labelled gpu are excluded.
- name: Test
run: ctest --test-dir port/build/windows-x64-release-tests --output-on-failure -j4 -LE gpu
- name: Test Rust data publisher
run: |
$env:CARGO_HOME = "$env:RUNNER_TEMP/deps/rust/cargo-home"
$rust = "$env:RUNNER_TEMP/deps/rust/1.99.0-gnullvm/bin"
$llvm = "$env:RUNNER_TEMP/deps/llvm/llvm-mingw-20260922-ucrt-x86_64/bin"
$env:PATH = "$rust;$llvm;$env:PATH"
& "$rust/cargo.exe" test --locked --manifest-path tools/kazarov/Cargo.toml
if ($LASTEXITCODE) { exit $LASTEXITCODE }
- name: Package the Windows build
run: |
./tools/windows/package.ps1 -BuildDirectory port/build/windows-x64-release-tests -Destination chronicletwo-windows-x64.zip
- name: Upload the Windows build
uses: actions/upload-artifact@v7
with:
name: chronicletwo-windows-x64
path: chronicletwo-windows-x64.zip
if-no-files-found: error
- name: Check the executable resolves a frame
run: |
$llvm = "$env:RUNNER_TEMP/deps/llvm/llvm-mingw-20260922-ucrt-x86_64/bin"
$exe = 'port/build/windows-x64-release-tests/darkchronicle.exe'
$address = (& "$llvm/llvm-nm.exe" $exe | Where-Object { $_ -match ' T wmain$' }).Split(' ')[0]
'#0 darkchronicle.exe+0x{0:x}' -f ([Convert]::ToUInt64($address, 16) - 0x140000000) | Set-Content report.txt
python tools/crash/symbolize.py report.txt --binary $exe --llvm-symbolizer "$llvm/llvm-symbolizer.exe" | Tee-Object symbolized.txt
if (!(Select-String -Quiet -Path symbolized.txt -Pattern 'main.cpp:')) { exit 1 }
# docs/SYMBOLS.md: the executables (their DWARF), any PDBs and their build ids, for tools/crash/symbolize.py.
- name: Package the Windows symbols
run: |
./tools/windows/package-symbols.ps1 -Root $env:RUNNER_TEMP -BuildDirectory port/build/windows-x64-release-tests -Destination chronicletwo-windows-x64-symbols.zip
- name: Upload the Windows symbols
uses: actions/upload-artifact@v7
with:
name: chronicletwo-windows-x64-symbols-${{ github.sha }}
path: chronicletwo-windows-x64-symbols.zip
if-no-files-found: error
# docs/FLATPAK.md: the Linux build packaged in Flathub's freedesktop 26.08 image. The manifest uses the
# commit under test as a git source, and the smoke run checks that the packaged binary reaches its data check.
flatpak:
name: Build the Flatpak (Linux x86_64)
runs-on: ubuntu-26.04
container:
image: ghcr.io/flathub-infra/flatpak-github-actions:freedesktop-26.08
options: --privileged
env:
MANIFEST: port/flatpak/ci.yml
steps:
- uses: actions/checkout@v7
with:
submodules: true
- name: Check that the vendored crates match Kazarov's Cargo.lock
run: |
# The workspace belongs to another user in the container, which git refuses until it is marked safe.
git config --global --add safe.directory "$GITHUB_WORKSPACE"
python3 port/flatpak/cargo_sources.py
git diff --exit-code port/flatpak/cargo-sources.json
- name: Point the manifest at this commit
run: |
awk -v commit="$GITHUB_SHA" '
/# chronicletwo-source:/ {
print
print " - type: git"
print " path: ../.."
print " commit: " commit
skip = 1
next
}
/# chronicletwo-source-end/ { skip = 0 }
!skip { print }
' port/flatpak/org.themoonpeople.ChronicleTwo.yml > "$MANIFEST"
sed -n '/name: chronicletwo$/,$p' "$MANIFEST" | head -80
- uses: flatpak/flatpak-github-actions/flatpak-builder@v6
with:
manifest-path: ${{ env.MANIFEST }}
bundle: chronicletwo.flatpak
artifact-name: chronicletwo-x86_64.flatpak
cache-key: flatpak-builder-${{ hashFiles('port/flatpak/org.themoonpeople.ChronicleTwo.yml', 'port/flatpak/cargo-sources.json') }}
- name: Start darkchronicle without data
run: |
set +e
flatpak build --env=XDG_DATA_HOME=/tmp/xdg flatpak_app darkchronicle --headless --frames 1 > run.txt 2>&1
status=$?
cat run.txt
echo "darkchronicle exited $status"
[ "$status" -eq 3 ] && grep -q 'No current Dark Chronicle data at /tmp/xdg/chronicletwo/data' run.txt
# The packaged darkchronicle keeps its line tables (the manifest sets no-debuginfo), so it is its own
# symbol file for tools/crash/symbolize.py.
- name: Upload the Flatpak symbols
uses: actions/upload-artifact@v7
with:
name: chronicletwo-flatpak-x86_64-symbols-${{ github.sha }}
path: flatpak_app/files/bin/darkchronicle
if-no-files-found: error