Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Linker error when trying to include more than one Rust bridge #956

Closed
akiselev opened this issue May 19, 2024 · 3 comments
Closed

Linker error when trying to include more than one Rust bridge #956

akiselev opened this issue May 19, 2024 · 3 comments

Comments

@akiselev
Copy link
Contributor

akiselev commented May 19, 2024

Repro repository here: https://github.com/akiselev/linker-repro

I am trying to bind several QWidgets classes but I'm getting undefined reference/symbol errors when trying to build more than one Rust file with CxxQt bindings.

For the above repro repository, this is the order in build.rs

    builder = builder.file("src/widgets/qmainwindow.rs");
    builder = builder.file("src/gui/window.rs");

This is the error (I have tried with lld and mold):

  = note: mold: error: undefined symbol: cxxbridge1$unique_ptr$QMainWindow$get
          >>> referenced by 1dndnmyx9n9inks4
          >>>               /home/akiselev/git/linker-repro/target/debug/deps/linker_repro-adcedbdfd5841a4f.1dndnmyx9n9inks4.rcgu.o:(cxx::unique_ptr::UniquePtr$LT$T$GT$::from_raw::h623f3965ec02390b)
          
          mold: error: undefined symbol: rust$cxxqtlib2$cxxbridge1$qmainwindow_new
          >>> referenced by 1dndnmyx9n9inks4
          >>>               /home/akiselev/git/linker-repro/target/debug/deps/linker_repro-adcedbdfd5841a4f.1dndnmyx9n9inks4.rcgu.o:(linker_repro::widgets::qmainwindow::ffi::qmainwindow_new::ha885b51589433ed5)
          
          mold: error: undefined symbol: cxxbridge1$unique_ptr$QMainWindow$drop
          >>> referenced by 1dndnmyx9n9inks4
          >>>               /home/akiselev/git/linker-repro/target/debug/deps/linker_repro-adcedbdfd5841a4f.1dndnmyx9n9inks4.rcgu.o:(_$LT$linker_repro..widgets..qmainwindow..ffi..QMainWindow$u20$as$u20$cxx..unique_ptr..UniquePtrTarget$GT$::__drop::h3a648050050949fc)
          
          mold: error: undefined symbol: cxxbridge1$QMainWindow$show
          >>> referenced by 1dndnmyx9n9inks4
          >>>               /home/akiselev/git/linker-repro/target/debug/deps/linker_repro-adcedbdfd5841a4f.1dndnmyx9n9inks4.rcgu.o:(linker_repro::widgets::qmainwindow::ffi::QMainWindow::show::h9d25c8f2737bd474)
          
          mold: error: undefined symbol: cxxbridge1$unique_ptr$QMainWindow$raw
          >>> referenced by 1dndnmyx9n9inks4
          >>>               /home/akiselev/git/linker-repro/target/debug/deps/linker_repro-adcedbdfd5841a4f.1dndnmyx9n9inks4.rcgu.o:(_$LT$linker_repro..widgets..qmainwindow..ffi..QMainWindow$u20$as$u20$cxx..unique_ptr..UniquePtrTarget$GT$::__raw::hed6cd98e7f4a8b30)
          
          collect2: error: ld returned 1 exit status

If I change the order of the builder.file calls in build.rs:

    builder = builder.file("src/gui/window.rs");
    builder = builder.file("src/widgets/qmainwindow.rs");

