Add emscripten-wasm32 as an opt-in target platform - #425
Open
Tobias-Fischer wants to merge 1 commit into
Open
Conversation
Adds emscripten-wasm32 support to the vinca-driven recipe pipeline,
enabling ROS 2 Humble to build for WebAssembly (via the Emscripten
toolchain) alongside the existing native platforms. All changes are
gated by wasm32/emscripten selectors in vinca.yaml/robostack.yaml/
conda_build_config.yaml -- no effect on existing platform builds.
Validated end-to-end: a full ~104-package build targeting
emscripten-wasm32 (using the pthreads-enabled vinca fork from the
companion PR at RoboStack/vinca), running a real rclcpp talker
continuously in the browser via a COOP/COEP-isolated page with genuine
SharedArrayBuffer-backed threads.
Key pieces:
- vinca.yaml: packages_select_by_deps/skip_by_deps/remove_from_deps
selectors adding a wasm32-appropriate package subset (dropping
packages with no viable wasm32 host deps: fastrtps/cyclonedds RMWs,
google-benchmark, gtest/gmock-heavy test infra, etc.)
- robostack.yaml: per-platform rosdep-key overrides for eigen/yaml/
yaml-cpp/spdlog, since emscripten-forge doesn't publish conda
packages for several of these and the vendored from-source fallback
needs to be used instead
- patch/dependencies.yaml: genuinely-missing host deps added per
package.xml audits (e.g. rmw_wasm_cpp needing libffi), gated to
emscripten where the dep is actually missing
- patch/ros-humble-{yaml-cpp-vendor,spdlog-vendor}.emscripten.patch:
fix CMAKE_PROJECT_INCLUDE propagation into each vendor's own nested
ExternalProject_Add build (without it, the nested build silently
loses vinca's global side-module/pthread flags)
- patch/ros-humble-rosidl-generator-py.patch: numpy 2.x header path
fix (numpy/core/include -> numpy/_core/include)
- patch/ros-humble-{wasm-cpp,rmw-wasm-cpp,test-wasm}.patch: patches
against github.com/ros2wasm/rmw_wasm's wasm_cpp/rmw_wasm_cpp/
test_wasm packages -- fix a genuine embind duplicate-registration
bug, drop dead SQLite3/ZLIB/BZip2 deps that broke once pthreads
were enabled (emscripten-forge's prebuilt static libs for these
aren't pthread-compatible, and nothing in rmw_wasm_cpp's own
sources ever calls into them), and remove the stale hardcoded
USE_PTHREADS=0 overrides now that vinca sets it globally
- patch/ros-humble-rcutils.emscripten.patch: the actual root-cause
fix for the demo running only once and then hanging forever --
rcutils_steady_time_now() (which rclcpp::WallTimer actually uses)
called clock_gettime(CLOCK_MONOTONIC_RAW, ...), which is silently
broken in this emscripten/pthread build (the nanosecond field gets
misread as the seconds field), even though plain CLOCK_MONOTONIC on
the same build works correctly. Switched both rcutils_system_time_now
and rcutils_steady_time_now to CLOCK_MONOTONIC under emscripten.
- conda_build_config.yaml/vinca_pinning.yaml: emscripten-forge/
recipes-specific version pins (emscripten SDK 4.0.9, python 3.13,
libffi 3.4.6, graphviz 15.1.0) where their published package set
doesn't match conda-forge-pinning's regular versions
- .github/workflows/testpr.yml: point the emscripten-wasm32 CI job at
repo.prefix.dev/emscripten-forge-4x (repo.mamba.pm/emscripten-forge
is stale/legacy, ~1/3 the package count as of 2026-09-07)
Depends on RoboStack/vinca#154 (pthreads support) -- pixi.toml
currently pins the Tobias-Fischer/vinca fork branch; re-point to the
merged upstream commit once that PR lands.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds
emscripten-wasm32support to the vinca-driven recipe pipeline, enabling ROS 2 Humble to build for WebAssembly (via the Emscripten toolchain) alongside the existing native platforms. All changes are gated bywasm32/emscriptenselectors invinca.yaml/robostack.yaml/conda_build_config.yaml— no effect on existing platform builds.Validated end-to-end: a full ~104-package build targeting
emscripten-wasm32, running a realrclcpptalker continuously in the browser via a COOP/COEP-isolated page with genuineSharedArrayBuffer-backed threads (real pthreads, not a JS shim).Depends on RoboStack/vinca#154 (pthreads support for emscripten-wasm32) —
pixi.tomlcurrently pins theTobias-Fischer/vincafork branch; re-point to the merged upstream commit once that PR lands.Key pieces
vinca.yaml:packages_select_by_deps/skip_by_deps/remove_from_depsselectors adding a wasm32-appropriate package subset (dropping packages with no viable wasm32 host deps: fastrtps/cyclonedds RMWs, google-benchmark, gtest/gmock-heavy test infra, etc.)robostack.yaml: per-platform rosdep-key overrides for eigen/yaml/yaml-cpp/spdlog, since emscripten-forge doesn't publish conda packages for several of these and the vendored from-source fallback needs to be used insteadpatch/dependencies.yaml: genuinely-missing host deps added perpackage.xmlaudits (e.g.rmw_wasm_cppneedinglibffi), gated to emscripten where the dep is actually missingpatch/ros-humble-{yaml-cpp-vendor,spdlog-vendor}.emscripten.patch: fixCMAKE_PROJECT_INCLUDEpropagation into each vendor's own nestedExternalProject_Addbuild (without it, the nested build silently loses vinca's global side-module/pthread flags)patch/ros-humble-rosidl-generator-py.patch: numpy 2.x header path fix (numpy/core/include→numpy/_core/include)patch/ros-humble-{wasm-cpp,rmw-wasm-cpp,test-wasm}.patch: patches againstgithub.com/ros2wasm/rmw_wasm'swasm_cpp/rmw_wasm_cpp/test_wasmpackages — fix a genuine embind duplicate-registration bug, drop dead SQLite3/ZLIB/BZip2 deps that broke once pthreads were enabled (emscripten-forge's prebuilt static libs for these aren't pthread-compatible, and nothing inrmw_wasm_cpp's own sources ever calls into them), and remove stale hardcodedUSE_PTHREADS=0overrides now that vinca sets it globallypatch/ros-humble-rcutils.emscripten.patch: the actual root-cause fix for the demo running only once and then hanging forever —rcutils_steady_time_now()(whichrclcpp::WallTimeractually uses) calledclock_gettime(CLOCK_MONOTONIC_RAW, ...), which is silently broken in this emscripten/pthread build (the nanosecond field gets misread as the seconds field), even though plainCLOCK_MONOTONICon the same build works correctly. Switched bothrcutils_system_time_nowandrcutils_steady_time_nowtoCLOCK_MONOTONICunder emscripten.vinca_pinning.yaml/conda_build_config.yaml: emscripten-forge/recipes-specific version overrides (emscripten SDK 4.0.9, python 3.13, libffi 3.4.6, graphviz 15.1.0) layered on top of the existing conda-forge-pinning-derived config, for the packages where emscripten-forge's published set doesn't match conda-forge-pinning's regular versions.github/workflows/testpr.yml: point the emscripten-wasm32 CI job atrepo.prefix.dev/emscripten-forge-4x(repo.mamba.pm/emscripten-forgeis stale/legacy, ~1/3 the package count as of 2026-09-07)Testing
Full 104-recipe build succeeded; extracted the resulting
test_wasmpackage into amicromamba-createdemscripten-wasm32environment, served it locally with COOP/COEP headers, and confirmed thetalkerdemo runs continuously (55+ consecutive correctly-timed publishes) and thelistenerdemo initializes and spins cleanly on the subscriber code path.🤖 Generated with Claude Code