mirror of
https://github.com/bryanthaboi/gen1recomp
synced 2026-10-25 06:36:36 -04:00
Ship pinned modern LuaJIT in the aarch64 Linux builds
The linux-arm64 AppImage, the SBC PortMaster zip and the RG34XXSP zip shipped LuaJIT 2.1.0-beta3 (2017): Debian bullseye's libluajit-5.1-dev for the AppImage, PortMaster's love_11.5 runtime library for the zips. With the JIT enabled, beta3 segfaulted 3/3 runs on a TrimUI Brick; LuaJIT v2.1 commit c6ffc141 ran a 26-minute JIT-on soak without a crash. - Build LuaJIT c6ffc141 from a sha256-pinned tarball in a digest-pinned debian:bullseye (glibc 2.31) with the same apt sources as the AppImage builder; compile with PREFIX=/usr so no build path is baked into package.path, stage-install, and verify before use. - AppImage: compile it inside the builder instead of libluajit-5.1-dev, bundle it with jit/*.lua and its license; cache keys include the LuaJIT commit, recipe hash and Dockerfile hash. - PortMaster zips: replace libs.aarch64/libluajit-5.1.so.2 with the pinned build, pin the PortMaster runtime to commit 715f50fd with sha256 checks (rg34xxsp followed main), ship LuaJIT-COPYRIGHT, verify the finished zip. - verify_luajit.sh gates every package: version string, not beta, aarch64 ELF, /usr module path, max GLIBC <= 2.31; offline selftests cover it and the PortMaster helpers. - CI/release build LuaJIT once on an arm64 runner and pass it to the zip jobs via GEN1RECOMP_LUAJIT_LIB. The JIT stays off by default (LÖVE's jitsetup disables it on arm/arm64). POKEPORT_JIT=1 needs stability testing on H700, RK3566 and A133P devices before it can be enabled by default.
This commit is contained in:
@@ -283,7 +283,7 @@ jobs:
|
||||
echo "changed=true" >> "$GITHUB_OUTPUT"
|
||||
exit 0
|
||||
fi
|
||||
if git diff --name-only "$BASE_SHA" "$HEAD_SHA" | grep -Eq '^(scripts/build_linux_arm64\.sh$|scripts/linux-arm64/|scripts/pack_love\.sh$|docs/linux-arm64-build\.md$|\.github/workflows/(ci|release)\.yml$)'; then
|
||||
if git diff --name-only "$BASE_SHA" "$HEAD_SHA" | grep -Eq '^(scripts/build_linux_arm64\.sh$|scripts/linux-arm64/|scripts/luajit/|scripts/lib/|scripts/pack_love\.sh$|docs/linux-arm64-build\.md$|\.github/workflows/(ci|release)\.yml$)'; then
|
||||
echo "changed=true" >> "$GITHUB_OUTPUT"
|
||||
else
|
||||
echo "changed=false" >> "$GITHUB_OUTPUT"
|
||||
@@ -302,6 +302,8 @@ jobs:
|
||||
# so the slow native job below only ever starts on a sane tree.
|
||||
- name: Linux arm64 offline selftest
|
||||
run: bash scripts/linux-arm64/selftest_build_linux_arm64.sh
|
||||
- name: PortMaster LuaJIT helpers offline selftest
|
||||
run: bash scripts/luajit/selftest_portmaster_runtime.sh
|
||||
|
||||
linux-arm64-build:
|
||||
name: Linux arm64 AppImage build
|
||||
@@ -486,12 +488,53 @@ jobs:
|
||||
if-no-files-found: error
|
||||
retention-days: 7
|
||||
|
||||
luajit-linux-arm64:
|
||||
name: build pinned LuaJIT (linux arm64)
|
||||
# Native arm64 runner: emulated aarch64 builds have miscompiled LuaJIT.
|
||||
# Built once here and shared by both PortMaster zip jobs below.
|
||||
runs-on: ubuntu-24.04-arm
|
||||
steps:
|
||||
- uses: actions/checkout@v7
|
||||
# The zip scripts depend on these helpers; fail fast before the build.
|
||||
- name: PortMaster LuaJIT helpers offline selftest
|
||||
run: bash scripts/luajit/selftest_portmaster_runtime.sh
|
||||
- name: Cache pinned LuaJIT
|
||||
uses: actions/cache@v6
|
||||
with:
|
||||
path: .bazinga/cache/luajit
|
||||
key: luajit-linux-arm64-${{ hashFiles('scripts/luajit/**', 'scripts/lib/fetch.sh') }}
|
||||
- name: Build pinned LuaJIT
|
||||
run: |
|
||||
set -euo pipefail
|
||||
lib="$(scripts/luajit/build_luajit.sh)"
|
||||
mkdir -p dist/luajit
|
||||
cp "$lib" "$(dirname "$lib")/COPYRIGHT" dist/luajit/
|
||||
- name: Verify LuaJIT
|
||||
run: scripts/luajit/verify_luajit.sh dist/luajit/libluajit-5.1.so.2
|
||||
- name: Upload LuaJIT
|
||||
uses: actions/upload-artifact@v7
|
||||
with:
|
||||
name: luajit-linux-arm64
|
||||
path: |
|
||||
dist/luajit/libluajit-5.1.so.2
|
||||
dist/luajit/COPYRIGHT
|
||||
if-no-files-found: error
|
||||
retention-days: 7
|
||||
|
||||
rg34xxsp-build:
|
||||
name: RG34XXSP PortMaster build
|
||||
needs: luajit-linux-arm64
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v7
|
||||
- name: Download pinned LuaJIT
|
||||
uses: actions/download-artifact@v8
|
||||
with:
|
||||
name: luajit-linux-arm64
|
||||
path: dist/native/luajit-linux-arm64
|
||||
- name: build RG34XXSP package
|
||||
env:
|
||||
GEN1RECOMP_LUAJIT_LIB: ${{ github.workspace }}/dist/native/luajit-linux-arm64/libluajit-5.1.so.2
|
||||
run: ./build-rg34xxsp.sh --version 0.0.0
|
||||
- name: upload RG34XXSP artifact
|
||||
uses: actions/upload-artifact@v7
|
||||
@@ -503,12 +546,19 @@ jobs:
|
||||
|
||||
linux-arm-sbc-build:
|
||||
name: Linux ARM SBC PortMaster build
|
||||
needs: luajit-linux-arm64
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v7
|
||||
- name: Download pinned LuaJIT
|
||||
uses: actions/download-artifact@v8
|
||||
with:
|
||||
name: luajit-linux-arm64
|
||||
path: dist/native/luajit-linux-arm64
|
||||
- name: build Linux ARM SBC package
|
||||
env:
|
||||
GEN1RECOMP_SOURCE_DIR: ${{ github.workspace }}
|
||||
GEN1RECOMP_LUAJIT_LIB: ${{ github.workspace }}/dist/native/luajit-linux-arm64/libluajit-5.1.so.2
|
||||
run: ./build-linux-arm-sbc.sh --version 0.0.0
|
||||
- name: upload Linux ARM SBC artifact
|
||||
uses: actions/upload-artifact@v7
|
||||
|
||||
@@ -165,7 +165,7 @@ jobs:
|
||||
uses: actions/cache@v6
|
||||
with:
|
||||
path: .bazinga/cache/linux-arm64
|
||||
key: linux-arm64-deps-${{ hashFiles('scripts/linux-arm64/**', 'scripts/build_linux_arm64.sh') }}
|
||||
key: linux-arm64-deps-${{ hashFiles('scripts/linux-arm64/**', 'scripts/luajit/**', 'scripts/build_linux_arm64.sh') }}
|
||||
|
||||
- name: Build Linux arm64 AppImage
|
||||
env:
|
||||
@@ -767,9 +767,39 @@ jobs:
|
||||
if-no-files-found: error
|
||||
retention-days: 7
|
||||
|
||||
luajit-linux-arm64:
|
||||
name: build pinned LuaJIT (linux arm64)
|
||||
needs: version
|
||||
# Native arm64 runner: emulated aarch64 builds have miscompiled LuaJIT.
|
||||
runs-on: ubuntu-24.04-arm
|
||||
steps:
|
||||
- uses: actions/checkout@v7
|
||||
- name: Cache pinned LuaJIT
|
||||
uses: actions/cache@v6
|
||||
with:
|
||||
path: .bazinga/cache/luajit
|
||||
key: luajit-linux-arm64-${{ hashFiles('scripts/luajit/**', 'scripts/lib/fetch.sh') }}
|
||||
- name: Build pinned LuaJIT
|
||||
run: |
|
||||
set -euo pipefail
|
||||
lib="$(scripts/luajit/build_luajit.sh)"
|
||||
mkdir -p dist/luajit
|
||||
cp "$lib" "$(dirname "$lib")/COPYRIGHT" dist/luajit/
|
||||
- name: Verify LuaJIT
|
||||
run: scripts/luajit/verify_luajit.sh dist/luajit/libluajit-5.1.so.2
|
||||
- name: Upload LuaJIT
|
||||
uses: actions/upload-artifact@v7
|
||||
with:
|
||||
name: luajit-linux-arm64
|
||||
path: |
|
||||
dist/luajit/libluajit-5.1.so.2
|
||||
dist/luajit/COPYRIGHT
|
||||
if-no-files-found: error
|
||||
retention-days: 7
|
||||
|
||||
rg34xxsp:
|
||||
name: build Anbernic RG34XXSP port
|
||||
needs: [version, shaderfx-bridge]
|
||||
needs: [version, shaderfx-bridge, luajit-linux-arm64]
|
||||
runs-on: ${{ fromJSON(github.repository == 'bryanthaboi/gen1recomp' && '["self-hosted", "macOS"]' || '"macos-latest"') }}
|
||||
steps:
|
||||
# The self-hosted runner lives under the machine owner's home
|
||||
@@ -787,9 +817,16 @@ jobs:
|
||||
name: shaderfx-bridge-linux-arm64
|
||||
path: dist/native/linux-arm64
|
||||
|
||||
- name: Download the pinned LuaJIT
|
||||
uses: actions/download-artifact@v8
|
||||
with:
|
||||
name: luajit-linux-arm64
|
||||
path: dist/native/luajit-linux-arm64
|
||||
|
||||
- name: Build Anbernic RG34XXSP port
|
||||
env:
|
||||
SHADERFX_BRIDGE_REQUIRED: "1"
|
||||
GEN1RECOMP_LUAJIT_LIB: ${{ github.workspace }}/dist/native/luajit-linux-arm64/libluajit-5.1.so.2
|
||||
run: |
|
||||
set -euo pipefail
|
||||
# Self-contained aarch64 PortMaster-style pack; pulls the LÖVE 11.5
|
||||
@@ -807,7 +844,7 @@ jobs:
|
||||
|
||||
linux-arm-sbc:
|
||||
name: build Linux ARM SBC PortMaster port
|
||||
needs: [version, shaderfx-bridge]
|
||||
needs: [version, shaderfx-bridge, luajit-linux-arm64]
|
||||
runs-on: ${{ fromJSON(github.repository == 'bryanthaboi/gen1recomp' && '["self-hosted", "macOS"]' || '"macos-latest"') }}
|
||||
steps:
|
||||
# The self-hosted runner lives under the machine owner's home
|
||||
@@ -825,6 +862,12 @@ jobs:
|
||||
name: shaderfx-bridge-linux-arm64
|
||||
path: dist/native/linux-arm64
|
||||
|
||||
- name: Download the pinned LuaJIT
|
||||
uses: actions/download-artifact@v8
|
||||
with:
|
||||
name: luajit-linux-arm64
|
||||
path: dist/native/luajit-linux-arm64
|
||||
|
||||
- name: Build Linux ARM SBC PortMaster port
|
||||
env:
|
||||
# The release workflow must package the commit being released. The
|
||||
@@ -833,6 +876,7 @@ jobs:
|
||||
GEN1RECOMP_SOURCE_DIR: ${{ github.workspace }}
|
||||
GEN1RECOMP_RELEASE_TAG: v${{ needs.version.outputs.version }}
|
||||
SHADERFX_BRIDGE_REQUIRED: "1"
|
||||
GEN1RECOMP_LUAJIT_LIB: ${{ github.workspace }}/dist/native/luajit-linux-arm64/libluajit-5.1.so.2
|
||||
run: |
|
||||
set -euo pipefail
|
||||
# Same aarch64 PortMaster-style pack for Linux ARM SBC PortMaster. The build
|
||||
|
||||
+28
-13
@@ -11,6 +11,11 @@
|
||||
# GEN1RECOMP_SOURCE_DIR="$PWD" ./build-linux-arm-sbc.sh --version X.Y.Z
|
||||
# ./build-linux-arm-sbc.sh --source /path/to/gen1recomp --version X.Y.Z
|
||||
#
|
||||
# LuaJIT: the zip ships a pinned LuaJIT, compiled during the build, so building
|
||||
# needs an aarch64 host with docker or podman. Alternatively set
|
||||
# GEN1RECOMP_LUAJIT_LIB=/path/libluajit-5.1.so.2 with its COPYRIGHT beside it
|
||||
# (or GEN1RECOMP_LUAJIT_COPYRIGHT=/path/to/COPYRIGHT).
|
||||
#
|
||||
# Output:
|
||||
# dist/linux-arm-sbc/gen1recomp-sbc-portmaster.zip
|
||||
#
|
||||
@@ -45,8 +50,6 @@ SOURCE_DIR_OVERRIDE="${GEN1RECOMP_SOURCE_DIR:-}"
|
||||
SOURCE_TAG_OVERRIDE="${GEN1RECOMP_RELEASE_TAG:-}"
|
||||
VERSION="${GEN1RECOMP_VERSION:-}"
|
||||
|
||||
# Official PortMaster LÖVE 11.5 aarch64 runtime (small love stub + liblove).
|
||||
PM_RUNTIME_BASE="https://raw.githubusercontent.com/PortsMaster/PortMaster-GUI/main/PortMaster/runtimes/love_${LOVE_VERSION}"
|
||||
RELEASES_LATEST_URL="https://github.com/bryanthaboi/gen1recomp/releases/latest"
|
||||
RELEASE_TARBALL_BASE="https://github.com/bryanthaboi/gen1recomp/archive/refs/tags"
|
||||
|
||||
@@ -60,7 +63,7 @@ while [ $# -gt 0 ]; do
|
||||
--source) [ $# -ge 2 ] || fail "--source needs a directory"; SOURCE_DIR_OVERRIDE="$2"; shift ;;
|
||||
--release-tag) [ $# -ge 2 ] || fail "--release-tag needs a tag"; SOURCE_TAG_OVERRIDE="$2"; shift ;;
|
||||
-h|--help)
|
||||
sed -n '2,24p' "$0"
|
||||
sed -n '2,29p' "$0"
|
||||
exit 0
|
||||
;;
|
||||
*) fail "unknown argument: $1" ;;
|
||||
@@ -86,6 +89,10 @@ download() {
|
||||
mv "$dest.tmp" "$dest"
|
||||
}
|
||||
|
||||
# PortMaster pins + LuaJIT pin (LUAJIT_COMMIT, ...) + download/verify helpers.
|
||||
# shellcheck source=scripts/luajit/portmaster_runtime.sh
|
||||
. "$ROOT/scripts/luajit/portmaster_runtime.sh"
|
||||
|
||||
# --------------------------------------------------------------- source + game tree
|
||||
# Release builds use the latest published source archive. A local checkout is
|
||||
# an explicit override for development and for CI's just-built release source.
|
||||
@@ -171,15 +178,12 @@ fi
|
||||
say "fetching LÖVE $LOVE_VERSION aarch64 runtime"
|
||||
LOVE_BIN="$CACHE/love.aarch64"
|
||||
LOVE_LIB="$CACHE/liblove-11.5.so"
|
||||
LUAJIT_LIB="$CACHE/libluajit-5.1.so.2"
|
||||
MODPLUG_LIB="$CACHE/libmodplug.so.1"
|
||||
OGG_LIB="$CACHE/libogg.so.0"
|
||||
|
||||
download "$PM_RUNTIME_BASE/love.aarch64" "$LOVE_BIN"
|
||||
download "$PM_RUNTIME_BASE/libs.aarch64/liblove-11.5.so" "$LOVE_LIB"
|
||||
download "$PM_RUNTIME_BASE/libs.aarch64/libluajit-5.1.so.2" "$LUAJIT_LIB"
|
||||
download "$PM_RUNTIME_BASE/libs.aarch64/libmodplug.so.1" "$MODPLUG_LIB"
|
||||
download "$PM_RUNTIME_BASE/libs.aarch64/libogg.so.0" "$OGG_LIB"
|
||||
pm_fetch_runtime "$CACHE"
|
||||
|
||||
pm_select_luajit
|
||||
|
||||
# Sanity: love stub must be an aarch64 ELF.
|
||||
file "$LOVE_BIN" | grep -qi 'aarch64\|ARM aarch64' \
|
||||
@@ -197,8 +201,9 @@ mkdir -p "$PORT_ROOT/$PORT_DIR_NAME/bin" \
|
||||
cp -R "$GAME_SRC" "$PORT_ROOT/$PORT_DIR_NAME/lovegame"
|
||||
cp "$LOVE_BIN" "$PORT_ROOT/$PORT_DIR_NAME/bin/love.aarch64"
|
||||
chmod +x "$PORT_ROOT/$PORT_DIR_NAME/bin/love.aarch64"
|
||||
cp "$LOVE_LIB" "$LUAJIT_LIB" "$MODPLUG_LIB" "$OGG_LIB" \
|
||||
cp "$LOVE_LIB" "$MODPLUG_LIB" "$OGG_LIB" \
|
||||
"$PORT_ROOT/$PORT_DIR_NAME/libs.aarch64/"
|
||||
pm_stage_luajit "$PORT_ROOT/$PORT_DIR_NAME/libs.aarch64" "$PORT_ROOT/$PORT_DIR_NAME/licenses"
|
||||
|
||||
BRIDGE_LIB="liblibrashader_bridge.so"
|
||||
BRIDGE_SRC="${SHADERFX_BRIDGE_LINUX_ARM64:-}"
|
||||
@@ -215,10 +220,14 @@ else
|
||||
fi
|
||||
|
||||
# Drop a short license pointer for the bundled LÖVE bits.
|
||||
cat > "$PORT_ROOT/$PORT_DIR_NAME/licenses/LICENSE.love2d.txt" <<'EOF'
|
||||
cat > "$PORT_ROOT/$PORT_DIR_NAME/licenses/LICENSE.love2d.txt" <<EOF
|
||||
This port bundles the LÖVE 11.5 aarch64 runtime from PortMaster
|
||||
(https://github.com/PortsMaster/PortMaster-GUI). LÖVE is zlib-licensed;
|
||||
see https://love2d.org/ for full terms.
|
||||
(https://github.com/PortsMaster/PortMaster-GUI, commit $PM_RUNTIME_COMMIT),
|
||||
except for LuaJIT. LÖVE is zlib-licensed; see https://love2d.org/ for full terms.
|
||||
|
||||
libs.aarch64/libluajit-5.1.so.2 is LuaJIT, built from source at LuaJIT commit
|
||||
$LUAJIT_COMMIT (https://github.com/LuaJIT/LuaJIT, MIT license; see
|
||||
LuaJIT-COPYRIGHT). It replaces PortMaster's LuaJIT 2.1.0-beta3.
|
||||
EOF
|
||||
|
||||
# --------------------------------------------------------------- launcher
|
||||
@@ -500,6 +509,10 @@ Put the `.gb` in `lovegame/`, then press **Choose ROM**. After import, the ROM-d
|
||||
|
||||
LÖVE runtime binaries from [PortMaster](https://portmaster.games/). PortMaster device support and runtime integration are maintained by the PortMaster team.
|
||||
EOF
|
||||
cat >> "$PORT_ROOT/README.md" <<EOF
|
||||
|
||||
LuaJIT (MIT license) is built from source at LuaJIT commit \`$LUAJIT_COMMIT\` instead of using PortMaster's older LuaJIT 2.1.0-beta3. The JIT stays off by default on this build.
|
||||
EOF
|
||||
sed -i.bak "s/__SOURCE_TAG__/$SOURCE_TAG/g" "$PORT_ROOT/README.md"
|
||||
rm -f "$PORT_ROOT/README.md.bak"
|
||||
|
||||
@@ -510,6 +523,8 @@ say "packing $ZIP_OUT"
|
||||
(cd "$PORT_ROOT" && zip -q -9 -r "$ZIP_OUT" \
|
||||
"$LAUNCHER_NAME" "$PORT_DIR_NAME" port.json gameinfo.xml README.md)
|
||||
|
||||
pm_verify_zip "$ZIP_OUT" "$PORT_DIR_NAME" "$WORK"
|
||||
|
||||
say "done."
|
||||
say "artifact: $ZIP_OUT ($(du -h "$ZIP_OUT" | cut -f1))"
|
||||
say "copy into the device PortMaster ports folder, then drop your .gb into gen1recomp-sbc/lovegame/"
|
||||
|
||||
+27
-24
@@ -11,6 +11,11 @@
|
||||
# Usage:
|
||||
# ./build-rg34xxsp.sh [--version X.Y.Z]
|
||||
#
|
||||
# LuaJIT: the zip ships a pinned LuaJIT, compiled during the build, so building
|
||||
# needs an aarch64 host with docker or podman. Alternatively set
|
||||
# GEN1RECOMP_LUAJIT_LIB=/path/libluajit-5.1.so.2 with its COPYRIGHT beside it
|
||||
# (or GEN1RECOMP_LUAJIT_COPYRIGHT=/path/to/COPYRIGHT).
|
||||
#
|
||||
# Output:
|
||||
# dist/rg34xxsp/gen1recomp-rg34xxsp-stockos64-mod.zip
|
||||
#
|
||||
@@ -41,9 +46,6 @@ LAUNCHER_NAME="Gen1recomp.sh"
|
||||
LOVE_VERSION="11.5"
|
||||
VERSION="$(git -C "$ROOT" rev-parse --short HEAD 2>/dev/null || echo dev)"
|
||||
|
||||
# Official PortMaster LÖVE 11.5 aarch64 runtime (small love stub + liblove).
|
||||
PM_RUNTIME_BASE="https://raw.githubusercontent.com/PortsMaster/PortMaster-GUI/main/PortMaster/runtimes/love_${LOVE_VERSION}"
|
||||
|
||||
say() { printf '\033[1;32m==>\033[0m %s\n' "$*"; }
|
||||
warn() { printf '\033[1;33mwarn:\033[0m %s\n' "$*" >&2; }
|
||||
fail() { printf '\033[1;31merror:\033[0m %s\n' "$*" >&2; exit 1; }
|
||||
@@ -52,7 +54,7 @@ while [ $# -gt 0 ]; do
|
||||
case "$1" in
|
||||
--version) VERSION="$2"; shift ;;
|
||||
-h|--help)
|
||||
sed -n '2,24p' "$0"
|
||||
sed -n '2,29p' "$0"
|
||||
exit 0
|
||||
;;
|
||||
*) fail "unknown argument: $1" ;;
|
||||
@@ -66,16 +68,9 @@ command -v unzip >/dev/null || fail "unzip is required"
|
||||
|
||||
mkdir -p "$CACHE" "$WORK" "$DIST"
|
||||
|
||||
download() {
|
||||
local url="$1" dest="$2"
|
||||
if [ -f "$dest" ] && [ -s "$dest" ]; then
|
||||
return 0
|
||||
fi
|
||||
say "downloading $(basename "$dest")"
|
||||
curl -fL --progress-bar "$url" -o "$dest.tmp" \
|
||||
|| fail "download failed: $url"
|
||||
mv "$dest.tmp" "$dest"
|
||||
}
|
||||
# PortMaster pins + LuaJIT pin (LUAJIT_COMMIT, ...) + download/verify helpers.
|
||||
# shellcheck source=scripts/luajit/portmaster_runtime.sh
|
||||
. "$ROOT/scripts/luajit/portmaster_runtime.sh"
|
||||
|
||||
# --------------------------------------------------------------- game tree
|
||||
# Unpacked directory (not a .love zip) so the player can drop a .gb next to
|
||||
@@ -129,15 +124,12 @@ fi
|
||||
say "fetching LÖVE $LOVE_VERSION aarch64 runtime"
|
||||
LOVE_BIN="$CACHE/love.aarch64"
|
||||
LOVE_LIB="$CACHE/liblove-11.5.so"
|
||||
LUAJIT_LIB="$CACHE/libluajit-5.1.so.2"
|
||||
MODPLUG_LIB="$CACHE/libmodplug.so.1"
|
||||
OGG_LIB="$CACHE/libogg.so.0"
|
||||
|
||||
download "$PM_RUNTIME_BASE/love.aarch64" "$LOVE_BIN"
|
||||
download "$PM_RUNTIME_BASE/libs.aarch64/liblove-11.5.so" "$LOVE_LIB"
|
||||
download "$PM_RUNTIME_BASE/libs.aarch64/libluajit-5.1.so.2" "$LUAJIT_LIB"
|
||||
download "$PM_RUNTIME_BASE/libs.aarch64/libmodplug.so.1" "$MODPLUG_LIB"
|
||||
download "$PM_RUNTIME_BASE/libs.aarch64/libogg.so.0" "$OGG_LIB"
|
||||
pm_fetch_runtime "$CACHE"
|
||||
|
||||
pm_select_luajit
|
||||
|
||||
# Sanity: love stub must be an aarch64 ELF.
|
||||
file "$LOVE_BIN" | grep -qi 'aarch64\|ARM aarch64' \
|
||||
@@ -155,8 +147,9 @@ mkdir -p "$PORT_ROOT/$PORT_DIR_NAME/bin" \
|
||||
cp -R "$GAME_SRC" "$PORT_ROOT/$PORT_DIR_NAME/lovegame"
|
||||
cp "$LOVE_BIN" "$PORT_ROOT/$PORT_DIR_NAME/bin/love.aarch64"
|
||||
chmod +x "$PORT_ROOT/$PORT_DIR_NAME/bin/love.aarch64"
|
||||
cp "$LOVE_LIB" "$LUAJIT_LIB" "$MODPLUG_LIB" "$OGG_LIB" \
|
||||
cp "$LOVE_LIB" "$MODPLUG_LIB" "$OGG_LIB" \
|
||||
"$PORT_ROOT/$PORT_DIR_NAME/libs.aarch64/"
|
||||
pm_stage_luajit "$PORT_ROOT/$PORT_DIR_NAME/libs.aarch64" "$PORT_ROOT/$PORT_DIR_NAME/licenses"
|
||||
|
||||
BRIDGE_LIB="liblibrashader_bridge.so"
|
||||
BRIDGE_SRC="${SHADERFX_BRIDGE_LINUX_ARM64:-}"
|
||||
@@ -173,10 +166,14 @@ else
|
||||
fi
|
||||
|
||||
# Drop a short license pointer for the bundled LÖVE bits.
|
||||
cat > "$PORT_ROOT/$PORT_DIR_NAME/licenses/LICENSE.love2d.txt" <<'EOF'
|
||||
cat > "$PORT_ROOT/$PORT_DIR_NAME/licenses/LICENSE.love2d.txt" <<EOF
|
||||
This port bundles the LÖVE 11.5 aarch64 runtime from PortMaster
|
||||
(https://github.com/PortsMaster/PortMaster-GUI). LÖVE is zlib-licensed;
|
||||
see https://love2d.org/ for full terms.
|
||||
(https://github.com/PortsMaster/PortMaster-GUI, commit $PM_RUNTIME_COMMIT),
|
||||
except for LuaJIT. LÖVE is zlib-licensed; see https://love2d.org/ for full terms.
|
||||
|
||||
libs.aarch64/libluajit-5.1.so.2 is LuaJIT, built from source at LuaJIT commit
|
||||
$LUAJIT_COMMIT (https://github.com/LuaJIT/LuaJIT, MIT license; see
|
||||
LuaJIT-COPYRIGHT). It replaces PortMaster's LuaJIT 2.1.0-beta3.
|
||||
EOF
|
||||
|
||||
# --------------------------------------------------------------- launcher
|
||||
@@ -355,6 +352,10 @@ Canonical SHA-1 (1 MiB US carts only):
|
||||
LÖVE runtime binaries from [PortMaster](https://portmaster.games/).
|
||||
Stock OS 64-bit MOD: [cbepx-me](https://github.com/cbepx-me/Anbernic-H700-RG-xx-StockOS-Modification).
|
||||
EOF
|
||||
cat >> "$PORT_ROOT/README.md" <<EOF
|
||||
|
||||
LuaJIT (MIT license) is built from source at LuaJIT commit \`$LUAJIT_COMMIT\` instead of using PortMaster's older LuaJIT 2.1.0-beta3. The JIT stays off by default on this build.
|
||||
EOF
|
||||
|
||||
# --------------------------------------------------------------- zip
|
||||
ZIP_OUT="$DIST/$APP_NAME-$ARTIFACT_SUFFIX.zip"
|
||||
@@ -363,6 +364,8 @@ say "packing $ZIP_OUT"
|
||||
(cd "$PORT_ROOT" && zip -q -9 -r "$ZIP_OUT" \
|
||||
"$LAUNCHER_NAME" "$PORT_DIR_NAME" port.json gameinfo.xml README.md)
|
||||
|
||||
pm_verify_zip "$ZIP_OUT" "$PORT_DIR_NAME" "$WORK"
|
||||
|
||||
say "done."
|
||||
say "artifact: $ZIP_OUT ($(du -h "$ZIP_OUT" | cut -f1))"
|
||||
say "copy onto the RG34XXSP SD card under roms/PORTS/ (Stock OS 64-bit MOD), then drop your .gb into gen1recomp/lovegame/"
|
||||
|
||||
@@ -98,6 +98,32 @@ casing and mount points.
|
||||
If a launch fails, `Roms/PORTS/gen1recomp/log.txt` holds the output of the
|
||||
last run.
|
||||
|
||||
## Bundled LuaJIT
|
||||
|
||||
The pack does not use PortMaster's `libluajit-5.1.so.2`. That one is LuaJIT
|
||||
2.1.0-beta3 (2017), which segfaulted 3 of 3 runs with the JIT on (TrimUI
|
||||
Brick). The pack ships a pinned LuaJIT 2.1 build instead (commit
|
||||
`c6ffc141a8762b41703f9287d63d93622a13dd8f`, MIT, license in
|
||||
`licenses/LuaJIT-COPYRIGHT`). It is compiled from source in a Debian bullseye
|
||||
aarch64 container (glibc 2.31, GC64, `make amalg`) by
|
||||
`scripts/luajit/build_luajit.sh`, and the build checks the version string and
|
||||
the glibc requirement before and after zipping. On the TrimUI Brick it ran a
|
||||
26-minute JIT-on soak with no crash.
|
||||
|
||||
The JIT still stays **off by default** on these builds: LÖVE turns it off on
|
||||
arm64, and nothing here sets `POKEPORT_JIT`. It has only been validated on one
|
||||
device (TrimUI Brick, A133P). Enabling `POKEPORT_JIT=1` by default needs
|
||||
stability testing on H700, RK3566 and A133P devices first.
|
||||
|
||||
Existing installs keep their old LuaJIT until the zip is re-extracted: in-app
|
||||
updates replace only the game's code, not the runtime libraries.
|
||||
|
||||
Building the port now needs an aarch64 host with docker or podman (non-aarch64
|
||||
hosts are refused), or a prebuilt library passed with
|
||||
`GEN1RECOMP_LUAJIT_LIB=/path/to/libluajit-5.1.so.2` (with its `COPYRIGHT` next
|
||||
to it, or `GEN1RECOMP_LUAJIT_COPYRIGHT`). The remaining PortMaster runtime
|
||||
files are pinned to a PortMaster-GUI commit and sha256-checked.
|
||||
|
||||
## Building the port
|
||||
|
||||
Release runs build this automatically (see `.github/workflows/release.yml`).
|
||||
|
||||
@@ -79,6 +79,44 @@ Environment variables for fine-tuning (configured in `gen1recomp-sbc.sh`):
|
||||
| `POKEPORT_CPU_GOVERNOR` | `schedutil` | CPU scaling governor (`schedutil`, `performance`, `ondemand`) |
|
||||
|
||||
|
||||
## Bundled LuaJIT
|
||||
|
||||
The pack does not use PortMaster's `libluajit-5.1.so.2`. That one is LuaJIT
|
||||
2.1.0-beta3 (2017), which segfaulted 3 of 3 runs with the JIT on (TrimUI
|
||||
Brick). The pack ships a pinned LuaJIT 2.1 build instead (commit
|
||||
`c6ffc141a8762b41703f9287d63d93622a13dd8f`, MIT, license in
|
||||
`licenses/LuaJIT-COPYRIGHT`). It is compiled from source in a Debian bullseye
|
||||
aarch64 container (glibc 2.31, GC64, `make amalg`) by
|
||||
`scripts/luajit/build_luajit.sh`, and the build checks the version string and
|
||||
the glibc requirement before and after zipping. On the TrimUI Brick it ran a
|
||||
26-minute JIT-on soak with no crash.
|
||||
|
||||
The JIT still stays **off by default** on these builds: LÖVE turns it off on
|
||||
arm64, and nothing here sets `POKEPORT_JIT`. It has only been validated on one
|
||||
device (TrimUI Brick, A133P). Enabling `POKEPORT_JIT=1` by default needs
|
||||
stability testing on H700, RK3566 and A133P devices first.
|
||||
|
||||
The PortMaster catalogue package (`scripts/portmaster/`, see
|
||||
[portmaster-submission.md](portmaster-submission.md)) is different: it runs on
|
||||
the device's own PortMaster `love_11.5` runtime, so it still uses that
|
||||
runtime's LuaJIT 2.1.0-beta3. Keep the JIT off there.
|
||||
|
||||
Existing installs keep their old LuaJIT until the zip is re-extracted: in-app
|
||||
updates replace only the game's code, not the runtime libraries.
|
||||
|
||||
Building the port now needs an aarch64 host with docker or podman (non-aarch64
|
||||
hosts are refused), or a prebuilt library passed with
|
||||
`GEN1RECOMP_LUAJIT_LIB=/path/to/libluajit-5.1.so.2` (with its `COPYRIGHT` next
|
||||
to it, or `GEN1RECOMP_LUAJIT_COPYRIGHT`). The remaining PortMaster runtime
|
||||
files are pinned to a PortMaster-GUI commit and sha256-checked.
|
||||
|
||||
For scripts that wrap `build-linux-arm-sbc.sh`: the library in
|
||||
`GEN1RECOMP_LUAJIT_LIB` must have a `COPYRIGHT` beside it (or set
|
||||
`GEN1RECOMP_LUAJIT_COPYRIGHT`) and must pass `scripts/luajit/verify_luajit.sh`
|
||||
(the pinned LuaJIT version, built with `PREFIX=/usr`). There is no longer any
|
||||
way to ship PortMaster's stock LuaJIT; a wrapper's "stock LuaJIT" mode should
|
||||
be removed, and the wrapper pointed at `scripts/luajit/build_luajit.sh` instead.
|
||||
|
||||
## Building
|
||||
|
||||
Release workflows build this automatically. Standalone builds resolve the latest published Gen1Recomp release by default:
|
||||
|
||||
@@ -201,6 +201,26 @@ Both pins live in `scripts/linux-arm64/common.sh`:
|
||||
source-built libraries. Bumping these is usually safe and occasionally
|
||||
necessary: `libmpg123` in particular must stay at least as new as what a
|
||||
target host's `libsndfile` expects, which is asserted for `mpg123_info2`.
|
||||
- `LUAJIT_*` in `scripts/luajit/pins.sh` (shared with the PortMaster builds) —
|
||||
LuaJIT is compiled from a pinned `v2.1`-branch commit inside the builder
|
||||
container instead of using bullseye's `libluajit-5.1-dev` (2.1.0-beta3, 2017,
|
||||
which segfaulted with the JIT on). The commit and a hash of
|
||||
`scripts/luajit/compile_luajit.sh` are part of the cached prefix
|
||||
name, and the build fails if the bundled library lacks
|
||||
`LUAJIT_VERSION_STRING` or if the system LuaJIT is present in the image.
|
||||
LuaJIT bakes its compile-time `PREFIX` into the default module paths, so it
|
||||
is compiled with `PREFIX=/usr` and only installed into the cached prefix;
|
||||
the build fails unless the library's default path is
|
||||
`/usr/share/luajit-2.1/?.lua` with no build prefix embedded. The install goes
|
||||
to a staging root first and is copied into the prefix only after
|
||||
`scripts/luajit/verify_luajit.sh` passes. `LUAJIT_BUILD_IMAGE` (digest-pinned)
|
||||
and `LUAJIT_APT_SOURCES` in `pins.sh` must match the builder Dockerfile's
|
||||
`FROM` and apt sources (see the re-pin notes in `pins.sh`). To
|
||||
bump: change `LUAJIT_COMMIT` and `LUAJIT_SHA256` (of the GitHub archive
|
||||
tarball) and set `LUAJIT_VERSION_STRING` to `LuaJIT 2.1.<contents of .relver
|
||||
at that commit>`. The license ships as `LuaJIT-COPYRIGHT` in the AppImage.
|
||||
The JIT stays off by default: LÖVE's `jitsetup` disables it on arm64, and
|
||||
enabling it by default needs stability testing on several devices first.
|
||||
- `APPIMAGE_RUNTIME_TAG` / `APPIMAGE_RUNTIME_SHA256` — always a dated tag
|
||||
from [AppImage/type2-runtime](https://github.com/AppImage/type2-runtime/releases).
|
||||
The selftest fails the build if this ever points at `continuous`.
|
||||
|
||||
@@ -62,7 +62,9 @@ cache are included. The project owner has explicitly permitted PortMaster
|
||||
distribution of the launcher, recorded in the included license.
|
||||
|
||||
I tested this catalogue candidate on my TrimUI Brick and confirmed it works.
|
||||
It uses PortMaster's LÖVE 11.5 runtime. I'm looking
|
||||
It uses PortMaster's LÖVE 11.5 runtime, including that runtime's LuaJIT
|
||||
2.1.0-beta3 (unlike the release zips, which bundle a pinned modern LuaJIT; see
|
||||
https://github.com/bryanthaboi/gen1recomp/blob/dev/docs/linux-arm-sbc.md#bundled-luajit), so the JIT must stay off. I'm looking
|
||||
for testing on the firmware and resolutions listed above, especially import,
|
||||
save/reload, controller exit and suspend/resume. Please include device,
|
||||
firmware, package checksum, result and `gen1recomp/log.txt` when reporting a
|
||||
|
||||
@@ -125,6 +125,7 @@ download_pinned "$THEORA_URL" "$CACHE/$THEORA_TARBALL" "$THEORA_SHA256"
|
||||
download_pinned "$OGG_URL" "$CACHE/$OGG_TARBALL" "$OGG_SHA256"
|
||||
download_pinned "$VORBIS_URL" "$CACHE/$VORBIS_TARBALL" "$VORBIS_SHA256"
|
||||
download_pinned "$MPG123_URL" "$CACHE/$MPG123_TARBALL" "$MPG123_SHA256"
|
||||
download_pinned "$LUAJIT_URL" "$CACHE/$LUAJIT_TARBALL" "$LUAJIT_SHA256"
|
||||
download_pinned "$APPIMAGE_RUNTIME_URL" "$CACHE/$APPIMAGE_RUNTIME_NAME" \
|
||||
"$APPIMAGE_RUNTIME_SHA256"
|
||||
|
||||
@@ -162,12 +163,18 @@ say "compiling and packaging inside $BUILDER_BASE_IMAGE"
|
||||
-e VORBIS_TARBALL="$VORBIS_TARBALL" \
|
||||
-e MPG123_VERSION="$MPG123_VERSION" \
|
||||
-e MPG123_TARBALL="$MPG123_TARBALL" \
|
||||
-e LUAJIT_COMMIT="$LUAJIT_COMMIT" \
|
||||
-e LUAJIT_TARBALL="$LUAJIT_TARBALL" \
|
||||
-e LUAJIT_VERSION_STRING="$LUAJIT_VERSION_STRING" \
|
||||
-e LUAJIT_MAX_GLIBC="$LUAJIT_MAX_GLIBC" \
|
||||
-e BUILDER_HASH="$BUILDER_HASH" \
|
||||
-e APP_NAME="$APP_NAME" \
|
||||
-e VERSION="$VERSION" \
|
||||
-v "$CACHE:/cache" \
|
||||
-v "$IN_DIR:/in:ro" \
|
||||
-v "$OUT_DIR:/out" \
|
||||
-v "$ROOT/scripts/linux-arm64:/scripts:ro" \
|
||||
-v "$ROOT/scripts/luajit:/luajit-scripts:ro" \
|
||||
"$BUILDER_IMAGE" bash /scripts/build_appimage.sh
|
||||
|
||||
# --------------------------------------------------------------- publish
|
||||
|
||||
Executable
+63
@@ -0,0 +1,63 @@
|
||||
#!/usr/bin/env bash
|
||||
# Sourceable download/hash/container helpers. No side effects on source.
|
||||
# The caller must define say, warn and fail.
|
||||
|
||||
# Print SHA-256 hex digest of PATH. Prefers sha256sum, falls back to shasum
|
||||
# (same order-agnostic pair scripts/switch/common.sh uses).
|
||||
sha256_file() {
|
||||
local path="$1"
|
||||
if command -v sha256sum >/dev/null 2>&1; then
|
||||
sha256sum "$path" | awk '{print $1}'
|
||||
elif command -v shasum >/dev/null 2>&1; then
|
||||
shasum -a 256 "$path" | awk '{print $1}'
|
||||
else
|
||||
fail "need sha256sum or shasum (install coreutils)"
|
||||
fi
|
||||
}
|
||||
|
||||
# download_pinned URL DEST EXPECTED_SHA256
|
||||
#
|
||||
# A cache hit is only trusted if it still hashes to the pin: a download
|
||||
# truncated by a network drop would otherwise be reused forever, which is the
|
||||
# same trap scripts/build.sh guards for the win64 zip and the x86_64 AppImage.
|
||||
download_pinned() {
|
||||
local url="$1" dest="$2" want="$3" got=""
|
||||
if [ -f "$dest" ]; then
|
||||
got="$(sha256_file "$dest")"
|
||||
if [ "$got" = "$want" ]; then
|
||||
return 0
|
||||
fi
|
||||
warn "cached $(basename "$dest") has the wrong digest, re-downloading"
|
||||
rm -f "$dest"
|
||||
fi
|
||||
say "downloading $(basename "$dest")"
|
||||
# --retry-all-errors because plain --retry skips TLS handshake failures,
|
||||
# which is how xiph.org drops these tarballs; the pin below still gates it.
|
||||
# curl < 7.71 lacks the flag and rejects it, so it is only passed if offered.
|
||||
local retry_all=()
|
||||
# No grep -q: it would exit early and SIGPIPE curl, which pipefail reports.
|
||||
if curl --help all 2>/dev/null | grep -- --retry-all-errors >/dev/null; then
|
||||
retry_all=(--retry-all-errors)
|
||||
fi
|
||||
curl -fL --retry 5 --retry-delay 2 ${retry_all[@]+"${retry_all[@]}"} --progress-bar \
|
||||
"$url" -o "$dest.tmp" || fail "download failed: $url"
|
||||
got="$(sha256_file "$dest.tmp")"
|
||||
[ "$got" = "$want" ] || fail "$(printf '%s\n expected %s\n got %s' \
|
||||
"checksum mismatch for $(basename "$dest")" "$want" "$got")"
|
||||
mv "$dest.tmp" "$dest"
|
||||
}
|
||||
|
||||
# Echo the container runtime to use: docker, else podman.
|
||||
container_runtime() {
|
||||
if [ -n "${GEN1_CONTAINER_RUNTIME:-}" ]; then
|
||||
printf '%s' "$GEN1_CONTAINER_RUNTIME"
|
||||
return 0
|
||||
fi
|
||||
if command -v docker >/dev/null 2>&1 && docker info >/dev/null 2>&1; then
|
||||
printf 'docker'
|
||||
elif command -v podman >/dev/null 2>&1; then
|
||||
printf 'podman'
|
||||
else
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
@@ -8,7 +8,8 @@
|
||||
#
|
||||
# This image is arch-native: build it on an aarch64 host (Raspberry Pi 5,
|
||||
# ubuntu-24.04-arm runner, Apple Silicon Docker) — no qemu emulation.
|
||||
FROM debian:bullseye
|
||||
# Must match LUAJIT_BUILD_IMAGE in scripts/luajit/pins.sh (checked by the selftest).
|
||||
FROM debian:bullseye@sha256:6f519a81440354a85eb592c5f32109ab80605f6b892455983a6f618bf87fabe9
|
||||
|
||||
ENV DEBIAN_FRONTEND=noninteractive
|
||||
|
||||
@@ -18,7 +19,9 @@ ENV DEBIAN_FRONTEND=noninteractive
|
||||
# Note what is deliberately ABSENT: libsdl2-dev, libtheora-dev and
|
||||
# libopenal-dev. All three are built from source instead (see common.sh for
|
||||
# why), and having Debian's copies installed would let pkg-config hand LÖVE's
|
||||
# configure the system ones and silently undo it.
|
||||
# configure the system ones and silently undo it. libluajit-5.1-dev is absent
|
||||
# for the same reason: LuaJIT is built from a pinned commit (scripts/luajit/),
|
||||
# because bullseye ships 2.1.0-beta3, which segfaulted with the JIT on.
|
||||
#
|
||||
# The remaining lib*-dev set is LÖVE's optional-module surface. A missing one
|
||||
# does not fail configure, it silently drops a module (love.sound decoders,
|
||||
@@ -37,7 +40,7 @@ RUN printf 'deb http://archive.debian.org/debian bullseye main\ndeb http://archi
|
||||
build-essential pkg-config autoconf automake libtool cmake \
|
||||
ca-certificates curl file xz-utils bzip2 zip unzip squashfs-tools \
|
||||
libogg-dev libvorbis-dev \
|
||||
libmodplug-dev libmpg123-dev libfreetype6-dev libluajit-5.1-dev \
|
||||
libmodplug-dev libmpg123-dev libfreetype6-dev \
|
||||
zlib1g-dev libgl1-mesa-dev libgles2-mesa-dev libegl1-mesa-dev \
|
||||
libasound2-dev libpulse-dev libudev-dev libdbus-1-dev \
|
||||
libx11-dev libxext-dev libxrandr-dev libxcursor-dev libxi-dev \
|
||||
|
||||
@@ -27,6 +27,11 @@ VORBIS_VERSION="${VORBIS_VERSION:?}"
|
||||
VORBIS_TARBALL="${VORBIS_TARBALL:?}"
|
||||
MPG123_VERSION="${MPG123_VERSION:?}"
|
||||
MPG123_TARBALL="${MPG123_TARBALL:?}"
|
||||
LUAJIT_COMMIT="${LUAJIT_COMMIT:?}"
|
||||
LUAJIT_TARBALL="${LUAJIT_TARBALL:?}"
|
||||
LUAJIT_VERSION_STRING="${LUAJIT_VERSION_STRING:?}"
|
||||
LUAJIT_MAX_GLIBC="${LUAJIT_MAX_GLIBC:?}"
|
||||
BUILDER_HASH="${BUILDER_HASH:?}"
|
||||
APP_NAME="${APP_NAME:?}"
|
||||
VERSION="${VERSION:?}"
|
||||
JOBS="${JOBS:-$(nproc)}"
|
||||
@@ -46,12 +51,40 @@ mkdir -p "$WORK"
|
||||
# the only slow part (~5 min cold on a Pi 5) and is identical for every game
|
||||
# version. The key includes every source version, so bumping any of them
|
||||
# invalidates the cache instead of silently reusing a stale mix.
|
||||
PREFIX="$CACHE/prefix-love$LOVE_VERSION-sdl$SDL2_VERSION-al$OPENAL_VERSION-theora$THEORA_VERSION-ogg$OGG_VERSION-vorbis$VORBIS_VERSION-mpg$MPG123_VERSION"
|
||||
# The key also carries a hash of the LuaJIT build recipe, so changing it
|
||||
# rebuilds LuaJIT instead of reusing a prefix built the old way. It also carries
|
||||
# the builder image's Dockerfile hash, so a toolchain/package change rebuilds
|
||||
# everything instead of reusing objects compiled by the old image.
|
||||
LUAJIT_RECIPE="$(sha256sum /luajit-scripts/compile_luajit.sh | cut -c1-12)"
|
||||
PREFIX="$CACHE/prefix-love$LOVE_VERSION-sdl$SDL2_VERSION-al$OPENAL_VERSION-theora$THEORA_VERSION-ogg$OGG_VERSION-vorbis$VORBIS_VERSION-mpg$MPG123_VERSION-luajit${LUAJIT_COMMIT:0:12}-${LUAJIT_RECIPE}-img${BUILDER_HASH}"
|
||||
export PKG_CONFIG_PATH="$PREFIX/lib/pkgconfig"
|
||||
# Our own libraries must win over the system ones during LÖVE's configure and
|
||||
# link, or the whole point of building them is lost.
|
||||
export LD_LIBRARY_PATH="$PREFIX/lib"
|
||||
|
||||
# ----------------------------------------------------------- compile LuaJIT
|
||||
# Built from the pinned commit, not bullseye's 2.1.0-beta3 (which segfaulted
|
||||
# with the JIT on). The cache key above carries the commit, so a prefix built
|
||||
# against any other LuaJIT is never reused.
|
||||
# COPYRIGHT is installed last by compile_luajit.sh, so it marks a finished install.
|
||||
if [ -f "$PREFIX/lib/libluajit-5.1.so.2" ] && [ -f "$PREFIX/lib/pkgconfig/luajit.pc" ] \
|
||||
&& [ -s "$PREFIX/share/doc/luajit/COPYRIGHT" ]; then
|
||||
say "reusing cached LuaJIT ${LUAJIT_COMMIT:0:12}"
|
||||
bash /luajit-scripts/verify_luajit.sh "$PREFIX/lib/libluajit-5.1.so.2" \
|
||||
|| fail "the cached LuaJIT in $PREFIX failed verification; re-run with --clean-cache"
|
||||
else
|
||||
say "compiling LuaJIT ${LUAJIT_COMMIT:0:12}"
|
||||
bash /luajit-scripts/compile_luajit.sh "$CACHE/$LUAJIT_TARBALL" "$PREFIX"
|
||||
fi
|
||||
# Debian's copy must not be able to win: a stale builder image that still has
|
||||
# libluajit-5.1-dev would let pkg-config hand LOVE the 2017 beta3.
|
||||
if ls /usr/lib/aarch64-linux-gnu/libluajit-5.1.so* >/dev/null 2>&1; then
|
||||
fail "the system libluajit-5.1 is installed in the builder image; rebuild it with --rebuild-image"
|
||||
fi
|
||||
luajit_prefix="$(pkg-config --variable=prefix luajit)"
|
||||
[ "$luajit_prefix" = "$PREFIX" ] \
|
||||
|| fail "pkg-config resolves luajit to '$luajit_prefix', not $PREFIX"
|
||||
|
||||
# ------------------------------------------------------ compile audio codecs
|
||||
# Ordered by dependency: vorbis needs ogg, and theora needs ogg too. All three
|
||||
# are small, plain autotools builds -- well under a minute each.
|
||||
@@ -250,6 +283,38 @@ for soname in libSDL2-2.0.so.0 libopenal.so.1 libfreetype.so.6 \
|
||||
|| fail "liblove is not linked against $soname (a -dev package went missing)"
|
||||
done
|
||||
|
||||
# liblove must really be linked against OUR LuaJIT. LD_LIBRARY_PATH points at
|
||||
# $PREFIX/lib for this whole script, so a plain ldd would resolve there no
|
||||
# matter how liblove was linked. Prove it without that crutch instead:
|
||||
# (a) every RPATH/RUNPATH entry stays inside $PREFIX (luajit.pc adds none;
|
||||
# libtool adds $PREFIX/lib because liblove links the .la libraries built
|
||||
# there -- SDL2, ogg, vorbis, theora, mpg123 -- and (b) relies on that),
|
||||
# (b) with LD_LIBRARY_PATH unset, the loader still finds libluajit-5.1.so.2,
|
||||
# and only at $PREFIX/lib -- via the checked rpath or the system search
|
||||
# path, so no other LuaJIT on the system could have satisfied the link, and
|
||||
# (c) when compiled in this run, configure recorded our include dir.
|
||||
love_rpath="$(objdump -p "$love_lib" | awk '/RPATH|RUNPATH/ {print $2}')"
|
||||
if [ -n "$love_rpath" ]; then
|
||||
IFS=: read -ra rpath_dirs <<<"$love_rpath"
|
||||
for rpath_dir in "${rpath_dirs[@]}"; do
|
||||
case "$rpath_dir" in
|
||||
"$PREFIX"|"$PREFIX"/*) ;;
|
||||
*) fail "liblove has an RPATH/RUNPATH entry outside $PREFIX: $rpath_dir" ;;
|
||||
esac
|
||||
done
|
||||
fi
|
||||
bare_ldd="$(env -u LD_LIBRARY_PATH ldd "$love_lib")"
|
||||
luajit_resolved="$(awk '$1 == "libluajit-5.1.so.2" {print $3}' <<<"$bare_ldd")"
|
||||
[ -n "$luajit_resolved" ] && [ "$luajit_resolved" != "not" ] \
|
||||
&& [ "$(readlink -f "$luajit_resolved")" = "$(readlink -f "$PREFIX/lib/libluajit-5.1.so.2")" ] \
|
||||
|| fail "without LD_LIBRARY_PATH liblove resolves libluajit-5.1.so.2 to '${luajit_resolved:-nothing}', not the pinned build in $PREFIX/lib"
|
||||
say "liblove -> libluajit-5.1.so.2 (no LD_LIBRARY_PATH): $luajit_resolved"
|
||||
if [ -f "$WORK/love-src/config.log" ]; then
|
||||
grep -qF -- "-I$PREFIX/include/luajit-2.1" "$WORK/love-src/config.log" \
|
||||
|| fail "LÖVE's configure did not record -I$PREFIX/include/luajit-2.1"
|
||||
say "config.log: $(grep -F -m1 -- "-I$PREFIX/include/luajit-2.1" "$WORK/love-src/config.log")"
|
||||
fi
|
||||
|
||||
# --------------------------------------------------------------- AppDir
|
||||
# Layout mirrors LÖVE's own x86_64 AppImage exactly (bin/ lib/ share/ at the
|
||||
# AppDir root, not usr/-prefixed), so the AppRun contract below -- and the
|
||||
@@ -324,6 +389,8 @@ chmod 0644 "$APPDIR/lib/liblove-$LOVE_VERSION.so"
|
||||
BUNDLED["liblove-$LOVE_VERSION.so"]=1
|
||||
bundle_needed "$APPDIR/bin/love"
|
||||
bundle_needed "$APPDIR/lib/liblove-$LOVE_VERSION.so"
|
||||
bash /luajit-scripts/verify_luajit.sh "$APPDIR/lib/libluajit-5.1.so.2" \
|
||||
|| fail "bundled libluajit-5.1.so.2 is not the pinned build"
|
||||
say "bundled $(ls "$APPDIR/lib" | wc -l) libraries: $(ls "$APPDIR/lib" | tr '\n' ' ')"
|
||||
|
||||
# ------------------------------------------------- host dependency contract
|
||||
@@ -363,8 +430,8 @@ say "host dependency contract holds (glibc, libstdc++ and the font stack only)"
|
||||
|
||||
# LÖVE loads jit.* (jit.status, the profiler) through LUA_PATH; without these
|
||||
# the modules are simply absent, so ship them the way upstream's image does.
|
||||
jit_share="$(ls -d /usr/share/luajit-* 2>/dev/null | head -1)"
|
||||
[ -n "$jit_share" ] || fail "luajit jit/*.lua modules not found under /usr/share"
|
||||
jit_share="$(ls -d "$PREFIX"/share/luajit-* 2>/dev/null | head -1)"
|
||||
[ -n "$jit_share" ] || fail "luajit jit/*.lua modules not found under $PREFIX/share"
|
||||
LUAJIT_SHARE_DIR="$(basename "$jit_share")"
|
||||
mkdir -p "$APPDIR/share/$LUAJIT_SHARE_DIR" "$APPDIR/share/lua/5.1" "$APPDIR/lib/lua/5.1"
|
||||
cp -R "$jit_share/jit" "$APPDIR/share/$LUAJIT_SHARE_DIR/"
|
||||
@@ -445,6 +512,8 @@ chmod +x "$APPDIR/AppRun"
|
||||
|
||||
[ -f "$PREFIX/license.txt" ] || fail "LÖVE license.txt missing from the build prefix"
|
||||
cp "$PREFIX/license.txt" "$APPDIR/license.love2d.txt"
|
||||
[ -s "$PREFIX/share/doc/luajit/COPYRIGHT" ] || fail "LuaJIT COPYRIGHT missing from the build prefix"
|
||||
cp "$PREFIX/share/doc/luajit/COPYRIGHT" "$APPDIR/LuaJIT-COPYRIGHT"
|
||||
|
||||
# --------------------------------------------------------------- fuse image
|
||||
# An AppImage is just <runtime ELF><squashfs>. gzip at 128K blocks matches what
|
||||
|
||||
@@ -8,6 +8,19 @@ if [ -z "${ROOT:-}" ]; then
|
||||
fi
|
||||
export ROOT
|
||||
|
||||
# Pinned LuaJIT (shared with the PortMaster builds). Built from source in the
|
||||
# builder container rather than taken from bullseye's libluajit-5.1-dev.
|
||||
# shellcheck source=../luajit/pins.sh
|
||||
. "$ROOT/scripts/luajit/pins.sh"
|
||||
|
||||
say() { printf '\033[1;32m==>\033[0m %s\n' "$*"; }
|
||||
warn() { printf '\033[1;33mwarn:\033[0m %s\n' "$*" >&2; }
|
||||
fail() { printf '\033[1;31merror:\033[0m %s\n' "$*" >&2; exit 1; }
|
||||
|
||||
# sha256_file, download_pinned, container_runtime (shared with scripts/luajit).
|
||||
# shellcheck source=../lib/fetch.sh
|
||||
. "$ROOT/scripts/lib/fetch.sh"
|
||||
|
||||
# ---------------------------------------------------------------- pins
|
||||
# LÖVE ships no aarch64 binary of any kind -- the 11.5 release has win32/win64,
|
||||
# macOS, Android, iOS and an x86_64 AppImage, and that is the whole list. So
|
||||
@@ -104,69 +117,15 @@ APPIMAGE_RUNTIME_SHA256="00cbdfcf917cc6c0ff6d3347d59e0ca1f7f45a6df1a428a0d6d8a78
|
||||
# AppImage cover Raspberry Pi OS bullseye/bookworm/trixie, Ubuntu 20.04+ and
|
||||
# the aarch64 handheld distros. Building on a newer base would silently
|
||||
# restrict the artifact to that base and newer.
|
||||
BUILDER_BASE_IMAGE="debian:bullseye"
|
||||
BUILDER_IMAGE="${GEN1_LINUX_ARM64_IMAGE:-gen1recomp-linux-arm64-builder}"
|
||||
BUILDER_BASE_IMAGE="$LUAJIT_BUILD_IMAGE"
|
||||
# The tag is derived from the Dockerfile content, so any change to the image
|
||||
# (packages, apt sources, base digest) yields a new tag and a stale local image
|
||||
# (e.g. one still carrying libluajit-5.1-dev) is never reused.
|
||||
BUILDER_HASH="$(sha256_file "$ROOT/scripts/linux-arm64/Dockerfile" | cut -c1-12)"
|
||||
BUILDER_IMAGE="${GEN1_LINUX_ARM64_IMAGE:-gen1recomp-linux-arm64-builder:$BUILDER_HASH}"
|
||||
|
||||
APP_NAME="gen1recomp"
|
||||
|
||||
say() { printf '\033[1;32m==>\033[0m %s\n' "$*"; }
|
||||
warn() { printf '\033[1;33mwarn:\033[0m %s\n' "$*" >&2; }
|
||||
fail() { printf '\033[1;31merror:\033[0m %s\n' "$*" >&2; exit 1; }
|
||||
|
||||
# Print SHA-256 hex digest of PATH. Prefers sha256sum, falls back to shasum
|
||||
# (same order-agnostic pair scripts/switch/common.sh uses).
|
||||
sha256_file() {
|
||||
local path="$1"
|
||||
if command -v sha256sum >/dev/null 2>&1; then
|
||||
sha256sum "$path" | awk '{print $1}'
|
||||
elif command -v shasum >/dev/null 2>&1; then
|
||||
shasum -a 256 "$path" | awk '{print $1}'
|
||||
else
|
||||
fail "need sha256sum or shasum (install coreutils)"
|
||||
fi
|
||||
}
|
||||
|
||||
# download_pinned URL DEST EXPECTED_SHA256
|
||||
#
|
||||
# A cache hit is only trusted if it still hashes to the pin: a download
|
||||
# truncated by a network drop would otherwise be reused forever, which is the
|
||||
# same trap scripts/build.sh guards for the win64 zip and the x86_64 AppImage.
|
||||
download_pinned() {
|
||||
local url="$1" dest="$2" want="$3" got=""
|
||||
if [ -f "$dest" ]; then
|
||||
got="$(sha256_file "$dest")"
|
||||
if [ "$got" = "$want" ]; then
|
||||
return 0
|
||||
fi
|
||||
warn "cached $(basename "$dest") has the wrong digest, re-downloading"
|
||||
rm -f "$dest"
|
||||
fi
|
||||
say "downloading $(basename "$dest")"
|
||||
# --retry-all-errors because plain --retry skips TLS handshake failures,
|
||||
# which is how xiph.org drops these tarballs; the pin below still gates it.
|
||||
curl -fL --retry 5 --retry-delay 2 --retry-all-errors --progress-bar \
|
||||
"$url" -o "$dest.tmp" || fail "download failed: $url"
|
||||
got="$(sha256_file "$dest.tmp")"
|
||||
[ "$got" = "$want" ] || fail "$(printf '%s\n expected %s\n got %s' \
|
||||
"checksum mismatch for $(basename "$dest")" "$want" "$got")"
|
||||
mv "$dest.tmp" "$dest"
|
||||
}
|
||||
|
||||
# Echo the container runtime to use: docker, else podman.
|
||||
container_runtime() {
|
||||
if [ -n "${GEN1_CONTAINER_RUNTIME:-}" ]; then
|
||||
printf '%s' "$GEN1_CONTAINER_RUNTIME"
|
||||
return 0
|
||||
fi
|
||||
if command -v docker >/dev/null 2>&1 && docker info >/dev/null 2>&1; then
|
||||
printf 'docker'
|
||||
elif command -v podman >/dev/null 2>&1; then
|
||||
printf 'podman'
|
||||
else
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
fail_need_container() {
|
||||
fail "$(cat <<'EOF'
|
||||
the aarch64 AppImage is compiled inside a Debian bullseye container and needs
|
||||
|
||||
@@ -60,11 +60,46 @@ printf '%s' "$LOVE_SRC_URL" | grep -q "/$LOVE_VERSION/$LOVE_SRC_TARBALL\$" \
|
||||
say "checking the builder base image"
|
||||
# Building on anything newer than bullseye silently raises the glibc floor and
|
||||
# strands every user on an older distro, with no symptom until they run it.
|
||||
grep -q '^FROM debian:bullseye$' "$SCRIPT_DIR/Dockerfile" \
|
||||
|| fail "Dockerfile no longer builds on debian:bullseye (that raises the glibc floor)"
|
||||
[ "$BUILDER_BASE_IMAGE" = "debian:bullseye" ] \
|
||||
grep -qxF "FROM $LUAJIT_BUILD_IMAGE" "$SCRIPT_DIR/Dockerfile" \
|
||||
|| fail "Dockerfile FROM is not LUAJIT_BUILD_IMAGE ($LUAJIT_BUILD_IMAGE)"
|
||||
printf '%s' "$LUAJIT_BUILD_IMAGE" | grep -Eq '^debian:bullseye@sha256:[0-9a-f]{64}$' \
|
||||
|| fail "LUAJIT_BUILD_IMAGE is not a digest-pinned debian:bullseye (that raises the glibc floor)"
|
||||
[ "$BUILDER_BASE_IMAGE" = "$LUAJIT_BUILD_IMAGE" ] \
|
||||
|| fail "BUILDER_BASE_IMAGE disagrees with the Dockerfile"
|
||||
|
||||
while IFS= read -r apt_line; do
|
||||
[ -n "$apt_line" ] || continue
|
||||
grep -qF -- "$apt_line" "$SCRIPT_DIR/Dockerfile" \
|
||||
|| fail "build_luajit.sh and the builder image must use the same apt sources (Dockerfile lacks: $apt_line)"
|
||||
done <<<"$LUAJIT_APT_SOURCES"
|
||||
|
||||
say "checking verify_luajit.sh rejection paths"
|
||||
# Synthetic files only: header = magic, 64-bit (02), little-endian (01), zeros,
|
||||
# e_machine at offset 18-19.
|
||||
lj_dir="$(mktemp -d "${TMPDIR:-/tmp}/gen1recomp-verify-luajit.XXXXXX")"
|
||||
temp_dir=""
|
||||
trap 'rm -rf "$lj_dir" ${temp_dir:+"$temp_dir"}' EXIT
|
||||
lj_hdr() { # $1 = e_machine as two hex bytes, e.g. b7 00
|
||||
printf '\177ELF\002\001'; head -c 12 /dev/zero; printf "\\x$1\\x$2"
|
||||
}
|
||||
lj_make() { # $1 file, $2 e_machine lo, $3 hi, $4 version, $5 path, $6 glibc
|
||||
{ lj_hdr "$2" "$3"; printf '\0%s\0%s\0%s\0' "$4" "$5" "$6"; } > "$1"
|
||||
}
|
||||
lj_path='/usr/share/luajit-2.1/?.lua'
|
||||
lj_verify() { bash "$ROOT/scripts/luajit/verify_luajit.sh" "$1" >/dev/null 2>&1; }
|
||||
lj_make "$lj_dir/ok" b7 00 "$LUAJIT_VERSION_STRING" "$lj_path" GLIBC_2.17
|
||||
lj_verify "$lj_dir/ok" || fail "verify_luajit.sh rejects a valid synthetic aarch64 library"
|
||||
printf '%s %s GLIBC_2.17' "$LUAJIT_VERSION_STRING" "$lj_path" > "$lj_dir/text"
|
||||
lj_make "$lj_dir/x86" 3e 00 "$LUAJIT_VERSION_STRING" "$lj_path" GLIBC_2.17
|
||||
lj_make "$lj_dir/nopath" b7 00 "$LUAJIT_VERSION_STRING" "/opt/build/share/luajit-2.1/?.lua" GLIBC_2.17
|
||||
lj_make "$lj_dir/glibc" b7 00 "$LUAJIT_VERSION_STRING" "$lj_path" GLIBC_2.34
|
||||
lj_make "$lj_dir/beta" b7 00 "$LUAJIT_VERSION_STRING LuaJIT 2.1.0-beta3" "$lj_path" GLIBC_2.17
|
||||
for bad in text x86 nopath glibc beta; do
|
||||
if lj_verify "$lj_dir/$bad"; then
|
||||
fail "verify_luajit.sh accepted the bad '$bad' library"
|
||||
fi
|
||||
done
|
||||
|
||||
say "checking the dependency exclude list"
|
||||
# Extract the live regex from the build script and classify known sonames
|
||||
# through it, so a future edit cannot quietly start bundling glibc or stop
|
||||
@@ -121,11 +156,17 @@ say "checking the dlopen guarantees"
|
||||
# turns an optional runtime capability into a mandatory startup dependency.
|
||||
# If a future edit drops the source build and reaches for the -dev package
|
||||
# again, the AppImage silently stops starting on lean systems.
|
||||
for forbidden_pkg in libsdl2-dev libtheora-dev libopenal-dev; do
|
||||
for forbidden_pkg in libsdl2-dev libtheora-dev libopenal-dev libluajit-5.1-dev; do
|
||||
if grep -qE "^ +.*\b$forbidden_pkg\b" "$SCRIPT_DIR/Dockerfile"; then
|
||||
fail "Dockerfile installs $forbidden_pkg; that library is built from source on purpose"
|
||||
fi
|
||||
done
|
||||
grep -qF 'compile_luajit.sh' "$SCRIPT_DIR/build_appimage.sh" \
|
||||
|| fail "build_appimage.sh no longer builds the pinned LuaJIT"
|
||||
grep -qF 'luajit${LUAJIT_COMMIT:0:12}-${LUAJIT_RECIPE}-img${BUILDER_HASH}' "$SCRIPT_DIR/build_appimage.sh" \
|
||||
|| fail "the PREFIX cache key does not include the LuaJIT commit, recipe hash and builder image hash"
|
||||
printf '%s' "$LUAJIT_SHA256" | grep -Eq '^[0-9a-f]{64}$' \
|
||||
|| fail "LUAJIT_SHA256 is not a sha256 digest: $LUAJIT_SHA256"
|
||||
grep -qF -- '--enable-alsa-shared' "$SCRIPT_DIR/build_appimage.sh" \
|
||||
|| fail "SDL2 is no longer configured to dlopen its audio backends"
|
||||
grep -qF -- '--enable-x11-shared' "$SCRIPT_DIR/build_appimage.sh" \
|
||||
@@ -158,7 +199,6 @@ done
|
||||
|
||||
say "checking the shared game.love payload"
|
||||
temp_dir="$(mktemp -d "${TMPDIR:-/tmp}/gen1recomp-linux-arm64-selftest.XXXXXX")"
|
||||
trap 'rm -rf "$temp_dir"' EXIT
|
||||
"$ROOT/scripts/pack_love.sh" \
|
||||
--output "$temp_dir/game.love" \
|
||||
--listing "$temp_dir/love-listing.txt" \
|
||||
|
||||
@@ -8,6 +8,8 @@ image="${1:?usage: verify_appimage.sh <AppImage>}"
|
||||
[ -f "$image" ] || { echo "::error::no such AppImage: $image"; exit 1; }
|
||||
image="$(cd "$(dirname "$image")" && pwd)/$(basename "$image")"
|
||||
|
||||
verify_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")/../luajit" && pwd)"
|
||||
|
||||
workdir="$(mktemp -d)"
|
||||
trap 'rm -rf "$workdir"' EXIT
|
||||
cd "$workdir"
|
||||
@@ -20,6 +22,14 @@ for required in AppRun bin/love game.love lib/liblove-11.5.so; do
|
||||
|| { echo "::error::AppImage is missing $required"; exit 1; }
|
||||
done
|
||||
|
||||
# The pinned LuaJIT, not bullseye's 2.1.0-beta3 (segfaults with the JIT on).
|
||||
[ -f "squashfs-root/lib/libluajit-5.1.so.2" ] \
|
||||
|| { echo "::error::AppImage is missing lib/libluajit-5.1.so.2"; exit 1; }
|
||||
bash "$verify_dir/verify_luajit.sh" squashfs-root/lib/libluajit-5.1.so.2 \
|
||||
|| { echo "::error::bundled LuaJIT is not the pinned build"; exit 1; }
|
||||
[ -s "squashfs-root/LuaJIT-COPYRIGHT" ] \
|
||||
|| { echo "::error::AppImage is missing LuaJIT-COPYRIGHT"; exit 1; }
|
||||
|
||||
bridge="squashfs-root/liblibrashader_bridge.so"
|
||||
if [ "${SHADERFX_BRIDGE_REQUIRED:-}" = "1" ] && [ ! -e "$bridge" ]; then
|
||||
echo "::error::AppImage is missing liblibrashader_bridge.so"
|
||||
|
||||
Executable
+82
@@ -0,0 +1,82 @@
|
||||
#!/usr/bin/env bash
|
||||
# Build the pinned LuaJIT for aarch64 Linux inside a debian:bullseye container.
|
||||
#
|
||||
# Usage: scripts/luajit/build_luajit.sh
|
||||
# Prints the path of the library on stdout; progress goes to stderr.
|
||||
# Output: .bazinga/cache/luajit/<commit>-<recipe hash>-<image digest>/{libluajit-5.1.so.2,COPYRIGHT}
|
||||
#
|
||||
# Must run on an aarch64 host (docker or podman). Emulated (qemu) aarch64
|
||||
# builds have miscompiled LuaJIT before, so other hosts are refused.
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
HERE="$(cd "$(dirname "$0")" && pwd)"
|
||||
ROOT="$(cd "$HERE/../.." && pwd)"
|
||||
# shellcheck source=pins.sh
|
||||
. "$HERE/pins.sh"
|
||||
|
||||
say() { printf '\033[1;32m==>\033[0m %s\n' "$*" >&2; }
|
||||
warn() { printf '\033[1;33mwarn:\033[0m %s\n' "$*" >&2; }
|
||||
fail() { printf '\033[1;31merror:\033[0m %s\n' "$*" >&2; exit 1; }
|
||||
# shellcheck source=../lib/fetch.sh
|
||||
. "$ROOT/scripts/lib/fetch.sh"
|
||||
|
||||
case "$(uname -m)" in
|
||||
aarch64|arm64) ;;
|
||||
*) fail "LuaJIT must be built on an aarch64 host (got $(uname -m)); emulated builds are unreliable. Build on arm64 or pass GEN1RECOMP_LUAJIT_LIB to the zip scripts." ;;
|
||||
esac
|
||||
|
||||
CACHE="$ROOT/.bazinga/cache/luajit"
|
||||
# Keyed by the build recipe and the pinned image digest, so changing either rebuilds.
|
||||
RECIPE_HASH="$(sha256_file "$HERE/compile_luajit.sh")"
|
||||
IMAGE_DIGEST="${LUAJIT_BUILD_IMAGE##*sha256:}"
|
||||
OUT_DIR="$CACHE/$LUAJIT_COMMIT-${RECIPE_HASH:0:12}-${IMAGE_DIGEST:0:12}"
|
||||
OUT="$OUT_DIR/libluajit-5.1.so.2"
|
||||
mkdir -p "$CACHE" "$OUT_DIR"
|
||||
|
||||
if [ -f "$OUT" ] && [ -s "$OUT_DIR/COPYRIGHT" ] \
|
||||
&& "$HERE/verify_luajit.sh" "$OUT" >/dev/null 2>&1; then
|
||||
say "LuaJIT $LUAJIT_COMMIT already built"
|
||||
echo "$OUT"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Pinned tarball (a cache hit must still match the pin). curl's progress goes
|
||||
# to stderr, but keep stdout clean regardless: it carries only the lib path.
|
||||
TARBALL="$CACHE/$LUAJIT_TARBALL"
|
||||
download_pinned "$LUAJIT_URL" "$TARBALL" "$LUAJIT_SHA256" >&2
|
||||
|
||||
RT="$(container_runtime)" \
|
||||
|| fail "docker or podman is required to build LuaJIT (or set GEN1RECOMP_LUAJIT_LIB for the zip scripts)"
|
||||
|
||||
STAGE="$(mktemp -d "$CACHE/stage.XXXXXX")"
|
||||
trap 'rm -rf "$STAGE"' EXIT
|
||||
mkdir -p "$STAGE/out"
|
||||
|
||||
say "building LuaJIT $LUAJIT_COMMIT in $RT ($LUAJIT_BUILD_IMAGE, arm64)"
|
||||
"$RT" run --rm --platform linux/arm64 \
|
||||
-e LUAJIT_VERSION_STRING="$LUAJIT_VERSION_STRING" \
|
||||
-e LUAJIT_MAX_GLIBC="$LUAJIT_MAX_GLIBC" \
|
||||
-e LUAJIT_APT_SOURCES="$LUAJIT_APT_SOURCES" \
|
||||
-v "$HERE:/luajit-scripts:ro" \
|
||||
-v "$TARBALL:/in/$LUAJIT_TARBALL:ro" \
|
||||
-v "$STAGE/out:/out" \
|
||||
"$LUAJIT_BUILD_IMAGE" bash -euo pipefail -c '
|
||||
# Bullseye is EOL; same sources/apt.conf as scripts/linux-arm64/Dockerfile.
|
||||
printf "%s\n" "$LUAJIT_APT_SOURCES" > /etc/apt/sources.list
|
||||
rm -f /etc/apt/sources.list.d/*
|
||||
printf "Acquire::Check-Valid-Until \"false\";\nAcquire::Retries \"5\";\nAcquire::http::Pipeline-Depth \"0\";\nAcquire::http::No-Cache \"true\";\n" > /etc/apt/apt.conf.d/99builder
|
||||
apt-get update -qq
|
||||
DEBIAN_FRONTEND=noninteractive apt-get install -y -qq build-essential binutils ca-certificates >/dev/null
|
||||
bash /luajit-scripts/compile_luajit.sh "/in/'"$LUAJIT_TARBALL"'" /tmp/prefix
|
||||
cp -L /tmp/prefix/lib/libluajit-5.1.so.2 /out/libluajit-5.1.so.2
|
||||
cp /tmp/prefix/share/doc/luajit/COPYRIGHT /out/COPYRIGHT
|
||||
' >&2 || fail "LuaJIT container build failed"
|
||||
|
||||
"$HERE/verify_luajit.sh" "$STAGE/out/libluajit-5.1.so.2" || fail "built library failed verification"
|
||||
[ -s "$STAGE/out/COPYRIGHT" ] || fail "built COPYRIGHT is missing or empty"
|
||||
# Install: COPYRIGHT first, library last, so the cache-hit test is atomic.
|
||||
mv -f "$STAGE/out/COPYRIGHT" "$OUT_DIR/COPYRIGHT"
|
||||
mv -f "$STAGE/out/libluajit-5.1.so.2" "$OUT"
|
||||
say "built $OUT"
|
||||
echo "$OUT"
|
||||
Executable
+62
@@ -0,0 +1,62 @@
|
||||
#!/usr/bin/env bash
|
||||
# Compile the pinned LuaJIT. Runs INSIDE an aarch64 Linux container
|
||||
# (debian:bullseye + build-essential; binutils for readelf).
|
||||
#
|
||||
# Usage: compile_luajit.sh <tarball> <prefix>
|
||||
# Env: LUAJIT_VERSION_STRING string the built library must contain (required)
|
||||
# LUAJIT_MAX_GLIBC highest GLIBC_x.y symbol allowed (required)
|
||||
#
|
||||
# No -mcpu flag: the validated recipe is plain `make amalg` with GC64.
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
fail() { printf 'error: %s\n' "$*" >&2; exit 1; }
|
||||
|
||||
[ $# -eq 2 ] || fail "usage: compile_luajit.sh <tarball> <prefix>"
|
||||
TARBALL="$1"
|
||||
PREFIX="$2"
|
||||
[ -f "$TARBALL" ] || fail "tarball not found: $TARBALL"
|
||||
: "${LUAJIT_VERSION_STRING:?LUAJIT_VERSION_STRING must be set}"
|
||||
: "${LUAJIT_MAX_GLIBC:?LUAJIT_MAX_GLIBC must be set}"
|
||||
|
||||
SRC_TMP="$(mktemp -d)"
|
||||
trap 'rm -rf "$SRC_TMP"' EXIT
|
||||
tar -xzf "$TARBALL" -C "$SRC_TMP"
|
||||
SRC="$(find "$SRC_TMP" -mindepth 1 -maxdepth 1 -type d -print -quit)"
|
||||
[ -n "$SRC" ] || fail "tarball had no top-level directory"
|
||||
|
||||
cd "$SRC"
|
||||
# Compile with PREFIX=/usr, install with the real prefix. LuaJIT bakes
|
||||
# LUA_ROOT=$(PREFIX) into its default package.path/cpath at compile time, so
|
||||
# compiling with the install prefix would leak a build-time directory
|
||||
# (/tmp/prefix, /cache/prefix-...) into the shipped library. The top-level
|
||||
# install only depends on src/luajit, so it does not recompile.
|
||||
make -j"$(nproc)" amalg PREFIX=/usr XCFLAGS=-DLUAJIT_ENABLE_GC64 >&2
|
||||
# Install into a staging root first (luajit.pc still says prefix=$PREFIX), so a
|
||||
# failed check below never leaves a half-trusted tree in $PREFIX.
|
||||
STAGE="$(mktemp -d)"
|
||||
trap 'rm -rf "$SRC_TMP" "$STAGE"' EXIT
|
||||
make install PREFIX="$PREFIX" DESTDIR="$STAGE" >&2
|
||||
mkdir -p "$STAGE$PREFIX/share/doc/luajit"
|
||||
cp COPYRIGHT "$STAGE$PREFIX/share/doc/luajit/COPYRIGHT"
|
||||
|
||||
LIB="$(readlink -f "$STAGE$PREFIX/lib/libluajit-5.1.so.2")"
|
||||
[ -f "$LIB" ] || fail "missing $STAGE$PREFIX/lib/libluajit-5.1.so.2"
|
||||
|
||||
soname="$(readelf -d "$LIB" | sed -n 's/.*SONAME.*\[\(.*\)\]/\1/p')"
|
||||
[ "$soname" = "libluajit-5.1.so.2" ] || fail "unexpected SONAME: $soname"
|
||||
if grep -aqF "$PREFIX" "$LIB"; then
|
||||
fail "library contains the build prefix '$PREFIX' (baked-in module path)"
|
||||
fi
|
||||
|
||||
# Version, module path, ELF class/arch and glibc ceiling: the same checks the
|
||||
# host-side gate runs (verify_luajit.sh needs only od, grep and awk).
|
||||
bash "$(dirname "$0")/verify_luajit.sh" "$LIB" >&2
|
||||
|
||||
# COPYRIGHT goes in last: callers treat it as the "install finished" marker, so
|
||||
# an interrupted copy never looks like a complete cached prefix.
|
||||
mv "$STAGE$PREFIX/share/doc/luajit/COPYRIGHT" "$STAGE/COPYRIGHT"
|
||||
mkdir -p "$PREFIX/share/doc/luajit"
|
||||
cp -a "$STAGE$PREFIX/." "$PREFIX/"
|
||||
cp "$STAGE/COPYRIGHT" "$PREFIX/share/doc/luajit/COPYRIGHT"
|
||||
echo "luajit ok: staged and installed to $PREFIX" >&2
|
||||
Executable
+31
@@ -0,0 +1,31 @@
|
||||
#!/usr/bin/env bash
|
||||
# Pinned LuaJIT for the aarch64 Linux builds (PortMaster zips, AppImage).
|
||||
# Source this file; it only sets variables and has no side effects.
|
||||
#
|
||||
# Why: PortMaster's LOVE 11.5 runtime ships LuaJIT 2.1.0-beta3 (2017), which
|
||||
# segfaulted 3/3 runs with the JIT on (TrimUI Brick). This pinned v2.1-branch
|
||||
# commit ran a 26-minute JIT-on soak without a crash. See docs/linux-arm-sbc.md.
|
||||
#
|
||||
# The commit's .relver is already expanded, so the built library contains the
|
||||
# string "LuaJIT 2.1.1788856981" (beta3 contains "LuaJIT 2.1.0-beta3").
|
||||
|
||||
# shellcheck disable=SC2034
|
||||
LUAJIT_COMMIT="c6ffc141a8762b41703f9287d63d93622a13dd8f"
|
||||
LUAJIT_URL="https://github.com/LuaJIT/LuaJIT/archive/$LUAJIT_COMMIT.tar.gz"
|
||||
LUAJIT_SHA256="6e5fec07750add912e7c3eae0c194d24cd6d023714e1f04a0298a5b4819e4457"
|
||||
LUAJIT_TARBALL="LuaJIT-$LUAJIT_COMMIT.tar.gz"
|
||||
LUAJIT_VERSION_STRING="LuaJIT 2.1.1788856981"
|
||||
# Built on debian:bullseye (glibc 2.31); the library must not need newer.
|
||||
# The standalone build (build_luajit.sh) pins the image by digest so a re-tag
|
||||
# cannot silently change the toolchain; the digest is part of its cache key.
|
||||
# To re-pin: `docker buildx imagetools inspect debian:bullseye` -> the top-level
|
||||
# "Digest:" line; put it here AND in the FROM line of
|
||||
# scripts/linux-arm64/Dockerfile (the selftest checks the two are equal).
|
||||
LUAJIT_BUILD_IMAGE="debian:bullseye@sha256:6f519a81440354a85eb592c5f32109ab80605f6b892455983a6f618bf87fabe9"
|
||||
LUAJIT_MAX_GLIBC="2.31"
|
||||
# apt sources for the build container (bullseye is EOL; security comes from a
|
||||
# dated snapshot). Newline-separated; must match scripts/linux-arm64/Dockerfile
|
||||
# so both LuaJIT builds see the same package state.
|
||||
LUAJIT_APT_SOURCES="deb http://archive.debian.org/debian bullseye main
|
||||
deb http://archive.debian.org/debian bullseye-updates main
|
||||
deb http://snapshot.debian.org/archive/debian-security/20260831T000000Z bullseye-security main"
|
||||
Executable
+74
@@ -0,0 +1,74 @@
|
||||
#!/usr/bin/env bash
|
||||
# Shared PortMaster zip helpers for build-linux-arm-sbc.sh and build-rg34xxsp.sh.
|
||||
# Source this file; it has no side effects at source time.
|
||||
# The caller must define ROOT, say, warn and fail.
|
||||
|
||||
# shellcheck source=scripts/luajit/pins.sh
|
||||
. "$ROOT/scripts/luajit/pins.sh"
|
||||
# shellcheck source=scripts/lib/fetch.sh
|
||||
. "$ROOT/scripts/lib/fetch.sh"
|
||||
|
||||
# shellcheck disable=SC2034
|
||||
LOVE_VERSION="${LOVE_VERSION:-11.5}"
|
||||
|
||||
# Official PortMaster LÖVE 11.5 aarch64 runtime (small love stub + liblove).
|
||||
# Pinned to the last PortMaster-GUI commit that touched runtimes/love_11.5, and
|
||||
# every file is sha256-checked. libluajit is deliberately NOT taken from
|
||||
# here: that one is LuaJIT 2.1.0-beta3 (2017), which crashes with the JIT on.
|
||||
PM_RUNTIME_COMMIT="715f50fd277febf942a66d59ac31e5a9c36c2f69"
|
||||
PM_RUNTIME_BASE="https://raw.githubusercontent.com/PortsMaster/PortMaster-GUI/$PM_RUNTIME_COMMIT/PortMaster/runtimes/love_${LOVE_VERSION}"
|
||||
PM_SHA_LOVE="c6c64453ed6163c8aeb14d303bad1e4d9ecc4d628097b3c6420ada2fa6a8690f"
|
||||
PM_SHA_LIBLOVE="a50c83729cb0e1c4d8389eaaa827f0a6e7f3362814d0504ca84074dd0e47c379"
|
||||
PM_SHA_MODPLUG="026b2287c9d68f920cf541b68b94f1a691168e4bbf301a8793f4114808aa8f95"
|
||||
PM_SHA_OGG="66015f344b53895affd3ff153f402097ebaa2add33246bea2d7fca27b682e07a"
|
||||
|
||||
# pm_fetch_runtime CACHE_DIR: download + sha256-check the 4 runtime files.
|
||||
pm_fetch_runtime() {
|
||||
local dir="$1"
|
||||
download_pinned "$PM_RUNTIME_BASE/love.aarch64" "$dir/love.aarch64" "$PM_SHA_LOVE"
|
||||
download_pinned "$PM_RUNTIME_BASE/libs.aarch64/liblove-11.5.so" "$dir/liblove-11.5.so" "$PM_SHA_LIBLOVE"
|
||||
download_pinned "$PM_RUNTIME_BASE/libs.aarch64/libmodplug.so.1" "$dir/libmodplug.so.1" "$PM_SHA_MODPLUG"
|
||||
download_pinned "$PM_RUNTIME_BASE/libs.aarch64/libogg.so.0" "$dir/libogg.so.0" "$PM_SHA_OGG"
|
||||
}
|
||||
|
||||
# pm_select_luajit: a pinned modern build, never PortMaster's beta3. Either
|
||||
# supplied via GEN1RECOMP_LUAJIT_LIB (CI release jobs) or built in a container.
|
||||
# Sets LUAJIT_LIB and LUAJIT_COPYRIGHT.
|
||||
pm_select_luajit() {
|
||||
if [ -n "${GEN1RECOMP_LUAJIT_LIB:-}" ]; then
|
||||
LUAJIT_LIB="$GEN1RECOMP_LUAJIT_LIB"
|
||||
[ -f "$LUAJIT_LIB" ] || fail "GEN1RECOMP_LUAJIT_LIB does not exist: $LUAJIT_LIB"
|
||||
LUAJIT_COPYRIGHT="$(dirname "$LUAJIT_LIB")/COPYRIGHT"
|
||||
[ -s "$LUAJIT_COPYRIGHT" ] || LUAJIT_COPYRIGHT="${GEN1RECOMP_LUAJIT_COPYRIGHT:-}"
|
||||
[ -s "$LUAJIT_COPYRIGHT" ] \
|
||||
|| fail "LuaJIT COPYRIGHT not found next to $LUAJIT_LIB; set GEN1RECOMP_LUAJIT_COPYRIGHT"
|
||||
else
|
||||
say "building pinned LuaJIT $LUAJIT_COMMIT"
|
||||
LUAJIT_LIB="$("$ROOT/scripts/luajit/build_luajit.sh")" \
|
||||
|| fail "LuaJIT build failed (needs an aarch64 host with docker/podman, or set GEN1RECOMP_LUAJIT_LIB)"
|
||||
LUAJIT_COPYRIGHT="$(dirname "$LUAJIT_LIB")/COPYRIGHT"
|
||||
fi
|
||||
[ -f "$LUAJIT_LIB" ] && [ -s "$LUAJIT_COPYRIGHT" ] || fail "LuaJIT library or COPYRIGHT missing"
|
||||
"$ROOT/scripts/luajit/verify_luajit.sh" "$LUAJIT_LIB" || fail "LuaJIT library failed verification: $LUAJIT_LIB"
|
||||
}
|
||||
|
||||
# pm_stage_luajit LIBS_DIR LICENSES_DIR
|
||||
pm_stage_luajit() {
|
||||
: "${LUAJIT_LIB:?call pm_select_luajit before pm_stage_luajit}"
|
||||
: "${LUAJIT_COPYRIGHT:?call pm_select_luajit before pm_stage_luajit}"
|
||||
cp "$LUAJIT_LIB" "$1/libluajit-5.1.so.2"
|
||||
cp "$LUAJIT_COPYRIGHT" "$2/LuaJIT-COPYRIGHT"
|
||||
}
|
||||
|
||||
# pm_verify_zip ZIP PORT_DIR_NAME WORK_DIR: verify the LuaJIT that actually
|
||||
# landed in the zip, not just the input file.
|
||||
pm_verify_zip() {
|
||||
local zip="$1" port="$2" work="$3" vdir
|
||||
vdir="$(mktemp -d "$work/verify.XXXXXX")"
|
||||
unzip -q "$zip" -d "$vdir"
|
||||
"$ROOT/scripts/luajit/verify_luajit.sh" "$vdir/$port/libs.aarch64/libluajit-5.1.so.2" \
|
||||
|| { rm -rf "$vdir"; fail "zip LuaJIT verification failed"; }
|
||||
[ -s "$vdir/$port/licenses/LuaJIT-COPYRIGHT" ] \
|
||||
|| { rm -rf "$vdir"; fail "zip is missing licenses/LuaJIT-COPYRIGHT"; }
|
||||
rm -rf "$vdir"
|
||||
}
|
||||
+97
@@ -0,0 +1,97 @@
|
||||
#!/usr/bin/env bash
|
||||
# Offline test of scripts/luajit/portmaster_runtime.sh (no docker, no network).
|
||||
# Usage: bash scripts/luajit/selftest_portmaster_runtime.sh
|
||||
# Each case runs in a subshell with a stub fail() that exits that subshell, so
|
||||
# failures can be asserted.
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
HERE="$(cd "$(dirname "$0")" && pwd)"
|
||||
ROOT="$(cd "$HERE/../.." && pwd)"
|
||||
TMP="$(mktemp -d)"
|
||||
trap 'rm -rf "$TMP"' EXIT
|
||||
|
||||
# shellcheck source=pins.sh
|
||||
. "$HERE/pins.sh"
|
||||
|
||||
say() { :; }
|
||||
warn() { :; }
|
||||
fail() { printf 'stub fail: %s\n' "$*" >&2; exit 1; }
|
||||
# shellcheck source=portmaster_runtime.sh
|
||||
. "$HERE/portmaster_runtime.sh"
|
||||
|
||||
bad() { printf 'FAIL: %s\n' "$*" >&2; exit 1; }
|
||||
# expect_ok NAME CMD... / expect_fail NAME CMD...: run CMD in a subshell.
|
||||
expect_ok() { local n="$1"; shift; ( "$@" ) >/dev/null 2>&1 || bad "$n: expected success"; }
|
||||
expect_fail() { local n="$1"; shift; if ( "$@" ) >/dev/null 2>&1; then bad "$n: expected failure"; fi; }
|
||||
|
||||
# Synthetic aarch64 "library" that passes verify_luajit.sh.
|
||||
lj_make() {
|
||||
{ printf '\177ELF\002\001'; head -c 12 /dev/zero; printf '\xb7\x00'
|
||||
printf '\0%s\0%s\0%s\0' "$LUAJIT_VERSION_STRING" '/usr/share/luajit-2.1/?.lua' GLIBC_2.17
|
||||
} > "$1"
|
||||
}
|
||||
|
||||
mkdir -p "$TMP/good" "$TMP/nocopy" "$TMP/emptycopy"
|
||||
lj_make "$TMP/good/libluajit-5.1.so.2"
|
||||
echo "LuaJIT license" > "$TMP/good/COPYRIGHT"
|
||||
lj_make "$TMP/nocopy/libluajit-5.1.so.2"
|
||||
lj_make "$TMP/emptycopy/libluajit-5.1.so.2"
|
||||
: > "$TMP/emptycopy/COPYRIGHT"
|
||||
echo "other license" > "$TMP/alt-COPYRIGHT"
|
||||
|
||||
case_stage_without_select() { unset LUAJIT_LIB LUAJIT_COPYRIGHT; pm_stage_luajit "$TMP" "$TMP"; }
|
||||
expect_fail "stage without select" case_stage_without_select
|
||||
|
||||
case_missing_lib() { GEN1RECOMP_LUAJIT_LIB="$TMP/nope.so" pm_select_luajit; }
|
||||
expect_fail "missing GEN1RECOMP_LUAJIT_LIB" case_missing_lib
|
||||
|
||||
case_empty_copyright() {
|
||||
GEN1RECOMP_LUAJIT_LIB="$TMP/emptycopy/libluajit-5.1.so.2" GEN1RECOMP_LUAJIT_COPYRIGHT= pm_select_luajit
|
||||
}
|
||||
expect_fail "empty COPYRIGHT" case_empty_copyright
|
||||
|
||||
case_no_copyright_anywhere() {
|
||||
GEN1RECOMP_LUAJIT_LIB="$TMP/nocopy/libluajit-5.1.so.2" GEN1RECOMP_LUAJIT_COPYRIGHT= pm_select_luajit
|
||||
}
|
||||
expect_fail "no COPYRIGHT anywhere" case_no_copyright_anywhere
|
||||
|
||||
# Verification is really reached: a bad library is rejected.
|
||||
printf 'not a library' > "$TMP/emptycopy/bad.so"
|
||||
echo x > "$TMP/emptycopy/COPYRIGHT"
|
||||
case_bad_lib() { GEN1RECOMP_LUAJIT_LIB="$TMP/emptycopy/bad.so" pm_select_luajit; }
|
||||
expect_fail "bad library" case_bad_lib
|
||||
|
||||
case_env_copyright() {
|
||||
export GEN1RECOMP_LUAJIT_LIB="$TMP/nocopy/libluajit-5.1.so.2"
|
||||
export GEN1RECOMP_LUAJIT_COPYRIGHT="$TMP/alt-COPYRIGHT"
|
||||
pm_select_luajit
|
||||
[ "$LUAJIT_LIB" = "$GEN1RECOMP_LUAJIT_LIB" ] || exit 1
|
||||
[ "$LUAJIT_COPYRIGHT" = "$TMP/alt-COPYRIGHT" ] || exit 1
|
||||
}
|
||||
expect_ok "COPYRIGHT via env" case_env_copyright
|
||||
|
||||
# Stage + zip round trip.
|
||||
build_tree() { # $1 = tree root
|
||||
mkdir -p "$1/port/libs.aarch64" "$1/port/licenses"
|
||||
GEN1RECOMP_LUAJIT_LIB="$TMP/good/libluajit-5.1.so.2" pm_select_luajit
|
||||
pm_stage_luajit "$1/port/libs.aarch64" "$1/port/licenses"
|
||||
}
|
||||
case_stage() {
|
||||
build_tree "$TMP/tree"
|
||||
cmp "$TMP/good/libluajit-5.1.so.2" "$TMP/tree/port/libs.aarch64/libluajit-5.1.so.2"
|
||||
cmp "$TMP/good/COPYRIGHT" "$TMP/tree/port/licenses/LuaJIT-COPYRIGHT"
|
||||
}
|
||||
expect_ok "stage copies both files" case_stage
|
||||
|
||||
command -v zip >/dev/null && command -v unzip >/dev/null || { echo "zip/unzip missing; skipping zip cases" >&2; echo "selftest_portmaster_runtime: ok (zip cases skipped)"; exit 0; }
|
||||
|
||||
( cd "$TMP/tree" && zip -q -r "$TMP/good.zip" port )
|
||||
rm "$TMP/tree/port/licenses/LuaJIT-COPYRIGHT"
|
||||
( cd "$TMP/tree" && zip -q -r "$TMP/nocopy.zip" port )
|
||||
|
||||
mkdir -p "$TMP/work"
|
||||
expect_ok "verify good zip" pm_verify_zip "$TMP/good.zip" port "$TMP/work"
|
||||
expect_fail "verify zip without COPYRIGHT" pm_verify_zip "$TMP/nocopy.zip" port "$TMP/work"
|
||||
|
||||
echo "selftest_portmaster_runtime: ok"
|
||||
Executable
+60
@@ -0,0 +1,60 @@
|
||||
#!/usr/bin/env bash
|
||||
# Host-side check of a built libluajit-5.1.so.2 (works on macOS and Linux, no
|
||||
# readelf needed). Fails if the library is not the pinned LuaJIT, is the old
|
||||
# 2.1.0-beta3, or needs a glibc newer than the pin allows.
|
||||
#
|
||||
# Usage: scripts/luajit/verify_luajit.sh <libluajit-5.1.so.2>
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
HERE="$(cd "$(dirname "$0")" && pwd)"
|
||||
# shellcheck source=pins.sh
|
||||
. "$HERE/pins.sh"
|
||||
|
||||
fail() { printf 'error: %s\n' "$*" >&2; exit 1; }
|
||||
|
||||
[ $# -eq 1 ] || fail "usage: verify_luajit.sh <libluajit-5.1.so.2>"
|
||||
LIB="$1"
|
||||
[ -f "$LIB" ] || fail "not a file: $LIB"
|
||||
|
||||
# 64-bit (byte 4 = 02), little-endian (byte 5 = 01), e_machine 0xb7 = aarch64.
|
||||
hdr="$(od -An -tx1 -N20 "$LIB" | tr -d ' \n')"
|
||||
[ "${hdr:0:8}" = "7f454c46" ] && [ "${hdr:8:2}" = "02" ] && [ "${hdr:10:2}" = "01" ] \
|
||||
&& [ "${hdr:36:4}" = "b700" ] \
|
||||
|| fail "$LIB is not a 64-bit little-endian aarch64 ELF"
|
||||
|
||||
grep -aqF "$LUAJIT_VERSION_STRING" "$LIB" \
|
||||
|| fail "$LIB does not contain '$LUAJIT_VERSION_STRING'"
|
||||
if grep -aq '2\.1\.0-beta' "$LIB"; then
|
||||
fail "$LIB contains '2.1.0-beta' (old LuaJIT)"
|
||||
fi
|
||||
|
||||
# Built with PREFIX=/usr; a build-prefix path here means a stale or wrong build.
|
||||
grep -aqF '/usr/share/luajit-2.1/?.lua' "$LIB" \
|
||||
|| fail "$LIB does not contain the default module path /usr/share/luajit-2.1/?.lua"
|
||||
|
||||
# Compare dotted versions numerically without relying on sort -V.
|
||||
ver_gt() {
|
||||
awk -v a="$1" -v b="$2" 'BEGIN {
|
||||
na = split(a, x, "."); nb = split(b, y, ".")
|
||||
n = na > nb ? na : nb
|
||||
for (i = 1; i <= n; i++) {
|
||||
if ((x[i] + 0) > (y[i] + 0)) exit 0
|
||||
if ((x[i] + 0) < (y[i] + 0)) exit 1
|
||||
}
|
||||
exit 1
|
||||
}'
|
||||
}
|
||||
|
||||
maxg=""
|
||||
while IFS= read -r v; do
|
||||
v="${v#GLIBC_}"
|
||||
[ -n "$v" ] || continue
|
||||
if [ -z "$maxg" ] || ver_gt "$v" "$maxg"; then maxg="$v"; fi
|
||||
done < <(grep -ao 'GLIBC_[0-9][0-9.]*' "$LIB" | sort -u)
|
||||
|
||||
[ -n "$maxg" ] || fail "$LIB has no GLIBC_ version strings"
|
||||
if ver_gt "$maxg" "$LUAJIT_MAX_GLIBC"; then
|
||||
fail "$LIB requires GLIBC_$maxg > $LUAJIT_MAX_GLIBC"
|
||||
fi
|
||||
echo "verify_luajit ok: '$LUAJIT_VERSION_STRING', max GLIBC=$maxg (limit $LUAJIT_MAX_GLIBC)" >&2
|
||||
Reference in New Issue
Block a user