Some other build system
You will need to achieve at least these three things:
- Produce the CXX-generated C++ bindings code.
- Compile the generated C++ code.
- Link the resulting objects together with your other C++ and Rust objects.
Not all build systems are created equal. If you're hoping to use a build system from the '90s, especially if you're hoping to overlaying the limitations of 2 or more build systems (like automake+cargo) and expect to solve them simultaneously, then be mindful that your expectations are set accordingly and seek sympathy from those who have imposed the same approach on themselves.
Producing the generated code
CXX's Rust code generation automatically happens when the #[cxx::bridge]
procedural macro is expanded during the normal Rust compilation process, so no
special build steps are required there.
But the C++ side of the bindings needs to be generated. Your options are:
-
Use the
cxxbridge
command, which is a standalone command line interface to the CXX C++ code generator. Wire up your build system to compile and invoke this tool.It's packaged as the
cxxbridge-cmd
crate on crates.io or can be built from the gen/cmd/ directory of the CXX GitHub repo. -
Or, build your own code generator frontend on top of the cxx-gen crate. This is currently unofficial and unsupported.
Compiling C++
However you like. We can provide no guidance.
Linking the C++ and Rust together
When linking a binary which contains mixed Rust and C++ code, you will have to
choose between using the Rust toolchain (rustc
) or the C++ toolchain which you
may already have extensively tuned.
The generated C++ code and the Rust code generated by the procedural macro both
depend on each other. Simple examples may only require one or the other, but in
general your linking will need to handle both directions. For some linkers, such
as llvm-ld, this is not a problem at all. For others, such as GNU ld, flags like
--start-lib
/--end-lib
may help.
Rust does not generate simple standalone .o
files, so you can't just throw the
Rust-generated code into your existing C++ toolchain linker. Instead you need to
choose one of these options:
-
Use
rustc
as the final linker. Pass any non-Rust libraries using-L <directory>
and-l<library>
rustc arguments, and/or#[link]
directives in your Rust code. If you need to link against C/C++.o
files you can use-Clink-arg=file.o
. -
Use your C++ linker. In this case, you first need to use
rustc
and/orcargo
to generate a single Ruststaticlib
target and pass that into your foreign linker invocation.- If you need to link multiple Rust subsystems, you will need to generate a
single
staticlib
perhaps using lots ofextern crate
statements to include multiple Rustrlib
s. Multiple Ruststaticlib
files are likely to conflict.
- If you need to link multiple Rust subsystems, you will need to generate a
single
Passing Rust rlib
s directly into your non-Rust linker is not supported (but
apparently sometimes works).
See the Rust reference's Linkage page for some general information here.
The following open rust-lang issues might hold more recent guidance or inspiration: rust-lang/rust#73632, rust-lang/rust#73295.