From 1a20fd8ceb1964f0d2da78756bee1664c3aaa0cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Chris=20Hasi=C5=84ski?= Date: Mon, 16 Feb 2026 23:56:34 +0100 Subject: [PATCH] Hide Go runtime symbols to allow coexistence with other Charm gems MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When multiple Charm gems (bubbletea, lipgloss, etc.) are loaded in the same Ruby process, each embeds its own Go runtime via c-archive static linking. Ruby loads .bundle files with RTLD_GLOBAL, causing ~1900 Go runtime symbols to clash in the global namespace, resulting in a segfault. Fix this by using -load_hidden (macOS) / --version-script (Linux) to make all Go runtime symbols local to the .bundle. Only Init_bubbletea is exported. The Go API symbols (tea_*) remain accessible within the bundle since they're resolved at link time. Tested: bubbletea + lipgloss loaded together in Ruby 4.0 — no segfault. --- ext/bubbletea/extconf.rb | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/ext/bubbletea/extconf.rb b/ext/bubbletea/extconf.rb index c7ce4ba..b7839ee 100644 --- a/ext/bubbletea/extconf.rb +++ b/ext/bubbletea/extconf.rb @@ -42,16 +42,20 @@ def detect_platform ERROR end +go_lib_path = File.join(go_lib_dir, "libbubbletea.a") + $LDFLAGS << " -L#{go_lib_dir}" $INCFLAGS << " -I#{go_lib_dir}" -$LOCAL_LIBS << " #{go_lib_dir}/libbubbletea.a" - case RbConfig::CONFIG["host_os"] when /darwin/ + $LDFLAGS << " -Wl,-load_hidden,#{go_lib_path}" + $LDFLAGS << " -Wl,-exported_symbol,_Init_bubbletea" $LDFLAGS << " -framework CoreFoundation -framework Security -framework SystemConfiguration" $LDFLAGS << " -lresolv" when /linux/ + $LOCAL_LIBS << " #{go_lib_path}" + $LDFLAGS << " -Wl,--exclude-libs,ALL" $LDFLAGS << " -lpthread -lm -ldl" $LDFLAGS << " -lresolv" if find_library("resolv", "res_query") end