cxx
cxx copied to clipboard
Adding C++ Code in Rust cxx bridge unit tests
I am writing some Rust code that will interface with existing C++, and I am trying to write unit tests for it. The C++ tests will require some test C++ functions (that will not be needed in normal operation) so I want them only to be compiled in when running the tests.
Here is a mock up of what I am trying to achieve:
#[cxx::bridge]
mod ffi {
unsafe extern "C++" {
include!("src/foo.h");
type Foo;
pub fn greet(&self);
}
}
#[cfg(test)]
mod tests {
#[cxx::bridge]
mod ffi {
unsafe extern "C++" {
include!("src/test.h");
fn make_foo() -> UniquePtr<Foo>;
}
}
#[test]
fn test_foo() {
let foo = unsafe { ffi::make_foo() };
foo.greet();
}
}
That leads to the error:
error: unsupported type: Foo
--> src/lib.rs:23:31
|
23 | fn make_foo() -> UniquePtr<Foo>;
| ^^^
OK, so I guess I need to make use of the feature Safely unifying occurrences of an extern type across bridges described in the documentation, so I add this to my test cxx bridge:
type Foo = super::ffi::Foo;
Now it is complaining about this:
error[cxxbridge]: the name `Foo` is defined multiple times
┌─ src/lib.rs:21:4
│
21 │ type Foo = super::ffi::Foo;
│ ^^^^^^^^ the name `Foo` is defined multiple times
But that Foo is in a different Rust module to the first one, so this shouldn't be a collision?
Is it a rule that a type can only be defined once in each source file regardless of the Rust namespaces that they occur in? Also what is the best practice for testing such bridges?
I've partially worked around this by making my tests integration tests instead of unit tests (arguably they should have been integration tests from the start). This means the "test" cxx bridge is in a different file and I don't get the multiple definition error.
But that opens up another problem: I need to have the build.rs compile the second file as well, but only when doing a 'cargo test' not when doing a regular build. And I can't find a way from inside the build.rs to detect that it is building the integration test.
And I can't find a way from inside the build.rs to detect that it is building the integration test.
Can't you test for the test cfg? https://doc.rust-lang.org/cargo/reference/environment-variables.html#environment-variables-cargo-sets-for-build-scripts
I got it to dump it's entire environment, and the only CARGO_CFG_xxx variables there were the ones listed on that page, relating to the target. There was no CARGO_CFG_TEST.