Zach Reizner | ab5fdd3 | 2017-08-05 02:48:45 | [diff] [blame] | 1 | # Rust on Chrome OS |
| 2 | |
Mike Frysinger | 05bebd5 | 2021-01-27 18:48:11 | [diff] [blame] | 3 | *** note |
| 4 | **Warning: This document is old & has moved. Please update any links:**<br> |
| 5 | https://chromium.googlesource.com/chromiumos/docs/+/HEAD/rust_on_cros.md |
| 6 | *** |
| 7 | |
paulhsia | a238e9f | 2019-03-12 09:41:19 | [diff] [blame] | 8 | This provides information on creating [Rust] projects for installation within |
| 9 | Chrome OS and Chrome OS SDK. All commands and paths given are from within the |
| 10 | SDK's chroot. |
Zach Reizner | ab5fdd3 | 2017-08-05 02:48:45 | [diff] [blame] | 11 | |
| 12 | [TOC] |
| 13 | |
Zach Reizner | ab5fdd3 | 2017-08-05 02:48:45 | [diff] [blame] | 14 | ## Usage |
| 15 | |
paulhsia | a238e9f | 2019-03-12 09:41:19 | [diff] [blame] | 16 | [cros-rust.eclass] is an eclass that supports first-party and third-party crate |
David Pursehouse | b3b7da1 | 2019-06-17 12:23:39 | [diff] [blame] | 17 | dependencies. Rust project's ebuild should inherit the eclass to support Rust |
paulhsia | a238e9f | 2019-03-12 09:41:19 | [diff] [blame] | 18 | building in Chrome OS build system. |
Zach Reizner | ab5fdd3 | 2017-08-05 02:48:45 | [diff] [blame] | 19 | |
paulhsia | a238e9f | 2019-03-12 09:41:19 | [diff] [blame] | 20 | > **WARNING**: Some legacy projects are still using [cargo.eclass]. These two |
| 21 | > eclasses can't be used together in a single project. Rust projects with |
| 22 | > dependencies should all use `cros-rust.eclass`. |
Zach Reizner | ab5fdd3 | 2017-08-05 02:48:45 | [diff] [blame] | 23 | |
paulhsia | a238e9f | 2019-03-12 09:41:19 | [diff] [blame] | 24 | ### cros-rust.eclass |
Zach Reizner | ab5fdd3 | 2017-08-05 02:48:45 | [diff] [blame] | 25 | |
paulhsia | a238e9f | 2019-03-12 09:41:19 | [diff] [blame] | 26 | All the Rust projects using `cros-rust.eclass` will get dependent crates from |
| 27 | `/build/${BOARD}/usr/lib/cros_rust_registry` instead of [crates.io]. |
| 28 | You'll learn how to publish first-party and third-party crates to |
| 29 | `cros_rust_registry` in the following sections. |
| 30 | |
| 31 | ### Third-party ebuild crates |
| 32 | |
| 33 | To import a third-party crate, we need to create an ebuild for it in |
| 34 | `~/chromiumos/src/third_party/chromiumos-overlay/dev-rust/<crate_name>/<crate_name>-<crate_version>.ebuild`. |
Fletcher Woodruff | b2acef8 | 2020-07-20 20:39:28 | [diff] [blame] | 35 | For an `example` crate with the following [SemVer] dependencies: |
paulhsia | a238e9f | 2019-03-12 09:41:19 | [diff] [blame] | 36 | |
| 37 | ```toml |
| 38 | [dependencies] |
Fletcher Woodruff | b2acef8 | 2020-07-20 20:39:28 | [diff] [blame] | 39 | libc = "0.2" |
| 40 | getopts = "1.2" |
| 41 | rayon = "1.4.1" |
| 42 | http = "^0.1.8" |
| 43 | indexmap = "^1.0" |
| 44 | string = "~1.2" |
| 45 | bit-set = "~2.7.1" |
| 46 | walkdir = "~2" |
paulhsia | a238e9f | 2019-03-12 09:41:19 | [diff] [blame] | 47 | ``` |
| 48 | |
Fletcher Woodruff | b2acef8 | 2020-07-20 20:39:28 | [diff] [blame] | 49 | We would create the following ebuild: |
Zach Reizner | ab5fdd3 | 2017-08-05 02:48:45 | [diff] [blame] | 50 | |
| 51 | ```bash |
| 52 | # Copyright <copyright_year> The Chromium OS Authors. All rights reserved. |
| 53 | # Distributed under the terms of the GNU General Public License v2 |
| 54 | |
Fletcher Woodruff | b2acef8 | 2020-07-20 20:39:28 | [diff] [blame] | 55 | EAPI="7" |
Zach Reizner | ab5fdd3 | 2017-08-05 02:48:45 | [diff] [blame] | 56 | |
Allen Webb | 7b9fc02 | 2019-09-24 20:58:51 | [diff] [blame] | 57 | CROS_RUST_REMOVE_DEV_DEPS=1 |
| 58 | |
paulhsia | a238e9f | 2019-03-12 09:41:19 | [diff] [blame] | 59 | inherit cros-rust |
| 60 | |
| 61 | DESCRIPTION="An example library" |
| 62 | HOMEPAGE="url/to/the/homepage" |
| 63 | SRC_URI="https://crates.io/api/v1/crates/${PN}/${PV}/download -> ${P}.crate" |
| 64 | |
| 65 | LICENSE="|| ( <fill in license> )" |
| 66 | SLOT="${PV}/${PR}" |
| 67 | KEYWORDS="*" |
| 68 | |
| 69 | DEPEND=" |
Fletcher Woodruff | b2acef8 | 2020-07-20 20:39:28 | [diff] [blame] | 70 | =dev-rust/libc-0.2*:= |
| 71 | =dev-rust/getopts-1.2*:= |
| 72 | >=dev-rust/rayon-1.4.1:= <dev-rust/rayon-2.0 |
| 73 | >=dev-rust/http-0.1.8:= <dev-rust/http-0.2 |
| 74 | =dev-rust/indexmap-1*:= |
| 75 | =dev-rust/string-1.2*:= |
| 76 | >=dev-rust/bit-set-2.7.1:= <dev-rust/bit-set-2.8 |
| 77 | =dev-rust/walkdir-2*:= |
Zach Reizner | ab5fdd3 | 2017-08-05 02:48:45 | [diff] [blame] | 78 | " |
Zach Reizner | ab5fdd3 | 2017-08-05 02:48:45 | [diff] [blame] | 79 | ``` |
| 80 | |
paulhsia | a238e9f | 2019-03-12 09:41:19 | [diff] [blame] | 81 | - `DESCRIPTION`, `HOMEPAGE`, `SRC_URI` and `LICENSE` should be found from |
| 82 | `Cargo.toml` or [crates.io]. |
| 83 | - All the dependencies should have a `cros-rust` ebuild and be listed in |
| 84 | DEPEND section. |
Fletcher Woodruff | b2acef8 | 2020-07-20 20:39:28 | [diff] [blame] | 85 | - Dependencies in `Cargo.toml` which do not have any operator specified in |
| 86 | their version number (for example, '^', '<', '~') are handled the same as |
| 87 | crates with '^' specified. |
paulhsia | a238e9f | 2019-03-12 09:41:19 | [diff] [blame] | 88 | - Download the crate from [crates.io] and upload it to [localmirror]. |
| 89 | (Check details in "Depending on Crates" section). |
| 90 | - Run command `ebuild example.ebuild digest` to generate Manifest. |
Zach Reizner | ab5fdd3 | 2017-08-05 02:48:45 | [diff] [blame] | 91 | |
paulhsia | a238e9f | 2019-03-12 09:41:19 | [diff] [blame] | 92 | After creating the ebuild file, running `emerge-${BOARD} <crate_name>` will |
| 93 | install the crate's package to `cros-rust-registry`. |
| 94 | |
Allen Webb | 7b9fc02 | 2019-09-24 20:58:51 | [diff] [blame] | 95 | Many third party crates have dev dependencies that are not actually needed |
| 96 | for Chrome OS. To keep dev dependencies from being enforced |
| 97 | `cros-rust.eclass` provides, `CROS_RUST_REMOVE_DEV_DEPS` which can be set to |
| 98 | remove the dev dependencies during `src_prepare`. This is especially useful when |
| 99 | there would otherwise be circular dependencies. |
| 100 | |
paulhsia | a238e9f | 2019-03-12 09:41:19 | [diff] [blame] | 101 | ### Empty crates |
| 102 | |
| 103 | If some third-party crates are dependent on some **unused** crates (e.g., |
| 104 | dependencies uses by unused features or they're in dev-dependencies) and we want |
| 105 | to mock those **unused** crates out, we could create empty-crate ebuilds for |
| 106 | them. Here is an empty ebuild for example crate: |
| 107 | |
| 108 | ```bash |
| 109 | # Copyright <copyright_year> The Chromium OS Authors. All rights reserved. |
| 110 | # Distributed under the terms of the GNU General Public License v2 |
| 111 | |
| 112 | EAPI="6" |
| 113 | |
| 114 | CROS_RUST_EMPTY_CRATE=1 |
| 115 | |
| 116 | inherit cros-rust |
| 117 | |
| 118 | DESCRIPTION="Empty example crate" |
| 119 | HOMEPAGE="" |
| 120 | |
| 121 | LICENSE="BSD-Google" |
| 122 | SLOT="${PV}/${PR}" |
| 123 | KEYWORDS="*" |
| 124 | ``` |
| 125 | |
| 126 | ### First-party crates |
| 127 | |
| 128 | You can create your Rust project in anywhere in the Chrome OS system and it's |
| 129 | ebuild in a suitable place in `chromiumos-overlay` with name |
| 130 | `<category>/<crate_name>-9999.ebuild`. Here is an ebuild for |
| 131 | an example **first-party** crate: |
| 132 | |
| 133 | ```bash |
| 134 | # Copyright <copyright_year> The Chromium OS Authors. All rights reserved. |
| 135 | # Distributed under the terms of the GNU General Public License v2 |
| 136 | |
| 137 | EAPI="6" |
| 138 | |
| 139 | CROS_WORKON_LOCALNAME="example" |
| 140 | CROS_WORKON_PROJECT="path/to/project/repository" |
| 141 | # We don't use CROS_WORKON_OUTOFTREE_BUILD here since project's Cargo.toml is |
| 142 | # using "provided by ebuild" macro which supported by cros-rust. |
| 143 | CROS_WORKON_SUBTREE="path/to/project/subtree" |
| 144 | |
| 145 | inherit cros-workon cros-rust |
| 146 | |
| 147 | DESCRIPTION="An example first party project" |
| 148 | HOMEPAGE="home_page_url" |
| 149 | |
| 150 | LICENSE="BSD-Google" |
Chirantan Ekbote | 61b7be3 | 2019-09-25 01:56:38 | [diff] [blame] | 151 | SLOT="0/${PVR}" |
paulhsia | a238e9f | 2019-03-12 09:41:19 | [diff] [blame] | 152 | KEYWORDS="~*" |
| 153 | IUSE="test" |
| 154 | |
| 155 | DEPEND=" |
| 156 | dev-rust/third_party_crate:= |
| 157 | example2/first_party_crate:= |
| 158 | " |
| 159 | |
| 160 | src_unpack() { |
| 161 | cros-workon_src_unpack |
| 162 | S+="/path/to/project/subtree" |
| 163 | |
| 164 | cros-rust_src_unpack |
| 165 | } |
| 166 | |
| 167 | src_compile() { |
Andrew McRae | 089013e | 2019-06-11 02:15:20 | [diff] [blame] | 168 | ecargo_build |
paulhsia | a238e9f | 2019-03-12 09:41:19 | [diff] [blame] | 169 | use test && ecargo_test --no-run |
| 170 | } |
| 171 | |
| 172 | src_test() { |
| 173 | if use x86 || use amd64; then |
| 174 | ecargo_test |
| 175 | else |
| 176 | elog "Skipping rust unit tests on non-x86 platform" |
| 177 | fi |
| 178 | } |
| 179 | |
| 180 | src_install() { |
| 181 | # You can |
| 182 | # 1. Publish this library for other first-party crates by |
| 183 | cros-rust_publish "${PN}" "$(cros-rust_get_crate_version)" |
| 184 | # 2. Install the binary to image by |
| 185 | dobin "$(cros-rust_get_build_dir)/example_bin" |
| 186 | } |
| 187 | ``` |
| 188 | |
| 189 | If the Rust project will be used by other first-party crates, remember to |
| 190 | publish it by using the `cros-rust_publish` command. |
| 191 | |
| 192 | > **WARNING**: Please make sure your project could be built by both steps for |
| 193 | > engineering productivity: |
| 194 | > |
| 195 | > 1. From chroot with `emerge-${BOARD} CRATE-EBUILD-NAME` |
| 196 | > |
| 197 | > **Tips**: You can set `USE=-lto` to speed up build times when using |
| 198 | > emerge. This turns off link time optimization, which is useful for |
| 199 | > release builds but significantly increases build times and isn't really |
| 200 | > needed during development. |
| 201 | > |
| 202 | > 2. From project root directory with `cargo build` |
| 203 | > |
David Pursehouse | b3b7da1 | 2019-06-17 12:23:39 | [diff] [blame] | 204 | > We add two macros to resolve conflicts between these two build system. Check |
paulhsia | a238e9f | 2019-03-12 09:41:19 | [diff] [blame] | 205 | > details from the following section. |
| 206 | |
| 207 | ### Cargo.toml macros |
| 208 | |
| 209 | Using `cros-rust` ebuild could support building crates in Chrome OS build |
| 210 | system, but it will break local `cargo build` in some situations. We add two |
David Pursehouse | b3b7da1 | 2019-06-17 12:23:39 | [diff] [blame] | 211 | macros which are recognized by ebuild for `Cargo.toml` to keep both build system |
paulhsia | a238e9f | 2019-03-12 09:41:19 | [diff] [blame] | 212 | work. |
| 213 | |
| 214 | - Provided by ebuild |
| 215 | |
| 216 | This macro introduces a replacement of: |
| 217 | |
| 218 | ```toml |
| 219 | [dependencies] |
| 220 | data_model = { path = "../data_model" } # provided by ebuild |
| 221 | ``` |
| 222 | |
| 223 | with: |
| 224 | |
| 225 | ```toml |
| 226 | [dependencies] |
| 227 | data_model = { version = "*" } |
| 228 | ``` |
| 229 | |
| 230 | **Example usage**: Add dependency to first-party crate |
| 231 | |
| 232 | 1. Add the dependent crate to DEPEND section in ebuild. |
David Pursehouse | b3b7da1 | 2019-06-17 12:23:39 | [diff] [blame] | 233 | 2. Use relative path for imported crates in `Cargo.toml` but with |
paulhsia | a238e9f | 2019-03-12 09:41:19 | [diff] [blame] | 234 | `# provided by ebuild` macro: |
| 235 | |
| 236 | ```toml |
| 237 | [dependencies] |
| 238 | data_model = { path = "../data_model" } # provided by ebuild |
| 239 | ``` |
| 240 | |
| 241 | - Ignored by ebuild |
| 242 | |
| 243 | We will use this to discard parts of `[patch.crates-io]` which should be |
| 244 | applied to local developer builds but not to ebuilds. |
| 245 | |
| 246 | This macro introduces a replacement of: |
| 247 | |
| 248 | ```toml |
| 249 | audio_streams = { path = "../../third_party/adhd/audio_streams" } # ignored by ebuild |
| 250 | ``` |
| 251 | |
| 252 | with empty line while building with emerge. |
| 253 | |
| 254 | **Example usage**: Add dependency to first-party crate for sub-crates from |
| 255 | root crate. |
| 256 | |
| 257 | 1. Add the dependent crate to DEPEND section in root crate's ebuild. |
David Pursehouse | b3b7da1 | 2019-06-17 12:23:39 | [diff] [blame] | 258 | 2. Use relative path for imported crates in `[patch.crates-io]` section in |
paulhsia | a238e9f | 2019-03-12 09:41:19 | [diff] [blame] | 259 | root crate's `Cargo.toml` but with `# ignored by ebuild` macro: |
| 260 | |
| 261 | ```toml |
| 262 | [patch.crates-io] |
| 263 | audio_streams = { path = "../../third_party/adhd/audio_streams" } # ignored by ebuild |
| 264 | ``` |
Zach Reizner | ab5fdd3 | 2017-08-05 02:48:45 | [diff] [blame] | 265 | |
| 266 | ## Depending on Crates |
| 267 | |
paulhsia | a238e9f | 2019-03-12 09:41:19 | [diff] [blame] | 268 | Because the sources for all ebuilds in Chrome OS must be available at |
| 269 | [localmirror], you will have to upload all third-party crate dependencies for |
| 270 | the project to localmirror. |
Zach Reizner | ab5fdd3 | 2017-08-05 02:48:45 | [diff] [blame] | 271 | |
paulhsia | a238e9f | 2019-03-12 09:41:19 | [diff] [blame] | 272 | The following will download a crate, upload it to localmirror, and make it |
| 273 | accessible for download: |
Zach Reizner | ab5fdd3 | 2017-08-05 02:48:45 | [diff] [blame] | 274 | |
paulhsia | a238e9f | 2019-03-12 09:41:19 | [diff] [blame] | 275 | > **WARNING**: localmirror is shared by all Chrome OS developers. If you break |
| 276 | > it, everybody will have a bad day. |
Zach Reizner | ab5fdd3 | 2017-08-05 02:48:45 | [diff] [blame] | 277 | |
Tom Hughes | e6f0511 | 2019-08-06 15:35:38 | [diff] [blame] | 278 | ```bash |
Zach Reizner | ab5fdd3 | 2017-08-05 02:48:45 | [diff] [blame] | 279 | curl -L 'https://crates.io/api/v1/crates/<crate_name>/<crate_version>/download' >/tmp/crates/<crate_name>-<crate_version>.crate |
paulhsia | a238e9f | 2019-03-12 09:41:19 | [diff] [blame] | 280 | gsutil cp -a public-read /tmp/crates/<crate_name>-<crate_version>.crate gs://chromeos-localmirror/distfiles/ |
Zach Reizner | ab5fdd3 | 2017-08-05 02:48:45 | [diff] [blame] | 281 | ``` |
| 282 | |
paulhsia | a238e9f | 2019-03-12 09:41:19 | [diff] [blame] | 283 | ## Cross-compiling |
Zach Reizner | ab5fdd3 | 2017-08-05 02:48:45 | [diff] [blame] | 284 | |
| 285 | The toolchain that is installed by default is targetable to the following triples: |
| 286 | |
Zach Reizner | e0434ea | 2018-12-01 02:40:52 | [diff] [blame] | 287 | | Target Triple | Description | |
| 288 | |-------------------------------|-------------------------------------------------------------------------------------| |
| 289 | | `x86_64-pc-linux-gnu` | **(default)** Used exclusively for packages installed in the chroot | |
| 290 | | `armv7a-cros-linux-gnueabihf` | Used by 32-bit usermode ARM devices | |
| 291 | | `aarch64-cros-linux-gnu` | Used by 64-bit usermode ARM devices (none of these exist as of November 30th, 2018) | |
| 292 | | `x86_64-cros-linux-gnu` | Used by x86_64 devices | |
Zach Reizner | ab5fdd3 | 2017-08-05 02:48:45 | [diff] [blame] | 293 | |
paulhsia | a238e9f | 2019-03-12 09:41:19 | [diff] [blame] | 294 | When building Rust projects for development, a non-default target can be |
| 295 | selected as follows: |
Zach Reizner | ab5fdd3 | 2017-08-05 02:48:45 | [diff] [blame] | 296 | |
Tom Hughes | e6f0511 | 2019-08-06 15:35:38 | [diff] [blame] | 297 | ```bash |
Zach Reizner | 9125e7f | 2017-08-22 18:05:19 | [diff] [blame] | 298 | cargo build --target=<target_triple> |
| 299 | ``` |
| 300 | |
paulhsia | a238e9f | 2019-03-12 09:41:19 | [diff] [blame] | 301 | If a specific board is being targeted, that board's sysroot can be used for |
| 302 | compiling and linking purposes by setting the `SYSROOT` environment variable as |
| 303 | follows: |
Zach Reizner | 9125e7f | 2017-08-22 18:05:19 | [diff] [blame] | 304 | |
Tom Hughes | e6f0511 | 2019-08-06 15:35:38 | [diff] [blame] | 305 | ```bash |
Zach Reizner | 9125e7f | 2017-08-22 18:05:19 | [diff] [blame] | 306 | export SYSROOT="/build/<board>" |
Zach Reizner | ab5fdd3 | 2017-08-05 02:48:45 | [diff] [blame] | 307 | ``` |
paulhsia | a238e9f | 2019-03-12 09:41:19 | [diff] [blame] | 308 | |
| 309 | If C files are getting compiled with a build script that uses the `cc` or `gcc` |
| 310 | crates, you may also need to set the `TARGET_CC` environment variable to point |
| 311 | at the appropriate C compiler. |
Sonny Rao | 3d6115d | 2018-02-07 00:42:24 | [diff] [blame] | 312 | |
Tom Hughes | e6f0511 | 2019-08-06 15:35:38 | [diff] [blame] | 313 | ```bash |
Sonny Rao | 3d6115d | 2018-02-07 00:42:24 | [diff] [blame] | 314 | export TARGET_CC="<target_triple>-clang" |
| 315 | ``` |
Zach Reizner | ab5fdd3 | 2017-08-05 02:48:45 | [diff] [blame] | 316 | |
paulhsia | a238e9f | 2019-03-12 09:41:19 | [diff] [blame] | 317 | If a C/C++ package is being pulled in via `pkg-config`, the |
| 318 | `PKG_CONFIG_ALLOW_CROSS` environment |
| 319 | variable should be exposed. Without this, you might see `CrossCompilation` |
| 320 | as part of an error message during build script execution. |
Zach Reizner | e0434ea | 2018-12-01 02:40:52 | [diff] [blame] | 321 | |
Tom Hughes | e6f0511 | 2019-08-06 15:35:38 | [diff] [blame] | 322 | ```bash |
Zach Reizner | e0434ea | 2018-12-01 02:40:52 | [diff] [blame] | 323 | export PKG_CONFIG_ALLOW_CROSS=1 |
| 324 | ``` |
| 325 | |
paulhsia | a238e9f | 2019-03-12 09:41:19 | [diff] [blame] | 326 | [rust]: https://www.rust-lang.org |
| 327 | [cargo]: https://crates.io/ |
Mike Frysinger | 9fc0fc0 | 2020-09-05 05:18:57 | [diff] [blame] | 328 | [cargo.eclass]: https://chromium.googlesource.com/chromiumos/overlays/chromiumos-overlay/+/HEAD/eclass/cargo.eclass |
paulhsia | a238e9f | 2019-03-12 09:41:19 | [diff] [blame] | 329 | [crates.io]: https://crates.io |
Mike Frysinger | 9fc0fc0 | 2020-09-05 05:18:57 | [diff] [blame] | 330 | [cros-rust.eclass]: https://chromium.googlesource.com/chromiumos/overlays/chromiumos-overlay/+/HEAD/eclass/cros-rust.eclass |
Daniel Verkamp | 8a12ef6 | 2018-12-03 21:55:58 | [diff] [blame] | 331 | [localmirror]: archive_mirrors.md |
Zach Reizner | ab5fdd3 | 2017-08-05 02:48:45 | [diff] [blame] | 332 | [link time optimizations]: https://en.wikipedia.org/wiki/Interprocedural_optimization |
paulhsia | a238e9f | 2019-03-12 09:41:19 | [diff] [blame] | 333 | [semver]: https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html |