build: add one-click Windows -> WSL ELF build scripts

Two scripts, so building for PS5 is one command:

  /usr/bin/bash .build/build-win.sh

build-win.sh (Windows side, Git Bash)
  Just pipes the WSL script into wsl.exe via stdin and propagates the
  exit code. Uses `wsl.exe -- bash < script` rather than `-- bash -c '...'`
  because the repo path contains spaces and -c's argument gets split.
  Copies the WSL script over first (.build/ is excluded from rsync so
  the WSL side may not have it yet).

build-elf-wsl.sh (WSL side)
  5 stages, each failing loudly:
    1. env check   -- SDK present, prospero-clang runnable,
                      libmicrohttpd in the sysroot
    2. rsync       -- Windows repo -> /home/song/ps5-web-file-manager,
                      incremental, skipping ps5-obj/ gen/ tests/ docs/,
                      then a smoke check that this session's key files
                      landed (sevenz_*.c, zipx_common.c, Makefile, ...)
    3. make all
    4. verify      -- size / sha256 / e_machine, with an explicit
                      aarch64 guard (183) since PS5 is x86-64 (62)
    5. copy back   -- ELF -> Windows project root

make's exit status is read through PIPESTATUS (the `| tail -120`
would otherwise swallow it), so a failed compile actually fails the
script instead of sailing on to the verify stage.

