Skip to content

MSVC and GCC Linking Errors to missing extern "Rust" function symbols #434

@david-cattermole

Description

@david-cattermole

Hello David,

Firstly, thank you for your amazing contributions to the world of Rust!

Secondly, I have begun testing your crate and have experienced some problems with the adoption on a small, but real-world example library I am starting on. I am very eager to start using the crate!

I have made an example project on GitHub to potentially help others, but also to explain the issues that I'm having.
https://github.com/david-cattermole/cxx-demo-example

Linking Errors

When building and linking the Rust library into a shared library (.so / .dll), I am getting linking errors on both Windows MSVC and CentOS Linux with GCC.

GCC 6.3.1:

CMakeFiles/mmscenegraph_tests.dir/tests/test_b.cpp.o: In function `test_b()':
test_b.cpp:(.text+0x65): undefined reference to `rust::cxxbridge05::Str::Str(std::string const&)'
CMakeFiles/mmscenegraph_tests.dir/src/lib.cpp.o: In function `mmscenegraph::make_demo(rust::cxxbridge05::Str)':
lib.cpp:(.text+0x14b): undefined reference to `rust::cxxbridge05::Str::operator std::string() const'
CMakeFiles/mmscenegraph_tests.dir/src/_cxxbridge.cpp.o: In function `mmscenegraph$cxxbridge05$make_demo':
_cxxbridge.cpp:(.text+0x10): undefined reference to `rust::cxxbridge05::Str::Str()'
CMakeFiles/mmscenegraph_tests.dir/src/_cxxbridge.cpp.o: In function `mmscenegraph$cxxbridge05$do_thing':
_cxxbridge.cpp:(.text+0x9c): undefined reference to `cxxbridge05$box$mmscenegraph$ThingR$drop'
CMakeFiles/mmscenegraph_tests.dir/src/_cxxbridge.cpp.o: In function `mmscenegraph::print_r(mmscenegraph::ThingR const&)':
_cxxbridge.cpp:(.text+0xb1): undefined reference to `mmscenegraph$cxxbridge05$print_r'
CMakeFiles/mmscenegraph_tests.dir/src/_cxxbridge.cpp.o: In function `rust::cxxbridge05::Box<mmscenegraph::ThingR>::uninit()':
_cxxbridge.cpp:(.text+0x131): undefined reference to `cxxbridge05$box$mmscenegraph$ThingR$uninit'
CMakeFiles/mmscenegraph_tests.dir/src/_cxxbridge.cpp.o: In function `rust::cxxbridge05::Box<mmscenegraph::ThingR>::drop()':
_cxxbridge.cpp:(.text+0x141): undefined reference to `cxxbridge05$box$mmscenegraph$ThingR$drop'

Visual Studio 2015:

CMakeFiles/mmscenegraph_tests.dir/tests/test_b.cpp.o: In function `test_b()':
test_b.cpp:(.text+0x65): undefined reference to `rust::cxxbridge05::Str::Str(std::string const&)'
CMakeFiles/mmscenegraph_tests.dir/src/lib.cpp.o: In function `mmscenegraph::make_demo(rust::cxxbridge05::Str)':
lib.cpp:(.text+0x14b): undefined reference to `rust::cxxbridge05::Str::operator std::string() const'
CMakeFiles/mmscenegraph_tests.dir/src/_cxxbridge.cpp.o: In function `mmscenegraph$cxxbridge05$make_demo':
_cxxbridge.cpp:(.text+0x10): undefined reference to `rust::cxxbridge05::Str::Str()'
CMakeFiles/mmscenegraph_tests.dir/src/_cxxbridge.cpp.o: In function `mmscenegraph$cxxbridge05$do_thing':
_cxxbridge.cpp:(.text+0x9c): undefined reference to `cxxbridge05$box$mmscenegraph$ThingR$drop'
CMakeFiles/mmscenegraph_tests.dir/src/_cxxbridge.cpp.o: In function `mmscenegraph::print_r(mmscenegraph::ThingR const&)':
_cxxbridge.cpp:(.text+0xb1): undefined reference to `mmscenegraph$cxxbridge05$print_r'
CMakeFiles/mmscenegraph_tests.dir/src/_cxxbridge.cpp.o: In function `rust::cxxbridge05::Box<mmscenegraph::ThingR>::uninit()':
_cxxbridge.cpp:(.text+0x131): undefined reference to `cxxbridge05$box$mmscenegraph$ThingR$uninit'
CMakeFiles/mmscenegraph_tests.dir/src/_cxxbridge.cpp.o: In function `rust::cxxbridge05::Box<mmscenegraph::ThingR>::drop()':
_cxxbridge.cpp:(.text+0x141): undefined reference to `cxxbridge05$box$mmscenegraph$ThingR$drop'

I am using CMake for the C++ side, and Cargo for the Rust side, with a Bash and Windows Batch script gluing them together.

My approach is to generate the headers using cxx, and cbindgen, then compile the Rust crate as a "staticlib" and link the Rust static library with a C++ shared library, combining the Rust symbols into the C++ shared library, with a single C++ interface.

I have noticed that most (but not all) of the problem functions are defined in the extern "Rust" block here:
https://github.com/david-cattermole/cxx-demo-example/blob/main/src/cxxbridge.rs#L22

I have also noticed that the generated C++ functions do not implement those functions and that is the true cause for the missing symbols at linking stage. For example mmscenegraph$cxxbridge05$print_r:
https://github.com/david-cattermole/cxx-demo-example/blob/main/src/_cxxbridge.cpp#L243

You can see the full output of the build_linux.bash and build_windows.bat scripts:
output_gcc_6_3_1.log or here on GitHub
output_msvc_19_0_24215_1.log or here on GitHub

I have also attempted to use "cxx v0.4.7", but I seem to get the same problem.

Am I missing something? Is my use case not supported? Is this a bug in cxx? I am I misusing cxx?

Example Project Goals

For context, the goal for the example project is to write a cross platform Rust and C++ library, with the main client being an existing C++ application, taking advantage of Rust whenever possible.
I also intend to call other C++ library dependencies, integrating well established C++ libraries that are dominate in my industry (Visual Effects).
Therefore I will use cxx/cxxbridge to create the C++ bindings, and then fallback on cbindgen whenever I hit a missing feature.

Thank you,
David Cattermole

Metadata

Metadata

Assignees

No one assigned

    Labels

    linkingIssues that manifest as link failuressupport

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions