Skip to content

build(moonshine): compile moonshine C++ core from source, eliminating libmoonshine dependency#61

Draft
staging-devin-ai-integration[bot] wants to merge 4 commits intodevin/1772057250-moonshine-stt-pluginfrom
devin/moonshine-static-linking
Draft

build(moonshine): compile moonshine C++ core from source, eliminating libmoonshine dependency#61
staging-devin-ai-integration[bot] wants to merge 4 commits intodevin/1772057250-moonshine-stt-pluginfrom
devin/moonshine-static-linking

Conversation

@staging-devin-ai-integration
Copy link
Contributor

@staging-devin-ai-integration staging-devin-ai-integration bot commented Feb 27, 2026

build(moonshine): compile C++ core from source via cc crate

Summary

Fixes the rust-lld: error: unable to find library -lmoonshine build failure by replacing the dynamic linking approach with building the moonshine C++ core from source during cargo build.

Before: build.rs emitted cargo:rustc-link-lib=moonshine, requiring users to manually build and install libmoonshine.so from the moonshine repo via CMake. The moonshine project doesn't publish pre-built Linux x86_64 shared libraries, so this always failed out of the box.

After: build.rs downloads moonshine v0.0.49 source from GitHub, compiles all 17 C++ source files into a static archive (libmoonshine_core.a) using the cc crate, and links statically. ONNX Runtime remains a dynamic dependency (libonnxruntime.so) — discovered from system paths or auto-downloaded from Microsoft's GitHub releases.

Key changes:

  • build.rs: Full rewrite (~300 lines). Downloads/caches moonshine source, finds/downloads ORT with version validation, compiles C++ with cc, sets RPATH=$ORIGIN. Uses cargo:warning= messages so download/compile progress is visible during builds (first build downloads ~100MB and compiles 17 C++ files, which takes a few minutes).
  • Cargo.toml: Added cc = "1.2" build-dependency
  • plugins.yml: Added lint-moonshine CI job and moonshine format check
  • verify_bundles.py: Added moonshine bundle portability check for libonnxruntime.so
  • ConvertView.tsx: Added moonshine to transcription pipeline detection
  • moonshine-stt.yml: Fixed model reference to match plugin.yml

Environment variable overrides: MOONSHINE_SRC_DIR (local source checkout), ORT_LIB_DIR (pre-installed ORT location).

Updates since last revision

  • ORT version validation: find_or_download_onnxruntime() now checks the version of any system libonnxruntime.so by parsing versioned symlinks (e.g., libonnxruntime.so.1.17.1). Incompatible versions are skipped with a warning, and the correct ORT 1.23.2 is downloaded automatically. Previously, any system ORT was accepted regardless of version, causing a runtime segfault when moonshine (requiring ORT API v23) loaded an older ORT (e.g., 1.17.1). If ORT_LIB_DIR is set explicitly with an incompatible version, the build panics with a clear error message.
  • Convert UI fix: Added plugin::native::moonshine to checkIfTranscriptionPipeline() in ConvertView.tsx so the Convert UI shows the transcription display instead of the audio playback/download interface when running the moonshine sample pipeline.
  • Sample pipeline fix: Updated moonshine-stt.yml to reference moonshine-base-en / model_arch: base instead of moonshine-tiny-en / model_arch: tiny. The previous reference didn't match any model defined in plugin.yml, which was contributing to the "Plugin failed to create instance" runtime error.
  • Switched all progress messages from eprintln! to println!("cargo:warning=...") so users see download and compilation progress during cargo build instead of a frozen progress bar.

Review & Testing Checklist for Human

  • End-to-end runtime test: Build the plugin (just build-plugin-native-moonshine), load the moonshine sample pipeline in Convert, upload an audio file, and verify transcription output appears. Critical: While the ORT version mismatch and model path issues are now fixed, the pipeline hasn't been tested with actual audio. There may be additional runtime issues (model file structure, initialization, etc.).
  • ORT version detection edge case: On systems where libonnxruntime.so exists without versioned symlinks (e.g., custom installs), ort_version_from_dir() returns None and the system ORT is skipped. Verify this behavior is acceptable, or if we should add readelf -d fallback to check SONAME.
  • Verify the 17 hardcoded .cpp filenames match moonshine v0.0.49's actual source tree. The list was derived from their CMakeLists.txt but any mismatch will cause build failures. Cross-reference with https://github.com/moonshine-ai/moonshine/tree/v0.0.49/core
  • Verify Convert UI: Load the moonshine sample pipeline and confirm the UI shows "Transcribe Audio" button and transcription output display (not audio playback controls). This was tested visually but not with actual transcription output.
  • Build requirements: Build requires curl and tar on the host. These are standard on Linux but the build script will panic if they're missing. Verify this is acceptable.

