blob: 2f510a21ef6582246c4ae9cc070bdff977e7daab [file] [log] [blame] [view]
Devin Jeanpierre68c7b622023-03-10 14:15:37 -08001# Rust bindings for C++ libraries
Marcel Hlopko7ebafb22021-07-30 12:14:00 +00002
Marcel Hlopkoe8f1c4e2021-07-28 18:12:49 +00003`:rs_bindings_from_cc` parses C++ headers and generates:
4
Devin Jeanpierre68c7b622023-03-10 14:15:37 -08005* A Rust source file with bindings for the C++ API
6* A C++ source file with the implementation of the bindings
7
8## Architecture
9
10At a high level, Crubit parses C++ headers using Clang (with the
Dmitri Gribenko6b84d332023-07-28 06:22:14 -070011[same configuration](../docs/bindings/overview/reproducible_builds.md) as when
12used to compile C++). A distilled intermediate representation is passed to Rust,
13which generates actual Rust and C++ source code for the bindings.
Devin Jeanpierre68c7b622023-03-10 14:15:37 -080014
15Some key source files:
16
17* [`rs_bindings_from_cc.cc`](rs_bindings_from_cc.cc): The `main()` function
18 for bindings generation.
19* [`importers/*`](importers/): The Clang-AST processing classes, which extract
20 the important details about the C++ AST. When implementing a new C++ feature
21 (e.g. supporting aliases, or typedefs), it must first be added here,
22* [`ir.h`](ir.h) and [`ir.rs`](ir.rs): The intermediate representation,
23 produced by `importers/*.cc` and consumed by `src_code_gen.rs`. If source
24 code generation needs to understand something about the AST, it must be
25 present here.
26* [`src_code_gen.rs`](src_code_gen.rs): The actual bindings code generation.
27 This is where the majority of decisions about source code generation go
28 (e.g. how to represent reference types, which traits to implement, etc.)
29
30In addition, the generated bindings can depend on runtime libraries, found in
31[`crubit/support/`](../support/). For example, the Rust type for rvalue
32references is found there.
33
34## Manual testing
35
36### Golden files
37
38The easiest way to see the output of Crubit on a C++ header is to add the header
39to the [`golden`](test/golden) directory and regenerate the golden outputs:
40
41```sh
42rs_bindings_from_cc/test/golden/update.sh
43```
44
45### Running Crubit on a Bazel target
46
47To specifically see what bindings Crubit generates for a bazel target, one can
48specifically invoke Crubit's aspect and inspect the generated output:
49
50```sh
51$ bazel build --aspects //rs_bindings_from_cc/bazel_support:rust_bindings_from_cc_aspect.bzl%rust_bindings_from_cc_aspect --output_groups=out //some/cc/library/target:here
52```
53
54The source files used for interop will be output into bazel-bin, and their paths
55will be output to the terminal.
56
57### `:test_wrapper`
Marcel Hlopkoe8f1c4e2021-07-28 18:12:49 +000058
59For convenience, `:test_wrapper` is a shell script that passes all Clang command
Marcel Hlopko9a94fc42022-04-06 23:35:36 -070060line flags from the current Bazel C++ toolchain:
Marcel Hlopkoe8f1c4e2021-07-28 18:12:49 +000061
62```
Devin Jeanpierred7f4b3b2021-10-06 15:28:18 +000063bazel run //rs_bindings_from_cc:test_wrapper -- --public_headers=hello_world.h
Marcel Hlopkoe8f1c4e2021-07-28 18:12:49 +000064```
65
66or:
67
68```
69bazel build //rs_bindings_from_cc:test_wrapper
Devin Jeanpierred7f4b3b2021-10-06 15:28:18 +000070bazel-bin/rs_bindings_from_cc/test_wrapper --public_headers=hello_world.h
Marcel Hlopkoe8f1c4e2021-07-28 18:12:49 +000071```
72
Devin Jeanpierre68c7b622023-03-10 14:15:37 -080073## Testing Practices
Marcel Hlopkoe8f1c4e2021-07-28 18:12:49 +000074
Marcel Hlopko5b8c1122021-12-10 06:59:23 +000075If possible follow these recommendations:
Marcel Hlopkoe8f1c4e2021-07-28 18:12:49 +000076
Marcel Hlopko5b8c1122021-12-10 06:59:23 +000077* Unit tests for
Kinuko Yasudaabf4f3e2022-08-16 12:09:49 -070078 [`src_code_gen`](rs_bindings_from_cc/src_code_gen.rs)
79 should:
80 * be written in Rust
Marcel Hlopko5b8c1122021-12-10 06:59:23 +000081 * have snippets of C++ as input
82 * use
Kinuko Yasudaabf4f3e2022-08-16 12:09:49 -070083 [`assert_cc_matches!/assert_rs_matches!/assert_cc_not_matches!/assert_rs_not_matches!`](rs_bindings_from_cc/token_stream_matchers.rs)
Marcel Hlopko5b8c1122021-12-10 06:59:23 +000084 macros
85* Unit tests for the
Kinuko Yasudaabf4f3e2022-08-16 12:09:49 -070086 [`importer`](rs_bindings_from_cc/importer.h)
87 should:
88 * be written in Rust
89 ([`ir_from_cc_test.rs`](rs_bindings_from_cc/ir_from_cc_test.rs))
Marcel Hlopko5b8c1122021-12-10 06:59:23 +000090 so they cover both AST logic and IR serialization/deserialization, but
91 C++ tests (thanks to its nice matchers) are also OK at the moment
Kinuko Yasudaabf4f3e2022-08-16 12:09:49 -070092 ([`importer_test.cc`](rs_bindings_from_cc/importer_test.cc))
Marcel Hlopko5b8c1122021-12-10 06:59:23 +000093 * have snippets of C++ as input
94 * make assertions on the content of the IR
95* Write tests for the command line interface of interop tools in
Kinuko Yasudaabf4f3e2022-08-16 12:09:49 -070096 [`rs_bindings_from_cc_test.sh`](rs_bindings_from_cc/test/rs_bindings_from_cc_test.sh).
Marcel Hlopko5b8c1122021-12-10 06:59:23 +000097* Write golden file tests (comparing both the C++ and Rust generated source
98 code against the checked-in files) in
Kinuko Yasudaabf4f3e2022-08-16 12:09:49 -070099 [`test/golden`](rs_bindings_from_cc/test/golden/).
100 * Run
101 [`rs_bindings_from_cc/test/golden/update.sh`](rs_bindings_from_cc/test/golden/update.sh)
102 to regenerate checked-in files.
Googlerb2ef22d2022-01-04 11:17:22 +0000103* Write full executable end-to-end tests (verifying that interop tools and
Marcel Hlopko9a94fc42022-04-06 23:35:36 -0700104 Bazel rules generate outputs that can be built and executed) as small
Marcel Hlopko5b8c1122021-12-10 06:59:23 +0000105 projects with a `rust_test` or `cc_test` on top in subpackages of `test`.
Devin Jeanpierred9c382a2021-12-15 10:23:25 +0000106
Devin Jeanpierre68c7b622023-03-10 14:15:37 -0800107To run individual rust tests with `bazel test` (like `bazel test
108--test_filter=<test>` for gtest cases), give the test function name as
109`--test_arg=<test>`.
Kinuko Yasudaed9efd82022-08-18 13:55:01 -0700110
Googlerb2ef22d2022-01-04 11:17:22 +0000111To get Rust backtraces for `rs_bindings_from_cc` when running end-to-end tests,
112use `bazel test --action_env=RUST_BACKTRACE=1` to run the tests.
113
Marcel Hlopko253ceb42022-09-21 04:10:35 -0700114## Debugging
115
116If you want to build the tool specially, for example using sanitizers, use the
Devin Jeanpierre68c7b622023-03-10 14:15:37 -0800117script at
118`rs_bindings_from_cc/generate_bindings_for_target_with_tool_flags.sh`,
119for example:
Marcel Hlopko253ceb42022-09-21 04:10:35 -0700120
121```
122rs_bindings_from_cc/generate_bindings_for_target_with_tool_flags.sh \
123 //base \
124 --config=asan
125```
126
127If you want to build the tool specially and use it for generating bindings from
128a golden file, use the `<header basename>_rs_test` target. For `types.h` the
129command would be:
130
131```
132rs_bindings_from_cc/generate_bindings_for_target_with_tool_flags.sh \
133 //rs_bindings_from_cc/test/golden:types_rs_test \
134 --config=asan
135```
136
Devin Jeanpierre68c7b622023-03-10 14:15:37 -0800137If you want to see the Clang AST dump of some file (generated files work too),
138run:
Marcel Hlopko253ceb42022-09-21 04:10:35 -0700139
140```
141bazel build --per_file_copt=<PATH_TO_FILE>@-Xclang,-ast-dump,-fno-color-diagnostics <TARGET> > /tmp/output_file
142```
143
Devin Jeanpierred9c382a2021-12-15 10:23:25 +0000144## Contributing
145
Kinuko Yasudaabf4f3e2022-08-16 12:09:49 -0700146Chat room (internal): https://chat.google.com/room/AAAAImO--WA
Devin Jeanpierred9c382a2021-12-15 10:23:25 +0000147
Kinuko Yasudaabf4f3e2022-08-16 12:09:49 -070014820% starter projects list (internal): b/hotlists/3645339