Actually ship the R libraries the modules need
The first full build succeeded and produced a package that would not have worked. Three separate causes, all silent: - R was configured --with-blas --with-lapack, so it linked Arch's external BLAS and never built libRblas.so/libRlapack.so. The JASP module bundles expect those inside R_HOME, the way a conventional R and the Flatpak ship them. Now --without-blas, with a hard check after install. - buildModuleBundlesLocally.R installs jaspModuleTools via install_github, which failed on anonymous GitHub rate limits. No bundles were produced at all. GITHUB_PAT is now required rather than merely recommended. - buildAllDefaultJaspModules.R calls the bundle builder through system2(), which ignores exit status, so all of the above exited 0. Added explicit guards: jaspModuleTools must exist, Modules/local must be non-empty, and the staged tree must contain the bundles and all three R libraries. Staging was also wrong: it copied ModuleBundleBuildDir/Modules, which is cloned module *sources* with zero compiled objects, while dropping LibraryR entirely - 267MB of R packages built against the bundled R.
This commit is contained in:
+89
-10
@@ -103,19 +103,38 @@ cd "R-${R_VERSION}"
|
||||
# config.site would otherwise pick, which keeps the rpath below predictable.
|
||||
# The install prefix equals the final install path, so the rpath stays valid
|
||||
# once the tarball is unpacked on the user's machine.
|
||||
#
|
||||
# --without-blas/--without-lapack is deliberate and load-bearing. With
|
||||
# --with-blas, R links Arch's external BLAS and does NOT build libRblas.so or
|
||||
# libRlapack.so. The JASP module bundles expect those files to exist inside
|
||||
# R_HOME (that is how a conventionally built R, and the Flatpak, ship), so
|
||||
# linking externally leaves the modules unable to resolve them. Reference BLAS
|
||||
# is slower than OpenBLAS, but a working install beats a fast broken one.
|
||||
./configure \
|
||||
--prefix="${R_HOME_DIR}" \
|
||||
--libdir="${R_HOME_DIR}/lib" \
|
||||
--enable-R-shlib \
|
||||
--enable-memory-profiling \
|
||||
--with-blas \
|
||||
--with-lapack \
|
||||
--without-blas \
|
||||
--without-lapack \
|
||||
--with-x=no \
|
||||
--with-tcltk=no \
|
||||
LDFLAGS="-Wl,-rpath,${R_HOME_DIR}/lib/R/lib"
|
||||
make -j"$JOBS"
|
||||
make install
|
||||
|
||||
# Guard the above: a silently external-BLAS build produces a JASP whose modules
|
||||
# fail at runtime, which is exactly the class of failure this package exists to
|
||||
# avoid. Better to stop here than ship it.
|
||||
for lib in libR.so libRblas.so libRlapack.so; do
|
||||
if [[ ! -f "${R_HOME_DIR}/lib/R/lib/${lib}" ]]; then
|
||||
echo "error: ${lib} missing from the bundled R — R linked an external BLAS?" >&2
|
||||
ls -la "${R_HOME_DIR}/lib/R/lib/" >&2
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
log "bundled R provides its own libR/libRblas/libRlapack"
|
||||
|
||||
export PATH="${R_HOME_DIR}/bin:${PATH}"
|
||||
# Ask R where it actually put itself rather than assuming lib vs lib64.
|
||||
# Deliberately NOT exported: R.cmake notes that a set R_HOME makes R print
|
||||
@@ -156,15 +175,46 @@ log "compiling JASP (-j$JOBS)"
|
||||
ninja -C "$BUILD_DIR" -j"$JOBS"
|
||||
|
||||
# The R modules are the long pole: several hundred R packages compiled from
|
||||
# source, installed into the bundled R's library.
|
||||
# source. buildAllDefaultJaspModules.R shells out to buildModuleBundlesLocally.R
|
||||
# via system2(), which does NOT check exit status — so every failure below is
|
||||
# silent and the script still exits 0. The guards after it are what actually
|
||||
# catch a broken module build.
|
||||
#
|
||||
# GITHUB_PAT is required, not optional: buildModuleBundlesLocally.R does
|
||||
# install_github('jasp-stats/jaspModuleTools'), and anonymous GitHub API rate
|
||||
# limits make that fail. When it fails, no bundles are produced at all and the
|
||||
# build otherwise looks successful.
|
||||
if [[ -z "${GITHUB_PAT:-}" ]]; then
|
||||
echo "error: GITHUB_PAT is required — jaspModuleTools is installed from GitHub" >&2
|
||||
echo " without it the module build silently produces nothing" >&2
|
||||
exit 1
|
||||
fi
|
||||
export GITHUB_PAT
|
||||
export GITHUB_TOKEN="${GITHUB_PAT}"
|
||||
|
||||
log "building R modules — this is the slow part"
|
||||
mkdir -p "$BUILD_DIR"/Modules/{binary_pkgs,manifests,module_libs,Tools}
|
||||
cd "$SRC_DIR/Tools"
|
||||
if [[ -z "${GITHUB_PAT:-}" ]]; then
|
||||
echo "warning: GITHUB_PAT is unset — R module downloads from GitHub may hit anonymous rate limits" >&2
|
||||
fi
|
||||
Rscript buildAllDefaultJaspModules.R
|
||||
|
||||
MODULE_LIBRARY="$SRC_DIR/Tools/ModuleBundleBuildDir/LibraryR"
|
||||
MODULE_BUNDLES="$SRC_DIR/Modules/local"
|
||||
|
||||
if [[ ! -d "$MODULE_LIBRARY/jaspModuleTools" ]]; then
|
||||
echo "error: jaspModuleTools was not installed — install_github failed" >&2
|
||||
echo " (GitHub rate limit, or GITHUB_PAT lacks read access)" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
bundle_count="$(find "$MODULE_BUNDLES" -mindepth 1 -maxdepth 1 2>/dev/null | wc -l)"
|
||||
if [[ "$bundle_count" -eq 0 ]]; then
|
||||
echo "error: the module build produced no bundles in ${MODULE_BUNDLES}" >&2
|
||||
echo " system2() in buildAllDefaultJaspModules.R hides the real error;" >&2
|
||||
echo " re-run buildModuleBundlesLocally.R by hand to see it" >&2
|
||||
exit 1
|
||||
fi
|
||||
log "module build produced ${bundle_count} bundles"
|
||||
|
||||
# -------------------------------------------------------------------- staging
|
||||
log "staging install tree"
|
||||
rm -rf "$STAGE_DIR"
|
||||
@@ -176,10 +226,25 @@ DESTDIR="$STAGE_DIR" ninja -C "$BUILD_DIR" install
|
||||
install -d "$STAGE_DIR$PREFIX"
|
||||
cp -a "$R_HOME_DIR" "$STAGE_DIR$PREFIX/"
|
||||
|
||||
# Everything the module build produced has to travel with the tarball, or JASP
|
||||
# falls back to downloading bundles at runtime — which is the failure mode this
|
||||
# package is meant to remove.
|
||||
#
|
||||
# Modules/local the compiled module bundles themselves
|
||||
# LibraryR the R library they were built with (jaspModuleTools, devtools
|
||||
# and ~95 dependencies), compiled against the bundled R 4.5.3
|
||||
#
|
||||
# ModuleBundleBuildDir/Modules is deliberately NOT copied: it is the cloned
|
||||
# module *sources* (no compiled objects at all), several hundred MB of git
|
||||
# checkouts that would bloat the tarball without being usable at runtime.
|
||||
install -d "$STAGE_DIR$PREFIX/Modules"
|
||||
if [[ -d "$SRC_DIR/Tools/ModuleBundleBuildDir/Modules" ]]; then
|
||||
cp -a "$SRC_DIR/Tools/ModuleBundleBuildDir/Modules/." "$STAGE_DIR$PREFIX/Modules/"
|
||||
fi
|
||||
|
||||
log "staging module bundles from ${MODULE_BUNDLES}"
|
||||
cp -a "$MODULE_BUNDLES/." "$STAGE_DIR$PREFIX/Modules/"
|
||||
|
||||
log "staging module R library from ${MODULE_LIBRARY}"
|
||||
install -d "$STAGE_DIR$PREFIX/ModuleLibrary"
|
||||
cp -a "$MODULE_LIBRARY/." "$STAGE_DIR$PREFIX/ModuleLibrary/"
|
||||
|
||||
install -Dm644 /work/packaging/org.jaspstats.JASP.desktop \
|
||||
"$STAGE_DIR/usr/share/applications/org.jaspstats.JASP.desktop"
|
||||
@@ -197,10 +262,24 @@ find . -maxdepth 2 \( -name 'COPYING*' -o -name 'LICENSE*' \) -type f \
|
||||
find "$STAGE_DIR" -name '*.o' -delete 2>/dev/null || true
|
||||
|
||||
# Make the tree independent of Arch's rolling libraries (ICU, jsoncpp, glpk,
|
||||
# JAGS, readstat, librdata, BLAS/LAPACK ...). Qt6 stays a system dependency.
|
||||
# JAGS, readstat, librdata ...). Qt6 stays a system dependency; BLAS/LAPACK now
|
||||
# come from the bundled R itself.
|
||||
log "bundling non-system shared libraries"
|
||||
bash /work/build/bundle-libs.sh "$STAGE_DIR" "$PREFIX"
|
||||
|
||||
# Final sanity check on what is about to be shipped. Each of these has already
|
||||
# been shipped missing once.
|
||||
log "verifying the staged tree"
|
||||
staged_r="$STAGE_DIR$PREFIX/R/lib/R/lib"
|
||||
for lib in libR.so libRblas.so libRlapack.so; do
|
||||
[[ -f "$staged_r/$lib" ]] || { echo "error: staged tree lacks $lib" >&2; exit 1; }
|
||||
done
|
||||
staged_bundles="$(find "$STAGE_DIR$PREFIX/Modules" -mindepth 1 -maxdepth 1 2>/dev/null | wc -l)"
|
||||
[[ "$staged_bundles" -gt 0 ]] || { echo "error: staged tree has no module bundles" >&2; exit 1; }
|
||||
staged_so="$(find "$STAGE_DIR$PREFIX" -name '*.so' 2>/dev/null | wc -l)"
|
||||
log "staged: ${staged_bundles} module bundles, ${staged_so} shared objects"
|
||||
du -sh "$STAGE_DIR$PREFIX"/* 2>/dev/null | sort -rh | head -8
|
||||
|
||||
# ------------------------------------------------------------------- metadata
|
||||
pkgver_of() { pacman -Q "$1" 2>/dev/null | awk '{print $2}'; }
|
||||
|
||||
|
||||
Reference in New Issue
Block a user