mirror of
https://github.com/RetroPortingToolKit/psxrecomp
synced 2026-10-25 18:05:12 -04:00
@@ -13,6 +13,22 @@ Normal runtime builds stage it automatically so players supply only a disc;
|
||||
`bios/OpenBIOS.LICENSE` always rides alongside the shipped image.
|
||||
|
||||
|
||||
## libchdr — CHD disc-image decompressor
|
||||
|
||||
[libchdr](https://github.com/rtissera/libchdr) by Romain Tisserand and
|
||||
contributors, licensed **BSD-3-Clause** (notice: `LICENSE.txt` inside the
|
||||
archive). Vendored as the pinned source archive
|
||||
`third_party/libchdr-<commit>.tar.gz`; the commit, digest, and upstream URL are
|
||||
recorded in `third_party/deps.manifest`, and `runtime/chd_dependency.cmake`
|
||||
verifies the archive against that digest before building it. It is compiled
|
||||
into the runtime as a static library, so the BSD notice must ship with any
|
||||
binary that links it.
|
||||
|
||||
The archive also carries libchdr's own bundled decompressors — Zstandard
|
||||
(BSD-3-Clause / GPL-2.0 dual), LZMA SDK (public domain), and miniz (MIT) —
|
||||
built from the same pinned tree; `WITH_SYSTEM_ZLIB`/`WITH_SYSTEM_ZSTD` are
|
||||
forced OFF so the disc decoder cannot change with the host's packages.
|
||||
|
||||
## TinyCC (TCC) — toolchain-free overlay compiler shipped to players
|
||||
|
||||
[TinyCC](https://bellard.org/tcc/) by Fabrice Bellard and contributors, licensed
|
||||
|
||||
@@ -0,0 +1,166 @@
|
||||
include_guard(GLOBAL)
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Offline-capable resolution of the FetchContent dependencies this tree pulls.
|
||||
#
|
||||
# A shipped game is configured and built on the *player's* machine, and that
|
||||
# machine frequently cannot reach github.com: corporate proxy, TLS-inspecting
|
||||
# firewall, or no network at all. A dependency fetched unconditionally turns
|
||||
# that into a failed setup with a CMake stack trace nobody can act on, so every
|
||||
# URL dependency here resolves in three steps:
|
||||
#
|
||||
# 1. a pre-extracted source tree — FETCHCONTENT_SOURCE_DIR_<NAME>, or the
|
||||
# dependency's documented env override — and nothing is downloaded;
|
||||
# 2. a vendored archive in third_party/, verified against the same SHA256 the
|
||||
# upstream pin carries;
|
||||
# 3. the upstream URL.
|
||||
#
|
||||
# third_party/deps.manifest is THE pin record. Both this file and
|
||||
# tools/ci/vendor_deps.sh read it, so a vendored archive cannot drift from the
|
||||
# URL/hash the build would otherwise have downloaded.
|
||||
#
|
||||
# -DPSX_DEPS_OFFLINE=ON (or PSX_DEPS_OFFLINE=1 in the environment) turns step 3
|
||||
# into a hard error that names the missing archive, instead of a download that
|
||||
# stalls behind a firewall and then fails deep inside a FetchContent subbuild
|
||||
# where the real cause is three stack frames up.
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
if(NOT DEFINED PSX_THIRD_PARTY_DIR)
|
||||
get_filename_component(_psx_third_party_default
|
||||
"${CMAKE_CURRENT_LIST_DIR}/../third_party" ABSOLUTE)
|
||||
set(PSX_THIRD_PARTY_DIR "${_psx_third_party_default}" CACHE PATH
|
||||
"Directory holding vendored dependency archives (third_party/)")
|
||||
unset(_psx_third_party_default)
|
||||
endif()
|
||||
|
||||
set(_psx_deps_offline_default OFF)
|
||||
if(NOT "$ENV{PSX_DEPS_OFFLINE}" STREQUAL "" AND
|
||||
NOT "$ENV{PSX_DEPS_OFFLINE}" STREQUAL "0")
|
||||
set(_psx_deps_offline_default ON)
|
||||
endif()
|
||||
set(PSX_DEPS_OFFLINE "${_psx_deps_offline_default}" CACHE BOOL
|
||||
"Never download a dependency: require a vendored archive or a pre-extracted source tree")
|
||||
unset(_psx_deps_offline_default)
|
||||
|
||||
# Look up one row of third_party/deps.manifest.
|
||||
function(_psx_dependency_pin name out_file out_sha out_url)
|
||||
set(_manifest "${PSX_THIRD_PARTY_DIR}/deps.manifest")
|
||||
if(NOT EXISTS "${_manifest}")
|
||||
message(FATAL_ERROR
|
||||
"psxrecomp: dependency manifest not found: ${_manifest}\n"
|
||||
" Point -DPSX_THIRD_PARTY_DIR=… at the framework's third_party/ "
|
||||
"directory.")
|
||||
endif()
|
||||
file(STRINGS "${_manifest}" _lines)
|
||||
foreach(_line IN LISTS _lines)
|
||||
string(STRIP "${_line}" _line)
|
||||
if(_line STREQUAL "" OR _line MATCHES "^#")
|
||||
continue()
|
||||
endif()
|
||||
string(REGEX MATCHALL "[^ \t]+" _fields "${_line}")
|
||||
list(LENGTH _fields _field_count)
|
||||
if(NOT _field_count EQUAL 4)
|
||||
message(FATAL_ERROR
|
||||
"psxrecomp: malformed row in ${_manifest} "
|
||||
"(want 'name file sha256 url'): ${_line}")
|
||||
endif()
|
||||
list(GET _fields 0 _row_name)
|
||||
if(_row_name STREQUAL "${name}")
|
||||
list(GET _fields 1 _row_file)
|
||||
list(GET _fields 2 _row_sha)
|
||||
list(GET _fields 3 _row_url)
|
||||
set(${out_file} "${_row_file}" PARENT_SCOPE)
|
||||
set(${out_sha} "${_row_sha}" PARENT_SCOPE)
|
||||
set(${out_url} "${_row_url}" PARENT_SCOPE)
|
||||
return()
|
||||
endif()
|
||||
endforeach()
|
||||
message(FATAL_ERROR "psxrecomp: no '${name}' row in ${_manifest}")
|
||||
endfunction()
|
||||
|
||||
# psxrecomp_dependency_archive(<name> OUT_URL <var> OUT_HASH <var>
|
||||
# [SOURCE_DIR <dir>])
|
||||
#
|
||||
# Sets OUT_URL to the vendored archive when third_party/ holds it, else to the
|
||||
# upstream URL (fatal under PSX_DEPS_OFFLINE). OUT_HASH is the URL_HASH string
|
||||
# for FetchContent_Declare and is the same either way — a vendored archive is
|
||||
# verified exactly as strictly as a downloaded one.
|
||||
#
|
||||
# Pass the result of psxrecomp_dependency_source_dir() as SOURCE_DIR. When it is
|
||||
# non-empty FetchContent uses that tree and ignores the URL, so the declaration
|
||||
# still needs to be well-formed but reports nothing about a download that will
|
||||
# not happen.
|
||||
function(psxrecomp_dependency_archive name)
|
||||
cmake_parse_arguments(_psx_dep "" "OUT_URL;OUT_HASH;SOURCE_DIR" "" ${ARGN})
|
||||
if(NOT _psx_dep_OUT_URL OR NOT _psx_dep_OUT_HASH)
|
||||
message(FATAL_ERROR
|
||||
"psxrecomp_dependency_archive(${name}): OUT_URL and OUT_HASH are required")
|
||||
endif()
|
||||
set(_psx_dep_SILENT OFF)
|
||||
if(NOT "${_psx_dep_SOURCE_DIR}" STREQUAL "")
|
||||
set(_psx_dep_SILENT ON)
|
||||
endif()
|
||||
|
||||
_psx_dependency_pin("${name}" _file _sha _url)
|
||||
set(${_psx_dep_OUT_HASH} "SHA256=${_sha}" PARENT_SCOPE)
|
||||
|
||||
set(_vendored "${PSX_THIRD_PARTY_DIR}/${_file}")
|
||||
if(EXISTS "${_vendored}")
|
||||
if(NOT _psx_dep_SILENT)
|
||||
message(STATUS
|
||||
"psxrecomp: ${name} from vendored archive third_party/${_file}")
|
||||
endif()
|
||||
set(${_psx_dep_OUT_URL} "${_vendored}" PARENT_SCOPE)
|
||||
return()
|
||||
endif()
|
||||
|
||||
string(TOUPPER "${name}" _uc_name)
|
||||
if(PSX_DEPS_OFFLINE)
|
||||
message(FATAL_ERROR
|
||||
"psxrecomp: PSX_DEPS_OFFLINE is ON but ${name} is not vendored.\n"
|
||||
" expected archive: ${_vendored}\n"
|
||||
" stage it with: tools/ci/vendor_deps.sh ${name}\n"
|
||||
" or point the build at an already-extracted tree with "
|
||||
"-DFETCHCONTENT_SOURCE_DIR_${_uc_name}=<dir>")
|
||||
endif()
|
||||
|
||||
if(NOT _psx_dep_SILENT)
|
||||
message(STATUS
|
||||
"psxrecomp: ${name} not vendored — will download ${_url} "
|
||||
"(tools/ci/vendor_deps.sh ${name} makes this build offline-capable)")
|
||||
endif()
|
||||
set(${_psx_dep_OUT_URL} "${_url}" PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
# psxrecomp_dependency_source_dir(<name> OUT <var> [ENV <var>] [MARKER <file>])
|
||||
#
|
||||
# Honours an already-extracted source tree, from -DFETCHCONTENT_SOURCE_DIR_<NAME>
|
||||
# or from the named environment variable (which is promoted into the cache var so
|
||||
# FetchContent picks it up). OUT is set to the directory, or "" when none applies.
|
||||
function(psxrecomp_dependency_source_dir name)
|
||||
cmake_parse_arguments(_psx_src "" "OUT;ENV;MARKER" "" ${ARGN})
|
||||
if(NOT _psx_src_OUT)
|
||||
message(FATAL_ERROR
|
||||
"psxrecomp_dependency_source_dir(${name}): OUT is required")
|
||||
endif()
|
||||
if(NOT _psx_src_MARKER)
|
||||
set(_psx_src_MARKER "CMakeLists.txt")
|
||||
endif()
|
||||
|
||||
string(TOUPPER "${name}" _uc_name)
|
||||
set(_dir "")
|
||||
if(NOT "${FETCHCONTENT_SOURCE_DIR_${_uc_name}}" STREQUAL "" AND
|
||||
EXISTS "${FETCHCONTENT_SOURCE_DIR_${_uc_name}}/${_psx_src_MARKER}")
|
||||
set(_dir "${FETCHCONTENT_SOURCE_DIR_${_uc_name}}")
|
||||
elseif(_psx_src_ENV AND NOT "$ENV{${_psx_src_ENV}}" STREQUAL "" AND
|
||||
EXISTS "$ENV{${_psx_src_ENV}}/${_psx_src_MARKER}")
|
||||
set(_dir "$ENV{${_psx_src_ENV}}")
|
||||
set(FETCHCONTENT_SOURCE_DIR_${_uc_name} "${_dir}" CACHE PATH
|
||||
"Pre-fetched ${name} source (skip download)" FORCE)
|
||||
endif()
|
||||
|
||||
if(_dir)
|
||||
message(STATUS "psxrecomp: using pre-fetched ${name} source ${_dir}")
|
||||
endif()
|
||||
set(${_psx_src_OUT} "${_dir}" PARENT_SCOPE)
|
||||
endfunction()
|
||||
@@ -153,6 +153,8 @@ On Windows with MSVC or plain MinGW makefiles, swap `-G Ninja` for your generato
|
||||
| `PSX_DEBUG_TOOLS` | ON for Debug/RelWithDebInfo, OFF for Release | TCP debug server + heartbeat + per-block recording |
|
||||
| `PSX_SDL_BACKEND` | `SDL3` | Host backend. Set `SDL2` explicitly for compatibility or A/B testing. |
|
||||
| `PSX_SDL3_FETCH` | ON | Fetch the pinned SDL3 release when a compatible system SDL3 package is unavailable. Set OFF for offline/system-only builds. |
|
||||
| `PSX_DEPS_OFFLINE` | OFF (env `PSX_DEPS_OFFLINE=1` flips it) | Never download a dependency. A dependency that is not vendored in `third_party/` and has no pre-extracted source tree becomes a hard error naming the missing archive, instead of a fetch that stalls behind a proxy. |
|
||||
| `PSX_THIRD_PARTY_DIR` | `<framework>/third_party` | Where vendored dependency archives are looked up (`deps.manifest` lives there). |
|
||||
| `PSX_STATIC_RUNTIME` | ON for MinGW Release | Self-contained exe (statically links SDL + libgcc/libstdc++) |
|
||||
| `PSX_RECOMP_UI` | ON | Wire a downstream game's pinned recomp-ui launcher; set OFF for headless/generated builds |
|
||||
| `PSX_ENABLE_VULKAN` | **ON** | Build the experimental Vulkan renderer when the SDK tools are present (skipped if not). Pass `OFF` to exclude it outright. |
|
||||
@@ -232,6 +234,27 @@ these files without it). If you hit this on a framework source file, please open
|
||||
an issue with your `gcc -v` / `as --version` — the build should apply the flag
|
||||
for you.
|
||||
|
||||
**`Build step for psx_libchdr failed: 1`, or any `FetchContent` populate
|
||||
failure.** The build could not download a pinned dependency archive — no
|
||||
network, a corporate proxy, or a TLS-inspecting firewall between you and
|
||||
github.com. libchdr is the first dependency the runtime resolves, so it is
|
||||
usually the one that reports the problem.
|
||||
|
||||
The pinned libchdr archive is vendored at `third_party/`, so an up-to-date
|
||||
framework checkout does not download it at all. If you are on an older
|
||||
checkout, or you need SDL3/zlib offline too, stage them once from a machine
|
||||
with access and copy `third_party/` across:
|
||||
|
||||
```sh
|
||||
psxrecomp/tools/ci/vendor_deps.sh # stage every pinned archive
|
||||
psxrecomp/tools/ci/vendor_deps.sh --check # verify; never downloads
|
||||
```
|
||||
|
||||
Then configure with `-DPSX_DEPS_OFFLINE=ON` so any remaining download attempt
|
||||
fails immediately with the name of the archive to stage, rather than deep
|
||||
inside a FetchContent subbuild. An already-extracted tree works too:
|
||||
`-DFETCHCONTENT_SOURCE_DIR_PSX_LIBCHDR=<dir>`.
|
||||
|
||||
**`SDL3 3.4+ was not found`.** The default build normally downloads the pinned
|
||||
release. Check network access, install a system SDL3 package and provide
|
||||
`SDL3_DIR`, or re-enable `-DPSX_SDL3_FETCH=ON`.
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
include_guard(GLOBAL)
|
||||
|
||||
include(FetchContent)
|
||||
include("${CMAKE_CURRENT_LIST_DIR}/../cmake/psx_dependency_archive.cmake")
|
||||
|
||||
# libchdr is the small, BSD-licensed decompressor used by MAME-compatible CHD
|
||||
# images. Pin the exact source archive (and its digest) so generated games do
|
||||
@@ -21,10 +22,26 @@ if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.24)
|
||||
DOWNLOAD_EXTRACT_TIMESTAMP TRUE)
|
||||
endif()
|
||||
|
||||
# This include is unconditional — there is no find_package path and no
|
||||
# toolchain pack that ships libchdr — so a player building a released game with
|
||||
# no route to github.com used to fail here, in a FetchContent subbuild, with no
|
||||
# usable diagnosis. The pinned archive is vendored at third_party/ for exactly
|
||||
# that reason; the upstream URL stays as the fallback for a stripped checkout.
|
||||
psxrecomp_dependency_source_dir(psx_libchdr
|
||||
ENV PSX_LIBCHDR_SOURCE_DIR
|
||||
OUT _psx_libchdr_src)
|
||||
psxrecomp_dependency_archive(psx_libchdr
|
||||
SOURCE_DIR "${_psx_libchdr_src}"
|
||||
OUT_URL _psx_libchdr_url OUT_HASH _psx_libchdr_hash)
|
||||
|
||||
FetchContent_Declare(psx_libchdr
|
||||
URL
|
||||
"https://github.com/rtissera/libchdr/archive/6cde5348eb118da3baf94f75a69577a005a484fd.tar.gz"
|
||||
"${_psx_libchdr_url}"
|
||||
URL_HASH
|
||||
"SHA256=a222b1f1c842f988c2aad51e5f56ba94a423ed87ccab71f1abdb757caa7444f5"
|
||||
"${_psx_libchdr_hash}"
|
||||
${_psx_libchdr_timestamp_args})
|
||||
FetchContent_MakeAvailable(psx_libchdr)
|
||||
|
||||
unset(_psx_libchdr_src)
|
||||
unset(_psx_libchdr_url)
|
||||
unset(_psx_libchdr_hash)
|
||||
|
||||
+21
-20
@@ -8,6 +8,7 @@ if(NOT DEFINED PSXRECOMP_ROOT)
|
||||
get_filename_component(PSXRECOMP_ROOT "${CMAKE_CURRENT_LIST_DIR}/.." ABSOLUTE)
|
||||
endif()
|
||||
|
||||
include("${PSXRECOMP_ROOT}/cmake/psx_dependency_archive.cmake")
|
||||
include("${PSXRECOMP_ROOT}/runtime/chd_dependency.cmake")
|
||||
|
||||
# Default to an optimized build. The recompiled game is a huge (~270 MB) block of
|
||||
@@ -166,30 +167,24 @@ if(_psx_sdl_backend STREQUAL "SDL3")
|
||||
# CI (tools/ci/prefetch_sdl3.sh) pre-extracts with curl --http1.1 to
|
||||
# avoid intermittent GitHub HTTP/2 REFUSED_STREAM failures from
|
||||
# CMake's file(DOWNLOAD). Prefer that tree when present.
|
||||
set(_psx_sdl3_src "")
|
||||
if(DEFINED FETCHCONTENT_SOURCE_DIR_SDL3 AND
|
||||
NOT FETCHCONTENT_SOURCE_DIR_SDL3 STREQUAL "" AND
|
||||
EXISTS "${FETCHCONTENT_SOURCE_DIR_SDL3}/CMakeLists.txt")
|
||||
set(_psx_sdl3_src "${FETCHCONTENT_SOURCE_DIR_SDL3}")
|
||||
elseif(DEFINED ENV{PSX_SDL3_SOURCE_DIR} AND
|
||||
NOT "$ENV{PSX_SDL3_SOURCE_DIR}" STREQUAL "" AND
|
||||
EXISTS "$ENV{PSX_SDL3_SOURCE_DIR}/CMakeLists.txt")
|
||||
set(_psx_sdl3_src "$ENV{PSX_SDL3_SOURCE_DIR}")
|
||||
set(FETCHCONTENT_SOURCE_DIR_SDL3 "${_psx_sdl3_src}" CACHE PATH
|
||||
"Pre-fetched SDL3 source (skip download)" FORCE)
|
||||
endif()
|
||||
if(_psx_sdl3_src)
|
||||
message(STATUS
|
||||
"psxrecomp: using pre-fetched SDL3 source ${_psx_sdl3_src}")
|
||||
endif()
|
||||
psxrecomp_dependency_source_dir(SDL3
|
||||
ENV PSX_SDL3_SOURCE_DIR
|
||||
OUT _psx_sdl3_src)
|
||||
# Pin (and any vendored archive) come from third_party/deps.manifest, so
|
||||
# an air-gapped tree staged by tools/ci/vendor_deps.sh needs no download.
|
||||
psxrecomp_dependency_archive(SDL3
|
||||
SOURCE_DIR "${_psx_sdl3_src}"
|
||||
OUT_URL _psx_sdl3_url OUT_HASH _psx_sdl3_hash)
|
||||
FetchContent_Declare(SDL3
|
||||
URL
|
||||
"https://github.com/libsdl-org/SDL/releases/download/release-3.4.10/SDL3-3.4.10.tar.gz"
|
||||
"${_psx_sdl3_url}"
|
||||
URL_HASH
|
||||
"SHA256=12b34280415ec8418c864408b93d008a20a6530687ee613d60bfbd20411f2785"
|
||||
"${_psx_sdl3_hash}"
|
||||
${_psx_sdl3_timestamp_args})
|
||||
FetchContent_MakeAvailable(SDL3)
|
||||
unset(_psx_sdl3_src)
|
||||
unset(_psx_sdl3_url)
|
||||
unset(_psx_sdl3_hash)
|
||||
endif()
|
||||
if(NOT TARGET SDL3::SDL3)
|
||||
message(FATAL_ERROR
|
||||
@@ -729,11 +724,17 @@ function(psxrecomp_ensure_zlib)
|
||||
if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.24)
|
||||
list(APPEND _psx_zlib_timestamp_args DOWNLOAD_EXTRACT_TIMESTAMP TRUE)
|
||||
endif()
|
||||
psxrecomp_dependency_source_dir(psx_zlib
|
||||
ENV PSX_ZLIB_SOURCE_DIR
|
||||
OUT _psx_zlib_src)
|
||||
psxrecomp_dependency_archive(psx_zlib
|
||||
SOURCE_DIR "${_psx_zlib_src}"
|
||||
OUT_URL _psx_zlib_url OUT_HASH _psx_zlib_hash)
|
||||
FetchContent_Declare(psx_zlib
|
||||
URL
|
||||
"https://github.com/madler/zlib/releases/download/v1.3.1/zlib-1.3.1.tar.gz"
|
||||
"${_psx_zlib_url}"
|
||||
URL_HASH
|
||||
"SHA256=9a93b2b7dfdac77ceba5a558a580e74667dd6fede4585b91eefb60f03b72df23"
|
||||
"${_psx_zlib_hash}"
|
||||
${_psx_zlib_timestamp_args})
|
||||
FetchContent_MakeAvailable(psx_zlib)
|
||||
# madler/zlib builds zlibstatic even when a shared zlib target exists.
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
# Vendored archives are opt-in. Only libchdr — the one dependency the build
|
||||
# cannot satisfy locally — is committed; tools/ci/vendor_deps.sh stages the
|
||||
# rest here on demand for air-gapped builds, and those must not be committed
|
||||
# (SDL3 alone is ~15 MB).
|
||||
*.tar.gz
|
||||
*.tar.xz
|
||||
*.tar.bz2
|
||||
*.zip
|
||||
!libchdr-*.tar.gz
|
||||
Vendored
+42
@@ -0,0 +1,42 @@
|
||||
# third_party/ — vendored dependency archives
|
||||
|
||||
Source archives the build would otherwise download, staged here so a checkout
|
||||
can configure with no network at all.
|
||||
|
||||
`deps.manifest` is the single pin record — name, archive file, SHA256, upstream
|
||||
URL. Both `cmake/psx_dependency_archive.cmake` and `tools/ci/vendor_deps.sh`
|
||||
read it, so a vendored archive can never drift from the pin the build would
|
||||
have fetched. A vendored archive is verified against the same `URL_HASH` as a
|
||||
downloaded one; nothing here is trusted because it is local.
|
||||
|
||||
## What is committed, and why only that
|
||||
|
||||
Only **libchdr** (`libchdr-<sha>.tar.gz`, ~520 KB, BSD-3-Clause — see
|
||||
`../THIRD_PARTY_ATTRIBUTION.md`).
|
||||
|
||||
`runtime/runtime.cmake` includes `chd_dependency.cmake` unconditionally, and
|
||||
libchdr has no `find_package` path and ships in no toolchain pack — so it is
|
||||
both the *first* network access a build makes and the only one with no local
|
||||
fallback. A player building a released game behind a firewall used to fail
|
||||
there, inside a FetchContent subbuild, before reaching any other dependency.
|
||||
|
||||
SDL3 (~15 MB) and zlib resolve from a system package or a toolchain pack first
|
||||
and are **not** committed; `.gitignore` keeps them out. Stage them on demand:
|
||||
|
||||
```sh
|
||||
tools/ci/vendor_deps.sh # every dependency in the manifest
|
||||
tools/ci/vendor_deps.sh SDL3 # just one
|
||||
tools/ci/vendor_deps.sh --check # verify what is staged; never downloads
|
||||
```
|
||||
|
||||
Then configure with `-DPSX_DEPS_OFFLINE=ON` to turn any remaining download
|
||||
attempt into a hard error that names the missing archive, instead of a fetch
|
||||
that stalls behind a proxy and fails three CMake frames deep.
|
||||
|
||||
## Adding a dependency
|
||||
|
||||
Add the row to `deps.manifest`, run `tools/ci/vendor_deps.sh <name>` to stage
|
||||
and verify the archive, and resolve it in CMake through
|
||||
`psxrecomp_dependency_archive()` / `psxrecomp_dependency_source_dir()` rather
|
||||
than a literal `URL` — a literal URL is a build that cannot go offline. Commit
|
||||
the archive only if the dependency has no local fallback and is small.
|
||||
Vendored
+23
@@ -0,0 +1,23 @@
|
||||
# psxrecomp vendored-dependency pins.
|
||||
#
|
||||
# THE single record of every source archive the build may fetch. Both
|
||||
# cmake/psx_dependency_archive.cmake and tools/ci/vendor_deps.sh read this
|
||||
# file, so a vendored archive under third_party/ can never drift from the
|
||||
# URL/hash the build would otherwise download.
|
||||
#
|
||||
# Columns, whitespace-separated:
|
||||
# name FetchContent name used in the CMake files
|
||||
# file archive name under third_party/ (vendored form)
|
||||
# sha256 digest of that archive; also the URL_HASH of the upstream pin
|
||||
# url upstream download location
|
||||
#
|
||||
# Only psx_libchdr is committed: it is the one dependency with no local
|
||||
# fallback (no find_package path, no toolchain-pack copy), so a build with no
|
||||
# network dies at it. SDL3 and zlib resolve from a system package or a
|
||||
# cmake-clang-v1 toolchain pack first; run tools/ci/vendor_deps.sh to stage
|
||||
# them here as well for a fully air-gapped tree.
|
||||
#
|
||||
# name file sha256 url
|
||||
psx_libchdr libchdr-6cde5348eb118da3baf94f75a69577a005a484fd.tar.gz a222b1f1c842f988c2aad51e5f56ba94a423ed87ccab71f1abdb757caa7444f5 https://github.com/rtissera/libchdr/archive/6cde5348eb118da3baf94f75a69577a005a484fd.tar.gz
|
||||
SDL3 SDL3-3.4.10.tar.gz 12b34280415ec8418c864408b93d008a20a6530687ee613d60bfbd20411f2785 https://github.com/libsdl-org/SDL/releases/download/release-3.4.10/SDL3-3.4.10.tar.gz
|
||||
psx_zlib zlib-1.3.1.tar.gz 9a93b2b7dfdac77ceba5a558a580e74667dd6fede4585b91eefb60f03b72df23 https://github.com/madler/zlib/releases/download/v1.3.1/zlib-1.3.1.tar.gz
|
||||
Binary file not shown.
Executable
+168
@@ -0,0 +1,168 @@
|
||||
#!/usr/bin/env bash
|
||||
# Stage the pinned dependency archives into third_party/ so a build needs no
|
||||
# network. Reads third_party/deps.manifest — the same pin record
|
||||
# cmake/psx_dependency_archive.cmake reads — so what lands here is byte-identical
|
||||
# to what the build would otherwise have downloaded.
|
||||
#
|
||||
# Usage:
|
||||
# tools/ci/vendor_deps.sh # stage every dependency
|
||||
# tools/ci/vendor_deps.sh SDL3 psx_zlib # stage only these
|
||||
# tools/ci/vendor_deps.sh --check # verify what is staged; never download
|
||||
# tools/ci/vendor_deps.sh --force # re-download even if present
|
||||
#
|
||||
# After a full run, configure with -DPSX_DEPS_OFFLINE=ON to make any remaining
|
||||
# download attempt a hard error rather than a silent trip to github.com.
|
||||
set -euo pipefail
|
||||
|
||||
ROOT="$(cd "$(dirname "$0")/../.." && pwd)"
|
||||
THIRD_PARTY="${ROOT}/third_party"
|
||||
MANIFEST="${THIRD_PARTY}/deps.manifest"
|
||||
|
||||
CHECK_ONLY=0
|
||||
FORCE=0
|
||||
WANTED=()
|
||||
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case "$1" in
|
||||
--check) CHECK_ONLY=1; shift ;;
|
||||
--force) FORCE=1; shift ;;
|
||||
-h|--help)
|
||||
sed -n '2,16p' "$0" | sed 's/^# \{0,1\}//'
|
||||
exit 0
|
||||
;;
|
||||
-*)
|
||||
echo "error: unknown option: $1" >&2
|
||||
exit 2
|
||||
;;
|
||||
*) WANTED+=("$1"); shift ;;
|
||||
esac
|
||||
done
|
||||
|
||||
if [[ ! -f "${MANIFEST}" ]]; then
|
||||
echo "error: missing manifest: ${MANIFEST}" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
sha256_of() {
|
||||
if command -v sha256sum >/dev/null 2>&1; then
|
||||
sha256sum "$1" | awk '{print $1}'
|
||||
elif command -v shasum >/dev/null 2>&1; then
|
||||
shasum -a 256 "$1" | awk '{print $1}'
|
||||
else
|
||||
echo "error: need sha256sum or shasum to verify archives" >&2
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
wanted() {
|
||||
[[ ${#WANTED[@]} -eq 0 ]] && return 0
|
||||
local n
|
||||
for n in "${WANTED[@]}"; do
|
||||
[[ "$n" == "$1" ]] && return 0
|
||||
done
|
||||
return 1
|
||||
}
|
||||
|
||||
download() {
|
||||
# Prefer HTTP/1.1: GitHub release assets intermittently REFUSED_STREAM under
|
||||
# HTTP/2, which is the same failure prefetch_sdl3.sh works around.
|
||||
local url="$1" dest="$2"
|
||||
if command -v curl >/dev/null 2>&1; then
|
||||
curl -fsSL --http1.1 --retry 5 --retry-all-errors --retry-delay 2 \
|
||||
-o "${dest}" "${url}"
|
||||
elif command -v wget >/dev/null 2>&1; then
|
||||
wget -q -O "${dest}" "${url}"
|
||||
else
|
||||
echo "error: need curl or wget to download ${url}" >&2
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
mkdir -p "${THIRD_PARTY}"
|
||||
|
||||
seen=0
|
||||
fail=0
|
||||
matched=()
|
||||
|
||||
while read -r name file sha url _rest; do
|
||||
case "${name}" in ""|\#*) continue ;; esac
|
||||
if [[ -z "${file}" || -z "${sha}" || -z "${url}" ]]; then
|
||||
echo "error: malformed manifest row: ${name} ${file} ${sha} ${url}" >&2
|
||||
fail=1
|
||||
continue
|
||||
fi
|
||||
wanted "${name}" || continue
|
||||
matched+=("${name}")
|
||||
seen=$((seen + 1))
|
||||
|
||||
target="${THIRD_PARTY}/${file}"
|
||||
|
||||
if [[ -f "${target}" && "${FORCE}" -eq 0 ]]; then
|
||||
have="$(sha256_of "${target}")"
|
||||
if [[ "${have}" == "${sha}" ]]; then
|
||||
echo "ok: ${name} — third_party/${file}"
|
||||
continue
|
||||
fi
|
||||
echo "error: ${name} — third_party/${file} digest mismatch" >&2
|
||||
echo " manifest: ${sha}" >&2
|
||||
echo " on disk: ${have}" >&2
|
||||
if [[ "${CHECK_ONLY}" -eq 1 ]]; then
|
||||
fail=1
|
||||
continue
|
||||
fi
|
||||
echo " re-downloading" >&2
|
||||
elif [[ "${CHECK_ONLY}" -eq 1 ]]; then
|
||||
echo "missing: ${name} — third_party/${file}" >&2
|
||||
fail=1
|
||||
continue
|
||||
fi
|
||||
|
||||
echo "fetching: ${name} <- ${url}"
|
||||
tmp="$(mktemp "${THIRD_PARTY}/.${file}.XXXXXX")"
|
||||
# shellcheck disable=SC2064
|
||||
trap "rm -f '${tmp}'" EXIT
|
||||
download "${url}" "${tmp}"
|
||||
have="$(sha256_of "${tmp}")"
|
||||
if [[ "${have}" != "${sha}" ]]; then
|
||||
echo "error: ${name} digest mismatch after download" >&2
|
||||
echo " want: ${sha}" >&2
|
||||
echo " got: ${have}" >&2
|
||||
rm -f "${tmp}"
|
||||
trap - EXIT
|
||||
fail=1
|
||||
continue
|
||||
fi
|
||||
mv -f "${tmp}" "${target}"
|
||||
chmod 0644 "${target}"
|
||||
trap - EXIT
|
||||
echo "ok: ${name} — third_party/${file}"
|
||||
done <"${MANIFEST}"
|
||||
|
||||
if [[ ${#WANTED[@]} -gt 0 ]]; then
|
||||
for n in "${WANTED[@]}"; do
|
||||
found=0
|
||||
for m in "${matched[@]:-}"; do
|
||||
[[ "$m" == "$n" ]] && found=1
|
||||
done
|
||||
if [[ "${found}" -eq 0 ]]; then
|
||||
echo "error: no '${n}' row in ${MANIFEST}" >&2
|
||||
fail=1
|
||||
fi
|
||||
done
|
||||
fi
|
||||
|
||||
if [[ "${seen}" -eq 0 ]]; then
|
||||
echo "error: nothing to do — no manifest rows selected" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ "${fail}" -ne 0 ]]; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ "${CHECK_ONLY}" -eq 1 ]]; then
|
||||
echo "all requested dependencies are vendored and verified."
|
||||
else
|
||||
echo "vendored ${seen} dependenc$([[ ${seen} -eq 1 ]] && echo y || echo ies) into third_party/."
|
||||
echo "configure with -DPSX_DEPS_OFFLINE=ON to forbid any further download."
|
||||
fi
|
||||
Reference in New Issue
Block a user