One gotcha worth recording: `od -An -tx2 -j 18 -N 2` prints the
2-byte little-endian *value*, so the on-disk bytes "3e 00" come out
as "003e", not "3e00". Matching on the byte order fails; convert with
$((16#$EM)) and compare numerically (62 = x86-64, 183 = aarch64).

Verified end to end: 1017864 bytes, sha256 2eb04581...473a157,
e_machine 0x003e (62), copied back to the Windows project root.
This commit is contained in:
Songlx516 committed 2026-09-15 13:15:10 +08:00
1 parent 98679423e0
commit a54f34bcab
2 files changed
+170

No files matched your search

+120
View File
@@ -0,0 +1,120 @@
#!/usr/bin/env bash
# ===========================================================================
# ps5-web-file-manager -- 一键在 WSL 里生成 PS5 ELF
#
# 这个脚本在 WSL (Ubuntu-22.04) 里执行,做四件事:
# 1. 把 Windows 仓库的源码 rsync 到 WSL 项目目录(增量,跳过构建缓存)
# 2. make all (PS5_PAYLOAD_SDK = /opt/ps5-payload-sdk)
# 3. 验证产物:size / sha256 / e_machine
# 4. 把 ELF 拷回 Windows 项目根
#
# 从 Windows 的 Git Bash / MinGW64 bash 里这样跑:
# wsl.exe -d Ubuntu-22.04 -- bash < \
# "/c/Users/songl/Desktop/Web File Manager/ps5-web-file-manager/.build/build-elf-wsl.sh"
#
# 注意:必须用 stdin 重定向 `bash < script`,不要 `bash -c '...'` ——
# 路径含空格时 -c 的参数会被 wsl.exe 拆断。
# ===========================================================================
set -uo pipefail
# ---------------------------------------------------------------- 配置 -----
SRC_WIN='/mnt/c/Users/songl/Desktop/Web File Manager/ps5-web-file-manager'
PROJ='/home/song/ps5-web-file-manager'
SDK='/opt/ps5-payload-sdk'
ELF="$PROJ/web-file-mgr.elf"
log() { printf '\033[1;36m%s\033[0m\n' "$*"; }
fail() { printf '\033[1;31m[FAIL] %s\033[0m\n' "$*"; exit 1; }
# ------------------------------------------------------- 1/5 环境检查 -----
log "[1/5] 环境检查"
[ -d "$SRC_WIN" ] || fail "Windows 源码目录不可见: $SRC_WIN (/mnt/c 挂载了吗?)"
[ -x "$SDK/bin/prospero-clang" ] || fail "SDK 缺失: $SDK/bin/prospero-clang"
export PS5_PAYLOAD_SDK="$SDK"
# shellcheck disable=SC1091
source "$SDK/toolchain/prospero.sh" 2>/dev/null || true
export CC="$SDK/bin/prospero-clang"
export CXX="$SDK/bin/prospero-clang++"
export PKG_CONFIG="$SDK/bin/prospero-pkg-config"
"$CC" --version | head -1
"$PKG_CONFIG" --modversion libmicrohttpd 2>/dev/null \
|| fail "libmicrohttpd 未装到 sysroot —— 先跑一次完整的 build-elf.sh v4"
echo
# ------------------------------------------------------- 2/5 同步源码 -----
log "[2/5] 同步源码 Windows -> WSL (rsync 增量)"
mkdir -p "$PROJ"
rsync -a --delete \
--exclude='/ps5-obj' --exclude='/linux-obj' \
--exclude='/web-file-mgr.elf' --exclude='/web-file-mgr-linux' \
--exclude='/gen' --exclude='/.build' --exclude='/tests' \
--exclude='/docs' --exclude='/HANDOVER.md' \
--exclude='/README.md' --exclude='/CHANGELOG.md' \
--exclude='/erssongl*' \
--include='/src' --include='/assets' \
--include='/third_party' --include='/Makefile' \
--include='/gen-asset-module.py' --include='/.gitignore' \
--exclude='/*' \
"$SRC_WIN/" "$PROJ/" || fail "rsync 失败"
# rsync 的 --include 只放行目录本身,这几个顶层文件再单独 cp 一次
for f in Makefile gen-asset-module.py .gitignore; do
[ -f "$SRC_WIN/$f" ] && cp -f "$SRC_WIN/$f" "$PROJ/$f"
done
# 冒烟:今天的关键文件都在不在
for f in src/sevenz_extract.c src/zipx_common.c src/sevenz_volstream.c \
src/sevenz_chain.c Makefile gen-asset-module.py; do
[ -f "$PROJ/$f" ] || fail "同步后缺失: $PROJ/$f"
done
[ -d "$PROJ/third_party/7z" ] || fail "同步后缺失: $PROJ/third_party/7z"
echo " src/ + assets/ + third_party/ + Makefile OK"
echo
# ---------------------------------------------------------- 3/5 编译 ------
log "[3/5] make all"
cd "$PROJ" || fail "cd $PROJ"
make all 2>&1 | tail -120
# make 的退出码被管道吃了,用 PIPESTATUS 取回来
if [ "${PIPESTATUS[0]}" -ne 0 ]; then
fail "make all 失败(详见上方输出)"
fi
echo
# ---------------------------------------------------------- 4/5 验证 ------
log "[4/5] 验证产物"
[ -f "$ELF" ] || fail "ELF 未生成: $ELF"
SIZE=$(stat -c%s "$ELF")
HASH=$(sha256sum "$ELF" | cut -d' ' -f1)
# ELF header: offset 18 起 2 字节 = e_machine。
# `od -tx2` 按 2 字节小端解释成一个 short 后打印其**值**,所以文件里的
# 字节序 "3e 00" 会输出成 "003e"(不是 "3e00")。别拿字节序去比对。
EM=$(od -An -tx2 -j 18 -N 2 "$ELF" | tr -d ' \n')
EM_NUM=$((16#$EM))
ls -lh "$ELF"
echo " size: $SIZE bytes (~$((SIZE / 1024)) KiB)"
echo " sha256: $HASH"
echo " e_machine = 0x$EM ($EM_NUM)"
case "$EM_NUM" in
62) echo " -> x86-64 / PS5 [OK]" ;;
183) fail "e_machine=$EM_NUM (0x$EM) 是 aarch64!PS5 是 x86-64,target 三元组错了" ;;
*) fail "e_machine=$EM_NUM (0x$EM) 非预期(期望 62 = 0x003e = x86-64)" ;;
esac
echo
# ------------------------------------------------- 5/5 拷回 Windows -------
log "[5/5] 拷回 Windows"
cp -f "$ELF" "$SRC_WIN/web-file-mgr.elf" || fail "拷回 Windows 失败"
ls -lh "$SRC_WIN/web-file-mgr.elf"
echo
printf '\033[1;32m[DONE]\033[0m %s\n' "$SRC_WIN/web-file-mgr.elf"
echo " $SIZE bytes / sha256 $HASH / e_machine 0x$EM"
+50
View File
@@ -0,0 +1,50 @@
#!/usr/bin/env bash
# ===========================================================================
# ps5-web-file-manager -- Windows 端一键构建入口
#
# 在 Windows 的 Git Bash / MinGW64 bash 里这样跑(注意用 /usr/bin/bash):
# /usr/bin/bash .build/build-win.sh
#
# 它只做一件事:把 WSL 脚本喂给 wsl.exe 执行,然后透传退出码。
# 真正的 sync / make / verify / 拷回都在 .build/build-elf-wsl.sh 里。
#
# 注意:
# * 用 `bash < script` 走 stdin,不要用 `bash -c '...'` ——
# 路径含空格时 -c 的参数会被 wsl.exe 拆断。
# * 别写裸 `bash .build/build-win.sh`,那个 bash 可能解析到
# C:\Windows\System32\bash.exe(WSL 启动器),脚本会跑进 Linux 环境。
# ===========================================================================
set -uo pipefail
REPO='/c/Users/songl/Desktop/Web File Manager/ps5-web-file-manager'
WSL_DISTRO='Ubuntu-22.04'
WSL_DIR='/home/song/ps5-web-file-manager/.build'
HOST_SCRIPT="$REPO/.build/build-elf-wsl.sh"
[ -f "$HOST_SCRIPT" ] || { echo "[FAIL] 找不到 $HOST_SCRIPT"; exit 1; }
# 先把 WSL 脚本推进去(.build/ 被 rsync 排除,WSL 侧可能没有)
if ! wsl.exe -d "$WSL_DISTRO" -- test -f "$WSL_DIR/build-elf-wsl.sh" 2>/dev/null; then
echo "[setup] WSL 侧缺少脚本,拷贝中..."
wsl.exe -d "$WSL_DISTRO" -- mkdir -p "$WSL_DIR" || exit 1
wsl.exe -d "$WSL_DISTRO" -- cp \
'/mnt/c/Users/songl/Desktop/Web File Manager/ps5-web-file-manager/.build/build-elf-wsl.sh' \
"$WSL_DIR/build-elf-wsl.sh" || {
echo "[FAIL] 无法写入 WSL 文件系统"
exit 1
}
fi
echo "[run] wsl.exe -d $WSL_DISTRO -- bash < build-elf-wsl.sh"
echo "=================================================================="
wsl.exe -d "$WSL_DISTRO" -- bash < "$HOST_SCRIPT"
rc=$?
echo "=================================================================="
if [ "$rc" -eq 0 ]; then
echo "[OK] 构建完成 -> $REPO/web-file-mgr.elf"
else
echo "[FAIL] 构建失败 (exit=$rc)"
fi
exit "$rc"