You've already forked comprehensive-rust
mirror of
https://github.com/google/comprehensive-rust.git
synced 2025-06-20 16:05:38 +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:
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
|
Reference in New Issue
Block a user