View on GitHub

IntaRNA

Efficient target prediction incorporating accessibility of interaction sites

Step 1: WebAssembly compilation (#286)

scripts/wasm/build.sh cross-compiles the unmodified CLI entry point and the Autotools library source lists. .github/workflows/build-wasm.yml uses the official setup-emsdk action with Emscripten 4.0.23. It runs on pull requests, pushes to this repository’s master branch, and manual dispatches. Build tools (Autotools, pkg-config, a native C++ compiler, curl, tar and bzip2) must be available.

Reproduce locally

Activate Emscripten 4.0.23 with source /path/to/emsdk/emsdk_env.sh, then run:

bash scripts/wasm/build.sh
node scripts/wasm/smoke.mjs
node scripts/wasm/smoke-protocol.mjs

WASM_BUILD_DIR changes the build directory; JOBS defaults to 2. Local builds pin ViennaRNA 2.7.2 and its official GitHub release asset SHA-256 in scripts/wasm/vienna-release.json. On every run, the GitHub workflow resolves the newest stable 2.x release (at least 2.7.2), excludes drafts/prereleases and major 3, and uses the asset’s published SHA-256. Selection compares numeric versions across all API pages, rather than using GitHub’s /latest endpoint. Missing release assets, digests or failed API requests stop the build.

To use that same selection locally (optionally set GITHUB_TOKEN for API limits):

python3 scripts/wasm/vienna-release.py --latest > /tmp/vienna-release.json
WASM_VIENNA_RELEASE=/tmp/vienna-release.json bash scripts/wasm/build.sh

Keep the resolved manifest to reproduce that exact release later with WASM_VIENNA_RELEASE. build-info.json and build-info.txt record the selected archive URL and checksum as well as the actual compiled library version.

Source archives are downloaded into build-wasm/downloads and verified by the selected SHA-256 hashes on every invocation. Use the official GitHub release asset, rather than an autogenerated source archive; the university endpoint returned an HTTP 200 text response instead of the archive in PR #291’s build. scripts/wasm/download.sh removes invalid cached archives and checks new downloads before moving them from .part into the cache. Failed transfers and checksum mismatches leave no cached archive or partial file, so a subsequent build can retry. Run python3 scripts/wasm/test-downloads.py to check download, cache recovery and failure handling against a local HTTP server, and python3 scripts/wasm/test-vienna-release.py for release selection and manifest validation, without an SDK or external network access. The build directory is ignored. ViennaRNA sources, its installation prefix and IntaRNA objects are separated by the selected version and checksum, so upgrades cannot reuse an older RNAlib or IntaRNA object cache (including the old 2.7.0 prefix). zlib and Boost use a separate build-wasm/deps/common prefix, so legacy ViennaRNA headers cannot override the selected release through Boost’s include path. Their caches remain reusable across ViennaRNA upgrades. Delete the build directory for a fresh build after changing compiler flags or SDKs. Native libraries are never accepted from system pkg-config paths.

The script supplies absolute source and generated-header include paths for the out-of-tree IntaRNA build, and uses generated files from the build directory. ViennaRNA also needs an explicit source include path when its no-SVM build omits the target’s normal include flags. ViennaRNA 2.7.2 bundles dlib 20.0, which already supports modern libc++; no downloaded sources are patched. Staging takes the ViennaRNA, dlib and Naview notices from the source archive identified by the compiled provenance, and displays their selected versions.

The legacy Boost and zlib configure macros declare dummy test functions with incorrect signatures (exit() and inflateEnd()), which wasm-ld correctly rejects. Before caching just those probes, dependency-probe.cpp links and executes actual filesystem, regex, options, archive, gzip and RNAlib APIs against the WASM libraries. Configure still checks C++23, headers, serialization and RNAlib APIs; the smoke test executes the real prediction. VRNA_LIBS supplies the static RNAlib link flags because the upstream .pc includes native-only linker flags.

Dependencies and runtime

All C++ compilation and linking enables exceptions (-fexceptions), including Boost (exception-handling-method=js) and the CLI’s input/error handling. The SDK’s single-thread mutex support retains ViennaRNA’s normal setup/logger locking without requiring browser SharedArrayBuffer or COOP/COEP headers (unavailable on ordinary GitHub Pages).

The output is an ES module factory (createIntaRNA) in build-wasm/site/wasm/intarna.js, paired with intarna.wasm. The factory does not run main automatically; it exports FS and callMain. The runtime exits and flushes C++ streams after one call. Each prediction must use a new instance. Memory grows on demand to a maximum of 1 GiB; stack size is 8 MiB. Allocation failure is reported as a failed prediction; devices may impose lower limits.

See Emscripten’s Autotools guidance for emconfigure/emmake. Generated configure files, dependency sources and WASM binaries are build outputs, not tracked source. The artifact must keep JS and WASM from the same build together. The Node smoke test runs real Turner/default-accessibility predictions and checks energy, coordinates, nonzero accessibility costs, suboptimal counts and C++ error handling against the native CLI.

Compiled version information and virtual overrides (PR #287 review)

After copying the paired JS/WASM assets, write-build-info.mjs invokes their actual --version entry point. It records IntaRNA package version, ViennaRNA and Boost versions, source repository/revision and dirty status, Emscripten version, zlib version and asset hashes in build-info.txt and build-info.json. The interface displays those versions and links both files. Staging checks the hashes and preserves provenance even if the staging checkout has moved.

IntaRNA’s inherited virtual methods and destructors declare override, including previously unannotated energy/accessibility, seed/helix, predictor and output families. The Emscripten build treats inconsistent missing overrides as errors. Vendored Easylogging++ remains unchanged. This annotation-only C++ change does not alter algorithms, virtual extension points or scientific defaults.