aboutsummaryrefslogtreecommitdiff
path: root/book/src/build/other.md
blob: af835e658cd595e2f893546521b18129fcf0e884 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
{{#title Other build systems — Rust ♡ C++}}
# 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.

  ```console
  $  cxxbridge src/bridge.rs --header > path/to/bridge.rs.h
  $  cxxbridge src/bridge.rs > path/to/bridge.rs.cc
  ```

  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.

[cxx-gen]: https://docs.rs/cxx-gen

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

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/or
  `cargo` to generate a _single_ Rust `staticlib` 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 of `extern crate` statements to
    include multiple Rust `rlib`s.  Multiple Rust `staticlib` files are likely
    to conflict.

Passing Rust `rlib`s directly into your non-Rust linker is not supported (but
apparently sometimes works).

See the [Rust reference's *Linkage*][linkage] page for some general information
here.

[linkage]: https://doc.rust-lang.org/reference/linkage.html

The following open rust-lang issues might hold more recent guidance or
inspiration: [rust-lang/rust#73632], [rust-lang/rust#73295].

[rust-lang/rust#73632]: https://github.com/rust-lang/rust/issues/73632
[rust-lang/rust#73295]: https://github.com/rust-lang/rust/issues/73295