From cd4a2aced6edb24c6370fbdf095f12be24af39a2 Mon Sep 17 00:00:00 2001 From: Shokunin <30949000+tetrisgm@users.noreply.github.com> Date: Wed, 30 Sep 2026 20:18:18 -0700 Subject: [PATCH] release: ship recomp-ui's license and asset notices in bundled zips A bundled release links recomp-ui (MIT) into the executable and copies its fonts and images into assets/ (OpenMoji CC BY-SA 4.0; Noto Sans Symbols 2, Lato and the Noto Color Emoji flag sheet, OFL-1.1), but package_game_release.sh staged only psxrecomp's own notices. The setup-host zips carried the whole recomp-ui tree, so the move to bundled releases dropped recomp-ui/LICENSE and assets/common/{fonts,img}/NOTICE.md from every title's release. The packager now stages recomp-ui's LICENSE as licenses/recomp-ui-LICENSE and its fonts/img NOTICE.md beside the files they cover, from the tree the build linked (RECOMP_UI_ROOT in the build's CMakeCache, else /recomp-ui), unless the build turned PSX_RECOMP_UI off. A title cannot do this itself with --runtime-file (the path would keep recomp-ui/, which the kit gate rejects) or --doc (staged by basename, so LICENSE would overwrite the title's own). Not covered: the TinyCC LGPL-2.1 notice for the Windows overlay_toolchain/tcc (THIRD_PARTY_ATTRIBUTION.md says it must ship with it). Co-Authored-By: Claude Opus 5.5 --- docs/ci/BUNDLED_RELEASES.md | 6 ++++-- tools/package_game_release.sh | 18 ++++++++++++++++++ tools/tests/test_bundled_release_layout.py | 9 +++++++++ 3 files changed, 31 insertions(+), 2 deletions(-) diff --git a/docs/ci/BUNDLED_RELEASES.md b/docs/ci/BUNDLED_RELEASES.md index a3193647..795769ca 100644 --- a/docs/ci/BUNDLED_RELEASES.md +++ b/docs/ci/BUNDLED_RELEASES.md @@ -45,8 +45,10 @@ Template: [`templates/game-release.yml`](templates/game-release.yml). executable, `assets/`, `bios/openbios.bin` + notice, `game.toml`, `game_options.toml`, the mod catalog (verified against the manifest the build published, developer-channel packages pruned), `overlay_toolchain/`, - third-party notices; refuse if anything kit-shaped is in the stage; sign on - Windows; zip. + third-party notices (psxrecomp's in `licenses/`, plus recomp-ui's license + as `licenses/recomp-ui-LICENSE` and its font/image notices as + `assets/{fonts,img}/NOTICE.md`); refuse if anything kit-shaped is in the + stage; sign on Windows; zip. 6. Verify the zip: executable + OpenBIOS + catalog present; no `psxrecomp/`, `recomp-ui/`, CLI, emitters at the root, sources, generated C, dumps, per-machine mod state. diff --git a/tools/package_game_release.sh b/tools/package_game_release.sh index 4324e95e..733fd6ca 100755 --- a/tools/package_game_release.sh +++ b/tools/package_game_release.sh @@ -377,6 +377,24 @@ if [[ -d "${FRAMEWORK}/runtime/licenses" ]]; then fi [[ -f "${FRAMEWORK}/THIRD_PARTY_ATTRIBUTION.md" ]] && cp -a "${FRAMEWORK}/THIRD_PARTY_ATTRIBUTION.md" "${STAGE}/licenses/" [[ -f "${FRAMEWORK}/LICENSE" ]] && cp -a "${FRAMEWORK}/LICENSE" "${STAGE}/licenses/psxrecomp-LICENSE" +# recomp-ui: the executable links it (MIT) and assets/ carries its fonts and +# images (OFL-1.1, CC BY-SA 4.0), so its license and asset notices ship too. +# The build's RECOMP_UI_ROOT says which tree it linked; /recomp-ui is the +# New Project Layout default. +if ! grep -qs '^PSX_RECOMP_UI:BOOL=OFF' "${BUILD_DIR}/CMakeCache.txt"; then + UI_ROOT="$(sed -n 's/^RECOMP_UI_ROOT:[A-Z]*=//p' "${BUILD_DIR}/CMakeCache.txt" 2>/dev/null | head -n1 || true)" + [[ -n "${UI_ROOT}" && -f "${UI_ROOT}/recomp_ui.cmake" ]] || UI_ROOT="${ROOT}/recomp-ui" + if [[ -f "${UI_ROOT}/recomp_ui.cmake" ]]; then + [[ -f "${UI_ROOT}/LICENSE" ]] || { echo "error: ${UI_ROOT}/LICENSE missing" >&2; exit 1; } + cp -a "${UI_ROOT}/LICENSE" "${STAGE}/licenses/recomp-ui-LICENSE" + for sub in fonts img; do + notice="${UI_ROOT}/assets/common/${sub}/NOTICE.md" + if [[ -f "${notice}" && -d "${STAGE}/assets/${sub}" ]]; then + cp -a "${notice}" "${STAGE}/assets/${sub}/NOTICE.md" + fi + done + fi +fi if [[ -z "$(ls -A "${STAGE}/licenses" 2>/dev/null)" ]]; then echo "error: no third-party notices staged (${FRAMEWORK}/runtime/licenses empty?)" >&2 exit 1 diff --git a/tools/tests/test_bundled_release_layout.py b/tools/tests/test_bundled_release_layout.py index 84bef96a..b42c1b2c 100644 --- a/tools/tests/test_bundled_release_layout.py +++ b/tools/tests/test_bundled_release_layout.py @@ -309,6 +309,15 @@ class PackagerScriptContract(unittest.TestCase): self.assertNotIn("--project-file", text) self.assertNotIn("--project-dir", text) + def test_bundled_packager_ships_recomp_ui_notices(self): + # The executable links recomp-ui and assets/ carries its fonts and + # images; their license and notices must ship with them. + text = (FW / "tools" / "package_game_release.sh").read_text(encoding="utf-8") + self.assertIn('"${STAGE}/licenses/recomp-ui-LICENSE"', text) + self.assertIn('assets/common/${sub}/NOTICE.md', text) + self.assertIn('"${STAGE}/assets/${sub}/NOTICE.md"', text) + self.assertIn("RECOMP_UI_ROOT", text, "must follow the tree the build linked") + def test_scripts_are_executable_and_parse(self): for rel in ("tools/package_game_release.sh", "tools/ci/check_generated.sh"): p = FW / rel