diff --git a/plugin/build.rs b/plugin/build.rs index f04019c..cb64c23 100644 --- a/plugin/build.rs +++ b/plugin/build.rs @@ -1,21 +1,27 @@ use cxx_qt_build::{CxxQtBuilder, PluginType, QmlModule}; fn main() { - // Two separate problems to defeat in the cdylib link: + // Two separate problems to defeat in the cdylib link for cxx-qt's QML plugin + // entry points (qt_plugin_instance / qt_plugin_query_metadata_v2): // 1. cc-rs uses -ffunction-sections, Rust's cdylib runs --gc-sections, and - // nothing internal references qt_plugin_instance / qt_plugin_query_metadata_v2 - // (moc emits them as dlsym entry points for Qt's plugin loader, not for - // in-binary calls), so the linker drops them entirely. --undefined= + // nothing internal references those symbols (moc emits them as dlsym + // entry points), so the linker drops them entirely. --undefined= // anchors them past --gc-sections. - // 2. Even once present, Rust's cdylib link hides C++ static-archive symbols by - // default - they end up as local (lowercase t in nm), invisible to dlsym. - // --export-dynamic-symbol= doesn't help: that flag only applies to - // -shared=no (executables). For shared libraries, bare --export-dynamic - // exports all global symbols and overrides the hide-by-default. + // 2. Rust's cdylib link passes an explicit --version-script that exports + // only Rust-public symbols - everything else, including our anchored C++ + // plugin symbols, is hidden as local. Neither --export-dynamic nor + // --export-dynamic-symbol overrides an explicit version script. The fix + // is --dynamic-list=, which is additive: it appends entries to the + // dynamic symtab without fighting the version script's hides. 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"); + let dynlist = std::path::Path::new(env!("CARGO_MANIFEST_DIR")).join("qt_plugin_exports.txt"); + println!("cargo:rerun-if-changed={}", dynlist.display()); + println!( + "cargo:rustc-link-arg=-Wl,--dynamic-list={}", + dynlist.display() + ); // 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 diff --git a/plugin/qt_plugin_exports.txt b/plugin/qt_plugin_exports.txt new file mode 100644 index 0000000..321aafe --- /dev/null +++ b/plugin/qt_plugin_exports.txt @@ -0,0 +1,4 @@ +{ + qt_plugin_instance; + qt_plugin_query_metadata_v2; +};