Skip to content
New issue

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

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

Already on GitHub? Sign in 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

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
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
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

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

No branches or pull requests

2 participants