]> git.lizzy.rs Git - rust.git/blob - src/doc/rustc/src/platform-support/fuchsia.md
Rollup merge of #100552 - petrochenkov:flavorcompat, r=lqd
[rust.git] / src / doc / rustc / src / platform-support / fuchsia.md
1 # `aarch64-fuchsia` and `x86_64-fuchsia`
2
3 **Tier: 2**
4
5 [Fuchsia] is a modern open source operating system that's simple, secure,
6 updatable, and performant.
7
8 ## Target maintainers
9
10 The [Fuchsia team]:
11
12 - Tyler Mandry ([@tmandry](https://github.com/tmandry))
13 - Dan Johnson ([@computerdruid](https://github.com/computerdruid))
14 - David Koloski ([@djkoloski](https://github.com/djkoloski))
15 - Andrew Pollack ([@andrewpollack](https://github.com/andrewpollack))
16 - Joseph Ryan ([@P1n3appl3](https://github.com/P1n3appl3))
17
18 As the team evolves over time, the specific members listed here may differ from
19 the members reported by the API. The API should be considered to be
20 authoritative if this occurs. Instead of pinging individual members, use
21 `@rustbot ping fuchsia` to contact the team on GitHub.
22
23 ## Table of contents
24
25 1. [Requirements](#requirements)
26 1. [Walkthrough structure](#walkthrough-structure)
27 1. [Compiling a Rust binary targeting Fuchsia](#compiling-a-rust-binary-targeting-fuchsia)
28     1. [Targeting Fuchsia with rustup and cargo](#targeting-fuchsia-with-rustup-and-cargo)
29     1. [Targeting Fuchsia with a compiler built from source](#targeting-fuchsia-with-a-compiler-built-from-source)
30 1. [Creating a Fuchsia package](#creating-a-fuchsia-package)
31     1. [Creating a Fuchsia component](#creating-a-fuchsia-component)
32     1. [Building a Fuchsia package](#building-a-fuchsia-package)
33 1. [Publishing a Fuchsia package](#publishing-a-fuchsia-package)
34     1. [Creating a Fuchsia package repository](#creating-a-fuchsia-package-repository)
35     1. [Publishing Fuchsia package to repository](#publishing-fuchsia-package-to-repository)
36 1. [Running a Fuchsia component on an emulator](#running-a-fuchsia-component-on-an-emulator)
37     1. [Starting the Fuchsia emulator](#starting-the-fuchsia-emulator)
38     1. [Watching emulator logs](#watching-emulator-logs)
39     1. [Serving a Fuchsia package](#serving-a-fuchsia-package)
40     1. [Running a Fuchsia component](#running-a-fuchsia-component)
41 1. [`.gitignore` extensions](#gitignore-extensions)
42 1. [Testing](#testing)
43     1. [Running unit tests](#running-unit-tests)
44     1. [Running the compiler test suite](#running-the-compiler-test-suite)
45
46 ## Requirements
47
48 This target is cross-compiled from a host environment. You will need a recent
49 copy of the [Fuchsia SDK], which provides the tools, libraries, and binaries
50 required to build and link programs for Fuchsia.
51
52 Development may also be done from the [source tree].
53
54 Fuchsia targets support `std` and follow the `sysv64` calling convention on
55 x86_64. Fuchsia binaries use the ELF file format.
56
57 ## Walkthrough structure
58
59 This walkthrough will cover:
60
61 1. Compiling a Rust binary targeting Fuchsia.
62 1. Building a Fuchsia package.
63 1. Publishing and running a Fuchsia package to a Fuchsia emulator.
64
65 For the purposes of this walkthrough, we will only target `x86_64-fuchsia`.
66
67 ## Compiling a Rust binary targeting Fuchsia
68
69 Today, there are two main ways to build a Rust binary targeting Fuchsia
70 using the Fuchsia SDK:
71 1. Allow [rustup] to handle the installation of Fuchsia targets for you.
72 1. Build a toolchain locally that can target Fuchsia.
73
74 ### Targeting Fuchsia with rustup and cargo
75
76 The easiest way to build a Rust binary targeting Fuchsia is by allowing [rustup]
77 to handle the installation of Fuchsia targets for you. This can be done by issuing
78 the following commands:
79
80 ```sh
81 rustup target add x86_64-fuchsia
82 rustup target add aarch64-fuchsia
83 ```
84
85 After installing our Fuchsia targets, we can now compile a Rust binary that targets
86 Fuchsia.
87
88 To create our Rust project, we can issue a standard `cargo` command as follows:
89
90 **From base working directory**
91 ```sh
92 cargo new hello_fuchsia
93 ```
94
95 The rest of this walkthrough will take place from `hello_fuchsia`, so we can
96 change into that directory now:
97
98 ```sh
99 cd hello_fuchsia
100 ```
101
102 *Note: From this point onwards, all commands will be issued from the `hello_fuchsia/`
103 directory, and all `hello_fuchsia/` prefixes will be removed from references for sake of brevity.*
104
105 We can edit our `src/main.rs` to include a test as follows:
106
107 **`src/main.rs`**
108 ```rust
109 fn main() {
110     println!("Hello Fuchsia!");
111 }
112
113 #[test]
114 fn it_works() {
115     assert_eq!(2 + 2, 4);
116 }
117 ```
118
119 In addition to the standard workspace created, we will want to create a
120 `.cargo/config.toml` file to link necessary libraries
121 during compilation:
122
123 **`.cargo/config.toml`**
124 ```txt
125 [target.x86_64-fuchsia]
126
127 rustflags = [
128     "-Lnative=<SDK_PATH>/arch/x64/lib",
129     "-Lnative=<SDK_PATH>/arch/x64/sysroot/lib"
130 ]
131 ```
132
133 *Note: Make sure to fill out `<SDK_PATH>` with the path to the downloaded [Fuchsia SDK].*
134
135 These options configure the following:
136
137 * `-Lnative=${SDK_PATH}/arch/${ARCH}/lib`: Link against Fuchsia libraries from
138   the SDK
139 * `-Lnative=${SDK_PATH}/arch/${ARCH}/sysroot/lib`: Link against Fuchsia kernel
140   libraries from the SDK
141
142 In total, our new project will look like:
143
144 **Current directory structure**
145 ```txt
146 hello_fuchsia/
147 ┣━ src/
148 ┃  ┗━ main.rs
149 ┣━ Cargo.toml
150 ┗━ .cargo/
151    ┗━ config.toml
152 ```
153
154 Finally, we can build our rust binary as:
155
156 ```sh
157 cargo build --target x86_64-fuchsia
158 ```
159
160 Now we have a Rust binary at `target/x86_64-fuchsia/debug/hello_fuchsia`,
161 targeting our desired Fuchsia target.
162
163 **Current directory structure**
164 ```txt
165 hello_fuchsia/
166 ┣━ src/
167 ┃  ┗━ main.rs
168 ┣━ target/
169 ┃  ┗━ x86_64-fuchsia/
170 ┃     ┗━ debug/
171 ┃        ┗━ hello_fuchsia
172 ┣━ Cargo.toml
173 ┗━ .cargo/
174    ┗━ config.toml
175 ```
176
177 ### Targeting Fuchsia with a compiler built from source
178
179 An alternative to the first workflow is to target Fuchsia by using
180 `rustc` built from source.
181
182 Before building Rust for Fuchsia, you'll need a clang toolchain that supports
183 Fuchsia as well. A recent version (14+) of clang should be sufficient to compile
184 Rust for Fuchsia.
185
186 x86-64 and AArch64 Fuchsia targets can be enabled using the following
187 configuration.
188
189 In `config.toml`, add:
190
191 ```toml
192 [build]
193 target = ["<host_platform>", "aarch64-fuchsia", "x86_64-fuchsia"]
194 ```
195
196 Additionally, the following environment variables must be configured (for
197 example, using a script like `config-env.sh`):
198
199 ```sh
200 # Configure this environment variable to be the path to the downloaded SDK
201 export SDK_PATH="<SDK path goes here>"
202
203 export CFLAGS_aarch64_fuchsia="--target=aarch64-fuchsia --sysroot=${SDK_PATH}/arch/arm64/sysroot -I${SDK_PATH}/pkg/fdio/include"
204 export CXXFLAGS_aarch64_fuchsia="--target=aarch64-fuchsia --sysroot=${SDK_PATH}/arch/arm64/sysroot -I${SDK_PATH}/pkg/fdio/include"
205 export LDFLAGS_aarch64_fuchsia="--target=aarch64-fuchsia --sysroot=${SDK_PATH}/arch/arm64/sysroot -L${SDK_PATH}/arch/arm64/lib"
206 export CARGO_TARGET_AARCH64_FUCHSIA_RUSTFLAGS="-C link-arg=--sysroot=${SDK_PATH}/arch/arm64/sysroot -Lnative=${SDK_PATH}/arch/arm64/sysroot/lib -Lnative=${SDK_PATH}/arch/arm64/lib"
207 export CFLAGS_x86_64_fuchsia="--target=x86_64-fuchsia --sysroot=${SDK_PATH}/arch/x64/sysroot -I${SDK_PATH}/pkg/fdio/include"
208 export CXXFLAGS_x86_64_fuchsia="--target=x86_64-fuchsia --sysroot=${SDK_PATH}/arch/x64/sysroot -I${SDK_PATH}/pkg/fdio/include"
209 export LDFLAGS_x86_64_fuchsia="--target=x86_64-fuchsia --sysroot=${SDK_PATH}/arch/x64/sysroot -L${SDK_PATH}/arch/x64/lib"
210 export CARGO_TARGET_X86_64_FUCHSIA_RUSTFLAGS="-C link-arg=--sysroot=${SDK_PATH}/arch/x64/sysroot -Lnative=${SDK_PATH}/arch/x64/sysroot/lib -Lnative=${SDK_PATH}/arch/x64/lib"
211 ```
212
213 These can be run together in a shell environment by executing
214 `(source config-env.sh && ./x.py install)`.
215
216 Once `rustc` is installed, we can create a new working directory to work from,
217 `hello_fuchsia` along with `hello_fuchsia/src`:
218
219 ```sh
220 mkdir hello_fuchsia
221 cd hello_fuchsia
222 mkdir src
223 ```
224
225 *Note: From this point onwards, all commands will be issued from the `hello_fuchsia/`
226 directory, and all `hello_fuchsia/` prefixes will be removed from references for sake of brevity.*
227
228 There, we can create a new file named `src/hello_fuchsia.rs`:
229
230 **`src/hello_fuchsia.rs`**
231 ```rust
232 fn main() {
233     println!("Hello Fuchsia!");
234 }
235
236 #[test]
237 fn it_works() {
238     assert_eq!(2 + 2, 4);
239 }
240 ```
241
242 **Current directory structure**
243 ```txt
244 hello_fuchsia/
245 ┗━ src/
246     ┗━ hello_fuchsia.rs
247 ```
248
249 Using your freshly installed `rustc`, you can compile a binary for Fuchsia using
250 the following options:
251
252 * `--target x86_64-fuchsia`/`--target aarch64-fuchsia`: Targets the Fuchsia
253   platform of your choice
254 * `-Lnative ${SDK_PATH}/arch/${ARCH}/lib`: Link against Fuchsia libraries from
255   the SDK
256 * `-Lnative ${SDK_PATH}/arch/${ARCH}/sysroot/lib`: Link against Fuchsia kernel
257   libraries from the SDK
258
259 Putting it all together:
260
261 ```sh
262 # Configure these for the Fuchsia target of your choice
263 TARGET_ARCH="<x86_64-fuchsia|aarch64-fuchsia>"
264 ARCH="<x64|aarch64>"
265
266 rustc \
267     --target ${TARGET_ARCH} \
268     -Lnative=${SDK_PATH}/arch/${ARCH}/lib \
269     -Lnative=${SDK_PATH}/arch/${ARCH}/sysroot/lib \
270     --out-dir bin src/hello_fuchsia.rs
271 ```
272
273 **Current directory structure**
274 ```txt
275 hello_fuchsia/
276 ┣━ src/
277 ┃   ┗━ hello_fuchsia.rs
278 ┗━ bin/
279    ┗━ hello_fuchsia
280 ```
281
282 ## Creating a Fuchsia package
283
284 Before moving on, double check your directory structure:
285
286 **Current directory structure**
287 ```txt
288 hello_fuchsia/
289 ┣━ src/                     (if using rustc)
290 ┃   ┗━ hello_fuchsia.rs     ...
291 ┣━ bin/                     ...
292 ┃  ┗━ hello_fuchsia         ...
293 ┣━ src/                     (if using cargo)
294 ┃  ┗━ main.rs               ...
295 ┗━ target/                  ...
296    ┗━ x86_64-fuchsia/       ...
297       ┗━ debug/             ...
298          ┗━ hello_fuchsia   ...
299 ```
300
301 With our Rust binary built, we can move to creating a Fuchsia package.
302 On Fuchsia, a package is the unit of distribution for software. We'll need to
303 create a new package directory where we will place files like our finished
304 binary and any data it may need.
305
306 To start, make the `pkg`, and `pkg/meta` directories:
307
308 ```sh
309 mkdir pkg
310 mkdir pkg/meta
311 ```
312
313 **Current directory structure**
314 ```txt
315 hello_fuchsia/
316 ┗━ pkg/
317    ┗━ meta/
318 ```
319
320 Now, create the following files inside:
321
322 **`pkg/meta/package`**
323 ```json
324 {
325   "name": "hello_fuchsia",
326   "version": "0"
327 }
328 ```
329
330 The `package` file describes our package's name and version number. Every
331 package must contain one.
332
333 **`pkg/hello_fuchsia.manifest`**
334 ```txt
335 bin/hello_fuchsia=target/x86_64-fuchsia/debug/hello_fuchsia     # If using cargo...
336 bin/hello_fuchsia=bin/hello_fuchsia                             # If using rustc...
337 lib/ld.so.1=<SDK_PATH>/arch/x64/sysroot/dist/lib/ld.so.1
338 lib/libfdio.so=<SDK_PATH>/arch/x64/dist/libfdio.so
339 meta/package=pkg/meta/package
340 meta/hello_fuchsia.cm=pkg/meta/hello_fuchsia.cm
341 ```
342
343 *Note: Relative manifest paths are resolved starting from the working directory
344 of `pm`. Make sure to fill out `<SDK_PATH>` with the path to the downloaded
345 SDK.*
346
347 The `.manifest` file will be used to describe the contents of the package by
348 relating their location when installed to their location on the file system. The
349 `bin/hello_fuchsia=` entry will be different depending on how your Rust binary
350 was built, so choose accordingly.
351
352 **Current directory structure**
353 ```txt
354 hello_fuchsia/
355 ┗━ pkg/
356    ┣━ meta/
357    ┃  ┗━ package
358    ┗━ hello_fuchsia.manifest
359 ```
360
361 ### Creating a Fuchsia component
362
363 On Fuchsia, components require a component manifest written in Fuchsia's markup
364 language called CML. The Fuchsia devsite contains an [overview of CML] and a
365 [reference for the file format]. Here's a basic one that can run our single binary:
366
367 **`pkg/hello_fuchsia.cml`**
368 ```txt
369 {
370     include: [ "syslog/client.shard.cml" ],
371     program: {
372         runner: "elf",
373         binary: "bin/hello_fuchsia",
374     },
375 }
376 ```
377
378 **Current directory structure**
379 ```txt
380 hello_fuchsia/
381 ┗━ pkg/
382    ┣━ meta/
383    ┃  ┗━ package
384    ┣━ hello_fuchsia.manifest
385    ┗━ hello_fuchsia.cml
386 ```
387
388 Now we can compile that CML into a component manifest:
389
390 ```sh
391 ${SDK_PATH}/tools/${ARCH}/cmc compile \
392     pkg/hello_fuchsia.cml \
393     --includepath ${SDK_PATH}/pkg \
394     -o pkg/meta/hello_fuchsia.cm
395 ```
396
397 *Note: `--includepath` tells the compiler where to look for `include`s from our CML.
398 In our case, we're only using `syslog/client.shard.cml`.*
399
400 **Current directory structure**
401 ```txt
402 hello_fuchsia/
403 ┗━ pkg/
404    ┣━ meta/
405    ┃  ┣━ package
406    ┃  ┗━ hello_fuchsia.cm
407    ┣━ hello_fuchsia.manifest
408    ┗━ hello_fuchsia.cml
409 ```
410
411 ### Building a Fuchsia package
412
413 Next, we'll build a package manifest as defined by our manifest:
414
415 ```sh
416 ${SDK_PATH}/tools/${ARCH}/pm \
417     -o pkg/hello_fuchsia_manifest \
418     -m pkg/hello_fuchsia.manifest \
419     build \
420     -output-package-manifest pkg/hello_fuchsia_package_manifest
421 ```
422
423 This will produce `pkg/hello_fuchsia_manifest/` which is a package manifest we can
424 publish directly to a repository.
425
426 **Current directory structure**
427 ```txt
428 hello_fuchsia/
429 ┗━ pkg/
430    ┣━ meta/
431    ┃  ┣━ package
432    ┃  ┗━ hello_fuchsia.cm
433    ┣━ hello_fuchsia_manifest/
434    ┃  ┗━ ...
435    ┣━ hello_fuchsia.manifest
436    ┣━ hello_fuchsia.cml
437    ┗━ hello_fuchsia_package_manifest
438 ```
439
440 We are now ready to publish the package.
441
442 ## Publishing a Fuchsia package
443
444 With our package and component manifests setup,
445 we can now publish our package. The first step will
446 be to create a Fuchsia package repository to publish
447 to.
448
449 ### Creating a Fuchsia package repository
450
451 We can set up our repository with:
452
453 ```sh
454 ${SDK_PATH}/tools/${ARCH}/pm newrepo \
455     -repo pkg/repo
456 ```
457
458 **Current directory structure**
459 ```txt
460 hello_fuchsia/
461 ┗━ pkg/
462    ┣━ meta/
463    ┃  ┣━ package
464    ┃  ┗━ hello_fuchsia.cm
465    ┣━ hello_fuchsia_manifest/
466    ┃  ┗━ ...
467    ┣━ repo/
468    ┃  ┗━ ...
469    ┣━ hello_fuchsia.manifest
470    ┣━ hello_fuchsia.cml
471    ┗━ hello_fuchsia_package_manifest
472 ```
473
474 ## Publishing Fuchsia package to repository
475
476 We can publish our new package to that repository with:
477
478 ```sh
479 ${SDK_PATH}/tools/${ARCH}/pm publish \
480     -repo pkg/repo \
481     -lp -f <(echo "pkg/hello_fuchsia_package_manifest")
482 ```
483
484 Then we can add the repository to `ffx`'s package server as `hello-fuchsia` using:
485
486 ```sh
487 ${SDK_PATH}/tools/${ARCH}/ffx repository add-from-pm \
488     pkg/repo \
489     -r hello-fuchsia
490 ```
491
492 ## Running a Fuchsia component on an emulator
493
494 At this point, we are ready to run our Fuchsia
495 component. For reference, our final directory
496 structure will look like:
497
498 **Final directory structure**
499 ```txt
500 hello_fuchsia/
501 ┣━ src/                     (if using rustc)
502 ┃   ┗━ hello_fuchsia.rs     ...
503 ┣━ bin/                     ...
504 ┃  ┗━ hello_fuchsia         ...
505 ┣━ src/                     (if using cargo)
506 ┃  ┗━ main.rs               ...
507 ┣━ target/                  ...
508 ┃  ┗━ x86_64-fuchsia/       ...
509 ┃     ┗━ debug/             ...
510 ┃        ┗━ hello_fuchsia   ...
511 ┗━ pkg/
512    ┣━ meta/
513    ┃  ┣━ package
514    ┃  ┗━ hello_fuchsia.cm
515    ┣━ hello_fuchsia_manifest/
516    ┃  ┗━ ...
517    ┣━ repo/
518    ┃  ┗━ ...
519    ┣━ hello_fuchsia.manifest
520    ┣━ hello_fuchsia.cml
521    ┗━ hello_fuchsia_package_manifest
522 ```
523
524 ### Starting the Fuchsia emulator
525
526 Start a Fuchsia emulator in a new terminal using:
527
528 ```sh
529 ${SDK_PATH}/tools/${ARCH}/ffx product-bundle get workstation_eng.qemu-${ARCH}
530 ${SDK_PATH}/tools/${ARCH}/ffx emu start workstation_eng.qemu-${ARCH} --headless
531 ```
532
533 ### Watching emulator logs
534
535 Once the emulator is running, open a separate terminal to watch the emulator logs:
536
537 **In separate terminal**
538 ```sh
539 ${SDK_PATH}/tools/${ARCH}/ffx log \
540     --since now
541 ```
542
543 ### Serving a Fuchsia package
544
545 Now, start a package repository server to serve our
546 package to the emulator:
547
548 ```sh
549 ${SDK_PATH}/tools/${ARCH}/ffx repository server start
550 ```
551
552 Once the repository server is up and running, register it with the target Fuchsia system running in the emulator:
553
554 ```sh
555 ${SDK_PATH}/tools/${ARCH}/ffx target repository register \
556     --repository hello-fuchsia
557 ```
558
559 ### Running a Fuchsia component
560
561 Finally, run the component:
562
563 ```sh
564 ${SDK_PATH}/tools/${ARCH}/ffx component run \
565     fuchsia-pkg://hello-fuchsia/hello_fuchsia_manifest#meta/hello_fuchsia.cm
566 ```
567
568 On reruns of the component, the `--recreate` argument may also need to be
569 passed.
570
571 ```sh
572 ${SDK_PATH}/tools/${ARCH}/ffx component run \
573     --recreate \
574     fuchsia-pkg://hello-fuchsia/hello_fuchsia_manifest#meta/hello_fuchsia.cm
575 ```
576
577 ## `.gitignore` extensions
578
579 Optionally, we can create/extend our `.gitignore` file to ignore files and
580 directories that are not helpful to track:
581
582 ```txt
583 pkg/repo
584 pkg/meta/hello_fuchsia.cm
585 pkg/hello_fuchsia_manifest
586 pkg/hello_fuchsia_package_manifest
587 ```
588
589 ## Testing
590
591 ### Running unit tests
592
593 Tests can be run in the same way as a regular binary.
594
595 * If using `cargo`, you can simply pass `test --no-run`
596 to the `cargo` invocation and then repackage and rerun the Fuchsia package. From our previous example,
597 this would look like `cargo test --target x86_64-fuchsia --no-run`, and moving the executable
598 binary path found from the line `Executable unittests src/main.rs (target/x86_64-fuchsia/debug/deps/hello_fuchsia-<HASH>)`
599 into `pkg/hello_fuchsia.manifest`.
600
601 * If using the compiled `rustc`, you can simply pass `--test`
602 to the `rustc` invocation and then repackage and rerun the Fuchsia package.
603
604 The test harness will run the applicable unit tests.
605
606 Often when testing, you may want to pass additional command line arguments to
607 your binary. Additional arguments can be set in the component manifest:
608
609 **`pkg/hello_fuchsia.cml`**
610 ```txt
611 {
612     include: [ "syslog/client.shard.cml" ],
613     program: {
614         runner: "elf",
615         binary: "bin/hello_fuchsia",
616         args: ["it_works"],
617     },
618 }
619 ```
620
621 This will pass the argument `it_works` to the binary, filtering the tests to
622 only those tests that match the pattern. There are many more configuration
623 options available in CML including environment variables. More documentation is
624 available on the [Fuchsia devsite].
625
626 ### Running the compiler test suite
627
628 Running the Rust test suite on Fuchsia is [not currently supported], but work is
629 underway to enable it.
630
631 [Fuchsia team]: https://team-api.infra.rust-lang.org/v1/teams/fuchsia.json
632 [Fuchsia]: https://fuchsia.dev/
633 [source tree]: https://fuchsia.dev/fuchsia-src/get-started/learn/build
634 [rustup]: https://rustup.rs/
635 [cargo]: https://doc.rust-lang.org/cargo/
636 [Fuchsia SDK]: https://chrome-infra-packages.appspot.com/p/fuchsia/sdk/core
637 [overview of CML]: https://fuchsia.dev/fuchsia-src/concepts/components/v2/component_manifests
638 [reference for the file format]: https://fuchsia.dev/reference/cml
639 [Fuchsia devsite]: https://fuchsia.dev/reference/cml
640 [not currently supported]: https://fxbug.dev/105393