dtolnay / cxx

Safe interop between Rust and C++
https://cxx.rs
Apache License 2.0
5.68k stars 320 forks source link

Link failure when using CXX-backed function from another crate #1352

Open toolCHAINZ opened 1 month ago

toolCHAINZ commented 1 month ago

Hello! First off, thank you for this amazing library, I can still hardly believe FFI with C++ is even possible.

I've written a small open-source crate using CXX internally. I have a separate rust binary crate using this FFI crate and I get link errors, both on macOS and in linux CI, whenever I try to use one of my FFI-backed functions.

The Error

I've been using these bindings for a couple months with no issues. However, when I attempt to use certain pieces of FFI-backed code from outside the crate containing the FFI, I get linking errors. The linking errors themselves, to my small knowledge, look like it's for some reason missing cxxbridge from the link, so I am very puzzled. An example:

          Undefined symbols for architecture arm64:
            "rust::cxxbridge1::Vec<RegisterInfoFFI>::reserve_total(unsigned long)", referenced from:
                void rust::cxxbridge1::Vec<RegisterInfoFFI>::emplace_back<RegisterInfoFFI>(RegisterInfoFFI&&) in libjingle_sleigh-55ff5eb70a22afff.rlib[44](9a90cf8c3965885f-context.o)
            "rust::cxxbridge1::Vec<RegisterInfoFFI>::drop()", referenced from:
                rust::cxxbridge1::Vec<RegisterInfoFFI>::~Vec() in libjingle_sleigh-55ff5eb70a22afff.rlib[44](9a90cf8c3965885f-context.o)
            "rust::cxxbridge1::Vec<RegisterInfoFFI>::set_len(unsigned long)", referenced from:
                void rust::cxxbridge1::Vec<RegisterInfoFFI>::emplace_back<RegisterInfoFFI>(RegisterInfoFFI&&) in libjingle_sleigh-55ff5eb70a22afff.rlib[44](9a90cf8c3965885f-context.o)
            "rust::cxxbridge1::Vec<RegisterInfoFFI>::Vec()", referenced from:
                ContextFFI::getRegisters() const in libjingle_sleigh-55ff5eb70a22afff.rlib[44](9a90cf8c3965885f-context.o)
            "rust::cxxbridge1::Vec<RegisterInfoFFI>::data() const", referenced from:
                rust::cxxbridge1::Vec<RegisterInfoFFI>::data() in libjingle_sleigh-55ff5eb70a22afff.rlib[44](9a90cf8c3965885f-context.o)
            "rust::cxxbridge1::Vec<RegisterInfoFFI>::size() const", referenced from:
                void rust::cxxbridge1::Vec<RegisterInfoFFI>::emplace_back<RegisterInfoFFI>(RegisterInfoFFI&&) in libjingle_sleigh-55ff5eb70a22afff.rlib[44](9a90cf8c3965885f-context.o)
          ld: symbol(s) not found for architecture arm64
          clang: error: linker command failed with exit code 1 (use -v to see invocation)

The library crate

https://github.com/toolCHAINZ/jingle

The subcrate named jingle_sleigh uses CXX and its build.rs is here: https://github.com/toolCHAINZ/jingle/blob/721cacd28677b0085059abaeca7fd2201433bdca/jingle_sleigh/build.rs

A minimized reproduction

I've made a very small example that triggers this link error on my machine, which you can find here:

https://github.com/toolCHAINZ/link_error/tree/main

It basically just consists of this main.rs:

use jingle::sleigh::context::{Image, SleighContextBuilder};
use jingle::sleigh::RegisterManager;

fn main() {
    let ctx = SleighContextBuilder::load_ghidra_installation("/Applications/ghidra")
        .unwrap()
        .set_image(Image::from(vec![0, 1, 2, 3]))
        .build("x86:LE:64:default").unwrap();
    ctx.read(0, 1);
    // uncomment this line to get a linking error
    // ctx.get_registers();
    println!("Hello, world!");
}

As reproduced above, this should build, but if the get_registers() line is uncommented, the link fails.

Any pointers you could give as to what I'm misconfiguring would be appreciated!