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.
60 lines
2.2 KiB
TOML
60 lines
2.2 KiB
TOML
[package]
|
|
name = "wickra-c"
|
|
description = "C ABI (cdylib + staticlib) for the Wickra streaming-first technical indicators library — the hub every C-capable language (C, C++, Go, C#, Java, R) links against."
|
|
version.workspace = true
|
|
authors.workspace = true
|
|
edition.workspace = true
|
|
rust-version.workspace = true
|
|
license.workspace = true
|
|
repository.workspace = true
|
|
homepage.workspace = true
|
|
readme = "README.md"
|
|
keywords.workspace = true
|
|
categories.workspace = true
|
|
publish = false
|
|
|
|
[lib]
|
|
name = "wickra"
|
|
crate-type = ["cdylib", "staticlib"]
|
|
|
|
# The C ABI inherently needs `unsafe` (raw pointers across the FFI boundary,
|
|
# `#[export_name]` symbol control). The workspace forbids `unsafe_code`, so this
|
|
# crate cannot inherit `workspace = true`; it mirrors every workspace lint and
|
|
# only relaxes `unsafe_code` to `allow` (parity with how the proc-macro bindings
|
|
# emit their unsafe). The Rust core stays `unsafe`-forbidden — this is the one
|
|
# crate where the boundary lives.
|
|
[lints.rust]
|
|
unsafe_code = "allow"
|
|
missing_debug_implementations = "warn"
|
|
unreachable_pub = "warn"
|
|
unused_must_use = "deny"
|
|
|
|
[lints.clippy]
|
|
all = { level = "warn", priority = -1 }
|
|
pedantic = { level = "warn", priority = -1 }
|
|
module_name_repetitions = "allow"
|
|
must_use_candidate = "allow"
|
|
missing_errors_doc = "allow"
|
|
missing_panics_doc = "allow"
|
|
cast_precision_loss = "allow"
|
|
cast_possible_truncation = "allow"
|
|
cast_sign_loss = "allow"
|
|
similar_names = "allow"
|
|
float_cmp = "allow"
|
|
|
|
[features]
|
|
# `parallel` (rayon-backed batch in wickra-core) is on by default for native
|
|
# builds. The wasm32-unknown-emscripten target has no threads, so the R
|
|
# package's wasm build (r-universe / webR) compiles this crate with
|
|
# --no-default-features to drop rayon; wickra-core falls back to its serial
|
|
# batch path, which is cfg-gated behind the same feature.
|
|
default = ["parallel"]
|
|
parallel = ["wickra-core/parallel"]
|
|
|
|
[dependencies]
|
|
# Direct path dep rather than `workspace = true`: a member-level
|
|
# `default-features = false` is ignored when inheriting a workspace dep that
|
|
# does not set it, which would leave rayon in the wasm build. wickra-c is
|
|
# `publish = false`, so no version pin is needed (and none to keep in sync).
|
|
wickra-core = { path = "../../crates/wickra-core", default-features = false }
|