Add the pinned RetroArch frontend build recipe - #19
Conversation
Completes the buildable half of the retro path. The cores recipe added in the previous change produces libretro cores; this produces the frontend that loads them, under the same D-185 boundary: nothing is vendored, the pinned archive is fetched and verified, and a digest mismatch refuses to build. Version 1.22.2 is not a new choice. It is the frontend version catalog/retro-2048.vcg-game.json already declares. RetroArch publishes no Linux or aarch64 binary asset for this release -- the only artifact on the release is retroarch-sourceonly-1.22.2.tar.xz -- so building from pinned source is the only option for the Raspberry Pi and also the one most consistent with D-185. Three independent downloads of that tarball were byte-identical at SHA-256 2a8b1713f7f4d2b53bad3e2297e48d78f5666098cf00d583d3e08f3c213f8aa6, 13564476 bytes. The dependency list was found by building this exact release rather than copied from documentation. A first attempt configured cleanly, compiled 450 objects, reached its link step, and failed only on libx11-xcb-dev, so that package is required rather than optional. The recipe checks every dependency up front with dpkg-query and prints the exact apt command instead of failing partway through a build. The configure profile is deliberately small: no Qt, which is a desktop UI this appliance never shows, and no CG, Vulkan, glslang, Discord, or cheevos stacks, which pull in large dependency sets for features the Pi profile does not use. Verified: fetch, digest check, configure, full build, and a binary that reports "Version: 1.22.2". A tampered pin is refused before any build runs. The GPL-3.0 licence text is captured beside the artifact. Verified on x86_64 only, and the script says so at runtime. A Raspberry Pi uses GLES rather than desktop GL, so libgles2-mesa-dev may be needed in place of libgl1-mesa-dev; the dependency error message states this. Nothing here is qualified. A built frontend is not evidence of working video, audio, input, compositor behaviour, or frame pacing on any target, and nothing has been built on or run on a Raspberry Pi. Signed package assembly for aarch64 and the per-system game manifests remain unimplemented. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
📝 WalkthroughWalkthroughAdds a shell script that validates the host, downloads and verifies RetroArch 1.22.2, builds a minimal SDL2/ALSA profile, installs the binary with GPL notices, and reports that target qualification is incomplete. ChangesRetroArch Raspberry Pi build
Estimated code review effort: 3 (Moderate) | ~20 minutes Sequence Diagram(s)sequenceDiagram
participant Developer
participant Script as build-retro-frontend.sh
participant Archive as RetroArch 1.22.2 archive
participant Host as Linux build host
participant Output as output directory
Developer->>Script: provide --out and --jobs options
Script->>Host: validate tools, packages, OS, and architecture
Script->>Archive: download pinned source archive
Script->>Script: verify size and SHA-256 digest
Script->>Host: configure and build SDL2/ALSA profile
Script->>Output: install binary and GPL notice
Script-->>Developer: report output path and qualification status
Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
✨ Simplify code
Comment |
There was a problem hiding this comment.
Actionable comments posted: 7
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@scripts/pi/build-retro-frontend.sh`:
- Around line 74-76: Add file to the prerequisite tool list in the
build-retro-frontend.sh validation loop so it is checked before installation and
post-install reporting. Preserve the existing missing-tool error and exit
behavior for all tools.
- Line 102: Update the curl download command in the build script to set finite
connection and total-transfer limits using --connect-timeout and --max-time, and
add bounded retries for transient failures while preserving the existing failure
behavior and archive output.
- Around line 135-144: Update the output flow around the retroarch copy and
THIRD_PARTY_NOTICES.txt generation to write both files into a staging directory
first. Publish or move the staged files into out_dir only after the
notice-generation block completes successfully, ensuring out_dir is not left
with an exposed binary without its required notice.
- Around line 69-88: Update the prerequisite validation before the BUILD_DEPS
dpkg-query loop to require and verify the supported Debian package tools,
including dpkg-query and apt-get, before reporting package dependencies. Keep
the existing Debian package names and installation guidance only for hosts where
those commands are available, and fail with a clear prerequisite message
otherwise.
- Around line 52-59: Update the argument parsing around the jobs variable so
nproc is validated for availability before it is used as the default, emitting a
clear diagnostic if unavailable. Validate both the default and --jobs value as
positive integers during option processing, before the workspace is created or
any fetch occurs.
- Line 35: Update the build profile selection before the
dependency-check/install loop in scripts/pi/build-retro-frontend.sh: choose a
GLES-specific BUILD_DEPS set using libgles2-mesa-dev instead of libgl1-mesa-dev,
retain the existing OpenGL package set for the default profile, and add
--enable-opengles --disable-opengl to the GLES ./configure arguments.
- Around line 40-49: Update the CONFIGURE_FLAGS array in build-retro-frontend.sh
to include --disable-glslang, ensuring system glslang libraries cannot alter the
build feature set.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro
Run ID: d1611fd7-7431-4c54-b028-1b92d5a9403c
📒 Files selected for processing (1)
scripts/pi/build-retro-frontend.sh
📜 Review details
⏰ Context from checks skipped due to timeout. (6)
- GitHub Check: node / ubuntu-latest
- GitHub Check: node / windows-latest
- GitHub Check: native / aarch64 cross
- GitHub Check: native / windows-latest
- GitHub Check: native / ubuntu-latest
- GitHub Check: e2e / ubuntu-latest
🔇 Additional comments (1)
scripts/pi/build-retro-frontend.sh (1)
1-34: LGTM!Also applies to: 61-68, 90-116, 118-125, 150-155
| # Discovered empirically by building this exact release, not copied from a wiki. | ||
| # The build reached its link step and failed only on libx11-xcb-dev, so that | ||
| # package is required and not optional. | ||
| BUILD_DEPS="pkg-config libsdl2-dev libgl1-mesa-dev libasound2-dev libx11-xcb-dev zlib1g-dev" |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟠 Major | 🏗️ Heavy lift
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
version="1.22.2"
url="https://github.com/libretro/RetroArch/releases/download/v${version}/retroarch-sourceonly-${version}.tar.xz"
archive="$(mktemp)"
trap 'rm -f "$archive"' EXIT
curl -fsSL "$url" -o "$archive"
configure_member="$(tar -tJf "$archive" | awk '/\/configure$/ { print; exit }')"
test -n "$configure_member"
tar -xJOf "$archive" "$configure_member" |
rg -n -- '--(enable|disable).*(gles|opengl)|GLES|OPENGL'Repository: Randroids-Dojo/VCG-Console
Length of output: 343
🏁 Script executed:
#!/bin/bash
set -euo pipefail
printf '%s\n' '--- target script ---'
sed -n '1,125p' scripts/pi/build-retro-frontend.sh
printf '%s\n' '--- RetroArch 1.22.2 configure flags ---'
python3 - <<'PY'
import io
import lzma
import tarfile
import urllib.request
url = "https://github.com/libretro/RetroArch/releases/download/v1.22.2/retroarch-sourceonly-1.22.2.tar.xz"
data = urllib.request.urlopen(url, timeout=30).read()
with tarfile.open(fileobj=io.BytesIO(lzma.decompress(data)), mode="r:") as archive:
members = [m for m in archive.getmembers() if m.name.endswith("/configure")]
if not members:
raise SystemExit("configure not found")
text = archive.extractfile(members[0]).read().decode("utf-8", "replace")
for number, line in enumerate(text.splitlines(), 1):
if any(token in line.lower() for token in ("gles", "opengl")):
print(f"{number}:{line}")
PYRepository: Randroids-Dojo/VCG-Console
Length of output: 7137
🏁 Script executed:
#!/bin/bash
set -euo pipefail
python3 - <<'PY'
import io
import lzma
import tarfile
import urllib.request
url = "https://github.com/libretro/RetroArch/releases/download/v1.22.2/retroarch-sourceonly-1.22.2.tar.xz"
data = urllib.request.urlopen(url, timeout=30).read()
with tarfile.open(fileobj=io.BytesIO(lzma.decompress(data)), mode="r:") as archive:
configure = next(m for m in archive.getmembers() if m.name.endswith("/configure"))
text = archive.extractfile(configure).read().decode("utf-8", "replace")
lines = text.splitlines()
for number, line in enumerate(lines, 1):
if any(token in line.lower() for token in ("gles", "opengl")):
start = max(1, number - 3)
end = min(len(lines), number + 3)
print(f"--- lines {start}-{end} ---")
for i in range(start, end + 1):
print(f"{i}:{lines[i-1]}")
PYRepository: Randroids-Dojo/VCG-Console
Length of output: 2450
🏁 Script executed:
#!/bin/bash
set -euo pipefail
printf '%s\n' '--- target script ---'
sed -n '1,125p' scripts/pi/build-retro-frontend.sh
printf '%s\n' '--- configure flags ---'
python3 - <<'PY'
import io, lzma, tarfile, urllib.request
url = "https://github.com/libretro/RetroArch/releases/download/v1.22.2/retroarch-sourceonly-1.22.2.tar.xz"
data = urllib.request.urlopen(url, timeout=30).read()
with tarfile.open(fileobj=io.BytesIO(lzma.decompress(data)), mode="r:") as archive:
member = next(m for m in archive.getmembers() if m.name.endswith("/configure"))
lines = archive.extractfile(member).read().decode("utf-8", "replace").splitlines()
for n, line in enumerate(lines, 1):
if "gles" in line.lower() or "opengl" in line.lower():
print(f"{n}:{line}")
PYRepository: Randroids-Dojo/VCG-Console
Length of output: 7120
🌐 Web query:
RetroArch 1.22.2 configure --enable-gles --disable-opengl configure.ac
💡 Result:
To compile RetroArch 1.22.2 with OpenGL ES enabled and standard desktop OpenGL disabled, you can use the following./configure flags [1][2]:./configure --enable-opengles --disable-opengl In RetroArch's build system, these flags function as follows: --enable-opengles: Enables the use of OpenGL ES (GLESv2) instead of the desktop OpenGL API [3]. --disable-opengl: Explicitly disables the desktop OpenGL 2.0+ support [3]. Additional context for your build: Depending on your target platform (e.g., Raspberry Pi, ARM-based devices), you may also need to explicitly disable legacy components if the configuration script does not automatically exclude them [1][2]. For example, common additions for embedded or GLES-focused builds include [1][2]: --disable-opengl1: Disables legacy OpenGL 1.1 support [3]. --disable-videocore: Often used on older Raspberry Pi builds to disable platform-specific legacy drivers [1][2]. If you are targeting more modern GLES support (GLES 3.0+), you can also use flags such as --enable-opengles3, --enable-opengles3_1, or --enable-opengles3_2 [3]. It is recommended to run./configure --help in the source root to view the complete, version-specific list of available configuration options for the 1.22.2 release [4]. If you have the necessary development libraries (headers and libraries for GLES) installed on your system, the configure script should detect them automatically, but passing the explicit flags helps ensure that missing dependencies are caught as errors during the configuration phase [1][2].
Citations:
- 1: https://docs.libretro.com/guides/rpi/
- 2: https://github.com/libretro/docs/blob/master/docs/guides/rpi.md
- 3: Build RetroArch using OpenGL instead of OpenGLES void-linux/void-packages#32246
- 4: https://github.com/libretro/RetroArch/releases/tag/v1.22.2
Fix the Raspberry Pi GLES profile.
BUILD_DEPS unconditionally checks libgl1-mesa-dev, so installing libgles2-mesa-dev as its replacement still exits before ./configure. Select the profile before the dependency loop, use the matching package set, and add --enable-opengles --disable-opengl for the GLES profile.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@scripts/pi/build-retro-frontend.sh` at line 35, Update the build profile
selection before the dependency-check/install loop in
scripts/pi/build-retro-frontend.sh: choose a GLES-specific BUILD_DEPS set using
libgles2-mesa-dev instead of libgl1-mesa-dev, retain the existing OpenGL package
set for the default profile, and add --enable-opengles --disable-opengl to the
GLES ./configure arguments.
| CONFIGURE_FLAGS=( | ||
| --disable-qt | ||
| --disable-cg | ||
| --disable-discord | ||
| --disable-cheevos | ||
| --disable-vulkan | ||
| --disable-wayland | ||
| --enable-sdl2 | ||
| --enable-alsa | ||
| ) |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
version="1.22.2"
url="https://github.com/libretro/RetroArch/releases/download/v${version}/retroarch-sourceonly-${version}.tar.xz"
archive="$(mktemp)"
trap 'rm -f "$archive"' EXIT
curl -fsSL "$url" -o "$archive"
configure_member="$(tar -tJf "$archive" | awk '/\/configure$/ { print; exit }')"
test -n "$configure_member"
tar -xJOf "$archive" "$configure_member" |
rg -n -- '--(enable|disable)-glslang|GLSLANG'Repository: Randroids-Dojo/VCG-Console
Length of output: 343
🏁 Script executed:
#!/bin/bash
set -euo pipefail
printf '%s\n' '--- target script ---'
sed -n '1,90p' scripts/pi/build-retro-frontend.sh
printf '%s\n' '--- local glslang references ---'
rg -n -i 'glslang|configure_flags|disable-.*glsl' . --glob '!build/**' --glob '!dist/**' || true
printf '%s\n' '--- RetroArch 1.22.2 configure options ---'
python3 - <<'PY'
import io
import lzma
import tarfile
import urllib.request
url = "https://github.com/libretro/RetroArch/releases/download/v1.22.2/retroarch-sourceonly-1.22.2.tar.xz"
with urllib.request.urlopen(url) as response:
archive = response.read()
with tarfile.open(fileobj=io.BytesIO(lzma.decompress(archive)), mode="r:") as tar:
members = [m for m in tar.getmembers() if m.name.endswith("/configure") or m.name == "configure"]
if not members:
raise SystemExit("configure not found")
data = tar.extractfile(members[0]).read().decode("utf-8", errors="replace")
for number, line in enumerate(data.splitlines(), 1):
if "glslang" in line.lower() or "GLSLANG" in line:
print(f"{number}:{line}")
PYRepository: Randroids-Dojo/VCG-Console
Length of output: 6264
🏁 Script executed:
#!/bin/bash
set -euo pipefail
python3 - <<'PY'
import io
import lzma
import subprocess
import tarfile
url = "https://github.com/libretro/RetroArch/releases/download/v1.22.2/retroarch-sourceonly-1.22.2.tar.xz"
archive = subprocess.check_output(["curl", "-kfsSL", url])
with tarfile.open(fileobj=io.BytesIO(lzma.decompress(archive)), mode="r:") as tar:
members = [m for m in tar.getmembers() if m.name.endswith("/configure") or m.name == "configure"]
if not members:
raise SystemExit("configure not found")
data = tar.extractfile(members[0]).read().decode("utf-8", errors="replace")
for number, line in enumerate(data.splitlines(), 1):
if "glslang" in line.lower() or "GLSLANG" in line:
print(f"{number}:{line}")
PYRepository: Randroids-Dojo/VCG-Console
Length of output: 164
🏁 Script executed:
#!/bin/bash
set -euo pipefail
python3 - <<'PY'
import io
import lzma
import subprocess
import tarfile
url = "https://github.com/libretro/RetroArch/releases/download/v1.22.2/retroarch-sourceonly-1.22.2.tar.xz"
archive = subprocess.check_output(["curl", "-kfsSL", url])
terms = ("glslang", "shaderc", "slang", "vulkan")
with tarfile.open(fileobj=io.BytesIO(lzma.decompress(archive)), mode="r:") as tar:
matches = []
for member in tar.getmembers():
if not member.isfile():
continue
try:
text = tar.extractfile(member).read().decode("utf-8")
except (UnicodeDecodeError, AttributeError):
continue
for number, line in enumerate(text.splitlines(), 1):
if any(term in line.lower() for term in terms):
matches.append(f"{member.name}:{number}:{line}")
print("\n".join(matches[:300]))
print(f"TOTAL_MATCHES={len(matches)}")
PYRepository: Randroids-Dojo/VCG-Console
Length of output: 38010
🏁 Script executed:
#!/bin/bash
set -euo pipefail
python3 - <<'PY'
import io
import lzma
import subprocess
import tarfile
url = "https://github.com/libretro/RetroArch/releases/download/v1.22.2/retroarch-sourceonly-1.22.2.tar.xz"
archive = subprocess.check_output(["curl", "-kfsSL", url])
with tarfile.open(fileobj=io.BytesIO(lzma.decompress(archive)), mode="r:") as tar:
files = {m.name: tar.extractfile(m).read().decode("utf-8", errors="replace")
for m in tar.getmembers() if m.isfile() and (
m.name.endswith("/configure") or
m.name.endswith("Makefile.common") or
m.name.endswith("Makefile.in") or
"glslang" in m.name.lower()
)}
for name, text in files.items():
lines = text.splitlines()
selected = [
f"{name}:{n}:{line}"
for n, line in enumerate(lines, 1)
if ("glslang" in line.lower() or
("vulkan" in line.lower() and
("enable" in line.lower() or "disable" in line.lower() or
"HAVE_VULKAN" in line or "VULKAN_LIBS" in line)))
]
if selected:
print("\n".join(selected[:160]))
PYRepository: Randroids-Dojo/VCG-Console
Length of output: 50383
🏁 Script executed:
#!/bin/bash
set -euo pipefail
python3 - <<'PY'
import io
import lzma
import subprocess
import tarfile
url = "https://github.com/libretro/RetroArch/releases/download/v1.22.2/retroarch-sourceonly-1.22.2.tar.xz"
archive = subprocess.check_output(["curl", "-kfsSL", url])
with tarfile.open(fileobj=io.BytesIO(lzma.decompress(archive)), mode="r:") as tar:
wanted = {
"configure",
"retroarch-sourceonly-1.22.2/Makefile.common",
"retroarch-sourceonly-1.22.2/Makefile.in",
}
for member in tar.getmembers():
if member.name not in wanted or not member.isfile():
continue
text = tar.extractfile(member).read().decode("utf-8", errors="replace")
lines = text.splitlines()
print(f"--- {member.name} ---")
for n, line in enumerate(lines, 1):
low = line.lower()
if "glslang" in low or "have_vulkan" in low or "built-in glslang" in low:
start = max(1, n - 3)
end = min(len(lines), n + 3)
for i in range(start, end + 1):
print(f"{i}:{lines[i-1]}")
print()
PYRepository: Randroids-Dojo/VCG-Console
Length of output: 14314
🏁 Script executed:
#!/bin/bash
set -euo pipefail
python3 - <<'PY'
import io
import lzma
import subprocess
import tarfile
url = "https://github.com/libretro/RetroArch/releases/download/v1.22.2/retroarch-sourceonly-1.22.2.tar.xz"
archive = subprocess.check_output(["curl", "-kfsSL", url])
with tarfile.open(fileobj=io.BytesIO(lzma.decompress(archive)), mode="r:") as tar:
member = next(m for m in tar.getmembers()
if m.isfile() and (m.name == "configure" or m.name.endswith("/configure")))
lines = tar.extractfile(member).read().decode("utf-8", errors="replace").splitlines()
terms = ("glslang", "slang", "builtin", "have_slang", "have_glslang")
hits = [n for n, line in enumerate(lines, 1)
if any(term in line.lower() for term in terms)]
print(f"configure_lines={len(lines)} matching_lines={len(hits)}")
for n in hits:
start = max(1, n - 2)
end = min(len(lines), n + 2)
print(f"--- context {n} ---")
for i in range(start, end + 1):
print(f"{i}:{lines[i-1]}")
PYRepository: Randroids-Dojo/VCG-Console
Length of output: 199
🏁 Script executed:
#!/bin/bash
set -euo pipefail
python3 - <<'PY'
import io
import lzma
import subprocess
import tarfile
url = "https://github.com/libretro/RetroArch/releases/download/v1.22.2/retroarch-sourceonly-1.22.2.tar.xz"
archive = subprocess.check_output(["curl", "-kfsSL", url])
with tarfile.open(fileobj=io.BytesIO(lzma.decompress(archive)), mode="r:") as tar:
members = [m for m in tar.getmembers()
if m.name == "configure" or m.name.endswith("/configure")]
print(f"configure_members={len(members)}")
for member in members:
print(f"--- {member.name} type={member.type!r} size={member.size} link={member.linkname!r} ---")
extracted = tar.extractfile(member)
if extracted is not None:
print(extracted.read().decode("utf-8", errors="replace")[:1000])
PYRepository: Randroids-Dojo/VCG-Console
Length of output: 707
🏁 Script executed:
#!/bin/bash
set -euo pipefail
python3 - <<'PY'
import io
import lzma
import subprocess
import tarfile
url = "https://github.com/libretro/RetroArch/releases/download/v1.22.2/retroarch-sourceonly-1.22.2.tar.xz"
archive = subprocess.check_output(["curl", "-kfsSL", url])
with tarfile.open(fileobj=io.BytesIO(lzma.decompress(archive)), mode="r:") as tar:
for member in tar.getmembers():
if not member.isfile() or "/qb/" not in f"/{member.name}":
continue
try:
text = tar.extractfile(member).read().decode("utf-8")
except UnicodeDecodeError:
continue
lines = text.splitlines()
for n, line in enumerate(lines, 1):
low = line.lower()
if any(term in low for term in (
"glslang", "have_slang", "builtingslang", "disable-slang",
"enable-slang", "slang shader", "slang support"
)):
print(f"{member.name}:{n}:{line}")
PYRepository: Randroids-Dojo/VCG-Console
Length of output: 3920
🏁 Script executed:
#!/bin/bash
set -euo pipefail
python3 - <<'PY'
import io
import lzma
import subprocess
import tarfile
url = "https://github.com/libretro/RetroArch/releases/download/v1.22.2/retroarch-sourceonly-1.22.2.tar.xz"
archive = subprocess.check_output(["curl", "-kfsSL", url])
with tarfile.open(fileobj=io.BytesIO(lzma.decompress(archive)), mode="r:") as tar:
wanted = (
"check_enabled",
"HAVE_GLSLANG",
"disable-",
"enable-",
"option",
)
for member in tar.getmembers():
if not member.isfile() or "/qb/" not in f"/{member.name}":
continue
try:
lines = tar.extractfile(member).read().decode("utf-8", errors="replace").splitlines()
except UnicodeDecodeError:
continue
hits = [n for n, line in enumerate(lines, 1)
if any(term.lower() in line.lower() for term in wanted)]
if not hits:
continue
print(f"--- {member.name} ---")
shown = set()
for n in hits:
start = max(1, n - 2)
end = min(len(lines), n + 2)
for i in range(start, end + 1):
if i not in shown:
print(f"{i}:{lines[i-1]}")
shown.add(i)
PYRepository: Randroids-Dojo/VCG-Console
Length of output: 10887
Disable glslang explicitly.
Add --disable-glslang to prevent system glslang libraries from changing the built feature set.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@scripts/pi/build-retro-frontend.sh` around lines 40 - 49, Update the
CONFIGURE_FLAGS array in build-retro-frontend.sh to include --disable-glslang,
ensuring system glslang libraries cannot alter the build feature set.
| jobs="$(nproc)" | ||
| while [ "$#" -gt 0 ]; do | ||
| case "$1" in | ||
| --out) out_dir="${2:?--out needs a directory}"; shift 2 ;; | ||
| --jobs) jobs="${2:?--jobs needs a count}"; shift 2 ;; | ||
| *) echo "unknown option: $1" >&2; exit 2 ;; | ||
| esac | ||
| done |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
Validate the job count before the fetch.
nproc runs before the prerequisite check. If it is unavailable, set -e exits without a clear diagnostic. --jobs also accepts invalid values and only fails after download and configuration.
Check nproc before using the default. Reject values that do not match a positive integer before creating the workspace.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@scripts/pi/build-retro-frontend.sh` around lines 52 - 59, Update the argument
parsing around the jobs variable so nproc is validated for availability before
it is used as the default, emitting a clear diagnostic if unavailable. Validate
both the default and --jobs value as positive integers during option processing,
before the workspace is created or any fetch occurs.
| [ "${uname_s}" = "Linux" ] || { echo "This recipe targets Linux." >&2; exit 1; } | ||
| if [ "${uname_m}" != "aarch64" ]; then | ||
| echo "warning: ${uname_m} build; this is not a Raspberry Pi artifact." >&2 | ||
| fi | ||
|
|
||
| for tool in curl tar make sha256sum cc; do | ||
| command -v "$tool" >/dev/null 2>&1 || { echo "Missing prerequisite: $tool" >&2; exit 1; } | ||
| done | ||
|
|
||
| missing="" | ||
| for dep in ${BUILD_DEPS}; do | ||
| dpkg-query -W -f='${Status}' "${dep}" 2>/dev/null | grep -q "install ok installed" || missing="${missing} ${dep}" | ||
| done | ||
| if [ -n "${missing}" ]; then | ||
| echo "Missing build dependencies:${missing}" >&2 | ||
| echo "Install them with: sudo apt-get install -y${missing}" >&2 | ||
| echo "On a Raspberry Pi the GPU stack is GLES rather than desktop GL, so" >&2 | ||
| echo "libgles2-mesa-dev may be required in place of libgl1-mesa-dev." >&2 | ||
| exit 1 | ||
| fi |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
Restrict the package check to supported package managers.
The Linux check accepts distributions without dpkg-query or apt-get. On those hosts, the script reports Debian package names and an apt-get command that cannot run.
Require Debian package tools before this loop, or detect the host package manager and provide matching package names.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@scripts/pi/build-retro-frontend.sh` around lines 69 - 88, Update the
prerequisite validation before the BUILD_DEPS dpkg-query loop to require and
verify the supported Debian package tools, including dpkg-query and apt-get,
before reporting package dependencies. Keep the existing Debian package names
and installation guidance only for hosts where those commands are available, and
fail with a clear prerequisite message otherwise.
| for tool in curl tar make sha256sum cc; do | ||
| command -v "$tool" >/dev/null 2>&1 || { echo "Missing prerequisite: $tool" >&2; exit 1; } | ||
| done |
There was a problem hiding this comment.
🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win
Check file before post-install reporting.
Line 147 requires file, but this prerequisite loop does not check it. If file is absent, the script installs the artifact and then exits as failed.
Add file to the checked tools.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@scripts/pi/build-retro-frontend.sh` around lines 74 - 76, Add file to the
prerequisite tool list in the build-retro-frontend.sh validation loop so it is
checked before installation and post-install reporting. Preserve the existing
missing-tool error and exit behavior for all tools.
| echo "== RetroArch ${RA_VERSION} ==" | ||
| archive="${scratch}/retroarch.tar.xz" | ||
| echo " fetching the official source-only release" | ||
| curl -fsSL "${RA_URL}" -o "${archive}" |
There was a problem hiding this comment.
🩺 Stability & Availability | 🟠 Major | ⚡ Quick win
Set finite download time limits.
curl -fsSL has no connection or total-transfer timeout. A stalled remote endpoint can block the build indefinitely.
Set --connect-timeout and --max-time. Add bounded retries for transient failures.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@scripts/pi/build-retro-frontend.sh` at line 102, Update the curl download
command in the build script to set finite connection and total-transfer limits
using --connect-timeout and --max-time, and add bounded retries for transient
failures while preserving the existing failure behavior and archive output.
| mkdir -p "${out_dir}" | ||
| cp "${source_root}/retroarch" "${out_dir}/retroarch" | ||
| { | ||
| echo "===============================================================================" | ||
| echo "RetroArch ${RA_VERSION} -- https://github.com/libretro/RetroArch" | ||
| echo "source archive SHA-256: ${RA_SHA256}" | ||
| echo "===============================================================================" | ||
| echo | ||
| cat "${source_root}/COPYING" | ||
| } > "${out_dir}/THIRD_PARTY_NOTICES.txt" |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟠 Major | 🏗️ Heavy lift
Publish the binary and notice only after both writes succeed.
Line 136 exposes retroarch before the GPL notice is written. If the notice write fails or the process stops, out_dir contains a binary without its required notice.
Write both files to a staging location. Publish the binary only after the notice is complete.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@scripts/pi/build-retro-frontend.sh` around lines 135 - 144, Update the output
flow around the retroarch copy and THIRD_PARTY_NOTICES.txt generation to write
both files into a staging directory first. Publish or move the staged files into
out_dir only after the notice-generation block completes successfully, ensuring
out_dir is not left with an exposed binary without its required notice.
Completes the buildable half of the retro path. The previous change builds the cores; this builds the frontend that loads them, under the same D-185 boundary — nothing vendored, pinned archive fetched and verified, digest mismatch refuses to build.
1.22.2 is not a new choice
It is the frontend version
catalog/retro-2048.vcg-game.jsonalready declares. And RetroArch publishes no Linux or aarch64 binary asset for this release — the only artifact isretroarch-sourceonly-1.22.2.tar.xz— so building from pinned source is the sole option for the Pi and also the most D-185-consistent one.Three independent downloads were byte-identical at
2a8b1713f7f4d2b53bad3e2297e48d78f5666098cf00d583d3e08f3c213f8aa6, 13564476 bytes.The dependency list was found by building, not by reading a wiki
A first attempt configured cleanly, compiled 450 objects, reached its link step, and failed only on
libx11-xcb-dev. So that package is required, not optional — something documentation would not have told me reliably.The recipe now checks every dependency up front with
dpkg-queryand prints the exactaptcommand, rather than failing partway through a build.The configure profile is deliberately small: no Qt (a desktop UI this appliance never shows), and no CG, Vulkan, glslang, Discord, or cheevos stacks, which pull large dependency sets for features the Pi profile does not use.
Verified
Version: 1.22.2Limits
Verified on x86_64 only, and the script says so at runtime. A Raspberry Pi uses GLES rather than desktop GL, so
libgles2-mesa-devmay be needed in place oflibgl1-mesa-dev— the dependency error message states this.Nothing here is qualified. A built frontend is not evidence of working video, audio, input, compositor behaviour, or frame pacing, and nothing has been built on or run on a Raspberry Pi. Signed package assembly for aarch64 and the per-system game manifests remain unimplemented.
🤖 Generated with Claude Code