Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions .github/workflows/build-wasm.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,19 @@ jobs:
- uses: actions/setup-python@v6
with:
python-version: '3.12'
- name: Test dependency download integrity and cache recovery
run: |
python scripts/wasm/test-downloads.py
python scripts/wasm/test-vienna-release.py
- name: Test input, worker lifecycle and CSV handling
run: npm test --prefix webinterface
- name: Resolve newest stable ViennaRNA 2.x release and checksum
env:
GITHUB_TOKEN: ${{ github.token }}
run: |
python scripts/wasm/vienna-release.py --latest > "$RUNNER_TEMP/vienna-release.json"
cat "$RUNNER_TEMP/vienna-release.json"
echo "WASM_VIENNA_RELEASE=$RUNNER_TEMP/vienna-release.json" >> "$GITHUB_ENV"
- name: Cross-compile dependencies and IntaRNA
run: bash scripts/wasm/build.sh
- name: Check real WASM predictions against the native reference
Expand Down
68 changes: 68 additions & 0 deletions ChangeLog
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@

## Interface and handling

- add selected-interaction vaRRI embeds and reproducible all-output ZIP downloads
to the browser interface; compact parameters into accessible tabs and update
the Freiburg group header and full-width result/footer notes (PR #287 review)

- extend the browser interface with vaRRI styling, prediction/evaluation tasks,
multi-FASTA, start indices, CLI parameter groups, selectable CSV columns and
additional output previews/downloads; label pair-relative differences mfe Δ
Expand Down Expand Up @@ -80,6 +84,14 @@

## Technical changes and Optimizations

- build WASM with ViennaRNA 2.7.2 locally and the newest stable 2.x in CI;
verify published archive checksums, isolate versioned caches and retain
selected dependency provenance and notices (PR #292 review)

- BUGFIX : restore WASM dependency downloads using the pinned official ViennaRNA
release asset; verify downloads before caching and recover invalid caches
(PR #291)

- annotate inherited virtual methods/destructors with override, preserve compiled
WASM asset provenance through staging, and expand protocol/browser validation
for the PR #287 review
Expand Down Expand Up @@ -241,6 +253,62 @@ energies, restricted partition sums, and trackers.
################################################################################
################################################################################

261022 Alexander Mitrofanov
* scripts/wasm/{vienna-release.py,vienna-release.json}, build.sh
+ Resolve the newest stable ViennaRNA >=2.7.2 and <3 from all official GitHub
release pages in CI; require its release tarball and published SHA-256.
* Pin 2.7.2 for reproducible local builds and accept saved release manifests.
Isolate RNAlib sources/installations and IntaRNA objects by archive identity
and keep Boost/zlib in a separate prefix to prevent reuse or include-path
shadowing of libraries/headers from another release (PR #292).
* scripts/wasm/patch-vienna.py
- Remove the dlib 19.24 compatibility patch; ViennaRNA 2.7.2 bundles dlib 20.0.
* scripts/wasm/{write-build-info.mjs,stage.sh,smoke-protocol.mjs,test-browser.py}
* Record the selected archive URL/checksum, check the compiled ViennaRNA
version, stage matching dependency notices and test actual version exports.
* scripts/wasm/test-vienna-release.py, .github/workflows/build-wasm.yml
+ Cover numeric version selection, pagination, major-3/prerelease exclusion,
missing/invalid asset metadata, API failures, manifest validation and
rejection of compiled engines with a stale ViennaRNA version.
* webinterface/docs/step1-wasm-compilation.md
* Document latest-2.x CI selection, pinned local reproduction, versioned
caches, current bundled dlib and archive provenance.

261022 Alexander Mitrofanov
* scripts/wasm/{build,download}.sh
* Use the official GitHub ViennaRNA 2.7.0 release asset and pin its SHA-256;
the university endpoint returned a short HTTP 200 text response, failing
the WASM build before compilation (PR #291).
+ Verify archives before caching, discard invalid cached responses and remove
failed partial downloads so rerunning a build can recover automatically.
* scripts/wasm/test-downloads.py, .github/workflows/build-wasm.yml
+ Test verified-cache reuse, invalid-cache recovery, checksum failures,
HTTP errors and truncated transfers against a local HTTP server in CI.
* webinterface/docs/step1-wasm-compilation.md
* Document the release source, archive verification and download regression
command, including recovery behavior for failed or outdated caches.

261022 Alexander Mitrofanov
* webinterface/{archive,visualization}.js
+ Build local UTF-8 ZIPs with normalized FASTA, compiled version provenance,
portable parameter files, selected CSV, auxiliary inputs and all outputs;
include separate replay configurations for native text report modes.
+ Construct selected-row vaRRI URLs from full target/query sequences, native
dot-bracket output, names and signed indices, preserving strand direction.
* webinterface/{app,results,protocol}.js, index.html, styles.css
+ Add row selection, embedded vaRRI/full-viewer link and Download ZIP action;
preserve completed-run inputs and clear exports/viewer when inputs change.
* Replace folded groups with keyboard-accessible tabs and compact parameter
grids; link Bioinformatics - University of Freiburg to the group website
and remove artificial width limits from table/footer notes.
* scripts/wasm/{stage.sh,smoke-protocol.mjs,test-browser.py}
* Stage the new modules; verify byte-identical replay through fresh engines
and browser tab/selection/ZIP behavior in Chromium and Firefox.
* webinterface/tests/export.test.mjs, README.md, webinterface/docs/*
+ Cover coordinate/identity mapping, effective settings and archive inputs;
document replay commands, external visualization and browser limitations
(https://github.com/BackofenLab/IntaRNA/pull/287#issuecomment-6321503136).

261021 Alexander Mitrofanov
* src/IntaRNA/*.h
* Mark 194 inherited virtual methods and 45 derived destructors override;
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
seeding of interaction sites**

Predict short RNA pairs or evaluate supplied structures locally with the [browser interface](https://backofenlab.github.io/IntaRNA/webinterface/).
Select an interaction to view it in vaRRI, or download a ZIP with inputs, compiled versions, reproducible parameters and all outputs.
See the [WebAssembly build instructions](webinterface/docs/step1-wasm-compilation.md) and
[interface/deployment notes](webinterface/docs/step4-results-and-deployment.md).

Expand Down
64 changes: 36 additions & 28 deletions scripts/wasm/build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -5,34 +5,42 @@ repo=$(cd "$(dirname "$0")/../.." && pwd)
build=${WASM_BUILD_DIR:-"$repo/build-wasm"}
mkdir -p "$build"
build=$(cd "$build" && pwd)
prefix="$build/deps"
# Keep legacy RNAlib headers out of Boost's -I path: ordinary -I searches take
# precedence over the -isystem ViennaRNA paths produced by IntaRNA's configure.
prefix="$build/deps/common"
jobs=${JOBS:-2}
for tool in emcc em++ emar emranlib emconfigure emmake curl pkg-config node; do
for tool in emcc em++ emar emranlib emconfigure emmake curl pkg-config node python3; do
command -v "$tool" >/dev/null || { echo "Missing tool: $tool" >&2; exit 1; }
done
mkdir -p "$build/downloads" "$build/sources" "$prefix" "$build/site/wasm"
fetch() {
local url=$1 name=$2 checksum=$3
if [[ ! -f "$build/downloads/$name" ]]; then
curl --fail --location --retry 3 "$url" -o "$build/downloads/$name.part"
mv "$build/downloads/$name.part" "$build/downloads/$name"
fi
echo "$checksum $build/downloads/$name" | sha256sum --check -
bash "$repo/scripts/wasm/download.sh" "$1" "$build/downloads/$2" "$3"
}
fetch https://zlib.net/fossils/zlib-1.3.1.tar.gz zlib-1.3.1.tar.gz \
9a93b2b7dfdac77ceba5a558a580e74667dd6fede4585b91eefb60f03b72df23
fetch https://archives.boost.io/release/1.87.0/source/boost_1_87_0.tar.bz2 boost_1_87_0.tar.bz2 \
af57be25cb4c4f4b413ed692fe378affb4352ea50fbe294a11ef548f4d527d89
fetch https://www.tbi.univie.ac.at/RNA/download/sourcecode/2_7_x/ViennaRNA-2.7.0.tar.gz ViennaRNA-2.7.0.tar.gz \
9a99fd68ed380894defb4d5e6a8a2871629270028cdf7f16f0a05da6e8c71473
# CI supplies the newest stable 2.x manifest; local builds use the checked-in pin.
read -r vienna_version vienna_url vienna_sha256 < <(
python3 "$repo/scripts/wasm/vienna-release.py" --fields \
--manifest "${WASM_VIENNA_RELEASE:-$repo/scripts/wasm/vienna-release.json}"
)
echo "Building ViennaRNA $vienna_version (SHA-256 $vienna_sha256)"
fetch "$vienna_url" "ViennaRNA-$vienna_version.tar.gz" "$vienna_sha256"
# Separate source, installed RNAlib and IntaRNA objects by archive identity so
# changing the release cannot reuse headers, libraries or objects from an old one.
vienna_id="vienna-$vienna_version-$vienna_sha256"
vienna_prefix="$build/deps/$vienna_id"
vienna_sources="$build/sources/$vienna_id"
intarna_build="$build/intarna-$vienna_id"

# Keep pkg-config searches inside the WASM prefix, including configure probes.
export PKG_CONFIG_LIBDIR="$prefix/lib/pkgconfig"
export PKG_CONFIG_LIBDIR="$vienna_prefix/lib/pkgconfig:$prefix/lib/pkgconfig"
export PKG_CONFIG_PATH="$PKG_CONFIG_LIBDIR"
export CFLAGS='-O3 -fexceptions'
export CXXFLAGS='-O3 -fexceptions'
export CPPFLAGS="-I$prefix/include"
export LDFLAGS="-L$prefix/lib -fexceptions"
export CPPFLAGS="-I$vienna_prefix/include -I$prefix/include"
export LDFLAGS="-L$vienna_prefix/lib -L$prefix/lib -fexceptions"
if [[ ! -f "$prefix/lib/libz.a" ]]; then
tar -xzf "$build/downloads/zlib-1.3.1.tar.gz" -C "$build/sources"
(cd "$build/sources/zlib-1.3.1"
Expand All @@ -52,27 +60,26 @@ if [[ ! -f "$prefix/.boost-1.87.0-js-exceptions-complete" ]]; then
-sZLIB_LIBPATH="$prefix/lib" --prefix="$prefix" install)
touch "$prefix/.boost-1.87.0-js-exceptions-complete"
fi
if [[ ! -f "$prefix/lib/libRNA.a" ]]; then
tar -xzf "$build/downloads/ViennaRNA-2.7.0.tar.gz" -C "$build/sources"
(cd "$build/sources/ViennaRNA-2.7.0"
CPPFLAGS="$CPPFLAGS -I$PWD/src" emconfigure ./configure --host=wasm32-unknown-emscripten --prefix="$prefix" \
if [[ ! -f "$vienna_prefix/.complete" ]]; then
mkdir -p "$vienna_sources"
tar -xzf "$build/downloads/ViennaRNA-$vienna_version.tar.gz" -C "$vienna_sources"
(cd "$vienna_sources/ViennaRNA-$vienna_version"
CPPFLAGS="$CPPFLAGS -I$PWD/src" emconfigure ./configure --host=wasm32-unknown-emscripten --prefix="$vienna_prefix" \
--disable-shared --enable-static --disable-openmp --disable-pthreads \
--disable-lto --disable-simd --disable-vectorize --disable-mpfr \
--without-svm --without-gsl --without-swig --without-perl --without-python \
--without-doc --without-cla --without-check --without-kinfold \
--without-forester --without-rnalocmin --without-rnaxplorer
# Backport dlib's upstream char32_t typedef for modern libc++ char_traits.
# Only the downloaded dependency is patched; RNAlib algorithms are unchanged.
python3 "$repo/scripts/wasm/patch-vienna.py" "$PWD"
emmake make -C src/ViennaRNA -j "$jobs"
emmake make -C src/ViennaRNA install
emmake make install-pkgconfigDATA)
touch "$vienna_prefix/.complete"
fi

# Legacy Autoconf probes declare exit()/inflateEnd() with the wrong signatures,
# which wasm-ld rejects. Verify real dependency APIs before caching those probes.
em++ -std=c++23 -O2 -fexceptions -I"$prefix/include" \
"$repo/scripts/wasm/dependency-probe.cpp" -L"$prefix/lib" \
em++ -std=c++23 -O2 -fexceptions -I"$vienna_prefix/include" -I"$prefix/include" \
"$repo/scripts/wasm/dependency-probe.cpp" -L"$vienna_prefix/lib" -L"$prefix/lib" \
-lboost_filesystem -lboost_system -lboost_program_options -lboost_regex \
-lboost_iostreams -lboost_serialization -lRNA -lz -o "$build/dependency-probe.js"
node "$build/dependency-probe.js"
Expand All @@ -83,15 +90,15 @@ export ac_cv_lib_boost_regex_exit=yes
export ac_cv_lib_boost_iostreams_exit=yes
export ac_cv_lib_z_inflateEnd=yes
# RNAlib's .pc embeds a native-only -Wl,-fno-lto; this is a static WASM build.
export VRNA_LIBS="-L$prefix/lib -lRNA -lm"
export VRNA_LIBS="-L$vienna_prefix/lib -lRNA -lm"

# Use the native Autotools source lists and CLI entry point, with a JS output.
(cd "$repo" && bash autotools-init.sh)
mkdir -p "$build/intarna"
(cd "$build/intarna"
CXXFLAGS="$CXXFLAGS -Werror=inconsistent-missing-override" CPPFLAGS="-I$build/intarna/src -I$repo/src $CPPFLAGS" emconfigure "$repo/configure" --host=wasm32-unknown-emscripten \
mkdir -p "$intarna_build"
(cd "$intarna_build"
CXXFLAGS="$CXXFLAGS -Werror=inconsistent-missing-override" CPPFLAGS="-I$intarna_build/src -I$repo/src $CPPFLAGS" emconfigure "$repo/configure" --host=wasm32-unknown-emscripten \
--disable-multithreading --disable-log-coloring --with-mdspan=kokkos \
--with-vrna="$prefix" --with-boost="$prefix" \
--with-vrna="$vienna_prefix" --with-boost="$prefix" \
--with-boost-libdir="$prefix/lib" --with-zlib="$prefix"
emmake make -C src -j "$jobs" EXEEXT=.js \
LDFLAGS="$LDFLAGS -sMODULARIZE=1 -sEXPORT_ES6=1 -sEXPORT_NAME=createIntaRNA -sENVIRONMENT=web,worker,node -sINVOKE_RUN=0 -sEXIT_RUNTIME=1 -sEXPORTED_RUNTIME_METHODS=FS,callMain -sALLOW_MEMORY_GROWTH=1 -sMAXIMUM_MEMORY=1073741824 -sSTACK_SIZE=8388608"
Expand All @@ -101,5 +108,6 @@ mkdir -p "$build/intarna"
printf '{"type":"module"}\n' > "$build/site/wasm/package.json"
node "$repo/scripts/wasm/write-build-info.mjs" "$repo" "$build/site" \
"$(emcc -dumpversion)" "$(git -C "$repo" rev-parse HEAD)" \
"$(git -C "$repo" status --porcelain --untracked-files=no)"
"$(git -C "$repo" status --porcelain --untracked-files=no)" \
"$vienna_version" "$vienna_url" "$vienna_sha256"
echo "WASM assets: $build/site/wasm"
23 changes: 23 additions & 0 deletions scripts/wasm/download.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
#!/usr/bin/env bash
# Cache only verified dependency archives; recover from invalid cached responses.
set -euo pipefail
url=$1
destination=$2
checksum=$3

# Verify existing archives too, including caches from earlier build scripts.
if [[ -f "$destination" ]]; then
if printf '%s %s\n' "$checksum" "$destination" | sha256sum --check --status; then
echo "$destination: OK (cached)"
exit 0
fi
echo "Discarding invalid cached archive: $destination" >&2
rm -- "$destination"
fi

# Never promote HTTP error pages or incomplete transfers to the download cache.
partial="$destination.part"
trap 'rm -f -- "$partial"' EXIT
curl --fail --location --retry 3 "$url" -o "$partial"
printf '%s %s\n' "$checksum" "$partial" | sha256sum --check -
mv -- "$partial" "$destination"
25 changes: 0 additions & 25 deletions scripts/wasm/patch-vienna.py

This file was deleted.

Loading
Loading