ratatui_ruby does not build/run on Cygwin without manual workarounds
Description
ratatui_ruby cannot be installed from source on Cygwin (x86_64-cygwin) without several manual workarounds — three separate, independent bugs each mask the next until fixed. No precompiled binary gem exists for Cygwin, so every Cygwin user hits the source build path and all three issues. Root causes are in rb_sys (two bugs) and crossterm’s Cygwin input handling (one bug), not ratatui_ruby itself, but they’re only reachable/visible through installing this gem.
Environment: Cygwin (Ruby 4.0.6), rb_sys 0.9.128, rb-sys 0.9.123, crossterm 0.29.0, magnus 0.8.2.
Steps to Reproduce
On a clean Cygwin install with ruby-devel, clang, libclang-devel, cargo/rustc installed:
gem install ratatui_ruby
Expected Results
Gem installs successfully, require 'ratatui_ruby' loads, and RatatuiRuby.run’s interactive event loop (arrow keys, q/Esc to quit) responds normally.
Actual Results
Fails in stages, each only visible after fixing the last:
1. bindgen/clang parse failure
rb-sys’s build script panics generating FFI bindings:
error: 'short __wchar_t' is invalid
thread 'main' panicked at rb-sys-build-0.9.123/build/main.rs:51: generate bindings: ClangDiagnostic(...)
Cygwin’s __wchar_t typedef conflicts with clang’s builtin under default flags.
2. Wrong build-artifact filename (rb_sys bug)
Once (1) is worked around, the build fails with:
cp: cannot stat 'target/release/libratatui_ruby.so'
rb_sys’s CargoBuilder#so_ext (lib/rb_sys/cargo_builder.rb) predicts Cargo’s raw cdylib output filename from RbConfig::CONFIG["SOEXT"], which is "so" on Cygwin — that’s Ruby’s own require-facing convention (true on every platform, including native Windows), not evidence of the underlying binary format. Cargo’s actual output for x86_64-pc-cygwin is ratatui_ruby.dll (no lib prefix, genuine Windows PE format) — verified directly with a throwaway cargo build --release cdylib crate. The win_target? fallback (Gem::WIN_PATTERNS) also excludes Cygwin, since RubyGems treats it as its own platform distinct from mingw/mswin, so there’s no branch that gets this right for Cygwin specifically.
3. Missing Ruby link flag (rb_sys bug)
Once (2) is worked around, the final Rust link step fails:
undefined reference to `rb_protect'
undefined reference to `rb_errinfo'
undefined reference to `rb_cBasicObject'
CargoBuilder#platform_specific_rustc_args only adds Ruby’s linker flags (LIBRUBYARG_SHARED, i.e. -lruby400) when mingw_target? is true — which, like (2), never matches Cygwin.
4. Interactive TUI hangs completely (crossterm bug)
Once the gem actually builds and installs, RatatuiRuby.run’s event loop draws its first frame then never responds to any key (q, arrows, Esc) or Ctrl-C, requiring the process to be killed externally. Reproduces identically in both mintty and Windows Terminal; unrelated to terminal choice. crossterm defaults to reading input via mio’s poll()-based selector on Cygwin (mio groups Cygwin with far-less-exercised targets like Solaris/QNX/Vita, not Linux’s epoll path), and that selector doesn’t reliably notice available input on a Cygwin tty.
Workaround
Full working recipe (env vars + a RUBYOPT-injected monkeypatch for the rb_sys bugs, plus a post-install Cargo.toml edit for the crossterm bug): RatatuiRuby Cygwin Install/Build Instructions
Summary of the pieces:
BINDGEN_EXTRA_CLANG_ARGS="-D__wchar_t=__cygwin_wchar_t"works around (1)- A
RbSys::CargoBuilder#so_extoverride returning"dll"on Cygwin works around (2) RUSTFLAGS="-C link-arg=-lruby400"works around (3)- Adding a direct
crosstermdependency withfeatures = ["use-dev-tty"]to the installed gem’s ownCargo.tomland rebuilding works around (4)