mirror of
https://github.com/google/comprehensive-rust.git
synced 2025-05-14 06:36:33 +02:00
Add Chromium section (#1479)
This is a contribution of a Chromium section for Comprehensive Rust. --------- Co-authored-by: Nicole L <dlegare.1001@gmail.com> Co-authored-by: Martin Geisler <martin@geisler.net>
This commit is contained in:
parent
5a7b4d568b
commit
7f469fb2c7
@ -7,9 +7,10 @@
|
||||
This repository has the source code for Comprehensive Rust 🦀, a multi-day Rust
|
||||
course developed by the Android team. The course covers all aspects of Rust,
|
||||
from basic syntax to generics and error handling. It also includes deep dives on
|
||||
[Android], [bare-metal], and [concurrency].
|
||||
[Android], [Chromium], [bare-metal], and [concurrency].
|
||||
|
||||
[Android]: https://google.github.io/comprehensive-rust/android.html
|
||||
[Chromium]: https://google.github.io/comprehensive-rust/comprehensive.html
|
||||
[bare-metal]: https://google.github.io/comprehensive-rust/bare-metal.html
|
||||
[concurrency]: https://google.github.io/comprehensive-rust/concurrency.html
|
||||
|
||||
|
@ -221,6 +221,42 @@
|
||||
- [Exercises](exercises/android/morning.md)
|
||||
|
||||
|
||||
|
||||
# Chromium
|
||||
|
||||
----
|
||||
|
||||
- [Welcome](chromium.md)
|
||||
- [Setup](chromium/setup.md)
|
||||
- [Using cargo for experimental tools](chromium/cargo.md)
|
||||
- [Policy](chromium/policy.md)
|
||||
- [Build Rules](chromium/build-rules.md)
|
||||
- [Unsafe code](chromium/build-rules/unsafe.md)
|
||||
- [Depending on Rust code from Chromium C++](chromium/build-rules/depending.md)
|
||||
- [Visual Studio code](chromium/build-rules/vscode.md)
|
||||
- [Exercise](exercises/chromium/build-rules.md)
|
||||
- [Interoperability with C++](chromium/interoperability-with-cpp.md)
|
||||
- [Example bindings](chromium/interoperability-with-cpp/example-bindings.md)
|
||||
- [Limitations of cxx](chromium/interoperability-with-cpp/limitations-of-cxx.md)
|
||||
- [cxx error handling](chromium/interoperability-with-cpp/error-handling.md)
|
||||
- [Using cxx in Chromium](chromium/interoperability-with-cpp/using-cxx-in-chromium.md)
|
||||
- [Exercise](exercises/chromium/interoperability-with-cpp.md)
|
||||
- [Adding third party crates](chromium/adding-third-party-crates.md)
|
||||
- [Configuring Cargo.toml](chromium/adding-third-party-crates/configuring-cargo-toml.md)
|
||||
- [Configuring gnrt_config.toml](chromium/adding-third-party-crates/configuring-gnrt-config-toml.md)
|
||||
- [Downloading crates](chromium/adding-third-party-crates/downloading-crates.md)
|
||||
- [Generating gn build rules](chromium/adding-third-party-crates/generating-gn-build-rules.md)
|
||||
- [Resolving problems](chromium/adding-third-party-crates/resolving-problems.md)
|
||||
- [Build scripts which generate code](chromium/adding-third-party-crates/resolving-problems/build-scripts-which-generate-code.md)
|
||||
- [Build scripts which build C++ or take arbitrary actions](chromium/adding-third-party-crates/resolving-problems/build-scripts-which-take-arbitrary-actions.md)
|
||||
- [Depending on a crate](chromium/adding-third-party-crates/depending-on-a-crate.md)
|
||||
- [Reviews and audits](chromium/adding-third-party-crates/reviews-and-audits.md)
|
||||
- [Checking into Chromium source code](chromium/adding-third-party-crates/checking-in.md)
|
||||
- [Keeping crates up to date](chromium/adding-third-party-crates/keeping-up-to-date.md)
|
||||
- [Exercise](exercises/chromium/third-party.md)
|
||||
- [Bringing it together - Exercise](exercises/chromium/bringing-it-together.md)
|
||||
|
||||
|
||||
# Bare Metal: Morning
|
||||
|
||||
----
|
||||
|
9
src/chromium.md
Normal file
9
src/chromium.md
Normal file
@ -0,0 +1,9 @@
|
||||
# Welcome to Rust in Chromium
|
||||
|
||||
Rust is supported for third-party libraries in Chromium, with first-party glue
|
||||
code to connect between Rust and existing Chromium C++ code.
|
||||
|
||||
> Today, we'll call into Rust to do something silly with strings. If you've
|
||||
> got a corner of the code where you're displaying a UTF8 string to the user,
|
||||
> feel free to follow this recipe in your part of the codebase instead of
|
||||
> the exact part we talk about.
|
32
src/chromium/adding-third-party-crates.md
Normal file
32
src/chromium/adding-third-party-crates.md
Normal file
@ -0,0 +1,32 @@
|
||||
# Adding third party crates
|
||||
|
||||
Rust libraries are called "crates" and are found at [crates.io][0]. It's *very
|
||||
easy* for Rust crates to depend upon one another. So they do!
|
||||
|
||||
| Property | C++ library | Rust crate |
|
||||
| --- | --- | --- |
|
||||
| Build system | Lots | Consistent - `Cargo.toml` |
|
||||
| Typical library size | Large-ish | Small |
|
||||
| Transitive dependencies | Few | Lots |
|
||||
|
||||
For a Chromium engineer, this has pros and cons:
|
||||
|
||||
* All crates use a common build system so we can automate their inclusion into
|
||||
Chromium...
|
||||
* ... but, crates typically have transitive dependencies, so you will
|
||||
likely have to bring in multiple libraries.
|
||||
|
||||
We'll discuss:
|
||||
|
||||
* How to put a crate in the Chromium source code tree
|
||||
* How to make `gn` build rules for it
|
||||
* How to audit its source code for sufficient safety.
|
||||
|
||||
[0]: https://crates.io
|
||||
|
||||
<details>
|
||||
All of the things in the table on this slide are generalizations, and
|
||||
counter-examples can be found. But in general it's important for students
|
||||
to understand that most Rust code depends on other Rust libraries, because
|
||||
it's easy to do so, and that this has both benefits and costs.
|
||||
</details>
|
23
src/chromium/adding-third-party-crates/checking-in.md
Normal file
23
src/chromium/adding-third-party-crates/checking-in.md
Normal file
@ -0,0 +1,23 @@
|
||||
# Checking crates into Chromium source code
|
||||
|
||||
`git status` should reveal:
|
||||
* Crate code in `//third_party/rust/chromium_crates_io`
|
||||
* Metadata (`BUILD.gn` and `README.chromium`) in `//third_party/rust/<crate>/<version>`
|
||||
|
||||
Please also add an `OWNERS` file in the latter location.
|
||||
|
||||
You should land all this, along with your `Cargo.toml` and `gnrt_config.toml` changes, into
|
||||
the Chromium repo.
|
||||
|
||||
**Important**: you need to use `git add -f` because otherwise `.gitignore` files
|
||||
may result in some files being skipped.
|
||||
|
||||
As you do so, you might find presubmit checks fail because of non-inclusive
|
||||
language. This is because Rust crate data tends to include names of git branches,
|
||||
and many projects still use non-inclusive terminology there. So you may need
|
||||
to run:
|
||||
|
||||
```shell
|
||||
infra/update_inclusive_language_presubmit_exempt_dirs.sh > infra/inclusive_language_presubmit_exempt_dirs.txt
|
||||
git add -p infra/inclusive_language_presubmit_exempt_dirs.txt # add whatever changes are yours
|
||||
```
|
@ -0,0 +1,23 @@
|
||||
# Configuring the `Cargo.toml` file to add crates
|
||||
|
||||
Chromium has a single set of centrally-managed direct crate dependencies.
|
||||
These are managed through a single [`Cargo.toml`][0]:
|
||||
|
||||
```toml
|
||||
[dependencies]
|
||||
bitflags = "1"
|
||||
cfg-if = "1"
|
||||
cxx = "1"
|
||||
# lots more...
|
||||
```
|
||||
|
||||
As with any other `Cargo.toml`, you can specify [more details about
|
||||
the dependencies][1] - most commonly, you'll want to specify the `features` that
|
||||
you wish to enable in the crate.
|
||||
|
||||
When adding a crate to Chromium, you'll often need to provide some extra
|
||||
information in an additional file, `gnrt_config.toml`, which we'll meet next.
|
||||
|
||||
|
||||
[0]: https://source.chromium.org/chromium/chromium/src/+/main:third_party/rust/chromium_crates_io/Cargo.toml
|
||||
[1]: https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html
|
@ -0,0 +1,29 @@
|
||||
# Configuring `gnrt_config.toml`
|
||||
|
||||
Alongside `Cargo.toml` is [`gnrt_config.toml`][0]. This contains Chromium-specific
|
||||
extensions to crate handling.
|
||||
|
||||
If you add a new crate, you should specify at least the `group`.
|
||||
This is one of:
|
||||
|
||||
```toml
|
||||
# 'safe': The library satisfies the rule-of-2 and can be used in any process.
|
||||
# 'sandbox': The library does not satisfy the rule-of-2 and must be used in
|
||||
# a sandboxed process such as the renderer or a utility process.
|
||||
# 'test': The library is only used in tests.
|
||||
```
|
||||
|
||||
For instance,
|
||||
|
||||
```toml
|
||||
[crate.my-new-crate]
|
||||
group = 'test' # only used in test code
|
||||
```
|
||||
|
||||
Depending on the crate source code layout, you may also need to use this
|
||||
file to specify where its `LICENSE` file(s) can be found.
|
||||
|
||||
Later, we'll see some other things you will need to configure in this file
|
||||
to resolve problems.
|
||||
|
||||
[0]: https://source.chromium.org/chromium/chromium/src/+/main:third_party/rust/chromium_crates_io/gnrt_config.toml
|
@ -0,0 +1,23 @@
|
||||
# Depending on a crate
|
||||
|
||||
Once you've added a third-party crate and generated build rules,
|
||||
depending on a crate is simple. Find your `rust_static_library` target,
|
||||
and add a `dep` on the `:lib` target within your crate.
|
||||
|
||||
Specifically,
|
||||
|
||||
```bob
|
||||
+------------+ +----------------------+
|
||||
"//third_party/rust" | crate name | "/v" | major semver version | "/:lib"
|
||||
+------------+ +----------------------+
|
||||
```
|
||||
|
||||
For instance,
|
||||
|
||||
```gn
|
||||
rust_static_library("my_rust_lib") {
|
||||
crate_root = "lib.rs"
|
||||
sources = [ "lib.rs" ]
|
||||
deps = [ "//third_party/rust/example_rust_crate/v1:lib" ]
|
||||
}
|
||||
```
|
30
src/chromium/adding-third-party-crates/downloading-crates.md
Normal file
30
src/chromium/adding-third-party-crates/downloading-crates.md
Normal file
@ -0,0 +1,30 @@
|
||||
# Downloading crates
|
||||
|
||||
A tool called `gnrt` knows how to download crates and how to generate `BUILD.gn`
|
||||
rules.
|
||||
|
||||
To start, download the crate you want like this:
|
||||
|
||||
```shell
|
||||
cd chromium/src
|
||||
vpython3 tools/crates/run_gnrt.py -- vendor
|
||||
```
|
||||
|
||||
> Although the `gnrt` tool is part of the Chromium source code,
|
||||
> by running this command you will be downloading and running its dependencies
|
||||
> from `crates.io`. See [the earlier section][0] discussing this security
|
||||
> decision.
|
||||
|
||||
This `vendor` command may download:
|
||||
* Your crate
|
||||
* Direct and transitive dependencies
|
||||
* New versions of other crates, as required by `cargo` to resolve
|
||||
the complete set of crates required by Chromium.
|
||||
|
||||
If a crate in `//third_party/rust/chromium_crates_io/patches` was updated as
|
||||
part of vendoring, then reapply patches to it by running
|
||||
`cd third_party/rust/chromium_crates_io; ./apply_patches.sh`.
|
||||
|
||||
|
||||
|
||||
[0]: ../cargo.md
|
@ -0,0 +1,25 @@
|
||||
# Generating `gn` build rules
|
||||
|
||||
Once you've downloaded the crate, generate the `BUILD.gn` files like this:
|
||||
|
||||
```shell
|
||||
vpython3 tools/crates/run_gnrt.py -- gen
|
||||
```
|
||||
|
||||
Now run `git status`. You should find:
|
||||
|
||||
* At least one new crate source code in `third_party/rust/chromium_crates_io/vendor`
|
||||
* At least one new `BUILD.gn` in `third_party/rust/<crate name>/v<major semver version>`
|
||||
* An appropriate `README.chromium`
|
||||
|
||||
The "major semver version" is a [Rust "semver" version number][0].
|
||||
|
||||
Take a close look, especially at the things generated in `third_party/rust`.
|
||||
|
||||
<details>
|
||||
Talk a little about semver - and specifically the way that in Chromium
|
||||
it's to allow multiple incompatible versions of a crate, which is discouraged
|
||||
but sometimes necessary in the cargo ecosystem.
|
||||
</detail>
|
||||
|
||||
[0]: https://doc.rust-lang.org/cargo/reference/semver.html
|
@ -0,0 +1,8 @@
|
||||
# Keeping crates up to date
|
||||
|
||||
As the OWNER of any third party Chromium dependency, you are
|
||||
[expected to keep it up to date with any security fixes][0]. It is hoped
|
||||
that we will soon automate this for Rust crates, but for now, it's still
|
||||
your responsibility just as it is for any other third party dependency.
|
||||
|
||||
[0]: https://chromium.googlesource.com/chromium/src/+/main/docs/adding_to_third_party.md#add-owners
|
21
src/chromium/adding-third-party-crates/resolving-problems.md
Normal file
21
src/chromium/adding-third-party-crates/resolving-problems.md
Normal file
@ -0,0 +1,21 @@
|
||||
# Resolving problems
|
||||
|
||||
If your build fails, it may be because of a `build.rs`: programs which do arbitrary
|
||||
things at build time. This is fundamentally at odds with the design of `gn`
|
||||
and `ninja` which aim for static, deterministic, build rules to maximize
|
||||
parallelism and repeatability of builds.
|
||||
|
||||
Some `build.rs` actions are automatically supported; others require action:
|
||||
|
||||
| build script effect | Supported by our gn templates | Work required by you |
|
||||
|-----|-----|-----|
|
||||
| Checking rustc version to configure features on and off | Yes | None |
|
||||
| Checking platform or CPU to configure features on and off | Yes | None |
|
||||
| Generating code | Yes | Yes - specify in `gnrt_config.toml` |
|
||||
| Building C/C++ | No | Patch around it |
|
||||
| Arbitrary other actions | No | Patch around it |
|
||||
|
||||
Fortunately, most crates don't contain a build script, and fortunately, most
|
||||
build scripts only do the top two actions.
|
||||
|
||||
[0]: https://doc.rust-lang.org/cargo/reference/build-scripts.html
|
@ -0,0 +1,22 @@
|
||||
# Build scripts which generate code
|
||||
|
||||
If `ninja` complains about missing files, check the `build.rs` to see if it
|
||||
writes source code files.
|
||||
|
||||
If so, modify [`gnrt_config.toml`][1] to add `build-script-outputs` to the
|
||||
crate. If this is a transitive dependency, that is, one on which Chromium
|
||||
code should not directly depend, also add `allow-first-party-usage=false`.
|
||||
There are several examples already in that file:
|
||||
|
||||
```toml
|
||||
[crate.unicode-linebreak]
|
||||
allow-first-party-usage = false
|
||||
build-script-outputs = [ "tables.rs" ]
|
||||
```
|
||||
|
||||
Now rerun [`gnrt.py -- gen`][2] to regenerate `BUILD.gn` files to inform ninja
|
||||
that this particular output file is input to subsequent build steps.
|
||||
|
||||
|
||||
[1]: ../configuring-gnrt-config-toml.md
|
||||
[2]: ../generating-gn-build-rules.md
|
@ -0,0 +1,24 @@
|
||||
# Build scripts which build C++ or take arbitrary actions
|
||||
|
||||
Some crates use the [`cc`][2] crate to build and link C/C++ libraries.
|
||||
Other crates parse C/C++ using [`bindgen`][3] within their build scripts.
|
||||
These actions can't be supported in a Chromium context - our gn, ninja
|
||||
and LLVM build system is very specific in expressing relationships between
|
||||
build actions.
|
||||
|
||||
So, your options are:
|
||||
|
||||
* Avoid these crates
|
||||
* Apply a patch to the crate.
|
||||
|
||||
Patches should be kept in `third_party/rust/chromium_crates_io/patches/<crate>` -
|
||||
see for example the [patches against the cxx crate][4]. There is currently
|
||||
no automation - [simply create and apply patches manually][5] to remove the
|
||||
problematic actions from the build script.
|
||||
|
||||
If your patches modify the `Cargo.toml` file, rerun `gnrt gen`.
|
||||
|
||||
[2]: https://crates.io/crates/cc
|
||||
[3]: https://crates.io/crates/bindgen
|
||||
[4]: https://source.chromium.org/chromium/chromium/src/+/main:third_party/rust/chromium_crates_io/patches/cxx/
|
||||
[5]: https://chromium.googlesource.com/chromium/src/+/refs/heads/main/docs/rust.md#patching-third_party-crates
|
33
src/chromium/adding-third-party-crates/reviews-and-audits.md
Normal file
33
src/chromium/adding-third-party-crates/reviews-and-audits.md
Normal file
@ -0,0 +1,33 @@
|
||||
# Auditing third party crates
|
||||
|
||||
Adding new libraries is subject to Chromium's standard [policies][0], but of
|
||||
course also subject to code review. As you may be bringing in not just a single
|
||||
crate but also transitive dependencies, there may be a lot of code to review.
|
||||
On the other hand, safe Rust code can have limited negative side effects.
|
||||
How should you review it?
|
||||
|
||||
Over time Chromium aims to move to a process based around [cargo vet][1].
|
||||
|
||||
Meanwhile, for each new crate addition, we are checking for the following:
|
||||
|
||||
* Understand why each crate is used. What's the relationship between crates?
|
||||
If the build system for each crate contains a `build.rs` or procedural
|
||||
macros, work out what they're for. Are they compatible with the way
|
||||
Chromium is normally built?
|
||||
* Check each crate seems to be reasonably well maintained
|
||||
* Use `cd third-party/rust/chromium_crates_io; cargo audit` to check for
|
||||
known vulnerabilities (first you'll need to `cargo install cargo-audit`,
|
||||
which ironically involves downloading lots of dependencies from the internet[2])
|
||||
* Ensure any unsafe code is good enough for the [Rule of Two][3]
|
||||
* Check for any use of `fs` or `net` APIs
|
||||
* Read all the code at a sufficient level to look for anything out of place
|
||||
that might have been maliciously inserted. (You can't realistically aim
|
||||
for 100% perfection here: there's often just too much code.)
|
||||
|
||||
These are just guidelines - work with reviewers from `security@chromium.org`
|
||||
to work out the right way to become confident of the crate.
|
||||
|
||||
[0]: https://chromium.googlesource.com/chromium/src/+/refs/heads/main/docs/rust.md#Third_party-review
|
||||
[1]: https://mozilla.github.io/cargo-vet/
|
||||
[2]: ../cargo.md
|
||||
[3]: https://chromium.googlesource.com/chromium/src/+/main/docs/security/rule-of-2.md#unsafe-code-in-safe-languages
|
38
src/chromium/build-rules.md
Normal file
38
src/chromium/build-rules.md
Normal file
@ -0,0 +1,38 @@
|
||||
# Build rules
|
||||
|
||||
Rust code is usually built using `cargo`. Chromium builds with `gn` and `ninja`
|
||||
for efficiency - its static rules allow maximum parallelism. Rust is no exception.
|
||||
|
||||
## Adding Rust code to Chromium
|
||||
|
||||
In some existing Chromium `BUILD.gn` file, declare a `rust_static_library`:
|
||||
|
||||
```gn
|
||||
import("//build/rust/rust_static_library.gni")
|
||||
|
||||
rust_static_library("my_rust_lib") {
|
||||
crate_root = "lib.rs"
|
||||
sources = [ "lib.rs" ]
|
||||
}
|
||||
```
|
||||
|
||||
You can also add `deps` on other Rust targets. Later we'll use this to
|
||||
depend upon third party code.
|
||||
|
||||
<details>
|
||||
You must specify _both_ the crate root, _and_ a full list of sources.
|
||||
The `crate_root` is the file given to the Rust compiler representing the root
|
||||
file of the compilation unit - typically `lib.rs`. `sources` is a complete
|
||||
list of all source files which `ninja` needs in order to determine when rebuilds
|
||||
are necessary.
|
||||
|
||||
(There's no such thing as a Rust `source_set`, because in Rust, an entire
|
||||
crate is a compilation unit. A `static_library` is the smallest unit.)
|
||||
|
||||
Students might be wondering why we need a gn template, rather than using
|
||||
[gn's built-in support for Rust static libraries][0].
|
||||
The answer is that this template provides support for cxx interop, Rust features,
|
||||
and unit tests, some of which we'll use later.
|
||||
</details>
|
||||
|
||||
[0]: https://gn.googlesource.com/gn/+/main/docs/reference.md#func_static_library
|
22
src/chromium/build-rules/depending.md
Normal file
22
src/chromium/build-rules/depending.md
Normal file
@ -0,0 +1,22 @@
|
||||
# Depending on Rust code from Chromium C++
|
||||
|
||||
Simply add the above target to the `deps` of some Chromium C++ target.
|
||||
|
||||
```gn
|
||||
import("//build/rust/rust_static_library.gni")
|
||||
|
||||
rust_static_library("my_rust_lib") {
|
||||
crate_root = "lib.rs"
|
||||
sources = [ "lib.rs" ]
|
||||
}
|
||||
|
||||
# or source_set, static_library etc.
|
||||
component("preexisting_cpp") {
|
||||
deps = [ ":my_rust_lib" ]
|
||||
}
|
||||
```
|
||||
|
||||
<details>
|
||||
We'll see that this relationship only works if the Rust code exposes plain C APIs
|
||||
which can be called from C++, or if we use a C++/Rust interop tool.
|
||||
</details>
|
17
src/chromium/build-rules/unsafe.md
Normal file
17
src/chromium/build-rules/unsafe.md
Normal file
@ -0,0 +1,17 @@
|
||||
# Including `unsafe` Rust code
|
||||
|
||||
Unsafe Rust code is forbidden in `rust_static_library` by default - it won't
|
||||
compile. If you need unsafe Rust code, add `allow_unsafe = true` to the
|
||||
gn target. (Later in the course we'll see circumstances where this is necessary.)
|
||||
|
||||
```gn
|
||||
import("//build/rust/rust_static_library.gni")
|
||||
|
||||
rust_static_library("my_rust_lib") {
|
||||
crate_root = "lib.rs"
|
||||
sources = [
|
||||
"lib.rs",
|
||||
"hippopotamus.rs"
|
||||
]
|
||||
allow_unsafe = true
|
||||
}
|
17
src/chromium/build-rules/vscode.md
Normal file
17
src/chromium/build-rules/vscode.md
Normal file
@ -0,0 +1,17 @@
|
||||
# Visual Studio code
|
||||
|
||||
Types are elided in Rust code, which makes a good IDE even more useful than
|
||||
for C++. Visual Studio code works well for Rust in Chromium. To use it,
|
||||
|
||||
* Ensure your VSCode has the `rust-analyzer` extension, not earlier forms
|
||||
of Rust support
|
||||
* `gn gen out/Debug --export-rust-project` (or equivalent for your output
|
||||
directory)
|
||||
* `ln -s out/Debug/rust-project.json rust-project.json`
|
||||
|
||||
<img src="vscode.png" style="border: 1px solid black;" alt="Example screenshot from VSCode">
|
||||
|
||||
<details>
|
||||
A demo of some of the code annotation and exploration features of rust-analyzer might be
|
||||
beneficial if the audience are naturally skeptical of IDEs.
|
||||
</details>
|
BIN
src/chromium/build-rules/vscode.png
Normal file
BIN
src/chromium/build-rules/vscode.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 87 KiB |
51
src/chromium/cargo.md
Normal file
51
src/chromium/cargo.md
Normal file
@ -0,0 +1,51 @@
|
||||
# Using cargo for experimental tools
|
||||
|
||||
Subjectively,
|
||||
|
||||
```bob
|
||||
High ^
|
||||
| x cargo
|
||||
|
|
||||
Development | x "cargo --offline"
|
||||
speed |
|
||||
| x "gn/ninja"
|
||||
| "rust_executable(...)"
|
||||
Low +---------------------------------------------------->
|
||||
Low Determinism High
|
||||
```
|
||||
|
||||
`cargo` works great for pure-Rust tools, but isn't optimized for large multi-
|
||||
language projects like Chromium. Chromium uses `gn` and `ninja`.
|
||||
|
||||
When writing a tool in Rust, your choices are:
|
||||
|
||||
* Use `gn` and `ninja` (using the `rust_executable` template we'll meet
|
||||
later)
|
||||
* Use `cargo`, but [restrict yourself to Chromium's audited toolchain and crates][0]
|
||||
* Use `cargo`, trusting a [toolchain][1] and [crates downloaded from the internet][2]
|
||||
|
||||
Your organization's policy, and/or common sense, may prohibit you from doing
|
||||
these things.
|
||||
|
||||
From here on we'll be focusing on `gn` and `ninja`.
|
||||
|
||||
## Mini exercise
|
||||
|
||||
Discuss in small groups the policies within your own team and organization,
|
||||
and come to a group agreement about what's an acceptable level of risk.
|
||||
|
||||
<details>
|
||||
Explain that it might seem strange to write tools in Rust, but this is
|
||||
increasingly popular across the industry - Rust tools are quicker and work
|
||||
more reliably.
|
||||
|
||||
Assuming folks taking the course are physically together, ask them to discuss
|
||||
in small groups of 3-4 people. Then, ask each table whether they've come
|
||||
to a consensus on the level of risk.
|
||||
|
||||
Later in the course, we'll be running an actual `cargo`-based tool, `gnrt`.
|
||||
</details>
|
||||
|
||||
[0]: https://chromium.googlesource.com/chromium/src/+/refs/heads/main/docs/rust.md#Using-cargo
|
||||
[1]: https://rustup.rs/
|
||||
[2]: https://crates.io/
|
25
src/chromium/interoperability-with-cpp.md
Normal file
25
src/chromium/interoperability-with-cpp.md
Normal file
@ -0,0 +1,25 @@
|
||||
# Interoperability with C++
|
||||
|
||||
The Rust community offers multiple options for C++/Rust interop, with new tools
|
||||
being developed all the time. At the moment, Chromium uses a tool called "cxx".
|
||||
|
||||
You describe your whole language boundary in an interface definition language
|
||||
(which looks a lot like Rust) and then cxx tools generate declarations for
|
||||
functions and types in both Rust and C++.
|
||||
|
||||
<img src="../android/interoperability/cpp/overview.svg" alt="Overview diagram of cxx, showing that the same interface definition is used to create both C++ and Rust side code which then communicate via a lowest common denominator C API">
|
||||
|
||||
See the [CXX tutorial][1] for a full example of using this.
|
||||
|
||||
|
||||
[1]: https://cxx.rs/tutorial.html
|
||||
[2]: https://cxx.rs/bindings.html
|
||||
|
||||
|
||||
<details>
|
||||
Talk through the diagram. Explain that behind the scenes, this is doing
|
||||
just the same as you previously did - but by programmatically ensuring that
|
||||
the C++ and Rust sides match, cxx can ensure there aren't obvious errors
|
||||
with object lifetimes, string lengths, etc. It reduces lots of fiddly
|
||||
boilerplate and the resulting code feels more "natural".
|
||||
</details>
|
41
src/chromium/interoperability-with-cpp/error-handling.md
Normal file
41
src/chromium/interoperability-with-cpp/error-handling.md
Normal file
@ -0,0 +1,41 @@
|
||||
# cxx error handling
|
||||
|
||||
cxx's support for `Result<T,E>` relies on C++ exceptions, so we can't use that
|
||||
in Chromium. Alternatives:
|
||||
|
||||
* Where success can be represented as a simple Boolean, as done in our [QR code generator][1]:
|
||||
Return a Boolean representing success, and record results using out-parameters:
|
||||
```rust,ignore
|
||||
#[cxx::bridge(namespace = "qr_code_generator")]
|
||||
mod ffi {
|
||||
extern "Rust" {
|
||||
fn generate_qr_code_using_rust(
|
||||
data: &[u8],
|
||||
min_version: i16,
|
||||
out_pixels: Pin<&mut CxxVector<u8>>,
|
||||
out_qr_size: &mut usize,
|
||||
) -> bool;
|
||||
}
|
||||
}
|
||||
```
|
||||
* Where success is more complex, provide a Rust
|
||||
object which can be queried for details of success or failure:
|
||||
```rust,ignore
|
||||
#[cxx::bridge]
|
||||
mod ffi {
|
||||
extern "Rust" {
|
||||
type PngDecoder;
|
||||
fn create_png_decoder() -> Box<PngDecoder>;
|
||||
fn decode(self: &PngDecoder, png: &[u8]) -> bool; // whether successful
|
||||
fn get_err_code(self: &PngDecoder) -> u32; // or some more complex error type
|
||||
fn get_decoded_image(self: &PngDecoder) -> &[u8];
|
||||
// or some more complex success type
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
The best way to learn cxx is by doing, so, another exercise!
|
||||
|
||||
[0]: https://cxx.rs/binding/result.html
|
||||
[1]: https://source.chromium.org/chromium/chromium/src/+/main:components/qr_code_generator/qr_code_generator_ffi_glue.rs;l=10
|
23
src/chromium/interoperability-with-cpp/example-bindings.md
Normal file
23
src/chromium/interoperability-with-cpp/example-bindings.md
Normal file
@ -0,0 +1,23 @@
|
||||
# Example bindings
|
||||
|
||||
cxx requires you to declare the whole C++/Rust boundary in one of your `.rs`
|
||||
files. For instance:
|
||||
|
||||
```rust,ignore
|
||||
{{#include ../../../third_party/cxx/book/snippets.rs:cxx_overview}}
|
||||
```
|
||||
|
||||
<details>
|
||||
Point out:
|
||||
|
||||
* Native support for C++'s `std::unique_ptr` in Rust
|
||||
* Native support for Rust slices in C++
|
||||
* Calls from C++ to Rust, and Rust types (in the top part)
|
||||
* Calls from Rust to C++, and C++ types (in the bottom part)
|
||||
* If the function definitions in C++ or Rust don't match the cxx::bridge,
|
||||
a compilation failure results.
|
||||
|
||||
**Common misconception**: It _looks_ like a C++ header is being parser by Rust,
|
||||
but this is misleading. This header is never interpreted by Rust, but simply
|
||||
`#include`d in the generated C++ code for the benefit of C++ compilers.
|
||||
</details>
|
31
src/chromium/interoperability-with-cpp/limitations-of-cxx.md
Normal file
31
src/chromium/interoperability-with-cpp/limitations-of-cxx.md
Normal file
@ -0,0 +1,31 @@
|
||||
## Limitations of cxx
|
||||
|
||||
By far the most useful page when using cxx is the [type reference][1].
|
||||
|
||||
cxx fundamentally suits cases where:
|
||||
|
||||
* Your Rust-C++ interface is sufficiently simple that you can declare all of it.
|
||||
* You're using only the types natively supported by cxx already, for example
|
||||
`std::unique_ptr`, `std::string`, `&[u8]` etc.
|
||||
|
||||
It has many limitations - for example lack of support for Rust's `Option` type.
|
||||
|
||||
These limitations constrain us to using Rust in Chromium only for well isolated
|
||||
"leaf nodes" rather than for arbitrary Rust-C++ interop. When considering
|
||||
a use-case for Rust in Chromium, a good starting point is to draft the cxx
|
||||
bindings for the language boundary to see if it appears simple enough.
|
||||
|
||||
|
||||
[1]: https://cxx.rs/bindings.html
|
||||
|
||||
<details>
|
||||
In addition, right now, Rust code in one component cannot depend on Rust
|
||||
code in another, due to linking details in our component build. That's another
|
||||
reason to restrict Rust to use in leaf nodes.
|
||||
|
||||
You should also discuss some of the other sticky points with cxx, for example:
|
||||
|
||||
* Its error handling is based around C++ exceptions (given on the next slide)
|
||||
* Function pointers are awkward to use.
|
||||
|
||||
</details>
|
@ -0,0 +1,41 @@
|
||||
## Using cxx in Chromium
|
||||
|
||||
In Chromium, we define an independent `#[cxx::bridge] mod` for each leaf-node
|
||||
where we want to use Rust. You'd typically have one for each
|
||||
`rust_static_library`. Just add
|
||||
|
||||
```gn
|
||||
cxx_bindings = [ "my_rust_file.rs" ]
|
||||
# list of files containing #[cxx::bridge], not all source files
|
||||
allow_unsafe = true
|
||||
```
|
||||
|
||||
to your existing `rust_static_library` target alongside `crate_root` and
|
||||
`sources`.
|
||||
|
||||
C++ headers will be generated at a sensible location, so you can just
|
||||
|
||||
```cpp
|
||||
#include "ui/base/my_rust_file.rs.h"
|
||||
```
|
||||
|
||||
You will find some utility functions in `//base` to convert to/from Chromium
|
||||
C++ types to cxx Rust types - for example [`SpanToRustSlice`][0].
|
||||
|
||||
<details>
|
||||
Students may ask - why do we still need `allow_unsafe = true`?
|
||||
|
||||
The broad answer is that no C/C++ code is "safe" by the normal Rust standards.
|
||||
Calling back and forth to C/C++ from Rust may do arbitrary things to memory, and
|
||||
compromise the safety of Rust's own data layouts. Presence of _too many_
|
||||
`unsafe` keywords in C/C++ interop can harm the signal-to-noise ratio of
|
||||
such a keyword, and is [controversial][1], but strictly, bringing any foreign
|
||||
code into a Rust binary can cause unexpected behavior from Rust's perspective.
|
||||
|
||||
The narrow answer lies in the diagram at the top of this page - behind the
|
||||
scenes, cxx generates Rust `unsafe` and `extern "C"` functions just like
|
||||
we did manually in the previous section.
|
||||
</details>
|
||||
|
||||
[0]: https://source.chromium.org/chromium/chromium/src/+/main:base/containers/span_rust.h;l=21
|
||||
[1]: https://steveklabnik.com/writing/the-cxx-debate
|
37
src/chromium/policy.md
Normal file
37
src/chromium/policy.md
Normal file
@ -0,0 +1,37 @@
|
||||
# Chromium Rust policy
|
||||
|
||||
Chromium does not yet allow first-party Rust except in rare cases as approved
|
||||
by Chromium's [Area Tech Leads](https://source.chromium.org/chromium/chromium/src/+/main:ATL_OWNERS).
|
||||
|
||||
Chromium's policy on third party libraries is outlined [here](https://chromium.googlesource.com/chromium/src/+/main/docs/adding_to_third_party.md#rust) -
|
||||
Rust is allowed for third party libraries under various circumstances, including
|
||||
if they're the best option for performance or for security.
|
||||
|
||||
Very few Rust libraries directly expose a C/C++ API, so that means that nearly
|
||||
all such libraries will require a small amount of first-party glue code.
|
||||
|
||||
```bob
|
||||
C++ Rust
|
||||
.- - - - - - - - - -. .- - - - - - - - - - - - - - - - - - - - - - -.
|
||||
: : : :
|
||||
: Existing Chromium : : Chromium Rust Existing Rust :
|
||||
: "C++" : : "wrapper" crate :
|
||||
: +---------------+ : : +----------------+ +-------------+ :
|
||||
: | | : : | | | | :
|
||||
: | o-----+-+-----------+-+-> o-+----------+--> | :
|
||||
: | | : Language : | | Crate | | :
|
||||
: +---------------+ : boundary : +----------------+ API +-------------+ :
|
||||
: : : :
|
||||
`- - - - - - - - - -' `- - - - - - - - - - - - - - - - - - - - - - -'
|
||||
```
|
||||
|
||||
> First-party Rust glue code for a particular third-party crate should
|
||||
> normally be kept in `third_party/rust/<crate>/<version>/wrapper`.
|
||||
|
||||
Because of this, today's course will be heavily focused on:
|
||||
|
||||
* Bringing in third-party Rust libraries ("crates")
|
||||
* Writing glue code to be able to use those crates from Chromium C++.
|
||||
|
||||
If this policy changes over time, the course will evolve to keep up.
|
||||
|
27
src/chromium/setup.md
Normal file
27
src/chromium/setup.md
Normal file
@ -0,0 +1,27 @@
|
||||
# Setup
|
||||
|
||||
Make sure you can build and run Chromium. Any platform and set of build flags is
|
||||
OK, so long as your code is relatively recent (commit position 1223636 onwards,
|
||||
corresponding to November 2023):
|
||||
|
||||
```shell
|
||||
gn gen out/Debug
|
||||
autoninja -C out/Debug chrome
|
||||
out/Debug/chrome # or on Mac, out/Debug/Chromium.app/Contents/MacOS/Chromium
|
||||
```
|
||||
|
||||
(A component, debug build is recommended for quickest iteration time. This
|
||||
is the default!)
|
||||
|
||||
See [How to build Chromium](https://www.chromium.org/developers/how-tos/get-the-code/)
|
||||
if you aren't already at that point. Be warned - setting up to build Chromium
|
||||
takes time.
|
||||
|
||||
It's also recommended that you have Visual Studio code installed.
|
||||
|
||||
# About the exercises
|
||||
|
||||
This part of the course has a series of exercises which build on each other.
|
||||
We'll be doing them spread throughout the course instead of just at the end.
|
||||
If you don't have time to complete a certain part, don't worry: you can
|
||||
catch up in the next slot.
|
61
src/exercises/chromium/bringing-it-together.md
Normal file
61
src/exercises/chromium/bringing-it-together.md
Normal file
@ -0,0 +1,61 @@
|
||||
# Bringing it together - Exercise
|
||||
|
||||
In this exercise, you're going to add a whole new Chromium feature, bringing
|
||||
together everything you already learned.
|
||||
|
||||
## The brief from Product Management
|
||||
|
||||
A community of pixies has been discovered living in a remote rainforest.
|
||||
It's important that we get Chromium for Pixies delivered to them as soon
|
||||
as possible.
|
||||
|
||||
The requirement is to translate all Chromium's UI strings into Pixie language.
|
||||
|
||||
There's not time to wait for proper translations, but fortunately pixie
|
||||
language is very close to English, and it turns out there's a Rust crate
|
||||
which does the translation.
|
||||
|
||||
In fact, you already [imported that crate in the previous exercise][0].
|
||||
|
||||
(Obviously, real translations of Chrome require incredible care and
|
||||
diligence. Don't ship this!)
|
||||
|
||||
## Steps
|
||||
|
||||
Modify `ResourceBundle::MaybeMangleLocalizedString` so that it uwuifies
|
||||
all strings before display. In this special build of Chromium, it should
|
||||
always do this irrespective of the setting of `mangle_localized_strings_`.
|
||||
|
||||
If you've done everything right across all these exercises, congratulations,
|
||||
you should have created Chrome for pixies!
|
||||
|
||||
<img src="chwomium.png" alt="Chromium UI screenshot with uwu language">
|
||||
|
||||
<details>
|
||||
Students will likely need some hints here. Hints include:
|
||||
|
||||
* UTF16 vs UTF8. Students should be aware that Rust strings are always
|
||||
UTF8, and will probably decide that it's better to do the conversion
|
||||
on the C++ side using `base::UTF16ToUTF8` and back again.
|
||||
* If students decide to do the conversion on the Rust side, they'll need to
|
||||
consider [`std::string::from_utf16`][1], consider error handling, and
|
||||
consider which [cxx supported types can transfer a lot of u16s][2].
|
||||
* Students may design the C++/Rust boundary in several different ways,
|
||||
e.g. taking and returning strings by value, or taking a mutable reference
|
||||
to a string. If a mutable reference is used, cxx will likely
|
||||
tell the student that they need to use [`Pin`][3]. You may need to explain
|
||||
what `Pin` does, and then explain why `cxx` needs it for mutable references
|
||||
to C++ data: the answer is that C++ data can't be moved around like Rust
|
||||
data, because it may contain self-referential pointers.
|
||||
* The C++ target containing `ResourceBundle::MaybeMangleLocalizedString`
|
||||
will need to depend on a `rust_static_library` target. The student
|
||||
probably already did this.
|
||||
* The `rust_static_library` target will need to depend on
|
||||
`//third_party/rust/uwuify/v0_2:lib`.
|
||||
|
||||
</details>
|
||||
|
||||
[0]: https://crates.io/uwuify
|
||||
[1]: https://doc.rust-lang.org/std/string/struct.String.html#method.from_utf16
|
||||
[2]: https://cxx.rs/binding/slice.html
|
||||
[3]: https://doc.rust-lang.org/std/pin/
|
58
src/exercises/chromium/build-rules.md
Normal file
58
src/exercises/chromium/build-rules.md
Normal file
@ -0,0 +1,58 @@
|
||||
# Build rules exercise
|
||||
|
||||
In your Chromium build, add a new Rust target to `//ui/base/BUILD.gn` containing:
|
||||
|
||||
```rust
|
||||
#[no_mangle]
|
||||
pub extern "C" fn hello_from_rust() {
|
||||
println!("Hello from Rust!")
|
||||
}
|
||||
```
|
||||
**Important**: note that `no_mangle` here is considered a type of unsafety
|
||||
by the Rust compiler, so you'll need to to allow unsafe code in your
|
||||
`gn` target.
|
||||
|
||||
Add this new Rust target as a dependency of `//ui/base:base`.
|
||||
Declare this function at the top of `ui/base/resource/resource_bundle.cc`
|
||||
(later, we'll see how this can be automated by bindings generation tools):
|
||||
```cpp
|
||||
extern "C" void hello_from_rust();
|
||||
```
|
||||
|
||||
Call this function from somewhere in `ui/base/resource/resource_bundle.cc` -
|
||||
we suggest the top of `ResourceBundle::MaybeMangleLocalizedString`.
|
||||
Build and run Chromium, and ensure that "Hello from Rust!" is printed lots of times.
|
||||
|
||||
If you use VSCode, now set up Rust to work well in VSCode. It will be useful
|
||||
in subsequent exercises. If you've succeeded, you will be able to use
|
||||
right-click "Go to definition" on `println!`.
|
||||
|
||||
## Where to find help
|
||||
|
||||
* The options available to the [`rust_static_library` gn template][0]
|
||||
* Information about [`#[no_mangle]`][1]
|
||||
* Information about [`extern "C"`][2]
|
||||
* Information about gn's [`--export-rust-project`][3] switch
|
||||
* [How to install rust-analyzer in VSCode][4]
|
||||
|
||||
<details>
|
||||
It's really important that students get this running, because future exercises
|
||||
will build on it.
|
||||
|
||||
This example is unusual because it boils down to the lowest-common-denominator
|
||||
interop language, C. Both C++ and Rust can natively declare and call C ABI
|
||||
functions. Later in the course, we'll connect C++ directly to Rust.
|
||||
|
||||
`allow_unsafe = true` is required here because `#[no_mangle]` might allow Rust
|
||||
to generate two functions with the same name, and Rust can no longer guarantee
|
||||
that the right one is called.
|
||||
|
||||
If you need a pure Rust executable, you can also do that using the
|
||||
`rust_executable` gn template.
|
||||
</details>
|
||||
|
||||
[0]: https://source.chromium.org/chromium/chromium/src/+/main:build/rust/rust_static_library.gni;l=16
|
||||
[1]: https://doc.rust-lang.org/beta/reference/abi.html#the-no_mangle-attribute
|
||||
[2]: https://doc.rust-lang.org/std/keyword.extern.html
|
||||
[3]: https://gn.googlesource.com/gn/+/main/docs/reference.md#compilation-database
|
||||
[4]: https://code.visualstudio.com/docs/languages/rust
|
BIN
src/exercises/chromium/chwomium.png
Normal file
BIN
src/exercises/chromium/chwomium.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 166 KiB |
71
src/exercises/chromium/interoperability-with-cpp.md
Normal file
71
src/exercises/chromium/interoperability-with-cpp.md
Normal file
@ -0,0 +1,71 @@
|
||||
# Exercise: Interoperability with C++
|
||||
|
||||
## Part one
|
||||
|
||||
* In the Rust file you previously created, add a `#[cxx::bridge]` which specifies a single function,
|
||||
to be called from C++, called `hello_from_rust`, taking no parameters and returning
|
||||
no value.
|
||||
* Modify your previous `hello_from_rust` function to remove `extern "C"` and `#[no_mangle]`.
|
||||
This is now just a standard Rust function.
|
||||
* Modify your `gn` target to build these bindings.
|
||||
* In your C++ code, remove the forward-declaration of `hello_from_rust`. Instead, include
|
||||
the generated header file.
|
||||
* Build and run!
|
||||
|
||||
## Part two
|
||||
|
||||
It's a good idea to play with cxx a little. It helps you think about how flexible
|
||||
Rust in Chromium actually is.
|
||||
|
||||
Some things to try:
|
||||
|
||||
* Call back into C++ from Rust. You will need:
|
||||
* An additional header file which you can `include!` from your `cxx::bridge`.
|
||||
You'll need to declare your C++ function in that new header file.
|
||||
* An `unsafe` block to call such a function, or alternatively specify the `unsafe`
|
||||
keyword in your `#[cxx::bridge]` [as described here][0].
|
||||
* You may also need to `#include "third_party/rust/cxx/v1/crate/include/cxx.h"`
|
||||
* Pass a C++ string from C++ into Rust.
|
||||
* Pass a reference to a C++ object into Rust.
|
||||
* Intentionally get the Rust function signatures mismatched from the `#[cxx::bridge]`,
|
||||
and get used to the errors you see.
|
||||
* Intentionally get the C++ function signatures mismatched from the `#[cxx::bridge]`,
|
||||
and get used to the errors you see.
|
||||
* Pass a `std::unique_ptr` of some type from C++ into Rust, so that Rust
|
||||
can own some C++ object.
|
||||
* Create a Rust object and pass it into C++, so that C++ owns it. (Hint:
|
||||
you need a `Box`).
|
||||
* Declare some methods on a C++ type. Call them from Rust.
|
||||
* Declare some methods on a Rust type. Call them from C++.
|
||||
|
||||
## Part three
|
||||
|
||||
Now you understand the strengths and limitations of cxx interop, think of
|
||||
a couple of use-cases for Rust in Chromium where the interface would be
|
||||
sufficiently simple. Sketch how you might define that interface.
|
||||
|
||||
## Where to find help
|
||||
|
||||
* The [cxx binding reference][1]
|
||||
* The [`rust_static_library` gn template][2]
|
||||
|
||||
<details>
|
||||
As students explore Part Two, they're bound to have lots of questions about how
|
||||
to achieve these things, and also how cxx works behind the scenes.
|
||||
|
||||
Some of the questions you may encounter:
|
||||
* I'm seeing a problem initializing a variable of type X with type Y, where
|
||||
X and Y are both function types.
|
||||
This is because your C++ function doesn't quite match the declaration in your
|
||||
`cxx::bridge`.
|
||||
* I seem to be able to freely convert C++ references into Rust references.
|
||||
Doesn't that risk UB?
|
||||
For cxx's _opaque_ types, no, because they are zero-sized. For cxx trivial types
|
||||
yes, it's _possible_ to cause UB, although cxx's design makes it quite
|
||||
difficult to craft such an example.
|
||||
</details>
|
||||
|
||||
|
||||
[0]: https://cxx.rs/extern-c++.html#functions-and-member-functions
|
||||
[1]: https://cxx.rs/bindings.html
|
||||
[2]: https://source.chromium.org/chromium/chromium/src/+/main:build/rust/rust_static_library.gni;l=16
|
22
src/exercises/chromium/third-party.md
Normal file
22
src/exercises/chromium/third-party.md
Normal file
@ -0,0 +1,22 @@
|
||||
# Exercise
|
||||
|
||||
Add [uwuify][0] to Chromium, turning off the crate's [default features][1].
|
||||
Assume that the crate will be used in shipping Chromium, but won't be used
|
||||
to handle untrustworthy input.
|
||||
|
||||
(In the next exercise we'll use uwuify from Chromium, but feel free to
|
||||
skip ahead and do that now if you like. Or, you could create a new
|
||||
[`rust_executable` target][2] which uses `uwuify`).
|
||||
|
||||
<details>
|
||||
Students will need to download lots of transitive dependencies.
|
||||
|
||||
The total crates needed are: uwuify, smallvec, scopeguard, parking_lot,
|
||||
parking_lot_core, lock_api and instant. If students are downloading even
|
||||
more than that, they probably forgot to turn off the default features.
|
||||
</detail>
|
||||
|
||||
|
||||
[0]: https://crates.io/crates/uwuify
|
||||
[1]: https://doc.rust-lang.org/cargo/reference/features.html#the-default-feature
|
||||
[2]: https://source.chromium.org/chromium/chromium/src/+/main:build/rust/rust_executable.gni
|
@ -127,6 +127,8 @@ Also, please keep the hard line breaks to ensure a nice formatting.
|
||||
Days 1 to 3 of this course.
|
||||
- Rust in Android:\
|
||||
See [Rust in Android](android.md).
|
||||
- Rust in Chromium:\
|
||||
See [Rust in Chromium](chromium.md).
|
||||
- safe:\
|
||||
Refers to code that adheres to Rust's ownership and borrowing rules, preventing memory-related errors.
|
||||
- scope:\
|
||||
|
@ -25,6 +25,9 @@ Building on this, you're invited to dive into one or more specialized topics:
|
||||
|
||||
* [Android](android.md): a half-day course on using Rust for Android platform
|
||||
development (AOSP). This includes interoperability with C, C++, and Java.
|
||||
* [Chromium](chromium.md): a half-day course on using Rust within Chromium
|
||||
based browsers. This includes interoperability with C++ and how to include
|
||||
third-party crates in Chromium.
|
||||
* [Bare-metal](bare-metal.md): a whole-day class on using Rust for bare-metal
|
||||
(embedded) development. Both microcontrollers and application processors are
|
||||
covered.
|
||||
|
@ -34,6 +34,17 @@ commands it runs and make sure they work when you run them by hand.
|
||||
[1]: https://source.android.com/docs/setup/download/downloading
|
||||
[2]: https://github.com/google/comprehensive-rust
|
||||
|
||||
### Rust in Chromium
|
||||
|
||||
The [Rust in Chromium](../chromium.md) deep dive is a half-day course on using
|
||||
Rust as part of the Chromium browser. It includes using Rust in Chromium's
|
||||
`gn` build system, bringing in third-party libraries ("crates") and C++
|
||||
interoperability.
|
||||
|
||||
You will need to be able to build Chromium - a debug, component build is
|
||||
[recommended](../chromium/setup.md) for speed but any build will work.
|
||||
Ensure that you can run the Chromium browser that you've built.
|
||||
|
||||
### Bare-Metal Rust
|
||||
|
||||
The [Bare-Metal Rust](../bare-metal.md) deep dive is a full day class on using Rust for
|
||||
|
22
third_party/cxx/book/snippets.rs
vendored
22
third_party/cxx/book/snippets.rs
vendored
@ -119,3 +119,25 @@ fn main() {
|
||||
}
|
||||
}
|
||||
// ANCHOR_END: cpp_exception
|
||||
|
||||
// ANCHOR: cxx_overview
|
||||
#[cxx::bridge]
|
||||
mod ffi {
|
||||
extern "Rust" {
|
||||
type MultiBuf;
|
||||
|
||||
fn next_chunk(buf: &mut MultiBuf) -> &[u8];
|
||||
}
|
||||
|
||||
unsafe extern "C++" {
|
||||
include!("example/include/blobstore.h");
|
||||
|
||||
type BlobstoreClient;
|
||||
|
||||
fn new_blobstore_client() -> UniquePtr<BlobstoreClient>;
|
||||
fn put(self: &BlobstoreClient, buf: &mut MultiBuf) -> Result<u64>;
|
||||
}
|
||||
}
|
||||
|
||||
// Definitions of Rust types and functions go here
|
||||
// ANCHOR_END: cxx_overview
|
Loading…
x
Reference in New Issue
Block a user