6433c9b3de
## Problem
r-universe builds every package to WebAssembly (webR) in addition to the native platforms, calling `./configure --host=wasm32-unknown-emscripten`. `bindings/r/configure` only knew Linux/macOS/Windows and exited with `unsupported OS 'Emscripten'`, so the **WASM job was the single red check** on an otherwise fully-published r-universe build (all native platforms + deploy are green; the package installs fine everywhere).
## Fix
The r-universe wasm build image ships **cargo** (`/usr/local/cargo/bin`) and **emscripten** (`EMSDK` on PATH). So instead of needing a prebuilt wasm lib (which would risk an emscripten ABI/version mismatch), `configure` now detects the Emscripten host and **builds the C ABI staticlib from source** for `wasm32-unknown-emscripten` in-place — compiled with the image's own emscripten, so the ABI always matches. The static `libwickra.a` is linked into the package object (no shared lib, no rpath).
`wickra-core`'s rayon batch needs threads (absent on wasm), so the wasm build drops it via `--no-default-features`. `wickra-c` now takes `wickra-core` as a direct path dep with `default-features = false` plus a default `parallel` feature that re-enables it for native builds (a member-level `default-features = false` is ignored when inheriting a workspace dep — that was the trap).
## Validated locally
- `cargo build -p wickra-c` (default) → rayon present, builds.
- `cargo build -p wickra-c --no-default-features` (the wasm feature path) → rayon **gone**, builds.
- `cargo build --workspace`, clippy, fmt all clean; `configure` passes `sh -n`.
## Cannot be validated locally
No Rust/emscripten wasm toolchain here. The wasm build only runs in r-universe, and `configure` downloads the matching `v${version}` source tag — so this takes effect from the **first release that includes it** (the tagged source must contain the feature toggle). Open risks: whether the image has the `wasm32-unknown-emscripten` Rust target pre-installed (configure runs `rustup target add` best-effort) and the wasm build time. Worth one r-universe rebuild to confirm.
Not merging — review first.
113 lines
4.7 KiB
Bash
Executable File
113 lines
4.7 KiB
Bash
Executable File
#!/bin/sh
|
|
# Resolve the Wickra C ABI (header + shared library) for the Unix build.
|
|
#
|
|
# Self-contained by default: download the prebuilt wickra-c-<triple>.tar.gz
|
|
# release asset that matches this package's version and stage the shared library
|
|
# into src/ so the compiled wickra.so links against it and bundles it (via
|
|
# install.libs.R), found post-install through an rpath ($ORIGIN on Linux,
|
|
# @loader_path on macOS). Set WICKRA_INCLUDE_DIR + WICKRA_LIB_DIR to build
|
|
# against a locally built C ABI instead (dev override; e.g.
|
|
# `cargo build -p wickra-c --release`). Download/extract uses base R (always
|
|
# present at build time), so there is no curl/wget system dependency.
|
|
set -e
|
|
|
|
inc=""
|
|
lib=""
|
|
|
|
# WebAssembly (r-universe / webR): there is no prebuilt wasm C ABI to download,
|
|
# but the build image ships cargo (/usr/local/cargo/bin) and emscripten
|
|
# (EMSDK on PATH), so build the C ABI staticlib from source for
|
|
# wasm32-unknown-emscripten right here. Building it in the same image with the
|
|
# same emscripten avoids any ABI/version mismatch a prebuilt lib would risk.
|
|
# rayon (threads) is dropped via --no-default-features; the indicators are pure
|
|
# computation, so the serial path is functionally identical.
|
|
if [ "$(uname -s)" = "Emscripten" ]; then
|
|
version=$(sed -n 's/^Version:[[:space:]]*//p' DESCRIPTION)
|
|
echo "wickra: building C ABI from source for wasm32-unknown-emscripten (v${version})"
|
|
build=$(mktemp -d)
|
|
url="https://github.com/wickra-lib/wickra/archive/refs/tags/v${version}.tar.gz"
|
|
"${R_HOME}/bin/Rscript" -e "download.file('${url}', '${build}/src.tar.gz', mode = 'wb', quiet = TRUE)" \
|
|
|| { echo "wickra: failed to download source ${url}"; exit 1; }
|
|
"${R_HOME}/bin/Rscript" -e "untar('${build}/src.tar.gz', exdir = '${build}')"
|
|
root="${build}/wickra-${version}"
|
|
rustup target add wasm32-unknown-emscripten 2>/dev/null || true
|
|
( cd "${root}" && cargo build -p wickra-c --release \
|
|
--target wasm32-unknown-emscripten --no-default-features ) \
|
|
|| { echo "wickra: cargo wasm build failed"; exit 1; }
|
|
cp "${root}/bindings/c/include/wickra.h" src/wickra.h
|
|
cp "${root}/target/wasm32-unknown-emscripten/release/libwickra.a" src/libwickra.a
|
|
rm -rf "${build}"
|
|
# The static archive is linked into the package object; no shared lib to
|
|
# bundle and no rpath needed.
|
|
sed "s|@WICKRA_RPATH@||" src/Makevars.in > src/Makevars
|
|
exit 0
|
|
fi
|
|
|
|
if [ -n "${WICKRA_INCLUDE_DIR}" ] && [ -n "${WICKRA_LIB_DIR}" ]; then
|
|
echo "wickra: using C ABI from WICKRA_INCLUDE_DIR / WICKRA_LIB_DIR (dev override)"
|
|
inc="${WICKRA_INCLUDE_DIR}"
|
|
lib="${WICKRA_LIB_DIR}"
|
|
else
|
|
version=$(sed -n 's/^Version:[[:space:]]*//p' DESCRIPTION)
|
|
os=$(uname -s)
|
|
arch=$(uname -m)
|
|
case "${os}" in
|
|
Linux)
|
|
case "${arch}" in
|
|
x86_64) triple="x86_64-unknown-linux-gnu" ;;
|
|
aarch64 | arm64) triple="aarch64-unknown-linux-gnu" ;;
|
|
*) echo "wickra: unsupported Linux arch '${arch}' — set WICKRA_INCLUDE_DIR/WICKRA_LIB_DIR"; exit 1 ;;
|
|
esac
|
|
;;
|
|
Darwin)
|
|
case "${arch}" in
|
|
x86_64) triple="x86_64-apple-darwin" ;;
|
|
arm64 | aarch64) triple="aarch64-apple-darwin" ;;
|
|
*) echo "wickra: unsupported macOS arch '${arch}' — set WICKRA_INCLUDE_DIR/WICKRA_LIB_DIR"; exit 1 ;;
|
|
esac
|
|
;;
|
|
*)
|
|
echo "wickra: unsupported OS '${os}' — set WICKRA_INCLUDE_DIR/WICKRA_LIB_DIR"
|
|
exit 1
|
|
;;
|
|
esac
|
|
url="https://github.com/wickra-lib/wickra/releases/download/v${version}/wickra-c-${triple}.tar.gz"
|
|
echo "wickra: downloading C ABI ${triple} for v${version}"
|
|
"${R_HOME}/bin/Rscript" -e "download.file('${url}', 'src/wickra-c.tar.gz', mode = 'wb', quiet = TRUE)" \
|
|
|| { echo "wickra: failed to download ${url}"; exit 1; }
|
|
"${R_HOME}/bin/Rscript" -e "untar('src/wickra-c.tar.gz', exdir = 'src/wickra-c')"
|
|
inc="src/wickra-c/wickra-c-${triple}/include"
|
|
lib="src/wickra-c/wickra-c-${triple}/lib"
|
|
fi
|
|
|
|
# Stage the header and the platform shared library into src/ so the package
|
|
# object links with -L. -lwickra and install.libs.R bundles the lib.
|
|
cp "${inc}/wickra.h" src/wickra.h
|
|
staged=""
|
|
for f in libwickra.so libwickra.dylib; do
|
|
if [ -f "${lib}/${f}" ]; then
|
|
cp "${lib}/${f}" "src/${f}"
|
|
staged="${f}"
|
|
fi
|
|
done
|
|
if [ -z "${staged}" ]; then
|
|
echo "wickra: no libwickra.so/.dylib found under ${lib}"
|
|
exit 1
|
|
fi
|
|
|
|
# rpath so the bundled lib is found next to wickra.so after install.
|
|
case "$(uname -s)" in
|
|
Darwin)
|
|
rpath="-Wl,-rpath,@loader_path"
|
|
# Normalise the dylib id to @rpath so @loader_path resolution applies.
|
|
install_name_tool -id "@rpath/${staged}" "src/${staged}" 2>/dev/null || true
|
|
;;
|
|
*)
|
|
rpath="-Wl,-rpath,'\$\$ORIGIN'"
|
|
;;
|
|
esac
|
|
|
|
sed "s|@WICKRA_RPATH@|${rpath}|" src/Makevars.in > src/Makevars
|
|
echo "wickra: configured (bundled ${staged})"
|
|
exit 0
|