Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
44 commits
Select commit Hold shift + click to select a range
c986411
fix(mappers)!: mapper 45 CHR-RAM is unbanked (T-GA23C-CHRRAM)
doublegate Oct 6, 2026
4aae8c1
build!: Rust 1.99 for the workspace, 1.96 for the libretro buildbot; …
doublegate Oct 7, 2026
aa55364
docs(plan): the v3.0.1 plan, and the odd-frame A12 task closed with w…
doublegate Oct 7, 2026
37e6406
docs(plan): name v3.0.1 "Mortar"
doublegate Oct 7, 2026
042a205
docs(plan): cite the v3.0.1 commits by their final hashes
doublegate Oct 7, 2026
9b879cc
ci(dependabot): one chore(deps) scope, and group the egui tier instea…
doublegate Oct 7, 2026
76c167f
fix(scripts): fail closed on partial review-thread payloads; diag out…
doublegate Oct 7, 2026
205e22d
docs(test-roms): point assorted/ at both LICENSES.md sections that ca…
doublegate Oct 7, 2026
a9acdd0
fix(perf): report zero discards without a presentation clock as UNVER…
doublegate Oct 7, 2026
314849c
fix(release): bump_release fails on a stale cosim lock, reads UTF-8, …
doublegate Oct 7, 2026
9a8e9e7
test(harness): release-notes render audit fails on a file it cannot read
doublegate Oct 7, 2026
4f72720
fix(review): test the 406 fallback matcher; use the API merge base on…
doublegate Oct 7, 2026
58ac019
ci(dependabot): drop the retired `reviewers` key; CODEOWNERS assigns …
doublegate Oct 7, 2026
49ea391
docs(provenance): name the upstream files in three headers; amend ADR…
doublegate Oct 7, 2026
8a8d420
docs(cpu): a taken branch defers NMI dispatch too, not only IRQ
doublegate Oct 7, 2026
7827c02
docs(mister): date the rung-0 text, name both rbf files, narrow gate …
doublegate Oct 7, 2026
19750b7
docs(agents): stage only intended paths; CodeRabbit plan and status
doublegate Oct 7, 2026
1da5e49
docs: correct stale figures, signatures and history across the records
doublegate Oct 7, 2026
97eda42
docs(provenance): restore "derived from Mesen2" at the 5B mix-level c…
doublegate Oct 7, 2026
8a28faf
docs(roadmap): open T-NTSC-PROVENANCE for the Bisqwit-style pass
doublegate Oct 7, 2026
d762953
fix(cosim): checkpoint parsing, overflow CSV and FFI docs from review
doublegate Oct 7, 2026
8149a35
style: four small leftovers from review (cpu, config, two probes)
doublegate Oct 7, 2026
e26d343
fix(gamedb): keep a mapper-0 override saved to the user overlay
doublegate Oct 7, 2026
8ab0d4b
test(ppu): round-trip the v6 snapshot tail at non-default values
doublegate Oct 7, 2026
4301fb9
fix(frontend): blank the Bisqwit index frame with no ROM; review left…
doublegate Oct 7, 2026
ad0dec7
test(harness): close four gaps in the release and feature-flag audits
doublegate Oct 7, 2026
93cc31b
fix(cosim): a public doc linked a private constant; CI now builds its…
doublegate Oct 7, 2026
1bf6f14
docs(changelog): the MiSTer dot-0 A12 fix and the review sweep in [Un…
doublegate Oct 7, 2026
9502c20
docs(libretro): the buildbot builds every pushed branch; v3.0.1 teste…
doublegate Oct 7, 2026
dece4a2
fix(provenance): record the shared Bisqwit NTSC pass as derived
doublegate Oct 7, 2026
416fe7d
chore(provenance): move the TriCNES source out of the repository
doublegate Oct 7, 2026
1740bf8
docs(changelog): the NTSC and TriCNES provenance changes in [Unreleased]
doublegate Oct 7, 2026
8cd0781
docs(roadmap): plan v3.1.0 to v4.0.0, from the 28 decisions of 2026-1…
doublegate Oct 7, 2026
2fa7e2c
docs(roadmap): move the hardware release to the end of v3.9.x (D29)
doublegate Oct 7, 2026
620c073
docs(agents): worktree-isolated agents cannot run git here
doublegate Oct 7, 2026
3175827
build(toolchain): move the libretro buildbot to Rust 1.99 too
doublegate Oct 7, 2026
fa48dfc
chore(release): cut v3.0.1 "Mortar"
doublegate Oct 7, 2026
de90569
docs(agents): condense AGENTS.md, archiving the removed text verbatim
doublegate Oct 7, 2026
a5f7aea
fix(ci): the NDK install step and the handbook build, both red on #590
doublegate Oct 7, 2026
0f90209
docs(agents): block-buffer 0.10.4 is locked but never compiled; Socke…
doublegate Oct 7, 2026
eecf8ea
docs: remove the 1.96 split everywhere it was still stated as current
doublegate Oct 7, 2026
61e9a42
fix: review round 1 on #590-#593 -- three gates that could pass wrongly
doublegate Oct 7, 2026
f1c3c47
fix(ci): run the toolchain-equality check for .gitlab-ci.yml-only PRs
doublegate Oct 7, 2026
36c15ea
docs: review round 3 (CodeRabbit on slice C, #593) -- 14 findings, 14…
doublegate Oct 7, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions .cargo/config.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,9 @@
# handled by the `getrandom` `js`-feature shim in the frontend's wasm32 deps.)
rustflags = ["--cfg=web_sys_unstable_apis", "--cfg=getrandom_backend=\"wasm_js\""]

# MSRV-aware (v1.3.0 bumped 1.86 -> 1.96) dependency resolution. The workspace pins
# rust-version = "1.96"; `fallback` makes `cargo update` prefer dependency
# MSRV-aware (v1.3.0 bumped 1.86 -> 1.96, v3.0.1 -> 1.99) dependency resolution.
# Every crate inherits the workspace's rust-version = "1.99" (seven libretro-path
# crates declared "1.96" for one day in v3.0.1); `fallback` makes `cargo update` prefer dependency
# versions compatible with that MSRV over the newest available. Without it, a
# future `cargo update` could pull a past-MSRV crate (e.g. `image` >= 0.26, a
# transitive dep of `arboard`'s clipboard image support, which needs a newer
Expand Down Expand Up @@ -54,7 +55,7 @@ full-build = "build --release -p rustynes-frontend --features full"
# self-heal instead of failing the job. This is repo-wide, so it covers EVERY
# cargo invocation: ci.yml, android.yml's `:app:cargoNdkBuild`, pgo.yml, web.yml,
# release.yml, and local builds. (Index fetches already use the sparse protocol
# by default on the pinned 1.96 toolchain; these settings harden the crate
# by default on the pinned toolchain; these settings harden the crate
# *download* step, which is where the failures occurred.)
[net]
retry = 10
Expand Down
2 changes: 1 addition & 1 deletion .github/actions/rust-setup/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ runs:
# them were reviewed rather than trusted -- runner updates, patch-release
# table entries, a cross-device-copy fix and checkout bumps.
- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@02cb101ec7c40f2c49e1d9714d64511d8e1b74de # v1
uses: dtolnay/rust-toolchain@7e38f4b43b4db5c8dd498af069a4f6196df1d067 # v1
with:
toolchain: ${{ steps.resolve.outputs.toolchain }}
targets: ${{ inputs.targets }}
Expand Down
72 changes: 32 additions & 40 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,47 +13,41 @@ updates:
labels:
- "dependencies"
- "rust"
# The prefix carries no scope: `include: "scope"` appends `(deps)` (or
# `(deps-dev)`) itself, so a `chore(deps)` prefix titled every PR
# `chore(deps)(deps): ...` until v3.0.1.
commit-message:
prefix: "chore(deps)"
prefix: "chore"
include: "scope"
reviewers:
- "doublegate"
# No `reviewers:` key: GitHub retired it in 2025 in favour of CODEOWNERS
# (github.blog changelog 2025-08-08), and `.github/CODEOWNERS` assigns
# @doublegate to every path. Removed in v3.0.1.
assignees:
- "doublegate"
# HOLD the egui tier. A comment in `Cargo.toml` explains WHY the pin exists,
# but a comment does not reach Dependabot -- it would keep re-opening the
# same three PRs every Monday, and the risk is not the noise, it is that the
# twentieth identical PR gets merged on the assumption it is routine.
#
# `egui-winit` 0.36.1 does not compile for `wasm32-unknown-unknown`, and
# RustyNES ships a wasm demo:
#
# error[E0407]: method `bytes` is not a member of trait `egui::DroppedFile`
#
# egui 0.36 split `DroppedFile` by target (`bytes_async` on wasm, `bytes` on
# native) while egui-winit's `NativeFile` impl has no cfg gate, so on wasm it
# implements a method the trait does not declare and omits the one it does.
# `wgpu` is held with them only because `egui-wgpu` 0.35 pins it.
#
# REMOVE ALL FOUR ENTRIES once upstream ships the fix -- this is a hold, not
# a policy. Re-check by bumping and running both wasm clippy invocations.
ignore:
- dependency-name: "egui"
versions: [">=0.36"]
- dependency-name: "egui-wgpu"
versions: [">=0.36"]
- dependency-name: "egui-winit"
versions: [">=0.36"]
- dependency-name: "wgpu"
versions: [">=30"]
# `naga` is a DIRECT dependency of `rustynes-frontend` (WGSL validation),
# not merely a wgpu transitive, so Dependabot would propose 30 on its own
# and the hold would be broken from a direction the four entries above do
# not cover. Caught in review on the v2.6.3 refresh.
- dependency-name: "naga"
versions: [">=30"]
# Group minor and patch updates together
# From 2026-09-12 to 2026-09-28 an `ignore` block here held egui,
# egui-wgpu, egui-winit (`>=0.36`), wgpu and naga (`>=30`) at the 0.35 tier,
# because egui-winit 0.36 did not compile for wasm32. The tier then moved to
# 0.36 / wgpu 30 with egui-winit vendored (see `Cargo.toml`), and the hold
# stayed behind until v3.0.1 -- silently blocking every later egui and wgpu
# release. The coupling it protected is real, so it is now a GROUP instead.
groups:
# ONE PR FOR THE WHOLE TIER. `Cargo.toml` says these five move together:
# `egui-wgpu` pins one wgpu major, a graph holding two wgpu majors fails
# every device/queue handoff, and `naga` is a DIRECT dependency of
# `rustynes-frontend` (WGSL validation) that must match wgpu's. Listed
# FIRST, with no `update-types`, because Dependabot puts a dependency in
# the first group it matches -- below the catch-all groups, a minor bump
# of one of these would land alone in `production-dependencies`. Before
# merging one: egui-winit is vendored (`vendor/egui-winit/VENDORED.md`),
# and a bump past 0.36.2 bypasses that patch, so run both wasm clippy gates.
egui-wgpu-tier:
patterns:
- "egui"
- "egui-wgpu"
- "egui-winit"
- "wgpu"
- "naga"
# Group minor and patch updates together
development-dependencies:
dependency-type: "development"
update-types:
Expand Down Expand Up @@ -119,7 +113,7 @@ updates:
- "dependencies"
- "android"
commit-message:
prefix: "chore(deps)"
prefix: "chore"
include: "scope"

# `crates/rustynes-cosim` is EXCLUDED from the workspace on purpose (cargo
Expand All @@ -142,7 +136,7 @@ updates:
- "dependencies"
- "rust"
commit-message:
prefix: "chore(deps)"
prefix: "chore"
include: "scope"

# Maintain GitHub Actions
Expand All @@ -159,7 +153,5 @@ updates:
- "github-actions"
commit-message:
prefix: "chore(ci)"
reviewers:
- "doublegate"
assignees:
- "doublegate"
2 changes: 2 additions & 0 deletions .github/release-notes/v2.6.7.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ A detent is the notch that holds a mechanism at an exact position and makes that

**The emulation core is unchanged.** AccuracyCoin 141/141 (RAM decoder) and nestest 0-diff hold by construction; the work is in the sibling repository and in the release machinery.

> Correction (v3.0.1): the sentence above is wrong. The emulation core changed in one place in this release, the taken-branch NMI poll in `Cpu::handle_interrupts` (`skip_irq_sample_q`, `CPU_SNAPSHOT_VERSION` 3 to 4; see "An interrupt polled on a cycle the documentation forbids" below), and AccuracyCoin 141/141 and nestest 0-diff were re-run against it rather than holding by construction.

## The gate

| # | criterion | result |
Expand Down
52 changes: 52 additions & 0 deletions .github/release-notes/v3.0.1.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
# RustyNES v3.0.1 — "Mortar"

A maintenance release on v3.0.0. It fixes one game's graphics, reaches the last untested exception of the MMC3 timing rule in the MiSTer core (and fixes the one-cycle defect that found), moves the toolchain and every dependency to its newest release, answers every bot review left unanswered since PR #1, settles two provenance questions, and writes the plan to v4.0.0. **Movies recorded with v3.0.0, and netplay peers running it, are refused**: the emulation epoch rises to 2. Save states are unaffected.

## Breaking change

- **Movies and netplay from v3.0.0 are refused.** The mapper 45 fix below changes what *Famicom Yarou Vol.1* produces, so `EMULATION_EPOCH` rises from 1 to 2 ([ADR 0045](https://github.com/doublegate/RustyNES/blob/main/docs/adr/0045-a-core-timing-epoch-guards-movies-and-netplay.md)). The refusal names both epochs. Save states load as before.

## Fixed

- ***Famicom Yarou Vol.1 7-in-1* draws its menu.** Mapper 45 (GA23C) addresses a cartridge's CHR-RAM unbanked, as the board does; the emulator had banked it like CHR-ROM and drew noise (T-GA23C-CHRRAM).
- **The MiSTer core's MMC3 timing, one cycle on odd frames.** v3.0.0's dot-0 rule for the background's A12 had an exception for the dot the odd-frame skip replaces, and nothing ever reached it. A new generated test ROM does, and found that a `$2001` write taking effect one dot late still applied the rule, so the MMC3 interrupt came one CPU cycle early. The rule now asks whether cycle 0 was rendering. The core and the emulator agree on all 2,978,055 cycles of the new test, and a new comparison of the cycle on which each interrupt rises catches the exception's mutant, which the bus comparison alone could not.
- **Every unanswered bot review, back to PR #1, answered.** 290 unanswered review threads, review-body findings and Antigravity reviews across both repositories got 473 verdicts; the 80 still valid were fixed. Among them: the Bisqwit NTSC filter kept showing the last game frame after a ROM was closed; a mapper-0 override saved from the ROM Database panel vanished on restart; the release tooling could exit 0 on a stale lockfile; three release audits could pass on prose they should fail; and Dependabot's egui holds blocked every future egui and wgpu update (now a group that moves them together).

## Provenance

- **The shared Bisqwit NTSC pass is recorded as derived.** Its documentation called it an independent implementation, but it is a generated copy of the desktop filter, whose tables were long recorded as ported from Bisqwit's C via Mesen2. It now carries the same attribution, and the audit lost the exception that hid it.
- **The TriCNES source moved out of the repository.** TriCNES (MIT, by the AccuracyCoin author) stays the one reference whose source may be consulted, for AccuracyCoin work and always attributed. The committed cross-diff evidence stays.
- **A softened comment in the Sunsoft 5B mixer says "derived from" again.**

## Toolchain and dependencies

- **Rust 1.99, everywhere.** The libretro buildbot moves too: the release first held it on 1.96 because its build image passed a flag Rust 1.97 rejects, then found the image had dropped it, and a test branch built all 15 buildbot jobs on 1.99, Apple included. CI now fails if the two toolchains ever differ.
- **Every dependency at its newest release**: crates, GitHub Actions (macOS jobs move to `macos-15`), Android (`cargo-ndk` 4, NDK r30), the web build (wasm-opt now pinned), the documentation build, and Docker images (Rust 1.99, Debian 13).

## The MiSTer core

- **Release candidate, not hardware-verified.** No hardware has run either bitstream.
- **The co-simulation ladder is 200 passed, 0 failed, 1 expected failure on-die and 201 passed, 0 failed, 1 expected failure off-die**, each from one run of a frozen tree, with nothing skipped. The one new gate is the odd-frame A12 test above.
- **New bitstreams, because the fix is RTL.** Both builds are compiled at fitter seed 2, chosen from eight seeds swept on one build date (261007), every one of which closes on both builds. Each was compiled twice to the same bytes:
- on-die `RustyNES_MiSTer-v3.0.1.rbf`, md5 `7e81a71869760b35a2fd04e6309c5c39` (timing margin +0.448 ns setup, +0.113 ns hold);
- off-die `RustyNES_MiSTer-v3.0.1-offdie.rbf`, md5 `88d1dfa53a94996a92c0f768b3be3039` (+0.401 / +0.096 ns; the SDRAM read +0.447 / +1.184 ns, assuming zero board delay).
- The bitstreams carry the sweep's build date, which may be earlier than the release date.

## The road to v4.0.0

The plan from v3.1.0 to v4.0.0 is written ([`to-dos/plans/v3.1-to-v4.0-line-plan.md`](https://github.com/doublegate/RustyNES/blob/main/to-dos/plans/v3.1-to-v4.0-line-plan.md)), from 29 maintainer decisions. v4.0.0 makes the remaining public enums `#[non_exhaustive]` and brings the MiSTer core to feature parity. The hardware-verification release (the SuperStation One board session and the mobile device run) comes at the end of the v3.9.x line, so it tests the near-final core.

## Verification

- `--features test-roms`: 3,234 passed, 0 failed, 11 ignored.
- The local commercial suites: `external_real_games` 60/0, `external_extended` 137/0, `external_coverage` 6/0 over every staged ROM. The one moved baseline is *Famicom Yarou Vol.1*, which now draws its menu.
- AccuracyCoin 144/144, nestest 0-diff.
- The libretro buildbot: all 15 jobs on Rust 1.99 before the pin was lifted.

## Install

- Download the pre-built binaries for Linux, macOS, and Windows below.
- The MiSTer core bitstreams are attached below, as a release candidate, not hardware-verified. The on-die build is `RustyNES_MiSTer-v3.0.1.rbf`, also attached under its datecoded name `RustyNES_20261007.rbf`, and the off-die build is `RustyNES_MiSTer-v3.0.1-offdie.rbf`.
- The WebAssembly build is live at [doublegate.github.io/RustyNES](https://doublegate.github.io/RustyNES/).
- The RetroArch core is in RetroArch's Online Updater on the platforms the libretro buildbot publishes to.
- Licensed under GPL-3.0-or-later.
72 changes: 58 additions & 14 deletions .github/workflows/android.yml
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,12 @@ concurrency:

env:
CARGO_TERM_COLOR: always
# v3.0.1: NDK r30, the newest stable (`ndk;30.0.16248370` in Google's SDK
# repository). The runner image ships r29 as its newest, so every job
# installs this one with `sdkmanager` in its "Resolve NDK" step. r30's
# changelog lists a newer clang, simpleperf prebuilts and sysroots up to
# API 37; nothing that touches a `--platform 26` build.
NDK_VERSION: "30.0.16248370"

jobs:
cross-build:
Expand Down Expand Up @@ -103,7 +109,7 @@ jobs:
- 'crates/rustynes-mobile/**'
- '.github/workflows/android.yml'

# The project toolchain (rust-toolchain.toml = 1.96) plus the two shipped
# The project toolchain (rust-toolchain.toml = 1.99) plus the two shipped
# Android targets (arm64 ships; x86_64 is the emulator/CI ABI), through
# the shared composite. A bare `rustup target add` made rustup
# AUTO-INSTALL the pinned toolchain first, which rustup now deprecates
Expand All @@ -122,19 +128,29 @@ jobs:
# `taiki-e/install-action` knows, which is why this is the caching form.
- uses: taiki-e/cache-cargo-install-action@v3
with:
tool: cargo-ndk@3
tool: cargo-ndk@4

# ubuntu-26.04 ships the Android SDK + an NDK; resolve its path so
# cargo-ndk finds the toolchain. (We pin a recent NDK; r27+ aligns .so to
# 16 KB by default — a Play requirement for Android 15+.)
# Both variables, to the same NDK. The runner image sets ANDROID_NDK_ROOT
# to its default NDK (27.x) while this job selects the latest (29.x) via
# to its default NDK (27.x) while this job selects its own (r30, above) via
# ANDROID_NDK_HOME, and cargo-ndk warned on every build that the two
# disagree -- a real ambiguity about which toolchain linked the library.
- name: Resolve NDK
run: |
echo "ANDROID_NDK_HOME=$ANDROID_NDK_LATEST_HOME" >> "$GITHUB_ENV"
echo "ANDROID_NDK_ROOT=$ANDROID_NDK_LATEST_HOME" >> "$GITHUB_ENV"
set -euo pipefail
sdk="${ANDROID_SDK_ROOT:-$ANDROID_HOME}"
# `yes` answers the licence prompt. Under `pipefail` its own exit
# status (EPIPE / SIGPIPE once sdkmanager closes the pipe, 141 here)
# failed the step even when the install succeeded, so it is absorbed;
# sdkmanager's status, and the clang check below, still decide.
(yes || true) | "$sdk/cmdline-tools/latest/bin/sdkmanager" --install "ndk;$NDK_VERSION" > /dev/null
ndk="$sdk/ndk/$NDK_VERSION"
test -x "$ndk/toolchains/llvm/prebuilt/linux-x86_64/bin/clang" \
|| { echo "::error::NDK $NDK_VERSION did not install at $ndk"; exit 1; }
echo "ANDROID_NDK_HOME=$ndk" >> "$GITHUB_ENV"
echo "ANDROID_NDK_ROOT=$ndk" >> "$GITHUB_ENV"

- name: Cross-compile mobile + android (arm64 + x86_64)
run: |
Expand Down Expand Up @@ -198,15 +214,29 @@ jobs:
cache-key: android-ndk
- uses: taiki-e/cache-cargo-install-action@v3
with:
tool: cargo-ndk@3
tool: cargo-ndk@4
# v3.0.1: Temurin 25, the newest LTS (was 17). This is the JDK that RUNS
# Gradle; the bytecode target stays JVM 17 (`jvmTarget` and
# `sourceCompatibility` in app/build.gradle.kts), which is AGP 9.4's
# floor. Gradle 9.8 supports running on Java 25 (9.1.0 and later).
- uses: actions/setup-java@v6
with:
distribution: temurin
java-version: '17'
java-version: '25'
- name: Resolve NDK
run: |
echo "ANDROID_NDK_HOME=$ANDROID_NDK_LATEST_HOME" >> "$GITHUB_ENV"
echo "ANDROID_NDK_ROOT=$ANDROID_NDK_LATEST_HOME" >> "$GITHUB_ENV"
set -euo pipefail
sdk="${ANDROID_SDK_ROOT:-$ANDROID_HOME}"
# `yes` answers the licence prompt. Under `pipefail` its own exit
# status (EPIPE / SIGPIPE once sdkmanager closes the pipe, 141 here)
# failed the step even when the install succeeded, so it is absorbed;
# sdkmanager's status, and the clang check below, still decide.
(yes || true) | "$sdk/cmdline-tools/latest/bin/sdkmanager" --install "ndk;$NDK_VERSION" > /dev/null
ndk="$sdk/ndk/$NDK_VERSION"
test -x "$ndk/toolchains/llvm/prebuilt/linux-x86_64/bin/clang" \
|| { echo "::error::NDK $NDK_VERSION did not install at $ndk"; exit 1; }
echo "ANDROID_NDK_HOME=$ndk" >> "$GITHUB_ENV"
echo "ANDROID_NDK_ROOT=$ndk" >> "$GITHUB_ENV"
- uses: gradle/actions/setup-gradle@v6.4.0
with:
cache-provider: basic
Expand Down Expand Up @@ -254,19 +284,33 @@ jobs:
# `taiki-e/install-action` knows, which is why this is the caching form.
- uses: taiki-e/cache-cargo-install-action@v3
with:
tool: cargo-ndk@3
tool: cargo-ndk@4
# v3.0.1: Temurin 25, the newest LTS (was 17). This is the JDK that RUNS
# Gradle; the bytecode target stays JVM 17 (`jvmTarget` and
# `sourceCompatibility` in app/build.gradle.kts), which is AGP 9.4's
# floor. Gradle 9.8 supports running on Java 25 (9.1.0 and later).
- uses: actions/setup-java@v6
with:
distribution: temurin
java-version: '17'
java-version: '25'
# Both variables, to the same NDK. The runner image sets ANDROID_NDK_ROOT
# to its default NDK (27.x) while this job selects the latest (29.x) via
# to its default NDK (27.x) while this job selects its own (r30, above) via
# ANDROID_NDK_HOME, and cargo-ndk warned on every build that the two
# disagree -- a real ambiguity about which toolchain linked the library.
- name: Resolve NDK
run: |
echo "ANDROID_NDK_HOME=$ANDROID_NDK_LATEST_HOME" >> "$GITHUB_ENV"
echo "ANDROID_NDK_ROOT=$ANDROID_NDK_LATEST_HOME" >> "$GITHUB_ENV"
set -euo pipefail
sdk="${ANDROID_SDK_ROOT:-$ANDROID_HOME}"
# `yes` answers the licence prompt. Under `pipefail` its own exit
# status (EPIPE / SIGPIPE once sdkmanager closes the pipe, 141 here)
# failed the step even when the install succeeded, so it is absorbed;
# sdkmanager's status, and the clang check below, still decide.
(yes || true) | "$sdk/cmdline-tools/latest/bin/sdkmanager" --install "ndk;$NDK_VERSION" > /dev/null
ndk="$sdk/ndk/$NDK_VERSION"
test -x "$ndk/toolchains/llvm/prebuilt/linux-x86_64/bin/clang" \
|| { echo "::error::NDK $NDK_VERSION did not install at $ndk"; exit 1; }
echo "ANDROID_NDK_HOME=$ndk" >> "$GITHUB_ENV"
echo "ANDROID_NDK_ROOT=$ndk" >> "$GITHUB_ENV"
- uses: gradle/actions/setup-gradle@v6.4.0
with:
# v6 extracted the default ("enhanced") Gradle User Home cache into the
Expand Down
Loading
Loading