It finds the QMainWindow symbols but instead fails to find the QWindow symbols:

  = note: mold: error: undefined symbol: rust$cxxqtlib2$cxxbridge1$qwindow_new
          >>> referenced by 15ze6smicxvukw75
          >>>               /home/akiselev/git/linker-repro/target/debug/deps/linker_repro-adcedbdfd5841a4f.15ze6smicxvukw75.rcgu.o:(linker_repro::gui::window::ffi::qwindow_new::ha8d93fde6a8567c7)
          
          mold: error: undefined symbol: cxxbridge1$unique_ptr$QWindow$drop
          >>> referenced by 15ze6smicxvukw75
          >>>               /home/akiselev/git/linker-repro/target/debug/deps/linker_repro-adcedbdfd5841a4f.15ze6smicxvukw75.rcgu.o:(_$LT$linker_repro..gui..window..ffi..QWindow$u20$as$u20$cxx..unique_ptr..UniquePtrTarget$GT$::__drop::hb2b2db5a56693e73)
          
          mold: error: undefined symbol: cxxbridge1$QWindow$show
          >>> referenced by 15ze6smicxvukw75
          >>>               /home/akiselev/git/linker-repro/target/debug/deps/linker_repro-adcedbdfd5841a4f.15ze6smicxvukw75.rcgu.o:(linker_repro::gui::window::ffi::QWindow::show::h354f6b949148b13e)
          
          mold: error: undefined symbol: cxxbridge1$unique_ptr$QWindow$raw
          >>> referenced by 15ze6smicxvukw75
          >>>               /home/akiselev/git/linker-repro/target/debug/deps/linker_repro-adcedbdfd5841a4f.15ze6smicxvukw75.rcgu.o:(_$LT$linker_repro..gui..window..ffi..QWindow$u20$as$u20$cxx..unique_ptr..UniquePtrTarget$GT$::__raw::ha9746a1dec5643c6)
          
          mold: error: undefined symbol: cxxbridge1$unique_ptr$QWindow$get
          >>> referenced by 15ze6smicxvukw75
          >>>               /home/akiselev/git/linker-repro/target/debug/deps/linker_repro-adcedbdfd5841a4f.15ze6smicxvukw75.rcgu.o:(_$LT$linker_repro..gui..window..ffi..QWindow$u20$as$u20$cxx..unique_ptr..UniquePtrTarget$GT$::__get::ha18cfff8f68f3aa1)
          
          collect2: error: ld returned 1 exit status

Whichever Rust file is last is the one that gets linked in, the rest get ignored. If I use this order in build.rs:

    builder = builder.file("src/widgets/qmainwindow.rs");
    builder = builder.file("src/gui/window.rs");

and remove QMainWindow from main.rs altogether:

fn main() {
    let mut app = QGuiApplication::new();

    let mut window = gui::QWindow::new();
    window.as_mut().unwrap().show();

    if let Some(app) = app.as_mut() {
        app.exec();
    }
}

It builds and shows a window when run.


Does anyone have any idea why this is happening?

@akiselev
Copy link
Contributor Author

After instrumenting cxx-qt-build it looks like it's generating all of the #[cxx_qt::bridge] code in the same ffi.cxx.cpp file path, where as cxx-qt-lib files annotated with #[cxx::bridge] have unique names.

warning: linker-repro@0.1.0: Generating "/home/akiselev/git/linker-repro/target/debug/build/linker-repro-ed6c7f718c01b592/out/cxx-qt-gen/src/ffi.cxx.cpp"
warning: linker-repro@0.1.0: Generating "/home/akiselev/git/linker-repro/target/debug/build/linker-repro-ed6c7f718c01b592/out/cxx-qt-gen/src/ffi.cxx.cpp"
warning: cxx-qt-lib@0.6.1: Generating "/home/akiselev/git/linker-repro/target/debug/build/cxx-qt-lib-22d15c8779448e22/out/cxx-qt-gen/src/qbytearray.cxx.cpp"
warning: cxx-qt-lib@0.6.1: Generating "/home/akiselev/git/linker-repro/target/debug/build/cxx-qt-lib-22d15c8779448e22/out/cxx-qt-gen/src/qcoreapplication.cxx.cpp"

Is this intentional behavior with cxx-qt? Is there a way I can fix it to generate separate files?

@akiselev
Copy link
Contributor Author

I think I found the culprit

Since the file is named after the module (ffi in both files in this case), it overwrote them. Turns out I have to have unique module names for the CxxQtBridge.

@ahayzen-kdab
Copy link
Collaborator

Yup, until rust-lang/rust#54725 is stabilised we cannot replicate the CXX behaviour, see the ancient WIP branch here #200 and issue here #855

Until that happens I was going to make cxx_file_stem mandatory to avoid this situation, one of the commits in #856

# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants