From 0395eec43d4be812f4932e9457ffd409820824cf Mon Sep 17 00:00:00 2001 From: agw Date: Wed, 30 Sep 2026 22:00:00 +0200 Subject: [PATCH] Patch module lockfiles after the modules are cloned, not before The later 1.4.6 -> 1.4.8 bump ran before the module repositories were cloned, found no lockfiles and patched nothing, so every module then failed on later's tinycthread vs glibc >= 2.43. The manual build only escaped because its module checkouts already existed from an earlier run. Move the patch after the clone loop and fail if there is nothing to patch. Claude-Session: https://claude.ai/code/session_01GGe7kUhooMFuzY6GaDb2w9 --- build/build-jasp.sh | 76 ++++++++++++++++++++++++--------------------- 1 file changed, 41 insertions(+), 35 deletions(-) diff --git a/build/build-jasp.sh b/build/build-jasp.sh index 6b74d4d..b1215e2 100755 --- a/build/build-jasp.sh +++ b/build/build-jasp.sh @@ -233,41 +233,6 @@ Rscript -e " stop('failed to install remotes') " -# Some of the versions JASP pins in its module renv.lock files predate the -# toolchain on a current Arch and cannot compile. Bump only those, by name, with -# the reason recorded — never a blanket "use latest", which would silently -# change the analysis code users get. -# -# later 1.4.6 bundles a tinycthread whose `#define once_flag pthread_once_t` -# collides with the C11 once_flag that glibc >= 2.43 now declares under -# C23, so it fails with "conflicting types for pthread_once_t". -# Fixed upstream in later 1.4.7 (r-lib/later#257). The 2026-04-22 RSPM -# snapshot the lockfiles already reference carries 1.4.8. -log "patching module lockfile pins that cannot build on this toolchain" -python3 - <<'PY' -import json, pathlib - -OVERRIDES = {"later": "1.4.8"} - -root = pathlib.Path("ModuleBundleBuildDir/Modules") -patched = 0 -for lock in root.glob("*/renv.lock"): - data = json.loads(lock.read_text()) - packages = data.get("Packages", {}) - changed = False - for name, want in OVERRIDES.items(): - pkg = packages.get(name) - if pkg and pkg.get("Version") != want: - print(f" {lock.parent.name}: {name} {pkg['Version']} -> {want}") - pkg["Version"] = want - # The recorded hash no longer matches the bumped version. - pkg.pop("Hash", None) - changed = True - if changed: - lock.write_text(json.dumps(data, indent=2) + "\n") - patched += 1 -print(f"patched {patched} lockfiles") -PY # renv restores packages concurrently and its ordering is not always # dependency-correct: a module can be lazy-loaded while a package it needs is @@ -405,6 +370,47 @@ for module in "${ALL_MODULES[@]}"; do fi done +# This has to run after the modules are cloned: it once ran before, found no +# lockfiles, patched nothing, and every module then failed on later 1.4.6. +# +# Some of the versions JASP pins in its module renv.lock files predate the +# toolchain on a current Arch and cannot compile. Bump only those, by name, with +# the reason recorded — never a blanket "use latest", which would silently +# change the analysis code users get. +# +# later 1.4.6 bundles a tinycthread whose `#define once_flag pthread_once_t` +# collides with the C11 once_flag that glibc >= 2.43 now declares under +# C23, so it fails with "conflicting types for pthread_once_t". +# Fixed upstream in later 1.4.7 (r-lib/later#257). The 2026-04-22 RSPM +# snapshot the lockfiles already reference carries 1.4.8. +log "patching module lockfile pins that cannot build on this toolchain" +python3 - <<'PY' +import json, pathlib + +OVERRIDES = {"later": "1.4.8"} + +root = pathlib.Path("ModuleBundleBuildDir/Modules") +patched = 0 +for lock in root.glob("*/renv.lock"): + data = json.loads(lock.read_text()) + packages = data.get("Packages", {}) + changed = False + for name, want in OVERRIDES.items(): + pkg = packages.get(name) + if pkg and pkg.get("Version") != want: + print(f" {lock.parent.name}: {name} {pkg['Version']} -> {want}") + pkg["Version"] = want + # The recorded hash no longer matches the bumped version. + pkg.pop("Hash", None) + changed = True + if changed: + lock.write_text(json.dumps(data, indent=2) + "\n") + patched += 1 +print(f"patched {patched} lockfiles") +if not any(root.glob("*/renv.lock")): + raise SystemExit("error: no module lockfiles to patch - modules not cloned yet?") +PY + for attempt in 1 2 3; do # Hand over only modules without a bundle yet: the script rebuilds everything # it is given, so a retry would otherwise redo every finished module.