Notes

  • Build was verified locally: cargo build --release succeeds, cargo clippy -- -D warnings passes, cargo fmt passes, all 212 project tests pass
  • UI fix was tested visually: the Convert page correctly detects the moonshine pipeline as a transcription pipeline and shows the "Transcribe Audio" button instead of audio playback/download controls (see screenshot: Convert UI with moonshine pipeline)
  • ORT version checking was tested locally: On a system with ORT 1.17.1, cargo build now correctly skips the old version with warning "Skipping onnxruntime 1.17 at /usr/local/lib (need 1.23)" and downloads ORT 1.23.2 instead. The segfault is resolved.
  • Runtime testing of the actual transcription pipeline was NOT performed — only the build system, UI detection logic, and ORT version checking were validated. The sample pipeline needs end-to-end testing with actual audio to verify model loading and transcription work correctly.
  • The approach mirrors how whisper-rs builds whisper.cpp from source
  • Linux x86_64 only: The ORT download fallback hardcodes onnxruntime-linux-x64. Confirm this is acceptable or if macOS/ARM support is needed.

Requested by @streamer45 · Devin session

… libmoonshine dependency

Rewrites build.rs to download the moonshine v0.0.49 source tarball and
compile its C++ core into a static archive using the cc crate. The plugin
no longer requires a pre-installed libmoonshine shared library.

ONNX Runtime (dynamic) is still needed at runtime and is auto-discovered
from system paths or downloaded from GitHub releases as a fallback.

Also adds:
- CI lint job for moonshine in plugins.yml
- Moonshine format check in plugins.yml
- Bundle portability check for moonshine in verify_bundles.py

Signed-off-by: StreamKit Devin <devin@streamkit.dev>
Co-Authored-By: Claudio Costa <cstcld91@gmail.com>
@staging-devin-ai-integration
Copy link
Contributor Author

🤖 Devin AI Engineer

I'll be helping with this pull request! Here's what you should know:

✅ I will automatically:

  • Address comments on this PR. Add '(aside)' to your comment to have me ignore it.
  • Look at CI failures and help fix them

Note: I can only respond to comments from users who have write access to this repository.

⚙️ Control Options:

  • Disable automatic comment and CI monitoring

streamkit-devin and others added 3 commits February 27, 2026 08:14
Switch from eprintln! to cargo:warning= so download and compilation
progress is visible to users during cargo build. The first build
downloads moonshine source and ORT, then compiles 17 C++ files,
which can take a few minutes with no other visible output.

Signed-off-by: StreamKit Devin <devin@streamkit.dev>
Co-Authored-By: Claudio Costa <cstcld91@gmail.com>
…ference

- Add plugin::native::moonshine to checkIfTranscriptionPipeline() so the
  convert UI shows transcription results instead of audio playback/download
- Fix sample pipeline to use moonshine-base-en model (matches plugin.yml)
  instead of moonshine-tiny-en which is not defined as a downloadable model

Signed-off-by: StreamKit Devin <devin@streamkit.dev>
Co-Authored-By: Claudio Costa <cstcld91@gmail.com>
The build.rs now checks the version of any discovered system
libonnxruntime.so (from versioned symlinks like libonnxruntime.so.1.17.1)
and rejects versions that don't match the required 1.23.x. If no
compatible system ORT is found, it automatically downloads ORT 1.23.2.

Previously, find_or_download_onnxruntime() accepted any libonnxruntime.so
regardless of version. Users with an older system ORT (e.g., 1.17.1)
would hit a runtime segfault because moonshine requires ORT API v23.

Signed-off-by: StreamKit Devin <devin@streamkit.dev>
Co-Authored-By: Claudio Costa <cstcld91@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants