From d47200932d3804f7664251140836607fa6fb2df9 Mon Sep 17 00:00:00 2001 From: Damocles Date: Sun, 3 May 2026 21:08:19 +0200 Subject: [PATCH] plugin: anchor qt_plugin entry symbols past --gc-sections so qt finds them --- plugin/build.rs | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/plugin/build.rs b/plugin/build.rs index 25f5ca8..6188563 100644 --- a/plugin/build.rs +++ b/plugin/build.rs @@ -1,12 +1,17 @@ use cxx_qt_build::{CxxQtBuilder, PluginType, QmlModule}; fn main() { - // Rust cdylib uses a version script that hides everything not declared - // `#[no_mangle] pub extern "C"`. cxx-qt's QQmlEngineExtensionPlugin entry - // points (qt_plugin_instance, qt_plugin_query_metadata_v2) come from - // compiled C++ and would otherwise be stripped to local visibility, so Qt's - // plugin loader finds nothing exported. --export-dynamic re-exposes them. - println!("cargo:rustc-link-arg=-Wl,--export-dynamic"); + // cc-rs compiles with -ffunction-sections, Rust's cdylib link runs --gc-sections, + // and nothing internal references qt_plugin_instance/qt_plugin_query_metadata_v2 + // - moc generates them as Qt's plugin entry points for dlopen, not for in-binary + // calls. So the linker drops them entirely (verified: `nm libNovaStats.so | grep + // qt_plugin_instance` returns nothing, only the static const inside the dropped + // function survives). --undefined anchors them past --gc-sections, then + // --export-dynamic-symbol exposes them for Qt's dlsym lookup. + for sym in ["qt_plugin_instance", "qt_plugin_query_metadata_v2"] { + println!("cargo:rustc-link-arg=-Wl,--undefined={sym}"); + println!("cargo:rustc-link-arg=-Wl,--export-dynamic-symbol={sym}"); + } // Crane's deps-only build stubs out lib.rs and removes our bridge sources to // build a dummy crate that only compiles dependencies. Skip cxx-qt codegen in